| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 #include "platform/PlatformExport.h" | 34 #include "platform/PlatformExport.h" |
| 35 #include "platform/heap/AddressSanitizer.h" | 35 #include "platform/heap/AddressSanitizer.h" |
| 36 #include "platform/heap/GCInfo.h" | 36 #include "platform/heap/GCInfo.h" |
| 37 #include "platform/heap/ThreadState.h" | 37 #include "platform/heap/ThreadState.h" |
| 38 #include "platform/heap/Visitor.h" | 38 #include "platform/heap/Visitor.h" |
| 39 #include "public/platform/WebThread.h" | 39 #include "public/platform/WebThread.h" |
| 40 #include "wtf/Assertions.h" | 40 #include "wtf/Assertions.h" |
| 41 #include "wtf/Atomics.h" | 41 #include "wtf/Atomics.h" |
| 42 #include "wtf/ContainerAnnotations.h" | 42 #include "wtf/ContainerAnnotations.h" |
| 43 #include "wtf/Forward.h" | 43 #include "wtf/Forward.h" |
| 44 #include "wtf/HashCountedSet.h" | |
| 45 #include "wtf/LinkedHashSet.h" | |
| 46 #include "wtf/ListHashSet.h" | |
| 47 #include "wtf/PageAllocator.h" | 44 #include "wtf/PageAllocator.h" |
| 48 #include <stdint.h> | 45 #include <stdint.h> |
| 49 | 46 |
| 50 namespace blink { | 47 namespace blink { |
| 51 | 48 |
| 52 const size_t blinkPageSizeLog2 = 17; | 49 const size_t blinkPageSizeLog2 = 17; |
| 53 const size_t blinkPageSize = 1 << blinkPageSizeLog2; | 50 const size_t blinkPageSize = 1 << blinkPageSizeLog2; |
| 54 const size_t blinkPageOffsetMask = blinkPageSize - 1; | 51 const size_t blinkPageOffsetMask = blinkPageSize - 1; |
| 55 const size_t blinkPageBaseMask = ~blinkPageOffsetMask; | 52 const size_t blinkPageBaseMask = ~blinkPageOffsetMask; |
| 56 | 53 |
| (...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1285 // TODO(haraken): We don't support reallocate() for finalizable objects. | 1282 // TODO(haraken): We don't support reallocate() for finalizable objects. |
| 1286 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); | 1283 ASSERT(!Heap::gcInfo(previousHeader->gcInfoIndex())->hasFinalizer()); |
| 1287 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); | 1284 ASSERT(previousHeader->gcInfoIndex() == GCInfoTrait<T>::index()); |
| 1288 size_t copySize = previousHeader->payloadSize(); | 1285 size_t copySize = previousHeader->payloadSize(); |
| 1289 if (copySize > size) | 1286 if (copySize > size) |
| 1290 copySize = size; | 1287 copySize = size; |
| 1291 memcpy(address, previous, copySize); | 1288 memcpy(address, previous, copySize); |
| 1292 return address; | 1289 return address; |
| 1293 } | 1290 } |
| 1294 | 1291 |
| 1295 template<typename T, typename Traits = WTF::VectorTraits<T>> class HeapVectorBac
king { | |
| 1296 public: | |
| 1297 static void finalize(void* pointer); | |
| 1298 void finalizeGarbageCollectedObject() { finalize(this); } | |
| 1299 }; | |
| 1300 | |
| 1301 template<typename T, typename Traits> | |
| 1302 void HeapVectorBacking<T, Traits>::finalize(void* pointer) | |
| 1303 { | |
| 1304 static_assert(Traits::needsDestruction, "Only vector buffers with items requ
iring destruction should be finalized"); | |
| 1305 // See the comment in HeapVectorBacking::trace. | |
| 1306 static_assert(Traits::canInitializeWithMemset || WTF::IsPolymorphic<T>::valu
e, "HeapVectorBacking doesn't support objects that cannot be initialized with me
mset or don't have a vtable"); | |
| 1307 | |
| 1308 ASSERT(!WTF::IsTriviallyDestructible<T>::value); | |
| 1309 HeapObjectHeader* header = HeapObjectHeader::fromPayload(pointer); | |
| 1310 // Use the payload size as recorded by the heap to determine how many | |
| 1311 // elements to finalize. | |
| 1312 size_t length = header->payloadSize() / sizeof(T); | |
| 1313 T* buffer = reinterpret_cast<T*>(pointer); | |
| 1314 #ifdef ANNOTATE_CONTIGUOUS_CONTAINER | |
| 1315 // As commented above, HeapVectorBacking calls finalizers for unused slots | |
| 1316 // (which are already zeroed out). | |
| 1317 ANNOTATE_CHANGE_SIZE(buffer, length, 0, length); | |
| 1318 #endif | |
| 1319 if (WTF::IsPolymorphic<T>::value) { | |
| 1320 for (unsigned i = 0; i < length; ++i) { | |
| 1321 if (blink::vTableInitialized(&buffer[i])) | |
| 1322 buffer[i].~T(); | |
| 1323 } | |
| 1324 } else { | |
| 1325 for (unsigned i = 0; i < length; ++i) { | |
| 1326 buffer[i].~T(); | |
| 1327 } | |
| 1328 } | |
| 1329 } | |
| 1330 | |
| 1331 template<typename Table> class HeapHashTableBacking { | |
| 1332 public: | |
| 1333 static void finalize(void* pointer); | |
| 1334 void finalizeGarbageCollectedObject() { finalize(this); } | |
| 1335 }; | |
| 1336 | |
| 1337 template<typename Table> | |
| 1338 void HeapHashTableBacking<Table>::finalize(void* pointer) | |
| 1339 { | |
| 1340 using Value = typename Table::ValueType; | |
| 1341 ASSERT(!WTF::IsTriviallyDestructible<Value>::value); | |
| 1342 HeapObjectHeader* header = HeapObjectHeader::fromPayload(pointer); | |
| 1343 // Use the payload size as recorded by the heap to determine how many | |
| 1344 // elements to finalize. | |
| 1345 size_t length = header->payloadSize() / sizeof(Value); | |
| 1346 Value* table = reinterpret_cast<Value*>(pointer); | |
| 1347 for (unsigned i = 0; i < length; ++i) { | |
| 1348 if (!Table::isEmptyOrDeletedBucket(table[i])) | |
| 1349 table[i].~Value(); | |
| 1350 } | |
| 1351 } | |
| 1352 | |
| 1353 class HeapAllocatorQuantizer { | |
| 1354 public: | |
| 1355 template<typename T> | |
| 1356 static size_t quantizedSize(size_t count) | |
| 1357 { | |
| 1358 RELEASE_ASSERT(count <= kMaxUnquantizedAllocation / sizeof(T)); | |
| 1359 return Heap::roundedAllocationSize(count * sizeof(T)); | |
| 1360 } | |
| 1361 static const size_t kMaxUnquantizedAllocation = maxHeapObjectSize; | |
| 1362 }; | |
| 1363 | |
| 1364 // CollectionBackingTraceTrait. Do nothing for things in collections that don't | |
| 1365 // need tracing, or call TraceInCollectionTrait for those that do. | |
| 1366 | |
| 1367 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW
eakPointersBeMarkedStrongly strongify, typename T, typename Traits> struct Colle
ctionBackingTraceTrait; | |
| 1368 | |
| 1369 // Specialization for things that don't need marking and have no weak pointers. | |
| 1370 // We do nothing, even if WTF::WeakPointersActStrong. | |
| 1371 template<WTF::ShouldWeakPointersBeMarkedStrongly strongify, typename T, typename
Traits> | |
| 1372 struct CollectionBackingTraceTrait<false, WTF::NoWeakHandlingInCollections, stro
ngify, T, Traits> { | |
| 1373 template<typename VisitorDispatcher> | |
| 1374 static bool trace(VisitorDispatcher, T&) { return false; } | |
| 1375 }; | |
| 1376 | |
| 1377 template<typename T> | |
| 1378 static void verifyGarbageCollectedIfMember(T*) | |
| 1379 { | |
| 1380 } | |
| 1381 | |
| 1382 template<typename T> | |
| 1383 static void verifyGarbageCollectedIfMember(Member<T>* t) | |
| 1384 { | |
| 1385 STATIC_ASSERT_IS_GARBAGE_COLLECTED(T, "non garbage collected object in membe
r"); | |
| 1386 } | |
| 1387 | |
| 1388 // Specialization for things that either need marking or have weak pointers or | |
| 1389 // both. | |
| 1390 template<bool needsTracing, WTF::WeakHandlingFlag weakHandlingFlag, WTF::ShouldW
eakPointersBeMarkedStrongly strongify, typename T, typename Traits> | |
| 1391 struct CollectionBackingTraceTrait { | |
| 1392 template<typename VisitorDispatcher> | |
| 1393 static bool trace(VisitorDispatcher visitor, T&t) | |
| 1394 { | |
| 1395 verifyGarbageCollectedIfMember(reinterpret_cast<T*>(0)); | |
| 1396 return WTF::TraceInCollectionTrait<weakHandlingFlag, strongify, T, Trait
s>::trace(visitor, t); | |
| 1397 } | |
| 1398 }; | |
| 1399 | |
| 1400 template<typename T> struct WeakHandlingHashTraits : WTF::SimpleClassHashTraits<
T> { | |
| 1401 // We want to treat the object as a weak object in the sense that it can | |
| 1402 // disappear from hash sets and hash maps. | |
| 1403 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCol
lections; | |
| 1404 // Normally whether or not an object needs tracing is inferred | |
| 1405 // automatically from the presence of the trace method, but we don't | |
| 1406 // necessarily have a trace method, and we may not need one because T | |
| 1407 // can perhaps only be allocated inside collections, never as independent | |
| 1408 // objects. Explicitly mark this as needing tracing and it will be traced | |
| 1409 // in collections using the traceInCollection method, which it must have. | |
| 1410 template<typename U = void> struct NeedsTracingLazily { | |
| 1411 static const bool value = true; | |
| 1412 }; | |
| 1413 // The traceInCollection method traces differently depending on whether we | |
| 1414 // are strongifying the trace operation. We strongify the trace operation | |
| 1415 // when there are active iterators on the object. In this case all | |
| 1416 // WeakMembers are marked like strong members so that elements do not | |
| 1417 // suddenly disappear during iteration. Returns true if weak pointers to | |
| 1418 // dead objects were found: In this case any strong pointers were not yet | |
| 1419 // traced and the entry should be removed from the collection. | |
| 1420 template<typename VisitorDispatcher> | |
| 1421 static bool traceInCollection(VisitorDispatcher visitor, T& t, WTF::ShouldWe
akPointersBeMarkedStrongly strongify) | |
| 1422 { | |
| 1423 return t.traceInCollection(visitor, strongify); | |
| 1424 } | |
| 1425 }; | |
| 1426 | |
| 1427 // This is a static-only class used as a trait on collections to make them heap | |
| 1428 // allocated. However see also HeapListHashSetAllocator. | |
| 1429 class HeapAllocator { | |
| 1430 public: | |
| 1431 using Quantizer = HeapAllocatorQuantizer; | |
| 1432 using Visitor = blink::Visitor; | |
| 1433 static const bool isGarbageCollected = true; | |
| 1434 | |
| 1435 template <typename T> | |
| 1436 static T* allocateVectorBacking(size_t size) | |
| 1437 { | |
| 1438 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
| 1439 ASSERT(state->isAllocationAllowed()); | |
| 1440 size_t gcInfoIndex = GCInfoTrait<HeapVectorBacking<T, VectorTraits<T>>>:
:index(); | |
| 1441 NormalPageHeap* heap = static_cast<NormalPageHeap*>(state->vectorBacking
Heap(gcInfoIndex)); | |
| 1442 return reinterpret_cast<T*>(heap->allocateObject(Heap::allocationSizeFro
mSize(size), gcInfoIndex)); | |
| 1443 } | |
| 1444 template <typename T> | |
| 1445 static T* allocateExpandedVectorBacking(size_t size) | |
| 1446 { | |
| 1447 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
| 1448 ASSERT(state->isAllocationAllowed()); | |
| 1449 size_t gcInfoIndex = GCInfoTrait<HeapVectorBacking<T, VectorTraits<T>>>:
:index(); | |
| 1450 NormalPageHeap* heap = static_cast<NormalPageHeap*>(state->vectorBacking
Heap(gcInfoIndex)); | |
| 1451 return reinterpret_cast<T*>(heap->allocateObject(Heap::allocationSizeFro
mSize(size), gcInfoIndex)); | |
| 1452 } | |
| 1453 PLATFORM_EXPORT static void freeVectorBacking(void*); | |
| 1454 PLATFORM_EXPORT static bool expandVectorBacking(void*, size_t); | |
| 1455 static inline bool shrinkVectorBacking(void* address, size_t quantizedCurren
tSize, size_t quantizedShrunkSize) | |
| 1456 { | |
| 1457 // Returns always true, so the inlining in turn enables call site simpli
fications. | |
| 1458 backingShrink(address, quantizedCurrentSize, quantizedShrunkSize); | |
| 1459 return true; | |
| 1460 } | |
| 1461 template <typename T> | |
| 1462 static T* allocateInlineVectorBacking(size_t size) | |
| 1463 { | |
| 1464 size_t gcInfoIndex = GCInfoTrait<HeapVectorBacking<T, VectorTraits<T>>>:
:index(); | |
| 1465 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
| 1466 return reinterpret_cast<T*>(Heap::allocateOnHeapIndex(state, size, Inlin
eVectorHeapIndex, gcInfoIndex)); | |
| 1467 } | |
| 1468 PLATFORM_EXPORT static void freeInlineVectorBacking(void*); | |
| 1469 PLATFORM_EXPORT static bool expandInlineVectorBacking(void*, size_t); | |
| 1470 static inline bool shrinkInlineVectorBacking(void* address, size_t quantized
CurrentSize, size_t quantizedShrunkSize) | |
| 1471 { | |
| 1472 backingShrink(address, quantizedCurrentSize, quantizedShrunkSize); | |
| 1473 return true; | |
| 1474 } | |
| 1475 | |
| 1476 template <typename T, typename HashTable> | |
| 1477 static T* allocateHashTableBacking(size_t size) | |
| 1478 { | |
| 1479 size_t gcInfoIndex = GCInfoTrait<HeapHashTableBacking<HashTable>>::index
(); | |
| 1480 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
| 1481 return reinterpret_cast<T*>(Heap::allocateOnHeapIndex(state, size, HashT
ableHeapIndex, gcInfoIndex)); | |
| 1482 } | |
| 1483 template <typename T, typename HashTable> | |
| 1484 static T* allocateZeroedHashTableBacking(size_t size) | |
| 1485 { | |
| 1486 return allocateHashTableBacking<T, HashTable>(size); | |
| 1487 } | |
| 1488 PLATFORM_EXPORT static void freeHashTableBacking(void* address); | |
| 1489 PLATFORM_EXPORT static bool expandHashTableBacking(void*, size_t); | |
| 1490 | |
| 1491 template <typename Return, typename Metadata> | |
| 1492 static Return malloc(size_t size) | |
| 1493 { | |
| 1494 return reinterpret_cast<Return>(Heap::allocate<Metadata>(size)); | |
| 1495 } | |
| 1496 static void free(void* address) { } | |
| 1497 template<typename T> | |
| 1498 static void* newArray(size_t bytes) | |
| 1499 { | |
| 1500 ASSERT_NOT_REACHED(); | |
| 1501 return 0; | |
| 1502 } | |
| 1503 | |
| 1504 static void deleteArray(void* ptr) | |
| 1505 { | |
| 1506 ASSERT_NOT_REACHED(); | |
| 1507 } | |
| 1508 | |
| 1509 static bool isAllocationAllowed() | |
| 1510 { | |
| 1511 return ThreadState::current()->isAllocationAllowed(); | |
| 1512 } | |
| 1513 | |
| 1514 template<typename VisitorDispatcher> | |
| 1515 static void markNoTracing(VisitorDispatcher visitor, const void* t) { visito
r->markNoTracing(t); } | |
| 1516 | |
| 1517 template<typename VisitorDispatcher, typename T, typename Traits> | |
| 1518 static void trace(VisitorDispatcher visitor, T& t) | |
| 1519 { | |
| 1520 CollectionBackingTraceTrait<WTF::ShouldBeTraced<Traits>::value, Traits::
weakHandlingFlag, WTF::WeakPointersActWeak, T, Traits>::trace(visitor, t); | |
| 1521 } | |
| 1522 | |
| 1523 template<typename VisitorDispatcher> | |
| 1524 static void registerDelayedMarkNoTracing(VisitorDispatcher visitor, const vo
id* object) | |
| 1525 { | |
| 1526 visitor->registerDelayedMarkNoTracing(object); | |
| 1527 } | |
| 1528 | |
| 1529 template<typename VisitorDispatcher> | |
| 1530 static void registerWeakMembers(VisitorDispatcher visitor, const void* closu
re, const void* object, WeakPointerCallback callback) | |
| 1531 { | |
| 1532 visitor->registerWeakMembers(closure, object, callback); | |
| 1533 } | |
| 1534 | |
| 1535 template<typename VisitorDispatcher> | |
| 1536 static void registerWeakTable(VisitorDispatcher visitor, const void* closure
, EphemeronCallback iterationCallback, EphemeronCallback iterationDoneCallback) | |
| 1537 { | |
| 1538 visitor->registerWeakTable(closure, iterationCallback, iterationDoneCall
back); | |
| 1539 } | |
| 1540 | |
| 1541 #if ENABLE(ASSERT) | |
| 1542 template<typename VisitorDispatcher> | |
| 1543 static bool weakTableRegistered(VisitorDispatcher visitor, const void* closu
re) | |
| 1544 { | |
| 1545 return visitor->weakTableRegistered(closure); | |
| 1546 } | |
| 1547 #endif | |
| 1548 | |
| 1549 template<typename T> | |
| 1550 struct ResultType { | |
| 1551 using Type = T*; | |
| 1552 }; | |
| 1553 | |
| 1554 template<typename T> | |
| 1555 struct OtherType { | |
| 1556 using Type = T*; | |
| 1557 }; | |
| 1558 | |
| 1559 template<typename T> | |
| 1560 static T& getOther(T* other) | |
| 1561 { | |
| 1562 return *other; | |
| 1563 } | |
| 1564 | |
| 1565 static void enterNoAllocationScope() | |
| 1566 { | |
| 1567 #if ENABLE(ASSERT) | |
| 1568 ThreadState::current()->enterNoAllocationScope(); | |
| 1569 #endif | |
| 1570 } | |
| 1571 | |
| 1572 static void leaveNoAllocationScope() | |
| 1573 { | |
| 1574 #if ENABLE(ASSERT) | |
| 1575 ThreadState::current()->leaveNoAllocationScope(); | |
| 1576 #endif | |
| 1577 } | |
| 1578 | |
| 1579 static void enterGCForbiddenScope() | |
| 1580 { | |
| 1581 ThreadState::current()->enterGCForbiddenScope(); | |
| 1582 } | |
| 1583 | |
| 1584 static void leaveGCForbiddenScope() | |
| 1585 { | |
| 1586 ThreadState::current()->leaveGCForbiddenScope(); | |
| 1587 } | |
| 1588 | |
| 1589 private: | |
| 1590 static void backingFree(void*); | |
| 1591 static bool backingExpand(void*, size_t); | |
| 1592 PLATFORM_EXPORT static void backingShrink(void*, size_t quantizedCurrentSize
, size_t quantizedShrunkSize); | |
| 1593 | |
| 1594 template<typename T, size_t u, typename V> friend class WTF::Vector; | |
| 1595 template<typename T, typename U, typename V, typename W> friend class WTF::H
ashSet; | |
| 1596 template<typename T, typename U, typename V, typename W, typename X, typenam
e Y> friend class WTF::HashMap; | |
| 1597 }; | |
| 1598 | |
| 1599 template<typename VisitorDispatcher, typename Value> | |
| 1600 static void traceListHashSetValue(VisitorDispatcher visitor, Value& value) | |
| 1601 { | |
| 1602 // We use the default hash traits for the value in the node, because | |
| 1603 // ListHashSet does not let you specify any specific ones. | |
| 1604 // We don't allow ListHashSet of WeakMember, so we set that one false | |
| 1605 // (there's an assert elsewhere), but we have to specify some value for the | |
| 1606 // strongify template argument, so we specify WTF::WeakPointersActWeak, | |
| 1607 // arbitrarily. | |
| 1608 CollectionBackingTraceTrait<WTF::ShouldBeTraced<WTF::HashTraits<Value>>::val
ue, WTF::NoWeakHandlingInCollections, WTF::WeakPointersActWeak, Value, WTF::Hash
Traits<Value>>::trace(visitor, value); | |
| 1609 } | |
| 1610 | |
| 1611 // The inline capacity is just a dummy template argument to match the off-heap | |
| 1612 // allocator. | |
| 1613 // This inherits from the static-only HeapAllocator trait class, but we do | |
| 1614 // declare pointers to instances. These pointers are always null, and no | |
| 1615 // objects are instantiated. | |
| 1616 template<typename ValueArg, size_t inlineCapacity> | |
| 1617 class HeapListHashSetAllocator : public HeapAllocator { | |
| 1618 public: | |
| 1619 using TableAllocator = HeapAllocator; | |
| 1620 using Node = WTF::ListHashSetNode<ValueArg, HeapListHashSetAllocator>; | |
| 1621 | |
| 1622 class AllocatorProvider { | |
| 1623 public: | |
| 1624 // For the heap allocation we don't need an actual allocator object, so | |
| 1625 // we just return null. | |
| 1626 HeapListHashSetAllocator* get() const { return 0; } | |
| 1627 | |
| 1628 // No allocator object is needed. | |
| 1629 void createAllocatorIfNeeded() { } | |
| 1630 void releaseAllocator() { } | |
| 1631 | |
| 1632 // There is no allocator object in the HeapListHashSet (unlike in the | |
| 1633 // regular ListHashSet) so there is nothing to swap. | |
| 1634 void swap(AllocatorProvider& other) { } | |
| 1635 }; | |
| 1636 | |
| 1637 void deallocate(void* dummy) { } | |
| 1638 | |
| 1639 // This is not a static method even though it could be, because it needs to | |
| 1640 // match the one that the (off-heap) ListHashSetAllocator has. The 'this' | |
| 1641 // pointer will always be null. | |
| 1642 void* allocateNode() | |
| 1643 { | |
| 1644 // Consider using a LinkedHashSet instead if this compile-time assert fa
ils: | |
| 1645 static_assert(!WTF::IsWeak<ValueArg>::value, "weak pointers in a ListHas
hSet will result in null entries in the set"); | |
| 1646 | |
| 1647 return malloc<void*, Node>(sizeof(Node)); | |
| 1648 } | |
| 1649 | |
| 1650 template<typename VisitorDispatcher> | |
| 1651 static void traceValue(VisitorDispatcher visitor, Node* node) | |
| 1652 { | |
| 1653 traceListHashSetValue(visitor, node->m_value); | |
| 1654 } | |
| 1655 }; | |
| 1656 | |
| 1657 // FIXME: These should just be template aliases: | |
| 1658 // | |
| 1659 // template<typename T, size_t inlineCapacity = 0> | |
| 1660 // using HeapVector = Vector<T, inlineCapacity, HeapAllocator>; | |
| 1661 // | |
| 1662 // as soon as all the compilers we care about support that. | |
| 1663 // MSVC supports it only in MSVC 2013. | |
| 1664 template< | |
| 1665 typename KeyArg, | |
| 1666 typename MappedArg, | |
| 1667 typename HashArg = typename DefaultHash<KeyArg>::Hash, | |
| 1668 typename KeyTraitsArg = HashTraits<KeyArg>, | |
| 1669 typename MappedTraitsArg = HashTraits<MappedArg>> | |
| 1670 class HeapHashMap : public HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, Map
pedTraitsArg, HeapAllocator> { }; | |
| 1671 | |
| 1672 template< | |
| 1673 typename ValueArg, | |
| 1674 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
| 1675 typename TraitsArg = HashTraits<ValueArg>> | |
| 1676 class HeapHashSet : public HashSet<ValueArg, HashArg, TraitsArg, HeapAllocator>
{ }; | |
| 1677 | |
| 1678 template< | |
| 1679 typename ValueArg, | |
| 1680 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
| 1681 typename TraitsArg = HashTraits<ValueArg>> | |
| 1682 class HeapLinkedHashSet : public LinkedHashSet<ValueArg, HashArg, TraitsArg, Hea
pAllocator> { }; | |
| 1683 | |
| 1684 template< | |
| 1685 typename ValueArg, | |
| 1686 size_t inlineCapacity = 0, // The inlineCapacity is just a dummy to match Li
stHashSet (off-heap). | |
| 1687 typename HashArg = typename DefaultHash<ValueArg>::Hash> | |
| 1688 class HeapListHashSet : public ListHashSet<ValueArg, inlineCapacity, HashArg, He
apListHashSetAllocator<ValueArg, inlineCapacity>> { }; | |
| 1689 | |
| 1690 template< | |
| 1691 typename Value, | |
| 1692 typename HashFunctions = typename DefaultHash<Value>::Hash, | |
| 1693 typename Traits = HashTraits<Value>> | |
| 1694 class HeapHashCountedSet : public HashCountedSet<Value, HashFunctions, Traits, H
eapAllocator> { }; | |
| 1695 | |
| 1696 template<typename T, size_t inlineCapacity = 0> | |
| 1697 class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> { | |
| 1698 public: | |
| 1699 HeapVector() { } | |
| 1700 | |
| 1701 explicit HeapVector(size_t size) : Vector<T, inlineCapacity, HeapAllocator>(
size) | |
| 1702 { | |
| 1703 } | |
| 1704 | |
| 1705 HeapVector(size_t size, const T& val) : Vector<T, inlineCapacity, HeapAlloca
tor>(size, val) | |
| 1706 { | |
| 1707 } | |
| 1708 | |
| 1709 template<size_t otherCapacity> | |
| 1710 HeapVector(const HeapVector<T, otherCapacity>& other) | |
| 1711 : Vector<T, inlineCapacity, HeapAllocator>(other) | |
| 1712 { | |
| 1713 } | |
| 1714 | |
| 1715 template<typename U> | |
| 1716 void append(const U* data, size_t dataSize) | |
| 1717 { | |
| 1718 Vector<T, inlineCapacity, HeapAllocator>::append(data, dataSize); | |
| 1719 } | |
| 1720 | |
| 1721 template<typename U> | |
| 1722 void append(const U& other) | |
| 1723 { | |
| 1724 Vector<T, inlineCapacity, HeapAllocator>::append(other); | |
| 1725 } | |
| 1726 | |
| 1727 template<typename U, size_t otherCapacity> | |
| 1728 void appendVector(const HeapVector<U, otherCapacity>& other) | |
| 1729 { | |
| 1730 const Vector<U, otherCapacity, HeapAllocator>& otherVector = other; | |
| 1731 Vector<T, inlineCapacity, HeapAllocator>::appendVector(otherVector); | |
| 1732 } | |
| 1733 }; | |
| 1734 | |
| 1735 template<typename T, size_t inlineCapacity = 0> | |
| 1736 class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> { | |
| 1737 public: | |
| 1738 HeapDeque() { } | |
| 1739 | |
| 1740 explicit HeapDeque(size_t size) : Deque<T, inlineCapacity, HeapAllocator>(si
ze) | |
| 1741 { | |
| 1742 } | |
| 1743 | |
| 1744 HeapDeque(size_t size, const T& val) : Deque<T, inlineCapacity, HeapAllocato
r>(size, val) | |
| 1745 { | |
| 1746 } | |
| 1747 | |
| 1748 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 | |
| 1749 HeapDeque<T, 0>& operator=(const HeapDeque& other) | |
| 1750 { | |
| 1751 HeapDeque<T> copy(other); | |
| 1752 swap(copy); | |
| 1753 return *this; | |
| 1754 } | |
| 1755 | |
| 1756 // FIXME: Doesn't work if there is an inline buffer, due to crbug.com/360572 | |
| 1757 void swap(HeapDeque& other) | |
| 1758 { | |
| 1759 Deque<T, inlineCapacity, HeapAllocator>::swap(other); | |
| 1760 } | |
| 1761 | |
| 1762 template<size_t otherCapacity> | |
| 1763 HeapDeque(const HeapDeque<T, otherCapacity>& other) | |
| 1764 : Deque<T, inlineCapacity, HeapAllocator>(other) | |
| 1765 { | |
| 1766 } | |
| 1767 | |
| 1768 template<typename U> | |
| 1769 void append(const U& other) | |
| 1770 { | |
| 1771 Deque<T, inlineCapacity, HeapAllocator>::append(other); | |
| 1772 } | |
| 1773 }; | |
| 1774 | |
| 1775 template<typename T, size_t i> | |
| 1776 inline void swap(HeapVector<T, i>& a, HeapVector<T, i>& b) { a.swap(b); } | |
| 1777 template<typename T, size_t i> | |
| 1778 inline void swap(HeapDeque<T, i>& a, HeapDeque<T, i>& b) { a.swap(b); } | |
| 1779 template<typename T, typename U, typename V> | |
| 1780 inline void swap(HeapHashSet<T, U, V>& a, HeapHashSet<T, U, V>& b) { a.swap(b);
} | |
| 1781 template<typename T, typename U, typename V, typename W, typename X> | |
| 1782 inline void swap(HeapHashMap<T, U, V, W, X>& a, HeapHashMap<T, U, V, W, X>& b) {
a.swap(b); } | |
| 1783 template<typename T, size_t i, typename U> | |
| 1784 inline void swap(HeapListHashSet<T, i, U>& a, HeapListHashSet<T, i, U>& b) { a.s
wap(b); } | |
| 1785 template<typename T, typename U, typename V> | |
| 1786 inline void swap(HeapLinkedHashSet<T, U, V>& a, HeapLinkedHashSet<T, U, V>& b) {
a.swap(b); } | |
| 1787 template<typename T, typename U, typename V> | |
| 1788 inline void swap(HeapHashCountedSet<T, U, V>& a, HeapHashCountedSet<T, U, V>& b)
{ a.swap(b); } | |
| 1789 | |
| 1790 } // namespace blink | 1292 } // namespace blink |
| 1791 | 1293 |
| 1792 #endif // Heap_h | 1294 #endif // Heap_h |
| OLD | NEW |