Changeset 205504 in webkit


Ignore:
Timestamp:
Sep 6, 2016 2:13:25 PM (8 years ago)
Author:
sbarati@apple.com
Message:

Make JSMap and JSSet faster
https://bugs.webkit.org/show_bug.cgi?id=160989

Reviewed by Filip Pizlo.

JSTests:

  • microbenchmarks/dense-set.js: Added.

(bench):

  • microbenchmarks/large-map-iteration-with-additions.js: Added.

(bar):
(foo):

  • microbenchmarks/large-map-iteration-with-mutation.js: Added.

(bar):
(foo):

  • microbenchmarks/large-map-iteration.js: Added.

(bar):
(foo):

  • microbenchmarks/map-get-get-cse.js: Added.

(bar):
(foo):

  • microbenchmarks/map-has-get-cse-opportunity.js: Added.

(bar):
(foo):

  • microbenchmarks/sparse-set.js: Added.

(bench):

  • stress/map-cse-correctness.js: Added.

(assert):
(testHas):
(testGet):
(foo):

  • stress/map-iteration.js: Added.

(assert):
(test1):
(test2):
(test3):
(test4):
(test5):
(test6):
(test7):
(test8):
(test9):
(test10):
(test11):
(test12):
(test13):
(test14):
(test15):
(test16):
(test17):
(test18):

Source/JavaScriptCore:

This patch revamps how we implement Map and Set. It uses
a new hash map implementation. The hash map uses linear
probing and it uses Wang's 64 bit hash function for JSValues
that aren't strings. Strings use StringImpl's hash function.
The reason I wanted to roll our own HashTable is twofold:
I didn't want to inline WTF::HashMap's implementation into our
JIT, since that seems error prone and unmaintainable. Also, I wanted
a different structure for hash map buckets where buckets also exist in
a linked list.

The reason for making buckets part of a linked list is that iteration
is now simple. Iteration works by just traversing a linked list.
This design also allows for a simple implementation when doing iteration
while the hash table is mutating. Whenever we remove a bucket from
the hash table, it is removed from the list, meaning items in the
list don't point to it. However, the removed bucket will still point
to things that are either in the list, or have also been removed.
e.g, from a removed bucket, you can always follow pointers until you
either find an item in the list, or you find the tail of the list.
This is a really nice property because it means that a Map or Set
does not need to reason about the all the iterators that point
into its list. Also, whenever we add items to the Map or Set, we
hijack the tail as the new item, and make the new item point to a newly
created tail. This means that any iterator that pointed to the "tail" now
points to non-tail items. This makes the implementation of adding things
to the Map/Set while iterating easy.

I also made Map.prototype.get, Map.prototype.has, and Set.prototype.has
into intrinsics in the DFG. The IR can now reason about hash map
operations and can even do CSE over Wang's hash function, hash map
bucket lookups, hash map bucket loads, and testing if a key is in
the hash table. This makes code patterns for Map like so, super fast
in the FTL, since we will only be doing a single hash and hash bucket lookup:

`
function getKeyIfPresent(map, key) {

if (map.has(key))

return map.get(key);

}
`

This patch is roughly an 8% speedup on ES6SampleBench.

  • CMakeLists.txt:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/SpeculatedType.cpp:

(JSC::speculationFromClassInfo):

  • bytecode/SpeculatedType.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
(JSC::DFG::AbstractInterpreter<AbstractStateType>::execute):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsicCall):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGEdge.h:

(JSC::DFG::Edge::shift):
(JSC::DFG::Edge::makeWord):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGHeapLocation.cpp:

(WTF::printInternal):

  • dfg/DFGHeapLocation.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasHeapPrediction):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::speculateMapObject):
(JSC::DFG::SpeculativeJIT::speculateSetObject):
(JSC::DFG::SpeculativeJIT::speculate):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGUseKind.cpp:

(WTF::printInternal):

  • dfg/DFGUseKind.h:

(JSC::DFG::typeFilterFor):
(JSC::DFG::isCell):

  • ftl/FTLAbstractHeapRepository.h:
  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileMapHash):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::lowMapObject):
(JSC::FTL::DFG::LowerDFGToB3::lowSetObject):
(JSC::FTL::DFG::LowerDFGToB3::lowMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::speculate):
(JSC::FTL::DFG::LowerDFGToB3::speculateMapObject):
(JSC::FTL::DFG::LowerDFGToB3::speculateSetObject):
(JSC::FTL::DFG::LowerDFGToB3::setMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::lowRegExpObject): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::lowStorage): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::speculateRegExpObject): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::setStorage): Deleted.

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::wangsInt64Hash):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted.

  • jit/JITOperations.h:
  • parser/ModuleAnalyzer.cpp:

(JSC::ModuleAnalyzer::ModuleAnalyzer):

  • runtime/HashMapImpl.cpp: Added.

(JSC::HashMapBucket<Data>::visitChildren):
(JSC::HashMapImpl<HashMapBucket>::visitChildren):
(JSC::HashMapImpl<HashMapBucket>::copyBackingStore):

  • runtime/HashMapImpl.h: Added.

(JSC::HashMapBucket::selectStructure):
(JSC::HashMapBucket::createStructure):
(JSC::HashMapBucket::create):
(JSC::HashMapBucket::HashMapBucket):
(JSC::HashMapBucket::setNext):
(JSC::HashMapBucket::setPrev):
(JSC::HashMapBucket::setKey):
(JSC::HashMapBucket::setValue):
(JSC::HashMapBucket::key):
(JSC::HashMapBucket::value):
(JSC::HashMapBucket::next):
(JSC::HashMapBucket::prev):
(JSC::HashMapBucket::deleted):
(JSC::HashMapBucket::setDeleted):
(JSC::HashMapBucket::offsetOfKey):
(JSC::HashMapBucket::offsetOfValue):
(JSC::HashMapBuffer::allocationSize):
(JSC::HashMapBuffer::buffer):
(JSC::HashMapBuffer::create):
(JSC::areKeysEqual):
(JSC::normalizeMapKey):
(JSC::jsMapHash):
(JSC::HashMapImpl::selectStructure):
(JSC::HashMapImpl::createStructure):
(JSC::HashMapImpl::create):
(JSC::HashMapImpl::HashMapImpl):
(JSC::HashMapImpl::buffer):
(JSC::HashMapImpl::finishCreation):
(JSC::HashMapImpl::emptyValue):
(JSC::HashMapImpl::isEmpty):
(JSC::HashMapImpl::deletedValue):
(JSC::HashMapImpl::isDeleted):
(JSC::HashMapImpl::findBucket):
(JSC::HashMapImpl::get):
(JSC::HashMapImpl::has):
(JSC::HashMapImpl::add):
(JSC::HashMapImpl::remove):
(JSC::HashMapImpl::size):
(JSC::HashMapImpl::clear):
(JSC::HashMapImpl::bufferSizeInBytes):
(JSC::HashMapImpl::offsetOfBuffer):
(JSC::HashMapImpl::offsetOfCapacity):
(JSC::HashMapImpl::head):
(JSC::HashMapImpl::tail):
(JSC::HashMapImpl::approximateSize):
(JSC::HashMapImpl::findBucketAlreadyHashedAndNormalized):
(JSC::HashMapImpl::rehash):
(JSC::HashMapImpl::makeAndSetNewBuffer):

  • runtime/Intrinsic.h:
  • runtime/JSCJSValue.h:
  • runtime/JSCJSValueInlines.h:

(JSC::sameValue):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSMap.cpp:

(JSC::JSMap::destroy): Deleted.
(JSC::JSMap::estimatedSize): Deleted.
(JSC::JSMap::visitChildren): Deleted.
(JSC::JSMap::copyBackingStore): Deleted.
(JSC::JSMap::has): Deleted.
(JSC::JSMap::size): Deleted.
(JSC::JSMap::get): Deleted.
(JSC::JSMap::set): Deleted.
(JSC::JSMap::clear): Deleted.
(JSC::JSMap::remove): Deleted.

  • runtime/JSMap.h:

(JSC::JSMap::createStructure):
(JSC::JSMap::create):
(JSC::JSMap::get):
(JSC::JSMap::set):
(JSC::JSMap::JSMap):
(JSC::JSMap::Entry::key): Deleted.
(JSC::JSMap::Entry::value): Deleted.
(JSC::JSMap::Entry::visitChildren): Deleted.
(JSC::JSMap::Entry::setKey): Deleted.
(JSC::JSMap::Entry::setKeyWithoutWriteBarrier): Deleted.
(JSC::JSMap::Entry::setValue): Deleted.
(JSC::JSMap::Entry::clear): Deleted.

  • runtime/JSMapIterator.cpp:

(JSC::JSMapIterator::finishCreation):
(JSC::JSMapIterator::visitChildren):
(JSC::JSMapIterator::clone):

  • runtime/JSMapIterator.h:

(JSC::JSMapIterator::advanceIter):
(JSC::JSMapIterator::next):
(JSC::JSMapIterator::nextKeyValue):
(JSC::JSMapIterator::JSMapIterator):
(JSC::JSMapIterator::setIterator):
(JSC::JSMapIterator::finish): Deleted.
(JSC::JSMapIterator::iteratorData): Deleted.

  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::finishCreation):

  • runtime/JSModuleLoader.h:

(JSC::JSModuleLoader::create):

  • runtime/JSModuleRecord.cpp:

(JSC::JSModuleRecord::finishCreation):

  • runtime/JSModuleRecord.h:

(JSC::JSModuleRecord::create):

  • runtime/JSSet.cpp:

(JSC::JSSet::destroy): Deleted.
(JSC::JSSet::estimatedSize): Deleted.
(JSC::JSSet::visitChildren): Deleted.
(JSC::JSSet::copyBackingStore): Deleted.
(JSC::JSSet::has): Deleted.
(JSC::JSSet::size): Deleted.
(JSC::JSSet::add): Deleted.
(JSC::JSSet::clear): Deleted.
(JSC::JSSet::remove): Deleted.

  • runtime/JSSet.h:

(JSC::JSSet::createStructure):
(JSC::JSSet::create):
(JSC::JSSet::add):
(JSC::JSSet::JSSet):
(JSC::JSSet::Entry::key): Deleted.
(JSC::JSSet::Entry::value): Deleted.
(JSC::JSSet::Entry::visitChildren): Deleted.
(JSC::JSSet::Entry::setKey): Deleted.
(JSC::JSSet::Entry::setKeyWithoutWriteBarrier): Deleted.
(JSC::JSSet::Entry::setValue): Deleted.
(JSC::JSSet::Entry::clear): Deleted.

  • runtime/JSSetIterator.cpp:

(JSC::JSSetIterator::finishCreation):
(JSC::JSSetIterator::visitChildren):
(JSC::JSSetIterator::clone):

  • runtime/JSSetIterator.h:

(JSC::JSSetIterator::advanceIter):
(JSC::JSSetIterator::next):
(JSC::JSSetIterator::JSSetIterator):
(JSC::JSSetIterator::setIterator):
(JSC::JSSetIterator::finish): Deleted.
(JSC::JSSetIterator::iteratorData): Deleted.

  • runtime/JSType.h:
  • runtime/MapBase.cpp: Added.

(JSC::MapBase<HashMapBucketType>::visitChildren):
(JSC::MapBase<HashMapBucketType>::estimatedSize):

  • runtime/MapBase.h: Added.

(JSC::MapBase::size):
(JSC::MapBase::has):
(JSC::MapBase::clear):
(JSC::MapBase::remove):
(JSC::MapBase::findBucket):
(JSC::MapBase::offsetOfHashMapImpl):
(JSC::MapBase::impl):
(JSC::MapBase::finishCreation):
(JSC::MapBase::MapBase):

  • runtime/MapConstructor.cpp:

(JSC::constructMap):

  • runtime/MapIteratorPrototype.cpp:

(JSC::MapIteratorPrototypeFuncNext):

  • runtime/MapPrototype.cpp:

(JSC::MapPrototype::finishCreation):
(JSC::getMap):
(JSC::privateFuncIsMap):
(JSC::privateFuncMapIteratorNext):

  • runtime/PropertyDescriptor.cpp:

(JSC::sameValue): Deleted.

  • runtime/PropertyDescriptor.h:
  • runtime/SetConstructor.cpp:

(JSC::constructSet):

  • runtime/SetIteratorPrototype.cpp:

(JSC::SetIteratorPrototypeFuncNext):

  • runtime/SetPrototype.cpp:

(JSC::SetPrototype::finishCreation):
(JSC::getSet):
(JSC::privateFuncSetIteratorNext):

  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Source/WebCore:

  • ForwardingHeaders/runtime/HashMapImpl.h: Added.
  • ForwardingHeaders/runtime/MapBase.h: Added.
  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneSerializer::serialize):
(WebCore::CloneDeserializer::deserialize):

Source/WTF:

I made s_flagCount public since JSC's JITs now use this field.

  • wtf/text/StringImpl.h:
