Changeset 205520 in webkit


Ignore:
Timestamp:
Sep 6, 2016 4:22:01 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:
  • assembler/MacroAssemblerARM64.h:

(JSC::MacroAssemblerARM64::not64):

  • 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 in StringImpl since JSC's JITs now use this field.

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

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r205511 r205520  
     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-09-06  Benjamin Poulain  <bpoulain@apple.com>
    254
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r205507 r205520  
    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

    r205511 r205520  
     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
     52        * CMakeLists.txt:
     53        * JavaScriptCore.xcodeproj/project.pbxproj:
     54        * assembler/MacroAssemblerARM64.h:
     55        (JSC::MacroAssemblerARM64::not64):
     56        * bytecode/SpeculatedType.cpp:
     57        (JSC::speculationFromClassInfo):
     58        * bytecode/SpeculatedType.h:
     59        * dfg/DFGAbstractInterpreterInlines.h:
     60        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     61        (JSC::DFG::AbstractInterpreter<AbstractStateType>::execute):
     62        * dfg/DFGByteCodeParser.cpp:
     63        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     64        * dfg/DFGClobberize.h:
     65        (JSC::DFG::clobberize):
     66        * dfg/DFGDoesGC.cpp:
     67        (JSC::DFG::doesGC):
     68        * dfg/DFGEdge.h:
     69        (JSC::DFG::Edge::shift):
     70        (JSC::DFG::Edge::makeWord):
     71        * dfg/DFGFixupPhase.cpp:
     72        (JSC::DFG::FixupPhase::fixupNode):
     73        * dfg/DFGHeapLocation.cpp:
     74        (WTF::printInternal):
     75        * dfg/DFGHeapLocation.h:
     76        * dfg/DFGNode.h:
     77        (JSC::DFG::Node::hasHeapPrediction):
     78        * dfg/DFGNodeType.h:
     79        * dfg/DFGOperations.cpp:
     80        * dfg/DFGOperations.h:
     81        * dfg/DFGPredictionPropagationPhase.cpp:
     82        * dfg/DFGSafeToExecute.h:
     83        (JSC::DFG::SafeToExecuteEdge::operator()):
     84        (JSC::DFG::safeToExecute):
     85        * dfg/DFGSpeculativeJIT.cpp:
     86        (JSC::DFG::SpeculativeJIT::speculateMapObject):
     87        (JSC::DFG::SpeculativeJIT::speculateSetObject):
     88        (JSC::DFG::SpeculativeJIT::speculate):
     89        * dfg/DFGSpeculativeJIT.h:
     90        (JSC::DFG::SpeculativeJIT::callOperation):
     91        * dfg/DFGSpeculativeJIT32_64.cpp:
     92        (JSC::DFG::SpeculativeJIT::compile):
     93        * dfg/DFGSpeculativeJIT64.cpp:
     94        (JSC::DFG::SpeculativeJIT::compile):
     95        * dfg/DFGUseKind.cpp:
     96        (WTF::printInternal):
     97        * dfg/DFGUseKind.h:
     98        (JSC::DFG::typeFilterFor):
     99        (JSC::DFG::isCell):
     100        * ftl/FTLAbstractHeapRepository.h:
     101        * ftl/FTLCapabilities.cpp:
     102        (JSC::FTL::canCompile):
     103        * ftl/FTLLowerDFGToB3.cpp:
     104        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     105        (JSC::FTL::DFG::LowerDFGToB3::compileMapHash):
     106        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
     107        (JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket):
     108        (JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket):
     109        (JSC::FTL::DFG::LowerDFGToB3::lowMapObject):
     110        (JSC::FTL::DFG::LowerDFGToB3::lowSetObject):
     111        (JSC::FTL::DFG::LowerDFGToB3::lowMapBucket):
     112        (JSC::FTL::DFG::LowerDFGToB3::speculate):
     113        (JSC::FTL::DFG::LowerDFGToB3::speculateMapObject):
     114        (JSC::FTL::DFG::LowerDFGToB3::speculateSetObject):
     115        (JSC::FTL::DFG::LowerDFGToB3::setMapBucket):
     116        (JSC::FTL::DFG::LowerDFGToB3::lowRegExpObject): Deleted.
     117        (JSC::FTL::DFG::LowerDFGToB3::lowStorage): Deleted.
     118        (JSC::FTL::DFG::LowerDFGToB3::speculateRegExpObject): Deleted.
     119        (JSC::FTL::DFG::LowerDFGToB3::setStorage): Deleted.
     120        * jit/AssemblyHelpers.cpp:
     121        (JSC::AssemblyHelpers::wangsInt64Hash):
     122        * jit/AssemblyHelpers.h:
     123        (JSC::AssemblyHelpers::emitAllocateDestructibleObject): Deleted.
     124        * jit/JITOperations.h:
     125        * parser/ModuleAnalyzer.cpp:
     126        (JSC::ModuleAnalyzer::ModuleAnalyzer):
     127        * runtime/HashMapImpl.cpp: Added.
     128        (JSC::HashMapBucket<Data>::visitChildren):
     129        (JSC::HashMapImpl<HashMapBucket>::visitChildren):
     130        (JSC::HashMapImpl<HashMapBucket>::copyBackingStore):
     131        * runtime/HashMapImpl.h: Added.
     132        (JSC::HashMapBucket::selectStructure):
     133        (JSC::HashMapBucket::createStructure):
     134        (JSC::HashMapBucket::create):
     135        (JSC::HashMapBucket::HashMapBucket):
     136        (JSC::HashMapBucket::setNext):
     137        (JSC::HashMapBucket::setPrev):
     138        (JSC::HashMapBucket::setKey):
     139        (JSC::HashMapBucket::setValue):
     140        (JSC::HashMapBucket::key):
     141        (JSC::HashMapBucket::value):
     142        (JSC::HashMapBucket::next):
     143        (JSC::HashMapBucket::prev):
     144        (JSC::HashMapBucket::deleted):
     145        (JSC::HashMapBucket::setDeleted):
     146        (JSC::HashMapBucket::offsetOfKey):
     147        (JSC::HashMapBucket::offsetOfValue):
     148        (JSC::HashMapBuffer::allocationSize):
     149        (JSC::HashMapBuffer::buffer):
     150        (JSC::HashMapBuffer::create):
     151        (JSC::areKeysEqual):
     152        (JSC::normalizeMapKey):
     153        (JSC::jsMapHash):
     154        (JSC::HashMapImpl::selectStructure):
     155        (JSC::HashMapImpl::createStructure):
     156        (JSC::HashMapImpl::create):
     157        (JSC::HashMapImpl::HashMapImpl):
     158        (JSC::HashMapImpl::buffer):
     159        (JSC::HashMapImpl::finishCreation):
     160        (JSC::HashMapImpl::emptyValue):
     161        (JSC::HashMapImpl::isEmpty):
     162        (JSC::HashMapImpl::deletedValue):
     163        (JSC::HashMapImpl::isDeleted):
     164        (JSC::HashMapImpl::findBucket):
     165        (JSC::HashMapImpl::get):
     166        (JSC::HashMapImpl::has):
     167        (JSC::HashMapImpl::add):
     168        (JSC::HashMapImpl::remove):
     169        (JSC::HashMapImpl::size):
     170        (JSC::HashMapImpl::clear):
     171        (JSC::HashMapImpl::bufferSizeInBytes):
     172        (JSC::HashMapImpl::offsetOfBuffer):
     173        (JSC::HashMapImpl::offsetOfCapacity):
     174        (JSC::HashMapImpl::head):
     175        (JSC::HashMapImpl::tail):
     176        (JSC::HashMapImpl::approximateSize):
     177        (JSC::HashMapImpl::findBucketAlreadyHashedAndNormalized):
     178        (JSC::HashMapImpl::rehash):
     179        (JSC::HashMapImpl::makeAndSetNewBuffer):
     180        * runtime/Intrinsic.h:
     181        * runtime/JSCJSValue.h:
     182        * runtime/JSCJSValueInlines.h:
     183        (JSC::sameValue):
     184        * runtime/JSGlobalObject.cpp:
     185        (JSC::JSGlobalObject::init):
     186        * runtime/JSMap.cpp:
     187        (JSC::JSMap::destroy): Deleted.
     188        (JSC::JSMap::estimatedSize): Deleted.
     189        (JSC::JSMap::visitChildren): Deleted.
     190        (JSC::JSMap::copyBackingStore): Deleted.
     191        (JSC::JSMap::has): Deleted.
     192        (JSC::JSMap::size): Deleted.
     193        (JSC::JSMap::get): Deleted.
     194        (JSC::JSMap::set): Deleted.
     195        (JSC::JSMap::clear): Deleted.
     196        (JSC::JSMap::remove): Deleted.
     197        * runtime/JSMap.h:
     198        (JSC::JSMap::createStructure):
     199        (JSC::JSMap::create):
     200        (JSC::JSMap::get):
     201        (JSC::JSMap::set):
     202        (JSC::JSMap::JSMap):
     203        (JSC::JSMap::Entry::key): Deleted.
     204        (JSC::JSMap::Entry::value): Deleted.
     205        (JSC::JSMap::Entry::visitChildren): Deleted.
     206        (JSC::JSMap::Entry::setKey): Deleted.
     207        (JSC::JSMap::Entry::setKeyWithoutWriteBarrier): Deleted.
     208        (JSC::JSMap::Entry::setValue): Deleted.
     209        (JSC::JSMap::Entry::clear): Deleted.
     210        * runtime/JSMapIterator.cpp:
     211        (JSC::JSMapIterator::finishCreation):
     212        (JSC::JSMapIterator::visitChildren):
     213        (JSC::JSMapIterator::clone):
     214        * runtime/JSMapIterator.h:
     215        (JSC::JSMapIterator::advanceIter):
     216        (JSC::JSMapIterator::next):
     217        (JSC::JSMapIterator::nextKeyValue):
     218        (JSC::JSMapIterator::JSMapIterator):
     219        (JSC::JSMapIterator::setIterator):
     220        (JSC::JSMapIterator::finish): Deleted.
     221        (JSC::JSMapIterator::iteratorData): Deleted.
     222        * runtime/JSModuleLoader.cpp:
     223        (JSC::JSModuleLoader::finishCreation):
     224        * runtime/JSModuleLoader.h:
     225        (JSC::JSModuleLoader::create):
     226        * runtime/JSModuleRecord.cpp:
     227        (JSC::JSModuleRecord::finishCreation):
     228        * runtime/JSModuleRecord.h:
     229        (JSC::JSModuleRecord::create):
     230        * runtime/JSSet.cpp:
     231        (JSC::JSSet::destroy): Deleted.
     232        (JSC::JSSet::estimatedSize): Deleted.
     233        (JSC::JSSet::visitChildren): Deleted.
     234        (JSC::JSSet::copyBackingStore): Deleted.
     235        (JSC::JSSet::has): Deleted.
     236        (JSC::JSSet::size): Deleted.
     237        (JSC::JSSet::add): Deleted.
     238        (JSC::JSSet::clear): Deleted.
     239        (JSC::JSSet::remove): Deleted.
     240        * runtime/JSSet.h:
     241        (JSC::JSSet::createStructure):
     242        (JSC::JSSet::create):
     243        (JSC::JSSet::add):
     244        (JSC::JSSet::JSSet):
     245        (JSC::JSSet::Entry::key): Deleted.
     246        (JSC::JSSet::Entry::value): Deleted.
     247        (JSC::JSSet::Entry::visitChildren): Deleted.
     248        (JSC::JSSet::Entry::setKey): Deleted.
     249        (JSC::JSSet::Entry::setKeyWithoutWriteBarrier): Deleted.
     250        (JSC::JSSet::Entry::setValue): Deleted.
     251        (JSC::JSSet::Entry::clear): Deleted.
     252        * runtime/JSSetIterator.cpp:
     253        (JSC::JSSetIterator::finishCreation):
     254        (JSC::JSSetIterator::visitChildren):
     255        (JSC::JSSetIterator::clone):
     256        * runtime/JSSetIterator.h:
     257        (JSC::JSSetIterator::advanceIter):
     258        (JSC::JSSetIterator::next):
     259        (JSC::JSSetIterator::JSSetIterator):
     260        (JSC::JSSetIterator::setIterator):
     261        (JSC::JSSetIterator::finish): Deleted.
     262        (JSC::JSSetIterator::iteratorData): Deleted.
     263        * runtime/JSType.h:
     264        * runtime/MapBase.cpp: Added.
     265        (JSC::MapBase<HashMapBucketType>::visitChildren):
     266        (JSC::MapBase<HashMapBucketType>::estimatedSize):
     267        * runtime/MapBase.h: Added.
     268        (JSC::MapBase::size):
     269        (JSC::MapBase::has):
     270        (JSC::MapBase::clear):
     271        (JSC::MapBase::remove):
     272        (JSC::MapBase::findBucket):
     273        (JSC::MapBase::offsetOfHashMapImpl):
     274        (JSC::MapBase::impl):
     275        (JSC::MapBase::finishCreation):
     276        (JSC::MapBase::MapBase):
     277        * runtime/MapConstructor.cpp:
     278        (JSC::constructMap):
     279        * runtime/MapIteratorPrototype.cpp:
     280        (JSC::MapIteratorPrototypeFuncNext):
     281        * runtime/MapPrototype.cpp:
     282        (JSC::MapPrototype::finishCreation):
     283        (JSC::getMap):
     284        (JSC::privateFuncIsMap):
     285        (JSC::privateFuncMapIteratorNext):
     286        * runtime/PropertyDescriptor.cpp:
     287        (JSC::sameValue): Deleted.
     288        * runtime/PropertyDescriptor.h:
     289        * runtime/SetConstructor.cpp:
     290        (JSC::constructSet):
     291        * runtime/SetIteratorPrototype.cpp:
     292        (JSC::SetIteratorPrototypeFuncNext):
     293        * runtime/SetPrototype.cpp:
     294        (JSC::SetPrototype::finishCreation):
     295        (JSC::getSet):
     296        (JSC::privateFuncSetIteratorNext):
     297        * runtime/VM.cpp:
     298        (JSC::VM::VM):
     299        * runtime/VM.h:
     300
    13012016-09-06  Benjamin Poulain  <bpoulain@apple.com>
    2302
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r205507 r205520  
    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/assembler/MacroAssemblerARM64.h

    r205462 r205520  
    944944    }
    945945
     946    void not64(RegisterID srcDst)
     947    {
     948        m_assembler.mvn<64>(srcDst, srcDst);
     949    }
     950
    946951    // Memory access operations:
    947952
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205511 r205520  
    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

    r205507 r205520  
    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

    r205511 r205520  
    12521252        write(SideState);
    12531253        return;
     1254
     1255    case MapHash:
     1256        def(PureValue(node));
     1257        return;
     1258    case GetMapBucket: {
     1259        read(MiscFields);
     1260        Edge& mapEdge = node->child1();
     1261        Edge& keyEdge = node->child2();
     1262        def(HeapLocation(MapBucketLoc, MiscFields, mapEdge, keyEdge), LazyNode(node));
     1263        return;
     1264    }
     1265    case LoadFromJSMapBucket: {
     1266        read(MiscFields);
     1267        Edge& bucketEdge = node->child1();
     1268        def(HeapLocation(JSMapGetLoc, MiscFields, bucketEdge), LazyNode(node));
     1269        return;
     1270    }
     1271    case IsNonEmptyMapBucket:
     1272        read(MiscFields);
     1273        def(HeapLocation(MapHasLoc, MiscFields, node->child1()), LazyNode(node));
     1274        return;
    12541275       
    12551276    case LastNodeType:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205511 r205520  
    15481548            break;
    15491549        }
     1550
     1551        case GetMapBucket:
     1552            if (node->child1().useKind() == MapObjectUse)
     1553                fixEdge<MapObjectUse>(node->child1());
     1554            else if (node->child1().useKind() == SetObjectUse)
     1555                fixEdge<SetObjectUse>(node->child1());
     1556            else
     1557                RELEASE_ASSERT_NOT_REACHED();
     1558            fixEdge<UntypedUse>(node->child2());
     1559            fixEdge<Int32Use>(node->child3());
     1560            break;
     1561
     1562        case LoadFromJSMapBucket:
     1563            fixEdge<KnownCellUse>(node->child1());
     1564            break;
     1565
     1566        case IsNonEmptyMapBucket:
     1567            fixEdge<KnownCellUse>(node->child1());
     1568            break;
     1569
     1570        case MapHash:
     1571            fixEdge<UntypedUse>(node->child1());
     1572            break;
    15501573
    15511574#if !ASSERT_DISABLED
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r205507 r205520  
    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

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

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

    r205511 r205520  
    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

    r205511 r205520  
    5151#include "JSGenericTypedArrayViewConstructorInlines.h"
    5252#include "JSLexicalEnvironment.h"
     53#include "JSMap.h"
     54#include "JSSet.h"
    5355#include "ObjectConstructor.h"
    5456#include "Repatch.h"
     
    18241826}
    18251827
     1828int32_t JIT_OPERATION operationMapHash(ExecState* exec, EncodedJSValue input)
     1829{
     1830    VM& vm = exec->vm();
     1831    NativeCallFrameTracer tracer(&vm, exec);
     1832
     1833    return jsMapHash(exec, vm, normalizeMapKey(JSValue::decode(input)));
     1834}
     1835
     1836JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
     1837{
     1838    VM& vm = exec->vm();
     1839    NativeCallFrameTracer tracer(&vm, exec);
     1840    JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
     1841    if (!bucket)
     1842        return nullptr;
     1843    return *bucket;
     1844}
     1845
     1846JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState* exec, JSCell* map, EncodedJSValue key, int32_t hash)
     1847{
     1848    VM& vm = exec->vm();
     1849    NativeCallFrameTracer tracer(&vm, exec);
     1850    JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
     1851    if (!bucket)
     1852        return nullptr;
     1853    return *bucket;
     1854}
     1855
    18261856extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
    18271857{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r205511 r205520  
    144144JSString* JIT_OPERATION operationSingleCharacterString(ExecState*, int32_t);
    145145
     146int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input);
     147JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
     148JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
     149
    146150JSCell* JIT_OPERATION operationNewStringObject(ExecState*, JSString*, Structure*);
    147151JSCell* JIT_OPERATION operationToStringOnCell(ExecState*, JSCell*);
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205511 r205520  
    74197419}
    74207420
     7421void SpeculativeJIT::speculateMapObject(Edge edge, GPRReg cell)
     7422{
     7423    speculateCellType(edge, cell, SpecMapObject, JSMapType);
     7424}
     7425
     7426void SpeculativeJIT::speculateMapObject(Edge edge)
     7427{
     7428    if (!needsTypeCheck(edge, SpecMapObject))
     7429        return;
     7430
     7431    SpeculateCellOperand operand(this, edge);
     7432    speculateMapObject(edge, operand.gpr());
     7433}
     7434
     7435void SpeculativeJIT::speculateSetObject(Edge edge, GPRReg cell)
     7436{
     7437    speculateCellType(edge, cell, SpecSetObject, JSSetType);
     7438}
     7439
     7440void SpeculativeJIT::speculateSetObject(Edge edge)
     7441{
     7442    if (!needsTypeCheck(edge, SpecSetObject))
     7443        return;
     7444
     7445    SpeculateCellOperand operand(this, edge);
     7446    speculateSetObject(edge, operand.gpr());
     7447}
     7448
    74217449void SpeculativeJIT::speculateObjectOrOther(Edge edge)
    74227450{
     
    77057733    case RegExpObjectUse:
    77067734        speculateRegExpObject(edge);
     7735        break;
     7736    case MapObjectUse:
     7737        speculateMapObject(edge);
     7738        break;
     7739    case SetObjectUse:
     7740        speculateSetObject(edge);
    77077741        break;
    77087742    case ObjectOrOtherUse:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r205511 r205520  
    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    {
     
    17451751    }
    17461752#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    }
    17471765
    17481766    JITCompiler::Call callOperation(J_JITOperation_EJJMic operation, JSValueRegs result, JSValueRegs arg1, JSValueRegs arg2, TrustedImmPtr mathIC)
     
    26902708    void speculateRegExpObject(Edge, GPRReg cell);
    26912709    void speculateRegExpObject(Edge);
     2710    void speculateMapObject(Edge);
     2711    void speculateMapObject(Edge, GPRReg cell);
     2712    void speculateSetObject(Edge);
     2713    void speculateSetObject(Edge, GPRReg cell);
    26922714    void speculateObjectOrOther(Edge);
    26932715    void speculateString(Edge edge, GPRReg cell);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r205507 r205520  
    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

    r205507 r205520  
    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, JSValueRegs(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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205511 r205520  
    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:
     
    62806293        m_out.appendTo(continuation, lastNext);
    62816294        setBoolean(m_out.phi(Int32, notCellResult, cellResult));
     6295    }
     6296
     6297    void compileMapHash()
     6298    {
     6299        LValue value = lowJSValue(m_node->child1());
     6300
     6301        LBasicBlock isCellCase = m_out.newBlock();
     6302        LBasicBlock notCell = m_out.newBlock();
     6303        LBasicBlock slowCase = m_out.newBlock();
     6304        LBasicBlock straightHash = m_out.newBlock();
     6305        LBasicBlock isNumberCase = m_out.newBlock();
     6306        LBasicBlock isStringCase = m_out.newBlock();
     6307        LBasicBlock nonEmptyStringCase = m_out.newBlock();
     6308        LBasicBlock continuation = m_out.newBlock();
     6309
     6310        m_out.branch(
     6311            isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(notCell));
     6312
     6313        LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
     6314        LValue isString = m_out.equal(m_out.load8ZeroExt32(value, m_heaps.JSCell_typeInfoType), m_out.constInt32(StringType));
     6315        m_out.branch(
     6316            isString, unsure(isStringCase), unsure(straightHash));
     6317
     6318        m_out.appendTo(isStringCase, nonEmptyStringCase);
     6319        LValue stringImpl = m_out.loadPtr(value, m_heaps.JSString_value);
     6320        m_out.branch(
     6321            m_out.equal(stringImpl, m_out.constIntPtr(0)), rarely(slowCase), usually(nonEmptyStringCase));
     6322
     6323        m_out.appendTo(nonEmptyStringCase, notCell);
     6324        LValue hash = m_out.lShr(m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags), m_out.constInt32(StringImpl::s_flagCount));
     6325        ValueFromBlock nonEmptyStringHashResult = m_out.anchor(hash);
     6326        m_out.branch(m_out.equal(hash, m_out.constInt32(0)),
     6327            rarely(slowCase), usually(continuation));
     6328
     6329        m_out.appendTo(notCell, isNumberCase);
     6330        m_out.branch(
     6331            isNumber(value), unsure(isNumberCase), unsure(straightHash));
     6332
     6333        m_out.appendTo(isNumberCase, straightHash);
     6334        m_out.branch(
     6335            isInt32(value), unsure(straightHash), unsure(slowCase));
     6336
     6337        m_out.appendTo(straightHash, slowCase);
     6338        // key += ~(key << 32);
     6339        LValue key = value;
     6340        LValue temp = key;
     6341        temp = m_out.shl(temp, m_out.constInt32(32));
     6342        temp = m_out.bitNot(temp);
     6343        key = m_out.add(key, temp);
     6344        // key ^= (key >> 22);
     6345        temp = key;
     6346        temp = m_out.lShr(temp, m_out.constInt32(22));
     6347        key = m_out.bitXor(key, temp);
     6348        // key += ~(key << 13);
     6349        temp = key;
     6350        temp = m_out.shl(temp, m_out.constInt32(13));
     6351        temp = m_out.bitNot(temp);
     6352        key = m_out.add(key, temp);
     6353        // key ^= (key >> 8);
     6354        temp = key;
     6355        temp = m_out.lShr(temp, m_out.constInt32(8));
     6356        key = m_out.bitXor(key, temp);
     6357        // key += (key << 3);
     6358        temp = key;
     6359        temp = m_out.shl(temp, m_out.constInt32(3));
     6360        key = m_out.add(key, temp);
     6361        // key ^= (key >> 15);
     6362        temp = key;
     6363        temp = m_out.lShr(temp, m_out.constInt32(15));
     6364        key = m_out.bitXor(key, temp);
     6365        // key += ~(key << 27);
     6366        temp = key;
     6367        temp = m_out.shl(temp, m_out.constInt32(27));
     6368        temp = m_out.bitNot(temp);
     6369        key = m_out.add(key, temp);
     6370        // key ^= (key >> 31);
     6371        temp = key;
     6372        temp = m_out.lShr(temp, m_out.constInt32(31));
     6373        key = m_out.bitXor(key, temp);
     6374        key = m_out.castToInt32(key);
     6375
     6376        ValueFromBlock fastResult = m_out.anchor(key);
     6377        m_out.jump(continuation);
     6378
     6379        m_out.appendTo(slowCase, continuation);
     6380        ValueFromBlock slowResult = m_out.anchor(
     6381            vmCall(Int32, m_out.operation(operationMapHash), m_callFrame, value));
     6382        m_out.jump(continuation);
     6383
     6384        m_out.appendTo(continuation, lastNext);
     6385        setInt32(m_out.phi(Int32, fastResult, slowResult, nonEmptyStringHashResult));
     6386    }
     6387
     6388    void compileGetMapBucket()
     6389    {
     6390        LBasicBlock loopStart = m_out.newBlock();
     6391        LBasicBlock loopAround = m_out.newBlock();
     6392        LBasicBlock slowPath = m_out.newBlock();
     6393        LBasicBlock notPresentInTable = m_out.newBlock();
     6394        LBasicBlock notEmptyValue = m_out.newBlock();
     6395        LBasicBlock notDeletedValue = m_out.newBlock();
     6396        LBasicBlock notBitEqual = m_out.newBlock();
     6397        LBasicBlock bucketKeyNotCell = m_out.newBlock();
     6398        LBasicBlock bucketKeyIsCell = m_out.newBlock();
     6399        LBasicBlock bothAreCells = m_out.newBlock();
     6400        LBasicBlock bucketKeyIsString = m_out.newBlock();
     6401        LBasicBlock bucketKeyIsNumber = m_out.newBlock();
     6402        LBasicBlock bothAreNumbers = m_out.newBlock();
     6403        LBasicBlock bucketKeyIsInt32 = m_out.newBlock();
     6404        LBasicBlock continuation = m_out.newBlock();
     6405
     6406        LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart);
     6407
     6408        LValue map;
     6409        if (m_node->child1().useKind() == MapObjectUse)
     6410            map = lowMapObject(m_node->child1());
     6411        else if (m_node->child1().useKind() == SetObjectUse)
     6412            map = lowSetObject(m_node->child1());
     6413        else
     6414            RELEASE_ASSERT_NOT_REACHED();
     6415
     6416        LValue key = lowJSValue(m_node->child2());
     6417        LValue hash = lowInt32(m_node->child3());
     6418
     6419        LValue hashMapImpl = m_out.loadPtr(map, m_node->child1().useKind() == MapObjectUse ? m_heaps.JSMap_hashMapImpl : m_heaps.JSSet_hashMapImpl);
     6420        LValue buffer = m_out.loadPtr(hashMapImpl, m_heaps.HashMapImpl_buffer);
     6421        LValue mask = m_out.sub(m_out.load32(hashMapImpl, m_heaps.HashMapImpl_capacity), m_out.int32One);
     6422
     6423        ValueFromBlock indexStart = m_out.anchor(hash);
     6424        m_out.jump(loopStart);
     6425
     6426        m_out.appendTo(loopStart, notEmptyValue);
     6427        LValue unmaskedIndex = m_out.phi(Int32, indexStart);
     6428        LValue index = m_out.bitAnd(mask, unmaskedIndex);
     6429        LValue hashMapBucket = m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), buffer, m_out.zeroExt(index, Int64), ScaleEight));
     6430        ValueFromBlock bucketResult = m_out.anchor(hashMapBucket);
     6431        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::emptyValue())),
     6432            unsure(notPresentInTable), unsure(notEmptyValue));
     6433
     6434        m_out.appendTo(notEmptyValue, notDeletedValue);
     6435        m_out.branch(m_out.equal(hashMapBucket, m_out.constIntPtr(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::deletedValue())),
     6436            unsure(loopAround), unsure(notDeletedValue));
     6437
     6438        m_out.appendTo(notDeletedValue, notBitEqual);
     6439        LValue bucketKey = m_out.load64(hashMapBucket, m_heaps.HashMapBucket_key);
     6440        // Perform Object.is()
     6441        m_out.branch(m_out.equal(key, bucketKey),
     6442            unsure(continuation), unsure(notBitEqual));
     6443
     6444        m_out.appendTo(notBitEqual, bucketKeyIsCell);
     6445        m_out.branch(isCell(bucketKey),
     6446            unsure(bucketKeyIsCell), unsure(bucketKeyNotCell));
     6447
     6448        m_out.appendTo(bucketKeyIsCell, bothAreCells);
     6449        m_out.branch(isCell(key),
     6450            unsure(bothAreCells), unsure(loopAround));
     6451
     6452        m_out.appendTo(bothAreCells, bucketKeyIsString);
     6453        m_out.branch(isString(bucketKey),
     6454            unsure(bucketKeyIsString), unsure(loopAround));
     6455
     6456        m_out.appendTo(bucketKeyIsString, bucketKeyNotCell);
     6457        m_out.branch(isString(key),
     6458            unsure(slowPath), unsure(loopAround));
     6459
     6460        m_out.appendTo(bucketKeyNotCell, bucketKeyIsNumber);
     6461        m_out.branch(isNotNumber(bucketKey),
     6462            unsure(loopAround), unsure(bucketKeyIsNumber));
     6463
     6464        m_out.appendTo(bucketKeyIsNumber, bothAreNumbers);
     6465        m_out.branch(isNotNumber(key),
     6466            unsure(loopAround), unsure(bothAreNumbers));
     6467
     6468        m_out.appendTo(bothAreNumbers, bucketKeyIsInt32);
     6469        m_out.branch(isNotInt32(bucketKey),
     6470            unsure(slowPath), unsure(bucketKeyIsInt32));
     6471
     6472        m_out.appendTo(bucketKeyIsInt32, loopAround);
     6473        m_out.branch(isNotInt32(key),
     6474            unsure(slowPath), unsure(loopAround));
     6475
     6476        m_out.appendTo(loopAround, slowPath);
     6477        m_out.addIncomingToPhi(unmaskedIndex, m_out.anchor(m_out.add(index, m_out.int32One)));
     6478        m_out.jump(loopStart);
     6479
     6480        m_out.appendTo(slowPath, notPresentInTable);
     6481        ValueFromBlock slowPathResult = m_out.anchor(vmCall(pointerType(),
     6482            m_out.operation(m_node->child1().useKind() == MapObjectUse ? operationJSMapFindBucket : operationJSSetFindBucket), m_callFrame, map, key, hash));
     6483        m_out.jump(continuation);
     6484
     6485        m_out.appendTo(notPresentInTable, continuation);
     6486        ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0));
     6487        m_out.jump(continuation);
     6488
     6489        m_out.appendTo(continuation, lastNext);
     6490        setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult));
     6491    }
     6492
     6493    void compileLoadFromJSMapBucket()
     6494    {
     6495        LValue mapBucket = lowMapBucket(m_node->child1());
     6496
     6497        LBasicBlock continuation = m_out.newBlock();
     6498        LBasicBlock hasBucket = m_out.newBlock();
     6499
     6500        ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())));
     6501
     6502        m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)),
     6503            unsure(continuation), unsure(hasBucket));
     6504
     6505        LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation);
     6506        ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value));
     6507        m_out.jump(continuation);
     6508
     6509        m_out.appendTo(continuation, lastNext);
     6510        setJSValue(m_out.phi(Int64, noBucketResult, bucketResult));
     6511    }
     6512
     6513    void compileIsNonEmptyMapBucket()
     6514    {
     6515        LValue bucket = lowMapBucket(m_node->child1());
     6516        LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0));
     6517        setBoolean(result);
    62826518    }
    62836519
     
    999010226        return result;
    999110227    }
     10228
     10229    LValue lowMapObject(Edge edge)
     10230    {
     10231        LValue result = lowCell(edge);
     10232        speculateMapObject(edge, result);
     10233        return result;
     10234    }
     10235
     10236    LValue lowSetObject(Edge edge)
     10237    {
     10238        LValue result = lowCell(edge);
     10239        speculateSetObject(edge, result);
     10240        return result;
     10241    }
    999210242   
    999310243    LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     
    1011310363        return result;
    1011410364    }
     10365
     10366    LValue lowMapBucket(Edge edge)
     10367    {
     10368        LoweredNodeValue value = m_mapBucketValues.get(edge.node());
     10369        if (isValid(value))
     10370            return value.value();
     10371       
     10372        LValue result = lowCell(edge);
     10373        setStorage(edge.node(), result);
     10374        return result;
     10375    }
    1011510376   
    1011610377    LValue strictInt52ToInt32(Edge edge, LValue value)
     
    1041510676        case RegExpObjectUse:
    1041610677            speculateRegExpObject(edge);
     10678            break;
     10679        case MapObjectUse:
     10680            speculateMapObject(edge);
     10681            break;
     10682        case SetObjectUse:
     10683            speculateSetObject(edge);
    1041710684            break;
    1041810685        case StringUse:
     
    1074411011        speculateRegExpObject(edge, lowCell(edge));
    1074511012    }
     11013
     11014    void speculateMapObject(Edge edge, LValue cell)
     11015    {
     11016        FTL_TYPE_CHECK(
     11017            jsValueValue(cell), edge, SpecMapObject, isNotType(cell, JSMapType));
     11018    }
     11019
     11020    void speculateMapObject(Edge edge)
     11021    {
     11022        speculateMapObject(edge, lowCell(edge));
     11023    }
     11024
     11025    void speculateSetObject(Edge edge, LValue cell)
     11026    {
     11027        FTL_TYPE_CHECK(
     11028            jsValueValue(cell), edge, SpecSetObject, isNotType(cell, JSSetType));
     11029    }
     11030
     11031    void speculateSetObject(Edge edge)
     11032    {
     11033        speculateSetObject(edge, lowCell(edge));
     11034    }
    1074611035   
    1074711036    void speculateString(Edge edge, LValue cell)
     
    1151211801        m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
    1151311802    }
     11803    void setMapBucket(Node* node, LValue value)
     11804    {
     11805        m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock));
     11806    }
    1151411807    void setDouble(Node* node, LValue value)
    1151511808    {
     
    1154411837    {
    1154511838        setStorage(m_node, value);
     11839    }
     11840    void setMapBucket(LValue value)
     11841    {
     11842        setMapBucket(m_node, value);
    1154611843    }
    1154711844    void setDouble(LValue value)
     
    1172812025    HashMap<Node*, LoweredNodeValue> m_booleanValues;
    1172912026    HashMap<Node*, LoweredNodeValue> m_storageValues;
     12027    HashMap<Node*, LoweredNodeValue> m_mapBucketValues;
    1173012028    HashMap<Node*, LoweredNodeValue> m_doubleValues;
    1173112029   
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205508 r205520  
    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

    r205507 r205520  
    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

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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

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

    r205519 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
    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

    r205507 r205520  
     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 in StringImpl since JSC's JITs now use this field.
     9
     10        * wtf/text/StringImpl.h:
     11
    1122016-09-06  Commit Queue  <commit-queue@webkit.org>
    213
  • trunk/Source/WTF/wtf/text/StringImpl.h

    r205507 r205520  
    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

    r205519 r205520  
     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-06  Myles C. Maxfield  <mmaxfield@apple.com>
    215
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r205507 r205520  
    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.