Changeset 153635 in webkit
- Timestamp:
- Aug 1, 2013, 11:01:54 PM (12 years ago)
- Location:
- trunk/Source/WTF
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r153633 r153635 1 2013-08-01 Mark Rowe <mrowe@apple.com> 2 3 <rdar://problem/14528244> False-positive leaks from FastMalloc. 4 5 A logic error in the page map enumeration code within FastMalloc could result in a subset of the memory regions 6 owned by FastMalloc being skipped by the malloc zone enumeration code used by leaks and other performance tools. 7 If the only reference to an allocated object lived within one of the skipped memory regions, leaks would believe 8 it had been leaked since it would not find any references to the object. 9 10 The logic error manifested when a FastMalloc span owned a region of memory that crossed a 16MB address space boundary, 11 and when there was one or more other spans immediately after it in the address space. Crossing the 16MB address space 12 boundary means that the start and end points of the span are in different leaf nodes of the page map trie, and the 13 code within the page map's visitValues method didn't correctly account this case when skipping to the end of the span 14 after visiting it. It would resume iterating from the start of the next leaf node rather than continuing to skip values 15 until the end of the span was passed. The value representing the end of the span would then be processed as if it were 16 the start of a new span, and more values would be skipped even though they may contain actual spans. 17 18 The solution is to rework the algorithm used in visitValues so that it will skip the correct number of values even when 19 some of the values are in different leaf nodes. This is a more involved change than it may seem since it's also necessary 20 to deal with the case where a memory region spans two separate root nodes, which can happen if the region happens to cross 21 a 64GB boundary in the address space. 22 23 Reviewed by Geoff Garen. 24 25 * wtf/TCPageMap.h: 26 (TCMalloc_PageMap3::visitValues): Use a single loop to iterate, with the loop index being the key in to the page map in the 27 same form as used by get and set. This allows us to correctly deal with the index being skipped to a different intermediate or 28 root node as a result of visiting a span that crosses a 16MB boundary in memory. 29 (TCMalloc_PageMap2::visitValues): Ditto, but without having to deal with intermediate nodes. 30 1 31 2013-08-01 Ruth Fong <ruth_fong@apple.com> 2 32 -
trunk/Source/WTF/wtf/TCPageMap.h
r113571 r153635 159 159 void visitValues(Visitor& visitor, const MemoryReader& reader) 160 160 { 161 for (int i = 0; i < ROOT_LENGTH; i++) { 162 if (!root_[i]) 163 continue; 164 165 Leaf* l = reader(reinterpret_cast<Leaf*>(root_[i])); 166 for (int j = 0; j < LEAF_LENGTH; j += visitor.visit(l->values[j])) 167 ; 161 const Number leafIndexMask = LEAF_LENGTH - 1; 162 163 const Number maxKey = (1l << BITS) - 1; 164 const Number invalidIndex = maxKey; 165 Number previousRootIndex = invalidIndex; 166 167 Leaf* leaf = 0; 168 169 for (Number key = 0; key < maxKey; ) { 170 const Number rootIndex = key >> LEAF_BITS; 171 const Number leafIndex = key & leafIndexMask; 172 173 if (rootIndex != previousRootIndex) { 174 if (!root_[rootIndex]) { 175 // There's no node at this index. Move on to the next index at the root level, 176 // clearing the leaf index so that we start from the beginning of the next node. 177 key += 1 << LEAF_BITS; 178 key &= ~leafIndexMask; 179 continue; 180 } 181 182 leaf = reader(root_[rootIndex]); 183 previousRootIndex = rootIndex; 184 } 185 186 key += visitor.visit(leaf->values[leafIndex]); 168 187 } 169 188 } … … 268 287 template<class Visitor, class MemoryReader> 269 288 void visitValues(Visitor& visitor, const MemoryReader& reader) { 289 const Number intermediateIndexMask = (INTERIOR_LENGTH - 1) << LEAF_BITS; 290 const Number leafIndexMask = LEAF_LENGTH - 1; 291 292 const Number maxKey = (1l << BITS) - 1; 293 const Number invalidIndex = maxKey; 294 Number previousRootIndex = invalidIndex; 295 Number previousIntermediateIndex = invalidIndex; 296 297 Node* intermediateNode = 0; 298 Leaf* leaf = 0; 299 270 300 Node* root = reader(root_); 271 for (int i = 0; i < INTERIOR_LENGTH; i++) { 272 if (!root->ptrs[i]) 273 continue; 274 275 Node* n = reader(root->ptrs[i]); 276 for (int j = 0; j < INTERIOR_LENGTH; j++) { 277 if (!n->ptrs[j]) 301 for (Number key = 0; key < maxKey; ) { 302 const Number rootIndex = key >> (LEAF_BITS + INTERIOR_BITS); 303 const Number intermediateIndex = (key & intermediateIndexMask) >> LEAF_BITS; 304 const Number leafIndex = key & leafIndexMask; 305 306 if (rootIndex != previousRootIndex) { 307 if (!root->ptrs[rootIndex]) { 308 // There's no node at this index. Move on to the next index at the root level, clearing the 309 // intermediate and leaf indices so that we start from the beginning of that next node. 310 key += 1 << (LEAF_BITS + INTERIOR_BITS); 311 key &= ~(leafIndexMask | intermediateIndexMask); 278 312 continue; 279 280 Leaf* l = reader(reinterpret_cast<Leaf*>(n->ptrs[j])); 281 for (int k = 0; k < LEAF_LENGTH; k += visitor.visit(l->values[k])) 282 ; 283 } 313 } 314 315 intermediateNode = reader(root->ptrs[rootIndex]); 316 previousRootIndex = rootIndex; 317 318 // Invalidate the previous intermediate index since we've moved on to a different node. 319 previousIntermediateIndex = invalidIndex; 320 } 321 322 if (intermediateIndex != previousIntermediateIndex) { 323 if (!intermediateNode->ptrs[intermediateIndex]) { 324 // There's no node at this index. Move on to the next index at the intermediate level, 325 // clearing the leaf index so that we start from the beginning of the next node. 326 key += 1 << LEAF_BITS; 327 key &= ~leafIndexMask; 328 continue; 329 } 330 331 leaf = reader(reinterpret_cast<Leaf*>(intermediateNode->ptrs[intermediateIndex])); 332 previousIntermediateIndex = intermediateIndex; 333 } 334 335 key += visitor.visit(leaf->values[leafIndex]); 284 336 } 285 337 }
Note:
See TracChangeset
for help on using the changeset viewer.