Location:
trunk
Files:
14 added
64 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r205462 r205504  
     12016-09-06  Saam Barati  <sbarati@apple.com>
     2
     3        Make JSMap and JSSet faster
     4        https://bugs.webkit.org/show_bug.cgi?id=160989
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * microbenchmarks/dense-set.js: Added.
     9        (bench):
     10        * microbenchmarks/large-map-iteration-with-additions.js: Added.
     11        (bar):
     12        (foo):
     13        * microbenchmarks/large-map-iteration-with-mutation.js: Added.
     14        (bar):
     15        (foo):
     16        * microbenchmarks/large-map-iteration.js: Added.
     17        (bar):
     18        (foo):
     19        * microbenchmarks/map-get-get-cse.js: Added.
     20        (bar):
     21        (foo):
     22        * microbenchmarks/map-has-get-cse-opportunity.js: Added.
     23        (bar):
     24        (foo):
     25        * microbenchmarks/sparse-set.js: Added.
     26        (bench):
     27        * stress/map-cse-correctness.js: Added.
     28        (assert):
     29        (testHas):
     30        (testGet):
     31        (foo):
     32        * stress/map-iteration.js: Added.
     33        (assert):
     34        (test1):
     35        (test2):
     36        (test3):
     37        (test4):
     38        (test5):
     39        (test6):
     40        (test7):
     41        (test8):
     42        (test9):
     43        (test10):
     44        (test11):
     45        (test12):
     46        (test13):
     47        (test14):
     48        (test15):
     49        (test16):
     50        (test17):
     51        (test18):
     52
    1532016-08-31  Filip Pizlo  <fpizlo@apple.com>
    254
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r205462 r205504  
    673673    runtime/GeneratorPrototype.cpp
    674674    runtime/GetterSetter.cpp
     675    runtime/HashMapImpl.cpp
    675676    runtime/Identifier.cpp
    676677    runtime/IndexingType.cpp
     
    758759    runtime/LiteralParser.cpp
    759760    runtime/Lookup.cpp
     761    runtime/MapBase.cpp
    760762    runtime/MapConstructor.cpp
    761763    runtime/MapIteratorPrototype.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r205494 r205504  
     12016-09-06  Saam Barati  <sbarati@apple.com>
     2
     3        Make JSMap and JSSet faster
     4        https://bugs.webkit.org/show_bug.cgi?id=160989
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This patch revamps how we implement Map and Set. It uses
     9        a new hash map implementation. The hash map uses linear
     10        probing and it uses Wang's 64 bit hash function for JSValues
     11        that aren't strings. Strings use StringImpl's hash function.
     12        The reason I wanted to roll our own HashTable is twofold:
     13        I didn't want to inline WTF::HashMap's implementation into our
     14        JIT, since that seems error prone and unmaintainable. Also, I wanted
     15        a different structure for hash map buckets where buckets also exist in
     16        a linked list.
     17
     18        The reason for making buckets part of a linked list is that iteration
     19        is now simple. Iteration works by just traversing a linked list.
     20        This design also allows for a simple implementation when doing iteration
     21        while the hash table is mutating. Whenever we remove a bucket from
     22        the hash table, it is removed from the list, meaning items in the
     23        list don't point to it. However, the removed bucket will still point
     24        to things that are either in the list, or have also been removed.
     25        e.g, from a removed bucket, you can always follow pointers until you
     26        either find an item in the list, or you find the tail of the list.
     27        This is a really nice property because it means that a Map or Set
     28        does not need to reason about the all the iterators that point
     29        into its list. Also, whenever we add items to the Map or Set, we
     30        hijack the tail as the new item, and make the new item point to a newly
     31        created tail. This means that any iterator that pointed to the "tail" now
     32        points to non-tail items. This makes the implementation of adding things
     33        to the Map/Set while iterating easy.
     34
     35        I also made Map.prototype.get, Map.prototype.has, and Set.prototype.has
     36        into intrinsics in the DFG. The IR can now reason about hash map
     37        operations and can even do CSE over Wang's hash function, hash map
     38        bucket lookups, hash map bucket loads, and testing if a key is in
     39        the hash table. This makes code patterns for Map like so, super fast
     40        in the FTL, since we will only be doing a single hash and hash bucket lookup:
     41
     42        ```
     43        function getKeyIfPresent(map, key) {
     44            if (map.has(key))
     45                return map.get(key);
     46        }
     47        ```
     48
     49        This patch is roughly an 8% speedup on ES6SampleBench.
     50
     51        * CMakeLists.txt:
     52        * JavaScriptCore.xcodeproj/project.pbxproj:
     53        * bytecode/SpeculatedType.cpp:
     54        (JSC::speculationFromClassInfo):
     55        * bytecode/SpeculatedType.h:
     56        * dfg/DFGAbstractInterpreterInlines.h:
     57        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     58        (JSC::DFG::AbstractInterpreter<AbstractStateType>::execute):
     59        * dfg/DFGByteCodeParser.cpp:
     60        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     61        * dfg/DFGClobberize.h:
     62        (JSC::DFG::clobberize):
     63        * dfg/DFGDoesGC.cpp:
     64        (JSC::DFG::doesGC):
     65        * dfg/DFGEdge.h:
     66        (JSC::DFG::Edge::shift):
     67        (JSC::DFG::Edge::makeWord):
     68        * dfg/DFGFixupPhase.cpp:
     69        (JSC::DFG::FixupPhase::fixupNode):
     70        * dfg/DFGHeapLocation.cpp:
     71        (WTF::printInternal):
     72        * dfg/DFGHeapLocation.h:
     73        * dfg/DFGNode.h:
     74        (JSC::DFG::Node::hasHeapPrediction):
     75        * dfg/DFGNodeType.h:
     76        * dfg/DFGOperations.cpp:
     77        * dfg/DFGOperations.h:
     78        * dfg/DFGPredictionPropagationPhase.cpp:
     79        * dfg/DFGSafeToExecute.h:
     80        (JSC::DFG::SafeToExecuteEdge::operator()):
     81        (JSC::DFG::safeToExecute):
     82        * dfg/DFGSpeculativeJIT.cpp:
     83        (JSC::DFG::SpeculativeJIT::speculateMapObject):
     84        (JSC::DFG::SpeculativeJIT::speculateSetObject):
     85        (JSC::DFG::SpeculativeJIT::speculate):
     86        * dfg/DFGSpeculativeJIT.h:
     87        (JSC::DFG::SpeculativeJIT::callOperation):
     88        * dfg/DFGSpeculativeJIT32_64.cpp:
     89        (JSC::DFG::SpeculativeJIT::compile):
     90        * dfg/DFGSpeculativeJIT64.cpp:
     91        (JSC::DFG::SpeculativeJIT::compile):
     92        * dfg/DFGUseKind.cpp:
     93        (WTF::printInternal):
     94        * dfg/DFGUseKind.h:
     95        (JSC::DFG::typeFilterFor):
     96        (JSC::DFG::isCell):
     97        * ftl/FTLAbstractHeapRepository.h:
     98        * ftl/FTLCapabilities.cpp:
     99        (JSC::FTL::canCompile):
     100        * ftl/FTLLowerDFGToB3.cpp:
     101        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     102        (JSC::FTL::DFG::LowerDFGToB3::compileMapHash):
     103        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
     104        (JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket):
     105        (JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket):
     106        (JSC::FTL::DFG::LowerDFGToB3::lowMapObject):
     107        (JSC::FTL::DFG::LowerDFGToB3::lowSetObject):
     108        (JSC::FTL::DFG::LowerDFGToB3::lowMapBucket):
     109        (JSC::FTL::DFG::LowerDFGToB3::speculate):
     110        (JSC::FTL::DFG::LowerDFGToB3::speculateMapObject):
     111        (JSC::FTL::DFG::LowerDFGToB3::speculateSetObject):
     112        (JSC::FTL::DFG::LowerDFGToB3::setMapBucket):
     113        (JSC::FTL::DFG::LowerDFGToB3::lowRegExpObject): Deleted.
     114        (JSC::FTL::DFG::LowerDFGToB3::lowStorage): Deleted.
     115        (JSC::FTL::DFG::LowerDFGToB3::speculateRegExpObject): Deleted.
     116        (JSC::FTL::DFG::LowerDFGToB3::setStorage): Deleted.
     117        * jit/AssemblyHelpers.cpp:
     118        (JSC::AssemblyHelpers::wangsInt64Hash):
     119        * jit/AssemblyHelpers.h:
     120        (JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted.
     121        * jit/JITOperations.h:
     122        * parser/ModuleAnalyzer.cpp:
     123        (JSC::ModuleAnalyzer::ModuleAnalyzer):
     124        * runtime/HashMapImpl.cpp: Added.
     125        (JSC::HashMapBucket<Data>::visitChildren):
     126        (JSC::HashMapImpl<HashMapBucket>::visitChildren):
     127        (JSC::HashMapImpl<HashMapBucket>::copyBackingStore):
     128        * runtime/HashMapImpl.h: Added.
     129        (JSC::HashMapBucket::selectStructure):
     130        (JSC::HashMapBucket::createStructure):
     131        (JSC::HashMapBucket::create):
     132        (JSC::HashMapBucket::HashMapBucket):
     133        (JSC::HashMapBucket::setNext):
     134        (JSC::HashMapBucket::setPrev):
     135        (JSC::HashMapBucket::setKey):
     136        (JSC::HashMapBucket::setValue):
     137        (JSC::HashMapBucket::key):
     138        (JSC::HashMapBucket::value):
     139        (JSC::HashMapBucket::next):
     140        (JSC::HashMapBucket::prev):
     141        (JSC::HashMapBucket::deleted):
     142        (JSC::HashMapBucket::setDeleted):
     143        (JSC::HashMapBucket::offsetOfKey):
     144        (JSC::HashMapBucket::offsetOfValue):
     145        (JSC::HashMapBuffer::allocationSize):
     146        (JSC::HashMapBuffer::buffer):
     147        (JSC::HashMapBuffer::create):
     148        (JSC::areKeysEqual):
     149        (JSC::normalizeMapKey):
     150        (JSC::jsMapHash):
     151        (JSC::HashMapImpl::selectStructure):
     152        (JSC::HashMapImpl::createStructure):
     153        (JSC::HashMapImpl::create):
     154        (JSC::HashMapImpl::HashMapImpl):
     155        (JSC::HashMapImpl::buffer):
     156        (JSC::HashMapImpl::finishCreation):
     157        (JSC::HashMapImpl::emptyValue):
     158        (JSC::HashMapImpl::isEmpty):
     159        (JSC::HashMapImpl::deletedValue):
     160        (JSC::HashMapImpl::isDeleted):
     161        (JSC::HashMapImpl::findBucket):
     162        (JSC::HashMapImpl::get):
     163        (JSC::HashMapImpl::has):
     164        (JSC::HashMapImpl::add):
     165        (JSC::HashMapImpl::remove):
     166        (JSC::HashMapImpl::size):
     167        (JSC::HashMapImpl::clear):
     168        (JSC::HashMapImpl::bufferSizeInBytes):
     169        (JSC::HashMapImpl::offsetOfBuffer):
     170        (JSC::HashMapImpl::offsetOfCapacity):
     171        (JSC::HashMapImpl::head):
     172        (JSC::HashMapImpl::tail):
     173        (JSC::HashMapImpl::approximateSize):
     174        (JSC::HashMapImpl::findBucketAlreadyHashedAndNormalized):
     175        (JSC::HashMapImpl::rehash):
     176        (JSC::HashMapImpl::makeAndSetNewBuffer):
     177        * runtime/Intrinsic.h:
     178        * runtime/JSCJSValue.h:
     179        * runtime/JSCJSValueInlines.h:
     180        (JSC::sameValue):
     181        * runtime/JSGlobalObject.cpp:
     182        (JSC::JSGlobalObject::init):
     183        * runtime/JSMap.cpp:
     184        (JSC::JSMap::destroy): Deleted.
     185        (JSC::JSMap::estimatedSize): Deleted.
     186        (JSC::JSMap::visitChildren): Deleted.
     187        (JSC::JSMap::copyBackingStore): Deleted.
     188        (JSC::JSMap::has): Deleted.
     189        (JSC::JSMap::size): Deleted.
     190        (JSC::JSMap::get): Deleted.
     191        (JSC::JSMap::set): Deleted.
     192        (JSC::JSMap::clear): Deleted.
     193        (JSC::JSMap::remove): Deleted.
     194        * runtime/JSMap.h:
     195        (JSC::JSMap::createStructure):
     196        (JSC::JSMap::create):
     197        (JSC::JSMap::get):
     198        (JSC::JSMap::set):
     199        (JSC::JSMap::JSMap):
     200        (JSC::JSMap::Entry::key): Deleted.
     201        (JSC::JSMap::Entry::value): Deleted.
     202        (JSC::JSMap::Entry::visitChildren): Deleted.
     203        (JSC::JSMap::Entry::setKey): Deleted.
     204        (JSC::JSMap::Entry::setKeyWithoutWriteBarrier): Deleted.
     205        (JSC::JSMap::Entry::setValue): Deleted.
     206        (JSC::JSMap::Entry::clear): Deleted.
     207        * runtime/JSMapIterator.cpp:
     208        (JSC::JSMapIterator::finishCreation):
     209        (JSC::JSMapIterator::visitChildren):
     210        (JSC::JSMapIterator::clone):
     211        * runtime/JSMapIterator.h:
     212        (JSC::JSMapIterator::advanceIter):
     213        (JSC::JSMapIterator::next):
     214        (JSC::JSMapIterator::nextKeyValue):
     215        (JSC::JSMapIterator::JSMapIterator):
     216        (JSC::JSMapIterator::setIterator):
     217        (JSC::JSMapIterator::finish): Deleted.
     218        (JSC::JSMapIterator::iteratorData): Deleted.
     219        * runtime/JSModuleLoader.cpp:
     220        (JSC::JSModuleLoader::finishCreation):
     221        * runtime/JSModuleLoader.h:
     222        (JSC::JSModuleLoader::create):
     223        * runtime/JSModuleRecord.cpp:
     224        (JSC::JSModuleRecord::finishCreation):
     225        * runtime/JSModuleRecord.h:
     226        (JSC::JSModuleRecord::create):
     227        * runtime/JSSet.cpp:
     228        (JSC::JSSet::destroy): Deleted.
     229        (JSC::JSSet::estimatedSize): Deleted.
     230        (JSC::JSSet::visitChildren): Deleted.
     231        (JSC::JSSet::copyBackingStore): Deleted.
     232        (JSC::JSSet::has): Deleted.
     233        (JSC::JSSet::size): Deleted.
     234        (JSC::JSSet::add): Deleted.
     235        (JSC::JSSet::clear): Deleted.
     236        (JSC::JSSet::remove): Deleted.
     237        * runtime/JSSet.h:
     238        (JSC::JSSet::createStructure):
     239        (JSC::JSSet::create):
     240        (JSC::JSSet::add):
     241        (JSC::JSSet::JSSet):
     242        (JSC::JSSet::Entry::key): Deleted.
     243        (JSC::JSSet::Entry::value): Deleted.
     244        (JSC::JSSet::Entry::visitChildren): Deleted.
     245        (JSC::JSSet::Entry::setKey): Deleted.
     246        (JSC::JSSet::Entry::setKeyWithoutWriteBarrier): Deleted.
     247        (JSC::JSSet::Entry::setValue): Deleted.
     248        (JSC::JSSet::Entry::clear): Deleted.
     249        * runtime/JSSetIterator.cpp:
     250        (JSC::JSSetIterator::finishCreation):
     251        (JSC::JSSetIterator::visitChildren):
     252        (JSC::JSSetIterator::clone):
     253        * runtime/JSSetIterator.h:
     254        (JSC::JSSetIterator::advanceIter):
     255        (JSC::JSSetIterator::next):
     256        (JSC::JSSetIterator::JSSetIterator):
     257        (JSC::JSSetIterator::setIterator):
     258        (JSC::JSSetIterator::finish): Deleted.
     259        (JSC::JSSetIterator::iteratorData): Deleted.
     260        * runtime/JSType.h:
     261        * runtime/MapBase.cpp: Added.
     262        (JSC::MapBase<HashMapBucketType>::visitChildren):
     263        (JSC::MapBase<HashMapBucketType>::estimatedSize):
     264        * runtime/MapBase.h: Added.
     265        (JSC::MapBase::size):
     266        (JSC::MapBase::has):
     267        (JSC::MapBase::clear):
     268        (JSC::MapBase::remove):
     269        (JSC::MapBase::findBucket):
     270        (JSC::MapBase::offsetOfHashMapImpl):
     271        (JSC::MapBase::impl):
     272        (JSC::MapBase::finishCreation):
     273        (JSC::MapBase::MapBase):
     274        * runtime/MapConstructor.cpp:
     275        (JSC::constructMap):
     276        * runtime/MapIteratorPrototype.cpp:
     277        (JSC::MapIteratorPrototypeFuncNext):
     278        * runtime/MapPrototype.cpp:
     279        (JSC::MapPrototype::finishCreation):
     280        (JSC::getMap):
     281        (JSC::privateFuncIsMap):
     282        (JSC::privateFuncMapIteratorNext):
     283        * runtime/PropertyDescriptor.cpp:
     284        (JSC::sameValue): Deleted.
     285        * runtime/PropertyDescriptor.h:
     286        * runtime/SetConstructor.cpp:
     287        (JSC::constructSet):
     288        * runtime/SetIteratorPrototype.cpp:
     289        (JSC::SetIteratorPrototypeFuncNext):
     290        * runtime/SetPrototype.cpp:
     291        (JSC::SetPrototype::finishCreation):
     292        (JSC::getSet):
     293        (JSC::privateFuncSetIteratorNext):
     294        * runtime/VM.cpp:
     295        (JSC::VM::VM):
     296        * runtime/VM.h:
     297
    12982016-09-06  Filip Pizlo  <fpizlo@apple.com>
    2299
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r205462 r205504  
    13191319                792CB3491C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */; };
    13201320                792CB34A1C4EED5C00D13AF3 /* PCToCodeOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1321                795B19971D78BE3500262FA0 /* MapBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 795B19951D78BE3500262FA0 /* MapBase.cpp */; };
     1322                795B19981D78BE3500262FA0 /* MapBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 795B19961D78BE3500262FA0 /* MapBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13211323                7964656A1B952FF0003059EE /* GetPutInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 796465681B952FF0003059EE /* GetPutInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13221324                797E07A91B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */; };
    13231325                797E07AA1B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13241326                799EF7C41C56ED96002B0534 /* B3PCToOriginMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1327                79A0907F1D768465008B889B /* HashMapImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A0907D1D768465008B889B /* HashMapImpl.cpp */; };
     1328                79A090801D768465008B889B /* HashMapImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A0907E1D768465008B889B /* HashMapImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13251329                79A228351D35D71E00D8E067 /* ArithProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 79A228331D35D71E00D8E067 /* ArithProfile.cpp */; };
    13261330                79A228361D35D71F00D8E067 /* ArithProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 79A228341D35D71E00D8E067 /* ArithProfile.h */; };
     
    35703574                792CB3471C4EED5C00D13AF3 /* PCToCodeOriginMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PCToCodeOriginMap.cpp; sourceTree = "<group>"; };
    35713575                792CB3481C4EED5C00D13AF3 /* PCToCodeOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PCToCodeOriginMap.h; sourceTree = "<group>"; };
     3576                795B19951D78BE3500262FA0 /* MapBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MapBase.cpp; sourceTree = "<group>"; };
     3577                795B19961D78BE3500262FA0 /* MapBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MapBase.h; sourceTree = "<group>"; };
    35723578                796465681B952FF0003059EE /* GetPutInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetPutInfo.h; sourceTree = "<group>"; };
    35733579                797E07A71B8FCFB9008400BA /* JSGlobalLexicalEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalLexicalEnvironment.cpp; sourceTree = "<group>"; };
    35743580                797E07A81B8FCFB9008400BA /* JSGlobalLexicalEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalLexicalEnvironment.h; sourceTree = "<group>"; };
    35753581                799EF7C31C56ED96002B0534 /* B3PCToOriginMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3PCToOriginMap.h; path = b3/B3PCToOriginMap.h; sourceTree = "<group>"; };
     3582                79A0907D1D768465008B889B /* HashMapImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashMapImpl.cpp; sourceTree = "<group>"; };
     3583                79A0907E1D768465008B889B /* HashMapImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashMapImpl.h; sourceTree = "<group>"; };
    35763584                79A228331D35D71E00D8E067 /* ArithProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArithProfile.cpp; sourceTree = "<group>"; };
    35773585                79A228341D35D71E00D8E067 /* ArithProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArithProfile.h; sourceTree = "<group>"; };
     
    58265834                                BC02E9B80E184545000F9297 /* GetterSetter.cpp */,
    58275835                                BC337BDE0E1AF0B80076918A /* GetterSetter.h */,
     5836                                79A0907D1D768465008B889B /* HashMapImpl.cpp */,
     5837                                79A0907E1D768465008B889B /* HashMapImpl.h */,
    58285838                                933A349D038AE80F008635CE /* Identifier.cpp */,
    58295839                                933A349A038AE7C6008635CE /* Identifier.h */,
     
    60366046                                F692A8680255597D01FF60F7 /* Lookup.cpp */,
    60376047                                F692A8690255597D01FF60F7 /* Lookup.h */,
     6048                                795B19951D78BE3500262FA0 /* MapBase.cpp */,
     6049                                795B19961D78BE3500262FA0 /* MapBase.h */,
    60386050                                A700873717CBE85300C3E643 /* MapConstructor.cpp */,
    60396051                                A700873817CBE85300C3E643 /* MapConstructor.h */,
     
    73277339                                1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */,
    73287340                                62EC9BB71B7EB07C00303AD1 /* CallFrameShuffleData.h in Headers */,
     7341                                795B19981D78BE3500262FA0 /* MapBase.h in Headers */,
    73297342                                62D755D71B84FB4A001801FA /* CallFrameShuffler.h in Headers */,
    73307343                                0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */,
     
    74947507                                A7D89CF817A0B8CC00773AD8 /* DFGFlushFormat.h in Headers */,
    74957508                                0F2DD8151AB3D8BE00BBB8E8 /* DFGForAllKills.h in Headers */,
     7509                                79A090801D768465008B889B /* HashMapImpl.h in Headers */,
    74967510                                0F69CC89193AC60A0045759E /* DFGFrozenValue.h in Headers */,
    74977511                                86EC9DC61328DF82002B2AD7 /* DFGGenerationInfo.h in Headers */,
     
    92269240                                0FB105851675480F00F8AB6E /* ExitKind.cpp in Sources */,
    92279241                                0FEA0A1C1708B00700BB722C /* FTLAbstractHeap.cpp in Sources */,
     9242                                79A0907F1D768465008B889B /* HashMapImpl.cpp in Sources */,
    92289243                                0FEA0A1E1708B00700BB722C /* FTLAbstractHeapRepository.cpp in Sources */,
    92299244                                0F93274D1C1F66AA00CF6564 /* GPRInfo.cpp in Sources */,
     
    92709285                                FE4BFF2B1AD476E700088F87 /* FunctionOverrides.cpp in Sources */,
    92719286                                147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */,
     9287                                795B19971D78BE3500262FA0 /* MapBase.cpp in Sources */,
    92729288                                62D2D38F1ADF103F000206C1 /* FunctionRareData.cpp in Sources */,
    92739289                                2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp

    r200034 r205504  
    3131
    3232#include "DirectArguments.h"
     33#include "JSCInlines.h"
    3334#include "JSArray.h"
    3435#include "JSFunction.h"
    35 #include "JSCInlines.h"
     36#include "JSMap.h"
     37#include "JSSet.h"
    3638#include "ScopedArguments.h"
    3739#include "StringObject.h"
     
    347349    if (classInfo == RegExpObject::info())
    348350        return SpecRegExpObject;
     351
     352    if (classInfo == JSMap::info())
     353        return SpecMapObject;
     354
     355    if (classInfo == JSSet::info())
     356        return SpecSetObject;
    349357   
    350358    if (classInfo->isSubClassOf(JSFunction::info()))
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r205107 r205504  
    4040typedef uint64_t SpeculatedType;
    4141static const SpeculatedType SpecNone               = 0; // We don't know anything yet.
    42 static const SpeculatedType SpecFinalObject        = 1u << 0; // It's definitely a JSFinalObject.
    43 static const SpeculatedType SpecArray              = 1u << 1; // It's definitely a JSArray.
    44 static const SpeculatedType SpecFunction           = 1u << 2; // It's definitely a JSFunction.
    45 static const SpeculatedType SpecInt8Array          = 1u << 3; // It's definitely an Int8Array or one of its subclasses.
    46 static const SpeculatedType SpecInt16Array         = 1u << 4; // It's definitely an Int16Array or one of its subclasses.
    47 static const SpeculatedType SpecInt32Array         = 1u << 5; // It's definitely an Int32Array or one of its subclasses.
    48 static const SpeculatedType SpecUint8Array         = 1u << 6; // It's definitely an Uint8Array or one of its subclasses.
    49 static const SpeculatedType SpecUint8ClampedArray  = 1u << 7; // It's definitely an Uint8ClampedArray or one of its subclasses.
    50 static const SpeculatedType SpecUint16Array        = 1u << 8; // It's definitely an Uint16Array or one of its subclasses.
    51 static const SpeculatedType SpecUint32Array        = 1u << 9; // It's definitely an Uint32Array or one of its subclasses.
    52 static const SpeculatedType SpecFloat32Array       = 1u << 10; // It's definitely an Uint16Array or one of its subclasses.
    53 static const SpeculatedType SpecFloat64Array       = 1u << 11; // It's definitely an Uint16Array or one of its subclasses.
     42static const SpeculatedType SpecFinalObject        = 1ull << 0; // It's definitely a JSFinalObject.
     43static const SpeculatedType SpecArray              = 1ull << 1; // It's definitely a JSArray.
     44static const SpeculatedType SpecFunction           = 1ull << 2; // It's definitely a JSFunction.
     45static const SpeculatedType SpecInt8Array          = 1ull << 3; // It's definitely an Int8Array or one of its subclasses.
     46static const SpeculatedType SpecInt16Array         = 1ull << 4; // It's definitely an Int16Array or one of its subclasses.
     47static const SpeculatedType SpecInt32Array         = 1ull << 5; // It's definitely an Int32Array or one of its subclasses.
     48static const SpeculatedType SpecUint8Array         = 1ull << 6; // It's definitely an Uint8Array or one of its subclasses.
     49static const SpeculatedType SpecUint8ClampedArray  = 1ull << 7; // It's definitely an Uint8ClampedArray or one of its subclasses.
     50static const SpeculatedType SpecUint16Array        = 1ull << 8; // It's definitely an Uint16Array or one of its subclasses.
     51static const SpeculatedType SpecUint32Array        = 1ull << 9; // It's definitely an Uint32Array or one of its subclasses.
     52static const SpeculatedType SpecFloat32Array       = 1ull << 10; // It's definitely an Uint16Array or one of its subclasses.
     53static const SpeculatedType SpecFloat64Array       = 1ull << 11; // It's definitely an Uint16Array or one of its subclasses.
    5454static const SpeculatedType SpecTypedArrayView     = SpecInt8Array | SpecInt16Array | SpecInt32Array | SpecUint8Array | SpecUint8ClampedArray | SpecUint16Array | SpecUint32Array | SpecFloat32Array | SpecFloat64Array;
    55 static const SpeculatedType SpecDirectArguments    = 1u << 12; // It's definitely a DirectArguments object.
    56 static const SpeculatedType SpecScopedArguments    = 1u << 13; // It's definitely a ScopedArguments object.
    57 static const SpeculatedType SpecStringObject       = 1u << 14; // It's definitely a StringObject.
    58 static const SpeculatedType SpecRegExpObject       = 1u << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
    59 static const SpeculatedType SpecObjectOther        = 1u << 16; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
    60 static const SpeculatedType SpecObject             = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
    61 static const SpeculatedType SpecStringIdent        = 1u << 17; // It's definitely a JSString, and it's an identifier.
    62 static const SpeculatedType SpecStringVar          = 1u << 18; // It's definitely a JSString, and it's not an identifier.
     55static const SpeculatedType SpecDirectArguments    = 1ull << 12; // It's definitely a DirectArguments object.
     56static const SpeculatedType SpecScopedArguments    = 1ull << 13; // It's definitely a ScopedArguments object.
     57static const SpeculatedType SpecStringObject       = 1ull << 14; // It's definitely a StringObject.
     58static const SpeculatedType SpecRegExpObject       = 1ull << 15; // It's definitely a RegExpObject (and not any subclass of RegExpObject).
     59static const SpeculatedType SpecMapObject          = 1ull << 16; // It's definitely Map object (can it be a subclass? FIXME).
     60static const SpeculatedType SpecSetObject          = 1ull << 17; // It's definitely s Set object (can it be a subclass? FIXME).
     61static const SpeculatedType SpecObjectOther        = 1ull << 18; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
     62static const SpeculatedType SpecObject             = SpecFinalObject | SpecArray | SpecFunction | SpecTypedArrayView | SpecDirectArguments | SpecScopedArguments | SpecStringObject | SpecRegExpObject | SpecMapObject | SpecSetObject | SpecObjectOther; // Bitmask used for testing for any kind of object prediction.
     63static const SpeculatedType SpecStringIdent        = 1ull << 19; // It's definitely a JSString, and it's an identifier.
     64static const SpeculatedType SpecStringVar          = 1ull << 20; // It's definitely a JSString, and it's not an identifier.
    6365static const SpeculatedType SpecString             = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
    64 static const SpeculatedType SpecSymbol             = 1u << 19; // It's definitely a Symbol.
    65 static const SpeculatedType SpecCellOther          = 1u << 20; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
     66static const SpeculatedType SpecSymbol             = 1ull << 21; // It's definitely a Symbol.
     67static const SpeculatedType SpecCellOther          = 1ull << 22; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
    6668static const SpeculatedType SpecCell               = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell.
    67 static const SpeculatedType SpecBoolInt32          = 1u << 21; // It's definitely an Int32 with value 0 or 1.
    68 static const SpeculatedType SpecNonBoolInt32       = 1u << 22; // It's definitely an Int32 with value other than 0 or 1.
     69static const SpeculatedType SpecBoolInt32          = 1ull << 23; // It's definitely an Int32 with value 0 or 1.
     70static const SpeculatedType SpecNonBoolInt32       = 1ull << 24; // It's definitely an Int32 with value other than 0 or 1.
    6971static const SpeculatedType SpecInt32Only          = SpecBoolInt32 | SpecNonBoolInt32; // It's definitely an Int32.
    70 static const SpeculatedType SpecInt52Only          = 1u << 23; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
     72static const SpeculatedType SpecInt52Only          = 1ull << 25; // It's definitely an Int52 and we intend it to unbox it. It's also definitely not an Int32.
    7173static const SpeculatedType SpecAnyInt             = SpecInt32Only | SpecInt52Only; // It's something that we can do machine int arithmetic on.
    72 static const SpeculatedType SpecAnyIntAsDouble     = 1u << 24; // It's definitely an Int52 and it's inside a double.
    73 static const SpeculatedType SpecNonIntAsDouble     = 1u << 25; // It's definitely not an Int52 but it's a real number and it's a double.
     74static const SpeculatedType SpecAnyIntAsDouble     = 1ull << 26; // It's definitely an Int52 and it's inside a double.
     75static const SpeculatedType SpecNonIntAsDouble     = 1ull << 27; // It's definitely not an Int52 but it's a real number and it's a double.
    7476static const SpeculatedType SpecDoubleReal         = SpecNonIntAsDouble | SpecAnyIntAsDouble; // It's definitely a non-NaN double.
    75 static const SpeculatedType SpecDoublePureNaN      = 1u << 26; // It's definitely a NaN that is sae to tag (i.e. pure).
    76 static const SpeculatedType SpecDoubleImpureNaN    = 1u << 27; // It's definitely a NaN that is unsafe to tag (i.e. impure).
     77static const SpeculatedType SpecDoublePureNaN      = 1ull << 28; // It's definitely a NaN that is sae to tag (i.e. pure).
     78static const SpeculatedType SpecDoubleImpureNaN    = 1ull << 29; // It's definitely a NaN that is unsafe to tag (i.e. impure).
    7779static const SpeculatedType SpecDoubleNaN          = SpecDoublePureNaN | SpecDoubleImpureNaN; // It's definitely some kind of NaN.
    7880static const SpeculatedType SpecBytecodeDouble     = SpecDoubleReal | SpecDoublePureNaN; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
     
    8284static const SpeculatedType SpecBytecodeNumber     = SpecInt32Only | SpecBytecodeDouble; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
    8385static const SpeculatedType SpecFullNumber         = SpecAnyInt | SpecFullDouble; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
    84 static const SpeculatedType SpecBoolean            = 1u << 28; // It's definitely a Boolean.
    85 static const SpeculatedType SpecOther              = 1u << 29; // It's definitely either Null or Undefined.
     86static const SpeculatedType SpecBoolean            = 1ull << 30; // It's definitely a Boolean.
     87static const SpeculatedType SpecOther              = 1ull << 31; // It's definitely either Null or Undefined.
    8688static const SpeculatedType SpecMisc               = SpecBoolean | SpecOther; // It's definitely either a boolean, Null, or Undefined.
    8789static const SpeculatedType SpecHeapTop            = SpecCell | SpecBytecodeNumber | SpecMisc; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN.
    8890static const SpeculatedType SpecPrimitive          = SpecString | SpecSymbol | SpecBytecodeNumber | SpecMisc; // It's any non-Object JSValue.
    89 static const SpeculatedType SpecEmpty              = 1u << 30; // It's definitely an empty value marker.
     91static const SpeculatedType SpecEmpty              = 1ull << 32; // It's definitely an empty value marker.
    9092static const SpeculatedType SpecBytecodeTop        = SpecHeapTop | SpecEmpty; // It can be any of the above, except for SpecInt52Only and SpecDoubleImpureNaN. Corresponds to what could be found in a bytecode local.
    9193static const SpeculatedType SpecFullTop            = SpecBytecodeTop | SpecFullNumber; // It can be anything that bytecode could see plus exotic encodings of numbers.
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r205112 r205504  
    977977        break;
    978978    }
     979
     980    case MapHash:
     981        forNode(node).setType(SpecInt32Only);
     982        break;
     983
     984    case LoadFromJSMapBucket:
     985        forNode(node).makeHeapTop();
     986        break;
     987
     988    case GetMapBucket:
     989        forNode(node).setType(m_graph, SpecCellOther);
     990        break;
     991
     992    case IsNonEmptyMapBucket:
     993        forNode(node).setType(SpecBoolean);
     994        break;
    979995
    980996    case IsEmpty:
     
    28842900{
    28852901    Node* node = m_state.block()->at(indexInBlock);
    2886    
     2902
    28872903    startExecuting();
    28882904    executeEdges(node);
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r205361 r205504  
    25392539        return true;
    25402540    }
    2541        
     2541
     2542    case JSMapGetIntrinsic: {
     2543        if (argumentCountIncludingThis != 2)
     2544            return false;
     2545
     2546        insertChecks();
     2547        Node* map = get(virtualRegisterForArgument(0, registerOffset));
     2548        Node* key = get(virtualRegisterForArgument(1, registerOffset));
     2549        Node* hash = addToGraph(MapHash, key);
     2550        Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash));
     2551        Node* result = addToGraph(LoadFromJSMapBucket, OpInfo(), OpInfo(prediction), bucket);
     2552        set(VirtualRegister(resultOperand), result);
     2553        return true;
     2554    }
     2555
     2556    case JSSetHasIntrinsic:
     2557    case JSMapHasIntrinsic: {
     2558        if (argumentCountIncludingThis != 2)
     2559            return false;
     2560
     2561        insertChecks();
     2562        Node* mapOrSet = get(virtualRegisterForArgument(0, registerOffset));
     2563        Node* key = get(virtualRegisterForArgument(1, registerOffset));
     2564        Node* hash = addToGraph(MapHash, key);
     2565        UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
     2566        Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash));
     2567        Node* result = addToGraph(IsNonEmptyMapBucket, bucket);
     2568        set(VirtualRegister(resultOperand), result);
     2569        return true;
     2570    }
     2571
    25422572    default:
    25432573        return false;
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r205112 r205504  
    12441244        write(SideState);
    12451245        return;
     1246
     1247    case MapHash:
     1248        def(PureValue(node));
     1249        return;
     1250    case GetMapBucket: {
     1251        read(MiscFields);
     1252        Edge& mapEdge = node->child1();
     1253        Edge& keyEdge = node->child2();
     1254        def(HeapLocation(MapBucketLoc, MiscFields, mapEdge, keyEdge), LazyNode(node));
     1255        return;
     1256    }
     1257    case LoadFromJSMapBucket: {
     1258        read(MiscFields);
     1259        Edge& bucketEdge = node->child1();
     1260        def(HeapLocation(JSMapGetLoc, MiscFields, bucketEdge), LazyNode(node));
     1261        return;
     1262    }
     1263    case IsNonEmptyMapBucket:
     1264        read(MiscFields);
     1265        def(HeapLocation(MapHasLoc, MiscFields, node->child1()), LazyNode(node));
     1266        return;
    12461267       
    12471268    case LastNodeType:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r204439 r205504  
    186186    case CheckWatchdogTimer:
    187187    case StringFromCharCode:
     188    case MapHash:
     189    case GetMapBucket:
     190    case LoadFromJSMapBucket:
     191    case IsNonEmptyMapBucket:
    188192    case Unreachable:
    189193    case ExtractOSREntryLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGEdge.h

    r203812 r205504  
    190190   
    191191#if USE(JSVALUE64)
    192     static uint32_t shift() { return 7; }
     192    static constexpr uint32_t shift() { return 8; }
    193193   
    194194    static uintptr_t makeWord(Node* node, UseKind useKind, ProofStatus proofStatus, KillStatus killStatus)
     
    198198        ASSERT((shiftedValue >> shift()) == bitwise_cast<uintptr_t>(node));
    199199        ASSERT(useKind >= 0 && useKind < LastUseKind);
    200         ASSERT((static_cast<uintptr_t>(LastUseKind) << 2) <= (static_cast<uintptr_t>(2) << shift()));
    201         return shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | static_cast<uintptr_t>(DFG::isProved(proofStatus));
     200        static_assert((static_cast<uintptr_t>(LastUseKind) << 2) < (static_cast<uintptr_t>(1) << shift()), "We rely on this being true to not clobber the node pointer.");
     201        uintptr_t result = shiftedValue | (static_cast<uintptr_t>(useKind) << 2) | (DFG::doesKill(killStatus) << 1) | static_cast<uintptr_t>(DFG::isProved(proofStatus));
     202        if (!ASSERT_DISABLED) {
     203            union U {
     204                U() { word = 0; }
     205                uintptr_t word;
     206                Edge edge;
     207            } u;
     208            u.word = result;
     209            ASSERT(u.edge.useKindUnchecked() == useKind);
     210            ASSERT(u.edge.node() == node);
     211            ASSERT(u.edge.proofStatusUnchecked() == proofStatus);
     212            ASSERT(u.edge.killStatusUnchecked() == killStatus);
     213        }
     214        return result;
    202215    }
    203216   
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r205216 r205504  
    15451545            break;
    15461546        }
     1547
     1548        case GetMapBucket:
     1549            if (node->child1().useKind() == MapObjectUse)
     1550                fixEdge<MapObjectUse>(node->child1());
     1551            else if (node->child1().useKind() == SetObjectUse)
     1552                fixEdge<SetObjectUse>(node->child1());
     1553            else
     1554                RELEASE_ASSERT_NOT_REACHED();
     1555            fixEdge<UntypedUse>(node->child2());
     1556            fixEdge<Int32Use>(node->child3());
     1557            break;
     1558
     1559        case LoadFromJSMapBucket:
     1560            fixEdge<KnownCellUse>(node->child1());
     1561            break;
     1562
     1563        case IsNonEmptyMapBucket:
     1564            fixEdge<KnownCellUse>(node->child1());
     1565            break;
     1566
     1567        case MapHash:
     1568            fixEdge<UntypedUse>(node->child1());
     1569            break;
    15471570
    15481571#if !ASSERT_DISABLED
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r203364 r205504  
    144144        out.print("RegExpObjectLastIndexLoc");
    145145        return;
     146    case MapBucketLoc:
     147        out.print("MapBucketLoc");
     148        return;
     149    case JSMapGetLoc:
     150        out.print("JSMapGetLoc");
     151        return;
     152    case MapHasLoc:
     153        out.print("MapHasLoc");
     154        return;
    146155    }
    147156   
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h

    r203364 r205504  
    5959    TypedArrayByteOffsetLoc,
    6060    StackLoc,
    61     StackPayloadLoc
     61    StackPayloadLoc,
     62    MapBucketLoc,
     63    JSMapGetLoc,
     64    MapHasLoc
    6265};
    6366
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r205321 r205504  
    14221422        case StringReplaceRegExp:
    14231423        case ToNumber:
     1424        case LoadFromJSMapBucket:
    14241425            return true;
    14251426        default:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r205112 r205504  
    389389    macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \
    390390    macro(GetEnumeratorGenericPname, NodeMustGenerate | NodeResultJS) \
    391     macro(ToIndexString, NodeResultJS)
     391    macro(ToIndexString, NodeResultJS) \
     392    /* Nodes for JSMap and JSSet */ \
     393    macro(MapHash, NodeResultInt32) \
     394    macro(GetMapBucket, NodeResultJS) \
     395    macro(LoadFromJSMapBucket, NodeResultJS) \
     396    macro(IsNonEmptyMapBucket, NodeResultBoolean) \
    392397
    393398// This enum generates a monotonically increasing id for all Node types,
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r205494 r205504  
    5151#include "JSGenericTypedArrayViewConstructorInlines.h"
    5252#include "JSLexicalEnvironment.h"
     53#include "JSMap.h"
     54#include "JSSet.h"
    5355#include "ObjectConstructor.h"
    5456#include "Repatch.h"
     
    18161818}
    18171819
     1820int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
     1821{
     1822    VM& vm = exec->vm();
     1823    NativeCallFrameTracer tracer(&vm, exec);
     1824
     1825    return jsMapHash(exec, vm, normalizeMapKey(JSValue::decode(input)));
     1826}
     1827
     1828JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
     1829{
     1830    VM& vm = exec->vm();
     1831    NativeCallFrameTracer tracer(&vm, exec);
     1832    JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
     1833    if (!bucket)
     1834        return nullptr;
     1835    return *bucket;
     1836}
     1837
     1838JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
     1839{
     1840    VM& vm = exec->vm();
     1841    NativeCallFrameTracer tracer(&vm, exec);
     1842    JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
     1843    if (!bucket)
     1844        return nullptr;
     1845    return *bucket;
     1846}
     1847
    18181848extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
    18191849{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r205494 r205504  
    143143JSString* JIT_OPERATION operationSingleCharacterString(ExecState*, int32_t);
    144144
     145int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input);
     146JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
     147JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
     148
    145149JSCell* JIT_OPERATION operationNewStringObject(ExecState*, JSString*, Structure*);
    146150JSCell* JIT_OPERATION operationToStringOnCell(ExecState*, JSCell*);
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r205321 r205504  
    709709        case GetClosureVar:
    710710        case GetFromArguments:
     711        case LoadFromJSMapBucket:
    711712        case ToNumber: {
    712713            setPrediction(m_currentNode->getHeapPrediction());
     
    738739            break;
    739740        }
     741
     742        case MapHash:
     743            setPrediction(SpecInt32Only);
     744            break;
     745        case GetMapBucket:
     746            setPrediction(SpecCellOther);
     747            break;
     748        case IsNonEmptyMapBucket:
     749            setPrediction(SpecBoolean);
     750            break;
    740751
    741752        case GetRestLength: {
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r204439 r205504  
    5959        case FinalObjectUse:
    6060        case RegExpObjectUse:
     61        case MapObjectUse:
     62        case SetObjectUse:
    6163        case ObjectOrOtherUse:
    6264        case StringIdentUse:
     
    356358    case PutDynamicVar:
    357359    case ResolveScope:
     360    case MapHash:
     361    case GetMapBucket:
     362    case LoadFromJSMapBucket:
     363    case IsNonEmptyMapBucket:
    358364        return true;
    359365
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r205494 r205504  
    74087408}
    74097409
     7410void SpeculativeJIT::speculateMapObject(Edge edge, GPRReg cell)
     7411{
     7412    speculateCellType(edge, cell, SpecMapObject, JSMapType);
     7413}
     7414
     7415void SpeculativeJIT::speculateMapObject(Edge edge)
     7416{
     7417    if (!needsTypeCheck(edge, SpecMapObject))
     7418        return;
     7419
     7420    SpeculateCellOperand operand(this, edge);
     7421    speculateMapObject(edge, operand.gpr());
     7422}
     7423
     7424void SpeculativeJIT::speculateSetObject(Edge edge, GPRReg cell)
     7425{
     7426    speculateCellType(edge, cell, SpecSetObject, JSSetType);
     7427}
     7428
     7429void SpeculativeJIT::speculateSetObject(Edge edge)
     7430{
     7431    if (!needsTypeCheck(edge, SpecSetObject))
     7432        return;
     7433
     7434    SpeculateCellOperand operand(this, edge);
     7435    speculateSetObject(edge, operand.gpr());
     7436}
     7437
    74107438void SpeculativeJIT::speculateObjectOrOther(Edge edge)
    74117439{
     
    76947722    case RegExpObjectUse:
    76957723        speculateRegExpObject(edge);
     7724        break;
     7725    case MapObjectUse:
     7726        speculateMapObject(edge);
     7727        break;
     7728    case SetObjectUse:
     7729        speculateSetObject(edge);
    76967730        break;
    76977731    case ObjectOrOtherUse:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r205494 r205504  
    13121312#if USE(JSVALUE64)
    13131313
     1314    JITCompiler::Call callOperation(C_JITOperation_ECJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
     1315    {
     1316        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
     1317        return appendCallSetResult(operation, result);
     1318    }
     1319
    13141320    JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
    13151321    {
     
    16921698    }
    16931699
     1700    JITCompiler::Call callOperation(Z_JITOperation_EJ operation, GPRReg result, GPRReg arg1)
     1701    {
     1702        m_jit.setupArgumentsWithExecState(arg1);
     1703        return appendCallSetResult(operation, result);
     1704    }
     1705
    16941706    JITCompiler::Call callOperation(Z_JITOperation_EJZZ operation, GPRReg result, GPRReg arg1, unsigned arg2, unsigned arg3)
    16951707    {
     
    17391751    }
    17401752#else // USE(JSVALUE32_64)
     1753
     1754    JITCompiler::Call callOperation(C_JITOperation_ECJZ operation, GPRReg result, GPRReg arg1, JSValueRegs arg2, GPRReg arg3)
     1755    {
     1756        m_jit.setupArgumentsWithExecState(arg1, arg2.payloadGPR(), arg2.tagGPR(), arg3);
     1757        return appendCallSetResult(operation, result);
     1758    }
     1759
     1760    JITCompiler::Call callOperation(Z_JITOperation_EJ operation, GPRReg result, JSValueRegs arg1)
     1761    {
     1762        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1.payloadGPR(), arg1.tagGPR());
     1763        return appendCallSetResult(operation, result);
     1764    }
    17411765
    17421766    JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
     
    26552679    void speculateRegExpObject(Edge, GPRReg cell);
    26562680    void speculateRegExpObject(Edge);
     2681    void speculateMapObject(Edge);
     2682    void speculateMapObject(Edge, GPRReg cell);
     2683    void speculateSetObject(Edge);
     2684    void speculateSetObject(Edge, GPRReg cell);
    26572685    void speculateObjectOrOther(Edge);
    26582686    void speculateString(Edge edge, GPRReg cell);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r205462 r205504  
    3838#include "DirectArguments.h"
    3939#include "GetterSetter.h"
     40#include "HashMapImpl.h"
    4041#include "JSEnvironmentRecord.h"
    4142#include "JSLexicalEnvironment.h"
     
    47204721    }
    47214722
     4723    case MapHash: {
     4724        JSValueOperand input(this, node->child1());
     4725
     4726        JSValueRegs inputRegs = input.jsValueRegs();
     4727
     4728        GPRFlushedCallResult result(this);
     4729        GPRReg resultGPR = result.gpr();
     4730
     4731        flushRegisters();
     4732        callOperation(operationMapHash, resultGPR, inputRegs);
     4733        m_jit.exceptionCheck();
     4734        int32Result(resultGPR, node);
     4735        break;
     4736    }
     4737
     4738    case GetMapBucket: {
     4739        SpeculateCellOperand map(this, node->child1());
     4740        JSValueOperand key(this, node->child2());
     4741        SpeculateInt32Operand hash(this, node->child3());
     4742        GPRFlushedCallResult result(this);
     4743
     4744        GPRReg mapGPR = map.gpr();
     4745        JSValueRegs keyRegs = key.jsValueRegs();
     4746        GPRReg hashGPR = hash.gpr();
     4747        GPRReg resultGPR = result.gpr();
     4748
     4749        if (node->child1().useKind() == MapObjectUse)
     4750            speculateMapObject(node->child1(), mapGPR);
     4751        else if (node->child1().useKind() == SetObjectUse)
     4752            speculateSetObject(node->child1(), mapGPR);
     4753        else
     4754            RELEASE_ASSERT_NOT_REACHED();
     4755
     4756        flushRegisters();
     4757        if (node->child1().useKind() == MapObjectUse)
     4758            callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
     4759        else
     4760            callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
     4761        m_jit.exceptionCheck();
     4762        cellResult(resultGPR, node);
     4763        break;
     4764    }
     4765
     4766    case LoadFromJSMapBucket: {
     4767        SpeculateCellOperand bucket(this, node->child1());
     4768        GPRTemporary resultPayload(this);
     4769        GPRTemporary resultTag(this);
     4770
     4771        GPRReg bucketGPR = bucket.gpr();
     4772        GPRReg resultPayloadGPR = resultPayload.gpr();
     4773        GPRReg resultTagGPR = resultTag.gpr();
     4774
     4775        auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR);
     4776        m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), JSValueRegs(resultTagGPR, resultPayloadGPR));
     4777        auto done = m_jit.jump();
     4778
     4779        notBucket.link(&m_jit);
     4780        m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
     4781        m_jit.move(TrustedImm32(0), resultPayloadGPR);
     4782        done.link(&m_jit);
     4783        jsValueResult(resultTagGPR, resultPayloadGPR, node);
     4784        break;
     4785    }
     4786
     4787    case IsNonEmptyMapBucket: {
     4788        SpeculateCellOperand bucket(this, node->child1());
     4789        GPRTemporary result(this);
     4790
     4791        GPRReg bucketGPR = bucket.gpr();
     4792        GPRReg resultGPR = result.gpr();
     4793
     4794        m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR);
     4795        booleanResult(resultGPR, node);
     4796        break;
     4797    }
     4798
    47224799    case Flush:
    47234800        break;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r205462 r205504  
    4040#include "JSEnvironmentRecord.h"
    4141#include "JSLexicalEnvironment.h"
     42#include "JSMap.h"
    4243#include "JSPropertyNameEnumerator.h"
     44#include "JSSet.h"
    4345#include "ObjectPrototype.h"
    4446#include "SetupVarargsFrame.h"
     
    46164618    }
    46174619
     4620    case MapHash: {
     4621        JSValueOperand input(this, node->child1());
     4622        GPRTemporary temp(this);
     4623        GPRTemporary result(this);
     4624
     4625        GPRReg inputGPR = input.gpr();
     4626        GPRReg resultGPR = result.gpr();
     4627        GPRReg tempGPR = temp.gpr();
     4628
     4629        MacroAssembler::JumpList straightHash;
     4630        MacroAssembler::JumpList done;
     4631        auto isNotCell = m_jit.branchIfNotCell(inputGPR);
     4632        MacroAssembler::JumpList slowPath;
     4633        straightHash.append(m_jit.branch8(MacroAssembler::NotEqual, MacroAssembler::Address(inputGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
     4634        m_jit.loadPtr(MacroAssembler::Address(inputGPR, JSString::offsetOfValue()), resultGPR);
     4635        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
     4636        m_jit.load32(MacroAssembler::Address(resultGPR, StringImpl::flagsOffset()), resultGPR);
     4637        m_jit.urshift64(MacroAssembler::TrustedImm32(StringImpl::s_flagCount), resultGPR);
     4638        slowPath.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
     4639        done.append(m_jit.jump());
     4640
     4641        isNotCell.link(&m_jit);
     4642        straightHash.append(m_jit.branchIfNotNumber(inputGPR));
     4643        straightHash.append(m_jit.branchIfInt32(JSValueRegs(inputGPR)));
     4644        slowPath.append(m_jit.jump());
     4645
     4646        straightHash.link(&m_jit);
     4647        m_jit.move(inputGPR, resultGPR);
     4648        m_jit.wangsInt64Hash(resultGPR, tempGPR);
     4649        done.append(m_jit.jump());
     4650
     4651        slowPath.link(&m_jit);
     4652        silentSpillAllRegisters(resultGPR);
     4653        callOperation(operationMapHash, resultGPR, inputGPR);
     4654        silentFillAllRegisters(resultGPR);
     4655        m_jit.exceptionCheck();
     4656
     4657        done.link(&m_jit);
     4658        int32Result(resultGPR, node);
     4659        break;
     4660    }
     4661    case GetMapBucket: {
     4662        SpeculateCellOperand map(this, node->child1());
     4663        JSValueOperand key(this, node->child2());
     4664        SpeculateInt32Operand hash(this, node->child3());
     4665        GPRTemporary mask(this);
     4666        GPRTemporary index(this);
     4667        GPRTemporary buffer(this);
     4668        GPRTemporary bucket(this);
     4669        GPRTemporary result(this);
     4670
     4671        GPRReg hashGPR = hash.gpr();
     4672        GPRReg mapGPR = map.gpr();
     4673        GPRReg maskGPR = mask.gpr();
     4674        GPRReg indexGPR = index.gpr();
     4675        GPRReg bufferGPR = buffer.gpr();
     4676        GPRReg bucketGPR = bucket.gpr();
     4677        GPRReg keyGPR = key.gpr();
     4678        GPRReg resultGPR = result.gpr();
     4679
     4680        if (node->child1().useKind() == MapObjectUse)
     4681            speculateMapObject(node->child1(), mapGPR);
     4682        else if (node->child1().useKind() == SetObjectUse)
     4683            speculateSetObject(node->child1(), mapGPR);
     4684        else
     4685            RELEASE_ASSERT_NOT_REACHED();
     4686
     4687        m_jit.loadPtr(MacroAssembler::Address(mapGPR, node->child1().useKind() == MapObjectUse ? JSMap::offsetOfHashMapImpl() : JSSet::offsetOfHashMapImpl()), bufferGPR);
     4688        m_jit.load32(MacroAssembler::Address(bufferGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()), maskGPR);
     4689        m_jit.loadPtr(MacroAssembler::Address(bufferGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()), bufferGPR);
     4690        m_jit.sub32(TrustedImm32(1), maskGPR);
     4691        m_jit.move(hashGPR, indexGPR);
     4692
     4693        MacroAssembler::Label loop = m_jit.label();
     4694        MacroAssembler::JumpList done;
     4695        MacroAssembler::JumpList slowPathCases;
     4696        MacroAssembler::JumpList loopAround;
     4697
     4698        m_jit.and32(maskGPR, indexGPR);
     4699        m_jit.loadPtr(MacroAssembler::BaseIndex(bufferGPR, indexGPR, MacroAssembler::TimesEight), bucketGPR);
     4700        m_jit.move(bucketGPR, resultGPR);
     4701        auto notPresentInTable = m_jit.branchPtr(MacroAssembler::Equal,
     4702            bucketGPR, TrustedImmPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue()));
     4703        loopAround.append(m_jit.branchPtr(MacroAssembler::Equal,
     4704            bucketGPR, TrustedImmPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue())));
     4705
     4706        m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKey>::offsetOfKey()), bucketGPR);
     4707
     4708        // Perform Object.is()
     4709        done.append(m_jit.branch64(MacroAssembler::Equal, bucketGPR, keyGPR)); // They're definitely the same value, we found the bucket we were looking for!
     4710        auto oneIsntCell = m_jit.branchIfNotCell(JSValueRegs(bucketGPR));
     4711        // first is a cell here.
     4712        loopAround.append(m_jit.branchIfNotCell(JSValueRegs(keyGPR)));
     4713        // Both are cells here.
     4714        loopAround.append(m_jit.branch8(JITCompiler::NotEqual,
     4715            JITCompiler::Address(bucketGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
     4716        // The first is a string here.
     4717        slowPathCases.append(m_jit.branch8(JITCompiler::Equal,
     4718            JITCompiler::Address(keyGPR, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
     4719        // The first is a string, but the second is not, we continue to loop around.
     4720        loopAround.append(m_jit.jump());
     4721
     4722        oneIsntCell.link(&m_jit);
     4723        // We've already done a 64-bit compare at this point, so if one is not a number, they're definitely not equal.
     4724        loopAround.append(m_jit.branchIfNotNumber(bucketGPR));
     4725        loopAround.append(m_jit.branchIfNotNumber(keyGPR));
     4726        // Both are definitely numbers. If we see a double, we go to the slow path.
     4727        slowPathCases.append(m_jit.branchIfNotInt32(bucketGPR));
     4728        slowPathCases.append(m_jit.branchIfNotInt32(keyGPR));
     4729       
     4730        loopAround.link(&m_jit);
     4731        m_jit.add32(TrustedImm32(1), indexGPR);
     4732        m_jit.jump().linkTo(loop, &m_jit);
     4733
     4734        slowPathCases.link(&m_jit);
     4735        silentSpillAllRegisters(indexGPR);
     4736        if (node->child1().useKind() == MapObjectUse)
     4737            callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyGPR, hashGPR);
     4738        else
     4739            callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyGPR, hashGPR);
     4740        silentFillAllRegisters(indexGPR);
     4741        m_jit.exceptionCheck();
     4742        done.append(m_jit.jump());
     4743
     4744        notPresentInTable.link(&m_jit);
     4745        m_jit.move(TrustedImmPtr(nullptr), resultGPR);
     4746        done.link(&m_jit);
     4747        cellResult(resultGPR, node);
     4748        break;
     4749    }
     4750
     4751    case LoadFromJSMapBucket: {
     4752        SpeculateCellOperand bucket(this, node->child1());
     4753        GPRTemporary result(this);
     4754
     4755        GPRReg bucketGPR = bucket.gpr();
     4756        GPRReg resultGPR = result.gpr();
     4757
     4758        auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR);
     4759        m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), resultGPR);
     4760        auto done = m_jit.jump();
     4761
     4762        notBucket.link(&m_jit);
     4763        m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), resultGPR);
     4764        done.link(&m_jit);
     4765        jsValueResult(resultGPR, node);
     4766        break;
     4767    }
     4768
     4769    case IsNonEmptyMapBucket: {
     4770        SpeculateCellOperand bucket(this, node->child1());
     4771        GPRTemporary result(this);
     4772
     4773        GPRReg bucketGPR = bucket.gpr();
     4774        GPRReg resultGPR = result.gpr();
     4775
     4776        m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR);
     4777        m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
     4778        jsValueResult(resultGPR, node, DataFormatJSBoolean);
     4779        break;
     4780    }
     4781
    46184782    case IsObject: {
    46194783        JSValueOperand value(this, node->child1());
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp

    r200034 r205504  
    9595        out.print("RegExpObject");
    9696        return;
     97    case MapObjectUse:
     98        out.print("MapObjectUse");
     99        return;
     100    case SetObjectUse:
     101        out.print("SetObjectUse");
     102        return;
    97103    case ObjectOrOtherUse:
    98104        out.print("ObjectOrOther");
  • trunk/Source/JavaScriptCore/dfg/DFGUseKind.h

    r200096 r205504  
    6464    KnownPrimitiveUse, // This bizarre type arises for op_strcat, which has a bytecode guarantee that it will only see primitives (i.e. not objects).
    6565    SymbolUse,
     66    MapObjectUse,
     67    SetObjectUse,
    6668    StringObjectUse,
    6769    StringOrStringObjectUse,
     
    135137    case SymbolUse:
    136138        return SpecSymbol;
     139    case MapObjectUse:
     140        return SpecMapObject;
     141    case SetObjectUse:
     142        return SpecSetObject;
    137143    case StringObjectUse:
    138144        return SpecStringObject;
     
    222228    case StringObjectUse:
    223229    case StringOrStringObjectUse:
     230    case MapObjectUse:
     231    case SetObjectUse:
    224232        return true;
    225233    default:
  • trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

    r205462 r205504  
    3333#include "FTLAbstractHeap.h"
    3434#include "IndexingType.h"
     35#include "JSMap.h"
     36#include "JSSet.h"
    3537
    3638namespace JSC { namespace FTL {
     
    102104    macro(Structure_globalObject, Structure::globalObjectOffset()) \
    103105    macro(Structure_prototype, Structure::prototypeOffset()) \
    104     macro(Structure_structureID, Structure::structureIDOffset())
     106    macro(Structure_structureID, Structure::structureIDOffset()) \
     107    macro(JSMap_hashMapImpl, JSMap::offsetOfHashMapImpl()) \
     108    macro(JSSet_hashMapImpl, JSSet::offsetOfHashMapImpl()) \
     109    macro(HashMapImpl_capacity, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()) \
     110    macro(HashMapImpl_buffer,  HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()) \
     111    macro(HashMapBucket_value, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()) \
     112    macro(HashMapBucket_key, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()) \
    105113
    106114#define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r205380 r205504  
    182182    case In:
    183183    case IsJSArray:
     184    case MapHash:
     185    case GetMapBucket:
     186    case LoadFromJSMapBucket:
     187    case IsNonEmptyMapBucket:
    184188    case IsEmpty:
    185189    case IsUndefined:
     
    426430                case StringOrStringObjectUse:
    427431                case SymbolUse:
     432                case MapObjectUse:
     433                case SetObjectUse:
    428434                case FinalObjectUse:
    429435                case RegExpObjectUse:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r205494 r205504  
    7171#include "JSGeneratorFunction.h"
    7272#include "JSLexicalEnvironment.h"
     73#include "JSMap.h"
    7374#include "OperandsInlines.h"
    7475#include "ScopedArguments.h"
     
    898899        case IsJSArray:
    899900            compileIsJSArray();
     901            break;
     902        case MapHash:
     903            compileMapHash();
     904            break;
     905        case GetMapBucket:
     906            compileGetMapBucket();
     907            break;
     908        case LoadFromJSMapBucket:
     909            compileLoadFromJSMapBucket();
     910            break;
     911        case IsNonEmptyMapBucket:
     912            compileIsNonEmptyMapBucket();
    900913            break;
    901914        case IsObject:
     
    62886301        m_out.appendTo(continuation, lastNext);
    62896302        setBoolean(m_out.phi(Int32, notCellResult, cellResult));
     6303    }
     6304
     6305    void compileMapHash()
     6306    {
     6307        LValue value = lowJSValue(m_node->child1());
     6308
     6309        LBasicBlock isCellCase = m_out.newBlock();
     6310        LBasicBlock notCell = m_out.newBlock();
     6311        LBasicBlock slowCase = m_out.newBlock();
     6312        LBasicBlock straightHash = m_out.newBlock();
     6313        LBasicBlock isNumberCase = m_out.newBlock();
     6314        LBasicBlock isStringCase = m_out.newBlock();
     6315        LBasicBlock nonEmptyStringCase = m_out.newBlock();
     6316        LBasicBlock continuation = m_out.newBlock();
     6317
     6318        m_out.branch(
     6319            isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(notCell));
     6320
     6321        LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
     6322        LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType));
     6323        m_out.branch(
     6324            isString, unsure(isStringCase), unsure(straightHash));
     6325
     6326        m_out.appendTo(isStringCase, nonEmptyStringCase);
     6327        LValue stringImpl = m_out.loadPtr(value, m_heaps.JSString_value);
     6328        m_out.branch(
     6329            m_out.equal(stringImpl, m_out.constIntPtr(0)), rarely(slowCase), usually(nonEmptyStringCase));
     6330
     6331        m_out.appendTo(nonEmptyStringCase, notCell);
     6332        LValue hash = m_out.lShr(m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount));
     6333        ValueFromBlock nonEmptyStringHashResult = m_out.anchor(hash);
     6334        m_out.branch(m_out.equal(hash, m_out.constInt32(0)),
     6335            rarely(slowCase), usually(continuation));
     6336
     6337        m_out.appendTo(notCell, isNumberCase);
     6338        m_out.branch(
     6339            isNumber(value), unsure(isNumberCase), unsure(straightHash));
     6340
     6341        m_out.appendTo(isNumberCase, straightHash);
     6342        m_out.branch(
     6343            isInt32(value), unsure(straightHash), unsure(slowCase));
     6344
     6345        m_out.appendTo(straightHash, slowCase);
     6346        // key += ~(key << 32);
     6347        LValue key = value;
     6348        LValue temp = key;
     6349        temp = m_out.shl(temp, m_out.constInt32(32));
     6350        temp = m_out.bitNot(temp);
     6351        key = m_out.add(key, temp);
     6352        // key ^= (key >> 22);
     6353        temp = key;
     6354        temp = m_out.lShr(temp, m_out.constInt32(22));
     6355        key = m_out.bitXor(key, temp);
     6356        // key += ~(key << 13);
     6357        temp = key;
     6358        temp = m_out.shl(temp, m_out.constInt32(13));
     6359        temp = m_out.bitNot(temp);
     6360        key = m_out.add(key, temp);
     6361        // key ^= (key >> 8);
     6362        temp = key;
     6363        temp = m_out.lShr(temp, m_out.constInt32(8));
     6364        key = m_out.bitXor(key, temp);
     6365        // key += (key << 3);
     6366        temp = key;
     6367        temp = m_out.shl(temp, m_out.constInt32(3));
     6368        key = m_out.add(key, temp);
     6369        // key ^= (key >> 15);
     6370        temp = key;
     6371        temp = m_out.lShr(temp, m_out.constInt32(15));
     6372        key = m_out.bitXor(key, temp);
     6373        // key += ~(key << 27);
     6374        temp = key;
     6375        temp = m_out.shl(temp, m_out.constInt32(27));
     6376        temp = m_out.bitNot(temp);
     6377        key = m_out.add(key, temp);
     6378        // key ^= (key >> 31);
     6379        temp = key;
     6380        temp = m_out.lShr(temp, m_out.constInt32(31));
     6381        key = m_out.bitXor(key, temp);
     6382        key = m_out.castToInt32(key);
     6383
     6384        ValueFromBlock fastResult = m_out.anchor(key);
     6385        m_out.jump(continuation);
     6386
     6387        m_out.appendTo(slowCase, continuation);
     6388        ValueFromBlock slowResult = m_out.anchor(
     6389            vmCall(Int32, m_out.operation(operationMapHash), m_callFrame, value));
     6390        m_out.jump(continuation);
     6391
     6392        m_out.appendTo(continuation, lastNext);
     6393        setInt32(m_out.phi(Int32, fastResult, slowResult, nonEmptyStringHashResult));
     6394    }
     6395
     6396    void compileGetMapBucket()
     6397    {
     6398        LBasicBlock loopStart = m_out.newBlock();
     6399        LBasicBlock loopAround = m_out.newBlock();
     6400        LBasicBlock slowPath = m_out.newBlock();
     6401        LBasicBlock notPresentInTable = m_out.newBlock();
     6402        LBasicBlock notEmptyValue = m_out.newBlock();
     6403        LBasicBlock notDeletedValue = m_out.newBlock();
     6404        LBasicBlock notBitEqual = m_out.newBlock();
     6405        LBasicBlock bucketKeyNotCell = m_out.newBlock();
     6406        LBasicBlock bucketKeyIsCell = m_out.newBlock();
     6407        LBasicBlock bothAreCells = m_out.newBlock();
     6408        LBasicBlock bucketKeyIsString = m_out.newBlock();
     6409        LBasicBlock bucketKeyIsNumber = m_out.newBlock();
     6410        LBasicBlock bothAreNumbers = m_out.newBlock();
     6411        LBasicBlock bucketKeyIsInt32 = m_out.newBlock();
     6412        LBasicBlock continuation = m_out.newBlock();
     6413
     6414        LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart);
     6415
     6416        LValue map;
     6417        if (m_node->child1().useKind() == MapObjectUse)
     6418            map = lowMapObject(m_node->child1());
     6419        else if (m_node->child1().useKind() == SetObjectUse)
     6420            map = lowSetObject(m_node->child1());
     6421        else
     6422            RELEASE_ASSERT_NOT_REACHED();
     6423
     6424        LValue key = lowJSValue(m_node->child2());
     6425        LValue hash = lowInt32(m_node->child3());
     6426
     6427        LValue hashMapImpl = m_out.loadPtr(map, m_node->child1().useKind() == MapObjectUse ? m_heaps.JSMap_hashMapImpl : m_heaps.JSSet_hashMapImpl);
     6428        LValue buffer = m_out.loadPtr(hashMapImpl, m_heaps.HashMapImpl_buffer);
     6429        LValue mask = m_out.sub(m_out.load32(hashMapImpl, m_heaps.HashMapImpl_capacity), m_out.int32One);
     6430
     6431        ValueFromBlock indexStart = m_out.anchor(hash);
     6432        m_out.jump(loopStart);
     6433
     6434        m_out.appendTo(loopStart, notEmptyValue);
     6435        LValue unmaskedIndex = m_out.phi(Int32, indexStart);
     6436        LValue index = m_out.bitAnd(mask, unmaskedIndex);
     6437        LValue hashMapBucket = m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), buffer, m_out.zeroExt(index, Int64), ScaleEight));
     6438        ValueFromBlock bucketResult = m_out.anchor(hashMapBucket);
     6439        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())),
     6440            unsure(notPresentInTable), unsure(notEmptyValue));
     6441
     6442        m_out.appendTo(notEmptyValue, notDeletedValue);
     6443        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue())),
     6444            unsure(loopAround), unsure(notDeletedValue));
     6445
     6446        m_out.appendTo(notDeletedValue, notBitEqual);
     6447        LValue bucketKey = m_out.load64(hashMapBucket, m_heaps.HashMapBucket_key);
     6448        // Perform Object.is()
     6449        m_out.branch(m_out.equal(key, bucketKey),
     6450            unsure(continuation), unsure(notBitEqual));
     6451
     6452        m_out.appendTo(notBitEqual, bucketKeyIsCell);
     6453        m_out.branch(isCell(bucketKey),
     6454            unsure(bucketKeyIsCell), unsure(bucketKeyNotCell));
     6455
     6456        m_out.appendTo(bucketKeyIsCell, bothAreCells);
     6457        m_out.branch(isCell(key),
     6458            unsure(bothAreCells), unsure(loopAround));
     6459
     6460        m_out.appendTo(bothAreCells, bucketKeyIsString);
     6461        m_out.branch(isString(bucketKey),
     6462            unsure(bucketKeyIsString), unsure(loopAround));
     6463
     6464        m_out.appendTo(bucketKeyIsString, bucketKeyNotCell);
     6465        m_out.branch(isString(key),
     6466            unsure(slowPath), unsure(loopAround));
     6467
     6468        m_out.appendTo(bucketKeyNotCell, bucketKeyIsNumber);
     6469        m_out.branch(isNotNumber(bucketKey),
     6470            unsure(loopAround), unsure(bucketKeyIsNumber));
     6471
     6472        m_out.appendTo(bucketKeyIsNumber, bothAreNumbers);
     6473        m_out.branch(isNotNumber(key),
     6474            unsure(loopAround), unsure(bothAreNumbers));
     6475
     6476        m_out.appendTo(bothAreNumbers, bucketKeyIsInt32);
     6477        m_out.branch(isNotInt32(bucketKey),
     6478            unsure(slowPath), unsure(bucketKeyIsInt32));
     6479
     6480        m_out.appendTo(bucketKeyIsInt32, loopAround);
     6481        m_out.branch(isNotInt32(key),
     6482            unsure(slowPath), unsure(loopAround));
     6483
     6484        m_out.appendTo(loopAround, slowPath);
     6485        m_out.addIncomingToPhi(unmaskedIndex, m_out.anchor(m_out.add(index, m_out.int32One)));
     6486        m_out.jump(loopStart);
     6487
     6488        m_out.appendTo(slowPath, notPresentInTable);
     6489        ValueFromBlock slowPathResult = m_out.anchor(vmCall(pointerType(),
     6490            m_out.operation(m_node->child1().useKind() == MapObjectUse ? operationJSMapFindBucket : operationJSSetFindBucket), m_callFrame, map, key, hash));
     6491        m_out.jump(continuation);
     6492
     6493        m_out.appendTo(notPresentInTable, continuation);
     6494        ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0));
     6495        m_out.jump(continuation);
     6496
     6497        m_out.appendTo(continuation, lastNext);
     6498        setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult));
     6499    }
     6500
     6501    void compileLoadFromJSMapBucket()
     6502    {
     6503        LValue mapBucket = lowMapBucket(m_node->child1());
     6504
     6505        LBasicBlock continuation = m_out.newBlock();
     6506        LBasicBlock hasBucket = m_out.newBlock();
     6507
     6508        ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())));
     6509
     6510        m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)),
     6511            unsure(continuation), unsure(hasBucket));
     6512
     6513        LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation);
     6514        ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value));
     6515        m_out.jump(continuation);
     6516
     6517        m_out.appendTo(continuation, lastNext);
     6518        setJSValue(m_out.phi(Int64, noBucketResult, bucketResult));
     6519    }
     6520
     6521    void compileIsNonEmptyMapBucket()
     6522    {
     6523        LValue bucket = lowMapBucket(m_node->child1());
     6524        LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0));
     6525        setBoolean(result);
    62906526    }
    62916527
     
    998010216        return result;
    998110217    }
     10218
     10219    LValue lowMapObject(Edge edge)
     10220    {
     10221        LValue result = lowCell(edge);
     10222        speculateMapObject(edge, result);
     10223        return result;
     10224    }
     10225
     10226    LValue lowSetObject(Edge edge)
     10227    {
     10228        LValue result = lowCell(edge);
     10229        speculateSetObject(edge, result);
     10230        return result;
     10231    }
    998210232   
    998310233    LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     
    1010310353        return result;
    1010410354    }
     10355
     10356    LValue lowMapBucket(Edge edge)
     10357    {
     10358        LoweredNodeValue value = m_mapBucketValues.get(edge.node());
     10359        if (isValid(value))
     10360            return value.value();
     10361       
     10362        LValue result = lowCell(edge);
     10363        setStorage(edge.node(), result);
     10364        return result;
     10365    }
    1010510366   
    1010610367    LValue strictInt52ToInt32(Edge edge, LValue value)
     
    1040510666        case RegExpObjectUse:
    1040610667            speculateRegExpObject(edge);
     10668            break;
     10669        case MapObjectUse:
     10670            speculateMapObject(edge);
     10671            break;
     10672        case SetObjectUse:
     10673            speculateSetObject(edge);
    1040710674            break;
    1040810675        case StringUse:
     
    1073411001        speculateRegExpObject(edge, lowCell(edge));
    1073511002    }
     11003
     11004    void speculateMapObject(Edge edge, LValue cell)
     11005    {
     11006        FTL_TYPE_CHECK(
     11007            jsValueValue(cell), edge, SpecMapObject, isNotType(cell, JSMapType));
     11008    }
     11009
     11010    void speculateMapObject(Edge edge)
     11011    {
     11012        speculateMapObject(edge, lowCell(edge));
     11013    }
     11014
     11015    void speculateSetObject(Edge edge, LValue cell)
     11016    {
     11017        FTL_TYPE_CHECK(
     11018            jsValueValue(cell), edge, SpecSetObject, isNotType(cell, JSSetType));
     11019    }
     11020
     11021    void speculateSetObject(Edge edge)
     11022    {
     11023        speculateSetObject(edge, lowCell(edge));
     11024    }
    1073611025   
    1073711026    void speculateString(Edge edge, LValue cell)
     
    1150211791        m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
    1150311792    }
     11793    void setMapBucket(Node* node, LValue value)
     11794    {
     11795        m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock));
     11796    }
    1150411797    void setDouble(Node* node, LValue value)
    1150511798    {
     
    1153411827    {
    1153511828        setStorage(m_node, value);
     11829    }
     11830    void setMapBucket(LValue value)
     11831    {
     11832        setMapBucket(m_node, value);
    1153611833    }
    1153711834    void setDouble(LValue value)
     
    1171812015    HashMap<Node*, LoweredNodeValue> m_booleanValues;
    1171912016    HashMap<Node*, LoweredNodeValue> m_storageValues;
     12017    HashMap<Node*, LoweredNodeValue> m_mapBucketValues;
    1172012018    HashMap<Node*, LoweredNodeValue> m_doubleValues;
    1172112019   
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r203364 r205504  
    627627}
    628628
     629#if USE(JSVALUE64)
     630void AssemblyHelpers::wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch)
     631{
     632    GPRReg input = inputAndResult;
     633    // key += ~(key << 32);
     634    move(input, scratch);
     635    lshift64(TrustedImm32(32), scratch);
     636    not64(scratch);
     637    add64(scratch, input);
     638    // key ^= (key >> 22);
     639    move(input, scratch);
     640    urshift64(TrustedImm32(22), scratch);
     641    xor64(scratch, input);
     642    // key += ~(key << 13);
     643    move(input, scratch);
     644    lshift64(TrustedImm32(13), scratch);
     645    not64(scratch);
     646    add64(scratch, input);
     647    // key ^= (key >> 8);
     648    move(input, scratch);
     649    urshift64(TrustedImm32(8), scratch);
     650    xor64(scratch, input);
     651    // key += (key << 3);
     652    move(input, scratch);
     653    lshift64(TrustedImm32(3), scratch);
     654    add64(scratch, input);
     655    // key ^= (key >> 15);
     656    move(input, scratch);
     657    urshift64(TrustedImm32(15), scratch);
     658    xor64(scratch, input);
     659    // key += ~(key << 27);
     660    move(input, scratch);
     661    lshift64(TrustedImm32(27), scratch);
     662    not64(scratch);
     663    add64(scratch, input);
     664    // key ^= (key >> 31);
     665    move(input, scratch);
     666    urshift64(TrustedImm32(31), scratch);
     667    xor64(scratch, input);
     668
     669    // return static_cast<unsigned>(result)
     670    void* mask = bitwise_cast<void*>(static_cast<uintptr_t>(UINT_MAX));
     671    and64(TrustedImmPtr(mask), inputAndResult);
     672}
     673#endif // USE(JSVALUE64)
     674
    629675} // namespace JSC
    630676
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h

    r205462 r205504  
    6262        }
    6363    }
    64    
     64
    6565    CodeBlock* codeBlock() { return m_codeBlock; }
    6666    VM* vm() { return m_vm; }
     
    15291529        storePtr(TrustedImmPtr(structure->classInfo()), Address(resultGPR, JSDestructibleObject::classInfoOffset()));
    15301530    }
     1531
     1532#if USE(JSVALUE64)
     1533    void wangsInt64Hash(GPRReg inputAndResult, GPRReg scratch);
     1534#endif
    15311535   
    15321536protected:
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r205494 r205504  
    206206typedef JSCell* (JIT_OPERATION *C_JITOperation_EZ)(ExecState*, int32_t);
    207207typedef JSCell* (JIT_OPERATION *C_JITOperation_EJscI)(ExecState*, JSScope*, UniquedStringImpl*);
     208typedef JSCell* (JIT_OPERATION *C_JITOperation_ECJZ)(ExecState*, JSCell*, EncodedJSValue, int32_t);
    208209typedef double (JIT_OPERATION *D_JITOperation_D)(double);
    209210typedef double (JIT_OPERATION *D_JITOperation_G)(JSGlobalObject*);
  • trunk/Source/JavaScriptCore/parser/ModuleAnalyzer.cpp

    r205462 r205504  
    3838ModuleAnalyzer::ModuleAnalyzer(ExecState* exec, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
    3939    : m_vm(&exec->vm())
    40     , m_moduleRecord(exec->vm(), JSModuleRecord::create(exec->vm(), exec->lexicalGlobalObject()->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables))
     40    , m_moduleRecord(exec->vm(), JSModuleRecord::create(exec, exec->vm(), exec->lexicalGlobalObject()->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables))
    4141{
    4242}
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r202363 r205504  
    6363    IsTypedArrayViewIntrinsic,
    6464    BoundThisNoArgsFunctionCallIntrinsic,
     65    JSMapGetIntrinsic,
     66    JSMapHasIntrinsic,
     67    JSSetHasIntrinsic,
    6568
    6669    // Getter intrinsics.
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.h

    r204995 r205504  
    607607bool isThisValueAltered(const PutPropertySlot&, JSObject* baseObject);
    608608
     609// See section 7.2.9: https://tc39.github.io/ecma262/#sec-samevalue
     610bool sameValue(ExecState*, JSValue a, JSValue b);
     611
    609612} // namespace JSC
    610613
  • trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h

    r205198 r205504  
    10591059}
    10601060
     1061// See section 7.2.9: https://tc39.github.io/ecma262/#sec-samevalue
     1062ALWAYS_INLINE bool sameValue(ExecState* exec, JSValue a, JSValue b)
     1063{
     1064    if (!a.isNumber())
     1065        return JSValue::strictEqual(exec, a, b);
     1066    if (!b.isNumber())
     1067        return false;
     1068    double x = a.asNumber();
     1069    double y = b.asNumber();
     1070    bool xIsNaN = std::isnan(x);
     1071    bool yIsNaN = std::isnan(y);
     1072    if (xIsNaN || yIsNaN)
     1073        return xIsNaN && yIsNaN;
     1074    return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);
     1075}
     1076
    10611077} // namespace JSC
    10621078
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r205372 r205504  
    642642
    643643    m_moduleLoaderStructure.set(vm, this, JSModuleLoader::createStructure(vm, this, m_moduleLoaderPrototype.get()));
    644     m_moduleLoader.set(vm, this, JSModuleLoader::create(vm, this, m_moduleLoaderStructure.get()));
     644    m_moduleLoader.set(vm, this, JSModuleLoader::create(globalExec(), vm, this, m_moduleLoaderStructure.get()));
    645645    if (Options::exposeInternalModuleLoader())
    646646        putDirectWithoutTransition(vm, vm.propertyNames->Loader, m_moduleLoader.get(), DontEnum);
  • trunk/Source/JavaScriptCore/runtime/JSMap.cpp

    r205131 r205504  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "JSMap.h"
    2828
    29 #include "CopiedBlockInlines.h"
    30 #include "JSCJSValueInlines.h"
    31 #include "JSMapIterator.h"
    32 #include "MapDataInlines.h"
    33 #include "SlotVisitorInlines.h"
    34 #include "StructureInlines.h"
     29#include "JSCInlines.h"
    3530
    3631namespace JSC {
    3732
    3833const ClassInfo JSMap::s_info = { "Map", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMap) };
    39 
    40 void JSMap::destroy(JSCell* cell)
    41 {
    42     JSMap* thisObject = jsCast<JSMap*>(cell);
    43     thisObject->JSMap::~JSMap();
    44 }
    45 
    46 size_t JSMap::estimatedSize(JSCell* cell)
    47 {
    48     JSMap* thisObject = jsCast<JSMap*>(cell);
    49     size_t mapDataSize = thisObject->m_mapData.capacityInBytes();
    50     return Base::estimatedSize(cell) + mapDataSize;
    51 }
    5234
    5335String JSMap::toStringName(const JSObject*, ExecState*)
     
    5638}
    5739
    58 void JSMap::visitChildren(JSCell* cell, SlotVisitor& visitor)
    59 {
    60     Base::visitChildren(cell, visitor);
    61     jsCast<JSMap*>(cell)->m_mapData.visitChildren(cell, visitor);
    6240}
    63 
    64 void JSMap::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token)
    65 {
    66     Base::copyBackingStore(cell, visitor, token);
    67     jsCast<JSMap*>(cell)->m_mapData.copyBackingStore(visitor, token);
    68 }
    69 
    70 bool JSMap::has(ExecState* exec, JSValue key)
    71 {
    72     return m_mapData.contains(exec, key);
    73 }
    74 
    75 size_t JSMap::size(ExecState* exec)
    76 {
    77     return m_mapData.size(exec);
    78 }
    79 
    80 JSValue JSMap::get(ExecState* exec, JSValue key)
    81 {
    82     JSValue result = m_mapData.get(exec, key);
    83     if (!result)
    84         return jsUndefined();
    85     return result;
    86 }
    87 
    88 void JSMap::set(ExecState* exec, JSValue key, JSValue value)
    89 {
    90     m_mapData.set(exec, this, key, value);
    91 }
    92 
    93 void JSMap::clear(ExecState*)
    94 {
    95     m_mapData.clear();
    96 }
    97 
    98 bool JSMap::remove(ExecState* exec, JSValue key)
    99 {
    100     return m_mapData.remove(exec, key);
    101 }
    102 
    103 }
  • trunk/Source/JavaScriptCore/runtime/JSMap.h

    r205131 r205504  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#define JSMap_h
    2828
    29 #include "JSDestructibleObject.h"
    3029#include "JSObject.h"
    31 #include "MapData.h"
     30#include "MapBase.h"
    3231
    3332namespace JSC {
     
    3534class JSMapIterator;
    3635
    37 class JSMap : public JSDestructibleObject {
     36class JSMap : public MapBase<HashMapBucket<HashMapBucketDataKeyValue>> {
     37    typedef MapBase<HashMapBucket<HashMapBucketDataKeyValue>> Base;
    3838public:
    39     typedef JSDestructibleObject Base;
    40 
    4139    friend class JSMapIterator;
    42 
    43     // Our marking functions expect Entry to maintain this layout, and have all
    44     // fields be WriteBarrier<Unknown>
    45     class Entry {
    46     private:
    47         WriteBarrier<Unknown> m_key;
    48         WriteBarrier<Unknown> m_value;
    49 
    50     public:
    51         const WriteBarrier<Unknown>& key() const
    52         {
    53             return m_key;
    54         }
    55 
    56         const WriteBarrier<Unknown>& value() const
    57         {
    58             return m_value;
    59         }
    60 
    61         void visitChildren(SlotVisitor& visitor)
    62         {
    63             visitor.append(&m_key);
    64             visitor.append(&m_value);
    65         }
    66 
    67         void setKey(VM& vm, const JSCell* owner, JSValue key)
    68         {
    69             m_key.set(vm, owner, key);
    70         }
    71 
    72         void setKeyWithoutWriteBarrier(JSValue key)
    73         {
    74             m_key.setWithoutWriteBarrier(key);
    75         }
    76 
    77         void setValue(VM& vm, const JSCell* owner, JSValue value)
    78         {
    79             m_value.set(vm, owner, value);
    80         }
    81 
    82         void clear()
    83         {
    84             m_key.clear();
    85             m_value.clear();
    86         }
    87     };
    88 
    89     typedef MapDataImpl<Entry, JSMapIterator> MapData;
    9040
    9141    DECLARE_EXPORT_INFO;
     
    9343    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    9444    {
    95         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     45        return Structure::create(vm, globalObject, prototype, TypeInfo(JSMapType, StructureFlags), info());
    9646    }
    9747
    98     static JSMap* create(VM& vm, Structure* structure)
     48    static JSMap* create(ExecState* exec, VM& vm, Structure* structure)
    9949    {
    10050        JSMap* instance = new (NotNull, allocateCell<JSMap>(vm.heap)) JSMap(vm, structure);
    101         instance->finishCreation(vm);
     51        instance->finishCreation(exec, vm);
    10252        return instance;
    10353    }
    10454
    105     static JSMap* create(ExecState* exec, Structure* structure)
     55    ALWAYS_INLINE JSValue get(ExecState* exec, JSValue key)
    10656    {
    107         return create(exec->vm(), structure);
     57        return m_map->get(exec, key);
    10858    }
    10959
    110     bool has(ExecState*, JSValue);
    111     size_t size(ExecState*);
    112     JSValue get(ExecState*, JSValue);
    113     JS_EXPORT_PRIVATE void set(ExecState*, JSValue key, JSValue value);
    114     void clear(ExecState*);
    115     bool remove(ExecState*, JSValue);
     60    ALWAYS_INLINE void set(ExecState* exec, JSValue key, JSValue value)
     61    {
     62        m_map->add(exec, key, value);
     63    }
    11664
    11765private:
    11866    JSMap(VM& vm, Structure* structure)
    11967        : Base(vm, structure)
    120         , m_mapData(vm, this)
    12168    {
    12269    }
    12370
    124     static void destroy(JSCell*);
    125     static size_t estimatedSize(JSCell*);
    126     static void visitChildren(JSCell*, SlotVisitor&);
    127     static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);
    12871    static String toStringName(const JSObject*, ExecState*);
    129 
    130     MapData m_mapData;
    13172};
    13273
  • trunk/Source/JavaScriptCore/runtime/JSMapIterator.cpp

    r205462 r205504  
    3939    Base::finishCreation(vm);
    4040    m_map.set(vm, this, iteratedObject);
     41    setIterator(vm, m_map->impl()->head());
    4142}
    4243
     
    4748    Base::visitChildren(thisObject, visitor);
    4849    visitor.append(&thisObject->m_map);
     50    visitor.append(&thisObject->m_iter);
    4951}
    5052
     
    6062JSMapIterator* JSMapIterator::clone(ExecState* exec)
    6163{
    62     auto clone = JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind);
    63     clone->m_iterator = m_iterator;
     64    VM& vm = exec->vm();
     65    auto clone = JSMapIterator::create(vm, exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind);
     66    clone->setIterator(vm, m_iter.get());
    6467    return clone;
    6568}
  • trunk/Source/JavaScriptCore/runtime/JSMapIterator.h

    r204358 r205504  
    11/*
    2  * Copyright (C) 2013 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2013, 2016 Apple, Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535
    3636class JSMapIterator : public JSNonFinalObject {
     37    typedef HashMapBucket<HashMapBucketDataKeyValue> HashMapBucketType;
    3738public:
    3839    typedef JSNonFinalObject Base;
     
    5253    }
    5354
    54     bool next(CallFrame* callFrame, JSValue& value)
     55    ALWAYS_INLINE HashMapBucketType* advanceIter(ExecState* exec)
    5556    {
    56         WTF::KeyValuePair<JSValue, JSValue> pair;
    57         if (!m_iterator.next(pair))
     57        HashMapBucketType* prev = m_iter.get();
     58        if (!prev)
     59            return nullptr;
     60        HashMapBucketType* bucket = m_iter->next();
     61        while (bucket && bucket->deleted()) {
     62            prev = bucket;
     63            bucket = bucket->next();
     64        }
     65        if (!bucket) {
     66            setIterator(exec->vm(), nullptr);
     67            return nullptr;
     68        }
     69        setIterator(exec->vm(), bucket); // We keep m_iter on the last value since the first thing we do in this function is call next().
     70        return bucket;
     71    }
     72    bool next(ExecState* exec, JSValue& value)
     73    {
     74        HashMapBucketType* bucket = advanceIter(exec);
     75        if (!bucket)
    5876            return false;
    5977
    6078        if (m_kind == IterateValue)
    61             value = pair.value;
     79            value = bucket->value();
    6280        else if (m_kind == IterateKey)
    63             value = pair.key;
     81            value = bucket->key();
    6482        else
    65             value = createPair(callFrame, pair.key, pair.value);
     83            value = createPair(exec, bucket->key(), bucket->value());
    6684        return true;
    6785    }
    6886
    69     bool nextKeyValue(JSValue& key, JSValue& value)
     87    bool nextKeyValue(ExecState* exec, JSValue& key, JSValue& value)
    7088    {
    71         WTF::KeyValuePair<JSValue, JSValue> pair;
    72         if (!m_iterator.next(pair))
     89        HashMapBucketType* bucket = advanceIter(exec);
     90        if (!bucket)
    7391            return false;
    7492
    75         key = pair.key;
    76         value = pair.value;
     93        key = bucket->key();
     94        value = bucket->value();
    7795        return true;
    78     }
    79 
    80     void finish()
    81     {
    82         m_iterator.finish();
    8396    }
    8497
     
    87100    JSMapIterator* clone(ExecState*);
    88101
    89     JSMap::MapData::IteratorData* iteratorData()
     102private:
     103    JSMapIterator(VM& vm, Structure* structure, JSMap*, IterationKind kind)
     104        : Base(vm, structure)
     105        , m_kind(kind)
     106    { }
     107
     108    void setIterator(VM& vm, HashMapBucketType* bucket)
    90109    {
    91         return &m_iterator;
    92     }
    93 
    94 private:
    95     JSMapIterator(VM& vm, Structure* structure, JSMap* iteratedObject, IterationKind kind)
    96         : Base(vm, structure)
    97         , m_iterator(iteratedObject->m_mapData.createIteratorData(this))
    98         , m_kind(kind)
    99     {
     110        m_iter.setMayBeNull(vm, this, bucket);
    100111    }
    101112
     
    105116
    106117    WriteBarrier<JSMap> m_map;
    107     JSMap::MapData::IteratorData m_iterator;
     118    WriteBarrier<HashMapBucketType> m_iter;
    108119    IterationKind m_kind;
    109120};
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp

    r205278 r205504  
    5656}
    5757
    58 void JSModuleLoader::finishCreation(VM& vm, JSGlobalObject* globalObject)
     58void JSModuleLoader::finishCreation(ExecState* exec, VM& vm, JSGlobalObject* globalObject)
    5959{
    6060    Base::finishCreation(vm);
    6161    ASSERT(inherits(info()));
    62     putDirect(vm, Identifier::fromString(&vm, "registry"), JSMap::create(vm, globalObject->mapStructure()));
     62    auto scope = DECLARE_THROW_SCOPE(vm);
     63    JSMap* map = JSMap::create(exec, vm, globalObject->mapStructure());
     64    RELEASE_ASSERT(!scope.exception());
     65    putDirect(vm, Identifier::fromString(&vm, "registry"), map);
    6366}
    6467
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h

    r205278 r205504  
    4848    };
    4949
    50     static JSModuleLoader* create(VM& vm, JSGlobalObject* globalObject, Structure* structure)
     50    static JSModuleLoader* create(ExecState* exec, VM& vm, JSGlobalObject* globalObject, Structure* structure)
    5151    {
    5252        JSModuleLoader* object = new (NotNull, allocateCell<JSModuleLoader>(vm.heap)) JSModuleLoader(vm, structure);
    53         object->finishCreation(vm, globalObject);
     53        object->finishCreation(exec, vm, globalObject);
    5454        return object;
    5555    }
     
    7878
    7979protected:
    80     void finishCreation(VM&, JSGlobalObject*);
     80    void finishCreation(ExecState*, VM&, JSGlobalObject*);
    8181};
    8282
  • trunk/Source/JavaScriptCore/runtime/JSModuleRecord.cpp

    r205462 r205504  
    4545}
    4646
    47 void JSModuleRecord::finishCreation(VM& vm)
     47void JSModuleRecord::finishCreation(ExecState* exec, VM& vm)
    4848{
    4949    Base::finishCreation(vm);
     
    5252    putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("evaluated")), jsBoolean(false));
    5353
    54     m_dependenciesMap.set(vm, this, JSMap::create(vm, globalObject()->mapStructure()));
     54    auto scope = DECLARE_THROW_SCOPE(vm);
     55    JSMap* map = JSMap::create(exec, vm, globalObject()->mapStructure());
     56    RELEASE_ASSERT(!scope.exception());
     57    m_dependenciesMap.set(vm, this, map);
    5558    putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("dependenciesMap")), m_dependenciesMap.get());
    5659}
  • trunk/Source/JavaScriptCore/runtime/JSModuleRecord.h

    r204330 r205504  
    8888    }
    8989
    90     static JSModuleRecord* create(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
     90    static JSModuleRecord* create(ExecState* exec, VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
    9191    {
    9292        JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
    93         instance->finishCreation(vm);
     93        instance->finishCreation(exec, vm);
    9494        return instance;
    9595    }
     
    153153    }
    154154
    155     void finishCreation(VM&);
     155    void finishCreation(ExecState*, VM&);
    156156
    157157    JSModuleNamespaceObject* getModuleNamespace(ExecState*);
  • trunk/Source/JavaScriptCore/runtime/JSSet.cpp

    r205131 r205504  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#include "JSSet.h"
    2828
    29 #include "CopiedBlockInlines.h"
    30 #include "JSCJSValueInlines.h"
    31 #include "JSSetIterator.h"
    32 #include "MapDataInlines.h"
    33 #include "SlotVisitorInlines.h"
    34 #include "StructureInlines.h"
     29#include "JSCInlines.h"
    3530
    3631namespace JSC {
    3732
    3833const ClassInfo JSSet::s_info = { "Set", &Base::s_info, 0, CREATE_METHOD_TABLE(JSSet) };
    39 
    40 void JSSet::destroy(JSCell* cell)
    41 {
    42     JSSet* thisObject = jsCast<JSSet*>(cell);
    43     thisObject->JSSet::~JSSet();
    44 }
    4534
    4635String JSSet::toStringName(const JSObject*, ExecState*)
     
    4938}
    5039
    51 size_t JSSet::estimatedSize(JSCell* cell)
    52 {
    53     JSSet* thisObject = jsCast<JSSet*>(cell);
    54     size_t setDataSize = thisObject->m_setData.capacityInBytes();
    55     return Base::estimatedSize(cell) + setDataSize;
    5640}
    57 
    58 void JSSet::visitChildren(JSCell* cell, SlotVisitor& visitor)
    59 {
    60     Base::visitChildren(cell, visitor);
    61     jsCast<JSSet*>(cell)->m_setData.visitChildren(cell, visitor);
    62 }
    63 
    64 void JSSet::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token)
    65 {
    66     Base::copyBackingStore(cell, visitor, token);
    67     jsCast<JSSet*>(cell)->m_setData.copyBackingStore(visitor, token);
    68 }
    69 
    70 bool JSSet::has(ExecState* exec, JSValue value)
    71 {
    72     return m_setData.contains(exec, value);
    73 }
    74 
    75 size_t JSSet::size(ExecState* exec)
    76 {
    77     return m_setData.size(exec);
    78 }
    79 
    80 void JSSet::add(ExecState* exec, JSValue value)
    81 {
    82     m_setData.set(exec, this, value, value);
    83 }
    84 
    85 void JSSet::clear(ExecState*)
    86 {
    87     m_setData.clear();
    88 }
    89 
    90 bool JSSet::remove(ExecState* exec, JSValue value)
    91 {
    92     return m_setData.remove(exec, value);
    93 }
    94 
    95 }
  • trunk/Source/JavaScriptCore/runtime/JSSet.h

    r205131 r205504  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2727#define JSSet_h
    2828
    29 #include "JSDestructibleObject.h"
    3029#include "JSObject.h"
    31 #include "MapData.h"
     30#include "MapBase.h"
    3231
    3332namespace JSC {
     
    3534class JSSetIterator;
    3635
    37 class JSSet : public JSDestructibleObject {
     36class JSSet : public MapBase<HashMapBucket<HashMapBucketDataKey>> {
     37    typedef MapBase<HashMapBucket<HashMapBucketDataKey>> Base;
    3838public:
    39     typedef JSDestructibleObject Base;
    4039
    4140    friend class JSSetIterator;
    42 
    43     // Our marking functions expect Entry to maintain this layout, and have all
    44     // fields be WriteBarrier<Unknown>
    45     class Entry {
    46     private:
    47         WriteBarrier<Unknown> m_key;
    48 
    49     public:
    50         const WriteBarrier<Unknown>& key() const
    51         {
    52             return m_key;
    53         }
    54 
    55         const WriteBarrier<Unknown>& value() const
    56         {
    57             return m_key;
    58         }
    59 
    60         void visitChildren(SlotVisitor& visitor)
    61         {
    62             visitor.append(&m_key);
    63         }
    64 
    65         void setKey(VM& vm, const JSCell* owner, JSValue key)
    66         {
    67             m_key.set(vm, owner, key);
    68         }
    69 
    70         void setKeyWithoutWriteBarrier(JSValue key)
    71         {
    72             m_key.setWithoutWriteBarrier(key);
    73         }
    74 
    75         void setValue(VM&, const JSCell*, JSValue)
    76         {
    77         }
    78 
    79         void clear()
    80         {
    81             m_key.clear();
    82         }
    83     };
    84 
    85     typedef MapDataImpl<Entry, JSSetIterator> SetData;
    8641
    8742    DECLARE_EXPORT_INFO;
     
    8944    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    9045    {
    91         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     46        return Structure::create(vm, globalObject, prototype, TypeInfo(JSSetType, StructureFlags), info());
    9247    }
    9348
    94     static JSSet* create(VM& vm, Structure* structure)
     49    static JSSet* create(ExecState* exec, VM& vm, Structure* structure)
    9550    {
    9651        JSSet* instance = new (NotNull, allocateCell<JSSet>(vm.heap)) JSSet(vm, structure);
    97         instance->finishCreation(vm);
     52        instance->finishCreation(exec, vm);
    9853        return instance;
    9954    }
    10055
    101     static JSSet* create(ExecState* exec, Structure* structure)
     56    ALWAYS_INLINE void add(ExecState* exec, JSValue key)
    10257    {
    103         return create(exec->vm(), structure);
     58        m_map->add(exec, key);
    10459    }
    105 
    106     bool has(ExecState*, JSValue);
    107     size_t size(ExecState*);
    108     JS_EXPORT_PRIVATE void add(ExecState*, JSValue);
    109     void clear(ExecState*);
    110     bool remove(ExecState*, JSValue);
    11160
    11261private:
    11362    JSSet(VM& vm, Structure* structure)
    11463        : Base(vm, structure)
    115         , m_setData(vm, this)
    11664    {
    11765    }
    11866
    119     static void destroy(JSCell*);
    120     static size_t estimatedSize(JSCell*);
    121     static void visitChildren(JSCell*, SlotVisitor&);
    122     static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);
    12367    static String toStringName(const JSObject*, ExecState*);
    124 
    125     SetData m_setData;
    12668};
    12769
  • trunk/Source/JavaScriptCore/runtime/JSSetIterator.cpp

    r205462 r205504  
    3939    Base::finishCreation(vm);
    4040    m_set.set(vm, this, iteratedObject);
     41    setIterator(vm, m_set->impl()->head());
    4142}
    4243
     
    4748    Base::visitChildren(thisObject, visitor);
    4849    visitor.append(&thisObject->m_set);
     50    visitor.append(&thisObject->m_iter);
    4951}
    5052
     
    6062JSSetIterator* JSSetIterator::clone(ExecState* exec)
    6163{
    62     auto clone = JSSetIterator::create(exec->vm(), exec->callee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind);
    63     clone->m_iterator = m_iterator;
     64    VM& vm = exec->vm();
     65    auto clone = JSSetIterator::create(vm, exec->callee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind);
     66    clone->setIterator(vm, m_iter.get());
    6467    return clone;
    6568}
  • trunk/Source/JavaScriptCore/runtime/JSSetIterator.h

    r204358 r205504  
    11/*
    2  * Copyright (C) 2013 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2013, 2016 Apple, Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3636
    3737class JSSetIterator : public JSNonFinalObject {
     38    typedef HashMapBucket<HashMapBucketDataKey> HashMapBucketType;
    3839public:
    3940    typedef JSNonFinalObject Base;
     
    5354    }
    5455
    55     bool next(CallFrame* callFrame, JSValue& value)
     56    ALWAYS_INLINE HashMapBucketType* advanceIter(ExecState* exec)
    5657    {
    57         WTF::KeyValuePair<JSValue, JSValue> pair;
    58         if (!m_iterator.next(pair))
    59             return false;
    60         if (m_kind == IterateValue || m_kind == IterateKey)
    61             value = pair.key;
    62         else
    63             value = createPair(callFrame, pair.key, pair.key);
    64         return true;
     58        HashMapBucketType* prev = m_iter.get();
     59        if (!prev)
     60            return nullptr;
     61        HashMapBucketType* bucket = m_iter->next();
     62        while (bucket && bucket->deleted()) {
     63            prev = bucket;
     64            bucket = bucket->next();
     65        }
     66        if (!bucket) {
     67            setIterator(exec->vm(), nullptr);
     68            return nullptr;
     69        }
     70        setIterator(exec->vm(), bucket); // We keep m_iter on the last value since the first thing we do in this function is call next().
     71        return bucket;
    6572    }
    6673
    67     void finish()
     74    bool next(ExecState* exec, JSValue& value)
    6875    {
    69         m_iterator.finish();
     76        HashMapBucketType* bucket = advanceIter(exec);
     77        if (!bucket)
     78            return false;
     79
     80        if (m_kind == IterateValue || m_kind == IterateKey)
     81            value = bucket->key();
     82        else
     83            value = createPair(exec, bucket->key(), bucket->key());
     84        return true;
    7085    }
    7186
     
    7489    JSSetIterator* clone(ExecState*);
    7590
    76     JSSet::SetData::IteratorData* iteratorData()
     91private:
     92    JSSetIterator(VM& vm, Structure* structure, JSSet*, IterationKind kind)
     93        : Base(vm, structure)
     94        , m_kind(kind)
    7795    {
    78         return &m_iterator;
    7996    }
    8097
    81 private:
    82     JSSetIterator(VM& vm, Structure* structure, JSSet* iteratedObject, IterationKind kind)
    83         : Base(vm, structure)
    84         , m_iterator(iteratedObject->m_setData.createIteratorData(this))
    85         , m_kind(kind)
     98    void setIterator(VM& vm, HashMapBucketType* bucket)
    8699    {
     100        m_iter.setMayBeNull(vm, this, bucket);
    87101    }
    88102
     
    92106
    93107    WriteBarrier<JSSet> m_set;
    94     JSSet::SetData::IteratorData m_iterator;
     108    WriteBarrier<HashMapBucketType> m_iter;
    95109    IterationKind m_kind;
    96110};
  • trunk/Source/JavaScriptCore/runtime/JSType.h

    r202125 r205504  
    8383    RegExpObjectType,
    8484    ProxyObjectType,
     85    JSMapType,
     86    JSSetType,
    8587
    86     LastJSCObjectType = ProxyObjectType,
     88    LastJSCObjectType = JSSetType,
    8789};
    8890
  • trunk/Source/JavaScriptCore/runtime/MapBase.cpp

    r205503 r205504  
    11/*
    2  * Copyright (C) 2013, 2016 Apple, Inc. All rights reserved.
     2 * Copyright (C) 2016 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2525
    2626#include "config.h"
    27 #include "JSMapIterator.h"
     27#include "MapBase.h"
    2828
    29 #include "JSCInlines.h"
    30 #include "JSMap.h"
    31 #include "MapDataInlines.h"
     29#include "SlotVisitorInlines.h"
    3230
    3331namespace JSC {
    3432
    35 const ClassInfo JSMapIterator::s_info = { "Map Iterator", &Base::s_info, 0, CREATE_METHOD_TABLE(JSMapIterator) };
    36 
    37 void JSMapIterator::finishCreation(VM& vm, JSMap* iteratedObject)
     33template <typename HashMapBucketType>
     34void MapBase<HashMapBucketType>::visitChildren(JSCell* cell, SlotVisitor& visitor)
    3835{
    39     Base::finishCreation(vm);
    40     m_map.set(vm, this, iteratedObject);
    41 }
    42 
    43 void JSMapIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
    44 {
    45     JSMapIterator* thisObject = jsCast<JSMapIterator*>(cell);
    46     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     36    MapBase* thisObject = static_cast<MapBase*>(cell);
    4737    Base::visitChildren(thisObject, visitor);
    4838    visitor.append(&thisObject->m_map);
    4939}
    5040
    51 JSValue JSMapIterator::createPair(CallFrame* callFrame, JSValue key, JSValue value)
     41template <typename HashMapBucketType>
     42size_t MapBase<HashMapBucketType>::estimatedSize(JSCell* cell)
    5243{
    53     MarkedArgumentBuffer args;
    54     args.append(key);
    55     args.append(value);
    56     JSGlobalObject* globalObject = callFrame->callee()->globalObject();
    57     return constructArray(callFrame, 0, globalObject, args);
     44    return Base::estimatedSize(cell) + static_cast<MapBase*>(cell)->m_map->approximateSize();
    5845}
    5946
    60 JSMapIterator* JSMapIterator::clone(ExecState* exec)
    61 {
    62     auto clone = JSMapIterator::create(exec->vm(), exec->callee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind);
    63     clone->m_iterator = m_iterator;
    64     return clone;
    65 }
     47template class MapBase<HashMapBucket<HashMapBucketDataKeyValue>>;
     48template class MapBase<HashMapBucket<HashMapBucketDataKey>>;
    6649
    67 }
     50} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp

    r205462 r205504  
    6262    JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
    6363    Structure* mapStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->mapStructure());
    64     if (exec->hadException())
     64    if (UNLIKELY(scope.exception()))
    6565        return JSValue::encode(JSValue());
    66     JSMap* map = JSMap::create(exec, mapStructure);
     66    JSMap* map = JSMap::create(exec, vm, mapStructure);
     67    if (UNLIKELY(scope.exception()))
     68        return JSValue::encode(JSValue());
    6769    JSValue iterable = exec->argument(0);
    6870    if (iterable.isUndefinedOrNull())
  • trunk/Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp

    r205462 r205504  
    5959    if (iterator->next(callFrame, result))
    6060        return JSValue::encode(createIteratorResultObject(callFrame, result, false));
    61     iterator->finish();
    6261    return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true));
    6362}
  • trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp

    r205462 r205504  
    6969    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, mapProtoFuncClear, DontEnum, 0);
    7070    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, mapProtoFuncDelete, DontEnum, 1);
    71     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, mapProtoFuncGet, DontEnum, 1);
    72     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, DontEnum, 1);
     71    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->get, mapProtoFuncGet, DontEnum, 1, JSMapGetIntrinsic);
     72    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, DontEnum, 1, JSMapHasIntrinsic);
    7373    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, mapProtoFuncSet, DontEnum, 2);
    7474    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), mapProtoFuncKeys, DontEnum, 0);
    7575    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().valuesPublicName(), mapProtoFuncValues, DontEnum, 0);
    7676
    77     // Private get / set operations.
    78     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, DontEnum, 1);
     77    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, DontEnum, 1, JSMapGetIntrinsic);
    7978    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, DontEnum, 2);
    8079
     
    9291    auto scope = DECLARE_THROW_SCOPE(vm);
    9392
    94     if (!thisValue.isObject()) {
     93    if (UNLIKELY(!thisValue.isCell())) {
    9594        throwVMError(callFrame, scope, createNotAnObjectError(callFrame, thisValue));
    9695        return nullptr;
    9796    }
    98     JSMap* map = jsDynamicCast<JSMap*>(thisValue);
    99     if (!map) {
    100         throwTypeError(callFrame, scope, ASCIILiteral("Map operation called on non-Map object"));
    101         return nullptr;
    102     }
    103     return map;
     97
     98    if (LIKELY(thisValue.asCell()->type() == JSMapType))
     99        return jsCast<JSMap*>(thisValue);
     100    throwTypeError(callFrame, scope, ASCIILiteral("Map operation called on non-Map object"));
     101    return nullptr;
     102}
     103
     104EncodedJSValue JSC_HOST_CALL privateFuncIsMap(ExecState* exec)
     105{
     106    JSValue value = exec->uncheckedArgument(0);
     107    return JSValue::encode(jsBoolean(value.isCell() && value.asCell()->type() == JSMapType));
    104108}
    105109
     
    188192}
    189193
    190 EncodedJSValue JSC_HOST_CALL privateFuncIsMap(ExecState* exec)
    191 {
    192     return JSValue::encode(jsBoolean(jsDynamicCast<JSMap*>(exec->uncheckedArgument(0))));
    193 }
    194 
    195194EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState* exec)
    196195{
     
    205204    JSMapIterator* iterator = jsCast<JSMapIterator*>(exec->thisValue());
    206205    JSValue key, value;
    207     if (iterator->nextKeyValue(key, value)) {
     206    if (iterator->nextKeyValue(exec, key, value)) {
    208207        JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0));
    209208        resultArray->putDirectIndex(exec, 0, key);
     
    211210        return JSValue::encode(jsBoolean(false));
    212211    }
    213     iterator->finish();
    214212    return JSValue::encode(jsBoolean(true));
    215213}
  • trunk/Source/JavaScriptCore/runtime/PropertyDescriptor.cpp

    r199731 r205504  
    192192}
    193193
    194 // See ES5.1 9.12
    195 bool sameValue(ExecState* exec, JSValue a, JSValue b)
    196 {
    197     if (!a.isNumber())
    198         return JSValue::strictEqual(exec, a, b);
    199     if (!b.isNumber())
    200         return false;
    201     double x = a.asNumber();
    202     double y = b.asNumber();
    203     bool xIsNaN = std::isnan(x);
    204     bool yIsNaN = std::isnan(y);
    205     if (xIsNaN || yIsNaN)
    206         return xIsNaN && yIsNaN;
    207     return bitwise_cast<uint64_t>(x) == bitwise_cast<uint64_t>(y);
    208 }
    209 
    210194bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const
    211195{
  • trunk/Source/JavaScriptCore/runtime/PropertyDescriptor.h

    r197295 r205504  
    3232
    3333class GetterSetter;
    34 
    35 // See ES5.1 9.12
    36 bool sameValue(ExecState*, JSValue, JSValue);
    3734
    3835class PropertyDescriptor {
  • trunk/Source/JavaScriptCore/runtime/SetConstructor.cpp

    r205462 r205504  
    6363    JSGlobalObject* globalObject = asInternalFunction(exec->callee())->globalObject();
    6464    Structure* setStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), globalObject->setStructure());
    65     if (exec->hadException())
     65    if (UNLIKELY(scope.exception()))
    6666        return JSValue::encode(JSValue());
    67     JSSet* set = JSSet::create(exec, setStructure);
     67    JSSet* set = JSSet::create(exec, vm, setStructure);
     68    if (UNLIKELY(scope.exception()))
     69        return JSValue::encode(JSValue());
    6870    JSValue iterable = exec->argument(0);
    6971    if (iterable.isUndefinedOrNull())
  • trunk/Source/JavaScriptCore/runtime/SetIteratorPrototype.cpp

    r205462 r205504  
    5959    if (iterator->next(callFrame, result))
    6060        return JSValue::encode(createIteratorResultObject(callFrame, result, false));
    61     iterator->finish();
    6261    return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true));
    6362}
  • trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp

    r205462 r205504  
    6969    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->clear, setProtoFuncClear, DontEnum, 0);
    7070    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->deleteKeyword, setProtoFuncDelete, DontEnum, 1);
    71     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, DontEnum, 1);
     71    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
    7272    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0);
    7373
     
    8686    auto scope = DECLARE_THROW_SCOPE(vm);
    8787
    88     if (!thisValue.isObject()) {
     88    if (UNLIKELY(!thisValue.isCell())) {
    8989        throwVMError(callFrame, scope, createNotAnObjectError(callFrame, thisValue));
    9090        return nullptr;
    9191    }
    92     JSSet* set = jsDynamicCast<JSSet*>(thisValue);
    93     if (!set) {
    94         throwTypeError(callFrame, scope, ASCIILiteral("Set operation called on non-Set object"));
    95         return nullptr;
    96     }
    97     return set;
     92    if (LIKELY(thisValue.asCell()->type() == JSSetType))
     93        return jsCast<JSSet*>(thisValue);
     94    throwTypeError(callFrame, scope, ASCIILiteral("Set operation called on non-Set object"));
     95    return nullptr;
    9896}
    9997
     
    185183        return JSValue::encode(jsBoolean(false));
    186184    }
    187     iterator->finish();
    188185    return JSValue::encode(jsBoolean(true));
    189186}
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r205462 r205504  
    6666#include "JSLexicalEnvironment.h"
    6767#include "JSLock.h"
     68#include "JSMap.h"
    6869#include "JSPromiseDeferred.h"
    6970#include "JSPropertyNameEnumerator.h"
     
    254255    webAssemblyCodeBlockStructure.set(*this, WebAssemblyCodeBlock::createStructure(*this, 0, jsNull()));
    255256#endif
     257    hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, 0, jsNull()));
     258    hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, 0, jsNull()));
     259    hashMapImplSetStructure.set(*this, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::createStructure(*this, 0, jsNull()));
     260    hashMapImplMapStructure.set(*this, HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>::createStructure(*this, 0, jsNull()));
    256261
    257262    iterationTerminator.set(*this, JSFinalObject::create(*this, JSFinalObject::createStructure(*this, 0, jsNull(), 1)));
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r205462 r205504  
    335335    Strong<Structure> functionCodeBlockStructure;
    336336    Strong<Structure> webAssemblyCodeBlockStructure;
     337    Strong<Structure> hashMapBucketSetStructure;
     338    Strong<Structure> hashMapBucketMapStructure;
     339    Strong<Structure> hashMapImplSetStructure;
     340    Strong<Structure> hashMapImplMapStructure;
    337341
    338342    Strong<JSCell> iterationTerminator;
  • trunk/Source/WTF/ChangeLog

    r205497 r205504  
     12016-09-06  Saam Barati  <sbarati@apple.com>
     2
     3        Make JSMap and JSSet faster
     4        https://bugs.webkit.org/show_bug.cgi?id=160989
     5
     6        Reviewed by Filip Pizlo.
     7
     8        I made s_flagCount public since JSC's JITs now use this field.
     9
     10        * wtf/text/StringImpl.h:
     11
    1122016-09-06  Per Arne Vollan  <pvollan@apple.com>
    213
  • trunk/Source/WTF/wtf/text/StringImpl.h

    r202506 r205504  
    149149
    150150    // The bottom 6 bits in the hash are flags.
     151public:
    151152    static const unsigned s_flagCount = 6;
     153private:
    152154    static const unsigned s_flagMask = (1u << s_flagCount) - 1;
    153155    COMPILE_ASSERT(s_flagCount <= StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags);
  • trunk/Source/WebCore/ChangeLog

    r205493 r205504  
     12016-09-06  Saam Barati  <sbarati@apple.com>
     2
     3        Make JSMap and JSSet faster
     4        https://bugs.webkit.org/show_bug.cgi?id=160989
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * ForwardingHeaders/runtime/HashMapImpl.h: Added.
     9        * ForwardingHeaders/runtime/MapBase.h: Added.
     10        * bindings/js/SerializedScriptValue.cpp:
     11        (WebCore::CloneSerializer::serialize):
     12        (WebCore::CloneDeserializer::deserialize):
     13
    1142016-09-05  Alex Christensen  <achristensen@webkit.org>
    215
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r205198 r205504  
    13691369                JSMapIterator* iterator = mapIteratorStack.last();
    13701370                JSValue key, value;
    1371                 if (!iterator->nextKeyValue(key, value)) {
     1371                if (!iterator->nextKeyValue(m_exec, key, value)) {
    13721372                    mapIteratorStack.removeLast();
    13731373                    JSObject* object = inputObjectStack.last();
     
    25462546            if (outputObjectStack.size() > maximumFilterRecursion)
    25472547                return std::make_pair(JSValue(), StackOverflowError);
    2548             JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
     2548            JSMap* map = JSMap::create(m_exec, m_exec->vm(), m_globalObject->mapStructure());
     2549            if (UNLIKELY(m_exec->hadException()))
     2550                goto error;
    25492551            m_gcBuffer.append(map);
    25502552            outputObjectStack.append(map);
     
    25752577            if (outputObjectStack.size() > maximumFilterRecursion)
    25762578                return std::make_pair(JSValue(), StackOverflowError);
    2577             JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
     2579            JSSet* set = JSSet::create(m_exec, m_exec->vm(), m_globalObject->setStructure());
     2580            if (UNLIKELY(m_exec->hadException()))
     2581                goto error;
    25782582            m_gcBuffer.append(set);
    25792583            outputObjectStack.append(set);
Note: See TracChangeset for help on using the changeset viewer.