| 292 | } |
| 293 | |
| 294 | void GLMemoryShadow::onAddressWrite(uintptr_t addr, size_t page) |
| 295 | { |
| 296 | const size_t relativePage = (addr - reinterpret_cast<uintptr_t>(shadowMemory)) / sPageSize; |
| 297 | if (isPageDirty(relativePage)) { |
| 298 | // It is possible if writing to the same buffer from two threads |
| 299 | return; |
| 300 | } |
| 301 | |
| 302 | if ((relativePage == lastDirtiedRelativePage + 1) && isPageDirty(relativePage - 1)) { |
| 303 | /* Ensure that we would have log(n) page exceptions if traced application writes |
| 304 | * to n consecutive pages. |
| 305 | */ |
| 306 | pagesToDirtyOnConsecutiveWrites *= 2; |
| 307 | } else { |
| 308 | pagesToDirtyOnConsecutiveWrites = 1; |
| 309 | } |
| 310 | |
| 311 | const size_t endPageToDirty = std::min(relativePage + pagesToDirtyOnConsecutiveWrites, nPages); |
| 312 | for (size_t pageToDirty = relativePage; pageToDirty < endPageToDirty; pageToDirty++) { |
| 313 | setPageDirty(pageToDirty); |
| 314 | } |
| 315 | |
| 316 | lastDirtiedRelativePage = endPageToDirty - 1; |
| 317 | |
| 318 | memProtect(reinterpret_cast<void*>(page * sPageSize), |
| 319 | (endPageToDirty - relativePage) * sPageSize, MemProtection::READ_WRITE); |
| 320 | } |
| 321 | |
| 322 | GLbitfield GLMemoryShadow::getMapFlags() const |
| 323 | { |
no test coverage detected