Changeset 221110 in webkit


Ignore:
Timestamp:
Aug 23, 2017 3:19:13 PM (7 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Optimize Map iteration with intrinsic
https://bugs.webkit.org/show_bug.cgi?id=174355

Reviewed by Saam Barati.

JSTests:

  • stress/map-iterator-result-should-have-expected-shape.js: Added.

(shouldBe):
(throw.new.Error):

  • stress/set-iterator-result-should-have-expected-shape.js: Added.

(shouldBe):
(throw.new.Error.let.iterator.set Symbol):
(throw.new.Error.set add):
(let.iterator.set Symbol):

Source/JavaScriptCore:

This patch optimizes Map/Set iteration by taking the approach similar to Array iteration.
We create a simple iterator object instead of JSMapIterator and JSSetIterator. And we
directly handles Map/Set buckets in JS builtins. We carefully create mapIteratorNext and
setIteratorNext functions which should be inlined. This leads significant performance boost
when they are inlined in for-of iteration.

This patch changes how DFG and FTL handles MapBucket if the bucket is not found.
Previously, we use nullptr for that, and DFG and FTL specially handle this nullptr as bucket.
Instead, this patch introduces sentinel buckets. They are marked as deleted, and not linked
to any hash maps. And its key and value fields are filled with Undefined. By returning this
sentinel bucket instead of returning nullptr, we simplify DFG and FTL's LoadXXXFromMapBucket
code.

We still keep JSMapIterator and JSSetIterator because they are useful to serialize Map and Set
in WebCore. So they are not used in user observable JS. We change them from JS objects to JS cells.

Existing microbenchmarks shows performance improvements.

large-map-iteration 164.1622+-4.1618 56.6284+-1.5355 definitely 2.8989x faster
set-for-of 15.4369+-1.0631 9.2955+-0.5979 definitely 1.6607x faster
map-for-each 7.5889+-0.5792 6.3011+-0.4816 definitely 1.2044x faster
map-for-of 32.3904+-1.3003 12.6907+-0.6118 definitely 2.5523x faster
map-rehash 13.9275+-0.9187 11.5367+-0.6430 definitely 1.2072x faster

  • CMakeLists.txt:
  • DerivedSources.make:
  • builtins/ArrayPrototype.js:

(globalPrivate.createArrayIterator):

  • builtins/BuiltinNames.h:
  • builtins/MapIteratorPrototype.js: Copied from Source/JavaScriptCore/builtins/MapPrototype.js.

(globalPrivate.mapIteratorNext):
(next):

  • builtins/MapPrototype.js:

(globalPrivate.createMapIterator):
(values):
(keys):
(entries):
(forEach):

  • builtins/SetIteratorPrototype.js: Copied from Source/JavaScriptCore/builtins/MapPrototype.js.

(globalPrivate.setIteratorNext):
(next):

  • builtins/SetPrototype.js:

(globalPrivate.createSetIterator):
(values):
(entries):
(forEach):

  • bytecode/BytecodeIntrinsicRegistry.cpp:

(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):

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

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

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGHeapLocation.cpp:

(WTF::printInternal):

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

(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasBucketOwnerType):
(JSC::DFG::Node::bucketOwnerType):
(JSC::DFG::Node::OpInfoWrapper::as const):

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

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileGetMapBucketHead):
(JSC::DFG::SpeculativeJIT::compileGetMapBucketNext):
(JSC::DFG::SpeculativeJIT::compileLoadKeyFromMapBucket):
(JSC::DFG::SpeculativeJIT::compileLoadValueFromMapBucket):
(JSC::DFG::SpeculativeJIT::compileCompareEqPtr): Deleted.

  • dfg/DFGSpeculativeJIT.h:
  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

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

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketHead):
(JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketNext):
(JSC::FTL::DFG::LowerDFGToB3::compileLoadValueFromMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::compileLoadKeyFromMapBucket):
(JSC::FTL::DFG::LowerDFGToB3::setStorage):
(JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::lowMapBucket): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::setMapBucket): Deleted.

  • inspector/JSInjectedScriptHost.cpp:

(Inspector::JSInjectedScriptHost::subtype):
(Inspector::JSInjectedScriptHost::getInternalProperties):
(Inspector::cloneMapIteratorObject):
(Inspector::cloneSetIteratorObject):
(Inspector::JSInjectedScriptHost::iteratorEntries):

  • runtime/HashMapImpl.h:

(JSC::HashMapBucket::createSentinel):
(JSC::HashMapBucket::offsetOfNext):
(JSC::HashMapBucket::offsetOfDeleted):
(JSC::HashMapImpl::offsetOfHead):

  • runtime/Intrinsic.cpp:

(JSC::intrinsicName):

  • runtime/Intrinsic.h:
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):

  • runtime/JSGlobalObject.h:
  • runtime/JSMap.h:
  • runtime/JSMapIterator.cpp:

(JSC::JSMapIterator::clone): Deleted.

  • runtime/JSMapIterator.h:

(JSC::JSMapIterator::iteratedValue const):

  • runtime/JSSet.h:
  • runtime/JSSetIterator.cpp:

(JSC::JSSetIterator::clone): Deleted.

  • runtime/JSSetIterator.h:

(JSC::JSSetIterator::iteratedValue const):

  • runtime/MapConstructor.cpp:

(JSC::mapPrivateFuncMapBucketHead):
(JSC::mapPrivateFuncMapBucketNext):
(JSC::mapPrivateFuncMapBucketKey):
(JSC::mapPrivateFuncMapBucketValue):

  • runtime/MapConstructor.h:
  • runtime/MapIteratorPrototype.cpp:

(JSC::MapIteratorPrototype::finishCreation):
(JSC::MapIteratorPrototypeFuncNext): Deleted.

  • runtime/MapPrototype.cpp:

(JSC::MapPrototype::finishCreation):
(JSC::mapProtoFuncValues): Deleted.
(JSC::mapProtoFuncEntries): Deleted.
(JSC::mapProtoFuncKeys): Deleted.
(JSC::privateFuncMapIterator): Deleted.
(JSC::privateFuncMapIteratorNext): Deleted.

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

(JSC::setPrivateFuncSetBucketHead):
(JSC::setPrivateFuncSetBucketNext):
(JSC::setPrivateFuncSetBucketKey):

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

(JSC::SetIteratorPrototype::finishCreation):
(JSC::SetIteratorPrototypeFuncNext): Deleted.

  • runtime/SetPrototype.cpp:

(JSC::SetPrototype::finishCreation):
(JSC::setProtoFuncSize):
(JSC::setProtoFuncValues): Deleted.
(JSC::setProtoFuncEntries): Deleted.
(JSC::privateFuncSetIterator): Deleted.
(JSC::privateFuncSetIteratorNext): Deleted.

  • runtime/SetPrototype.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • runtime/VM.h:

Source/WebCore:

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::CloneSerializer::serialize):

Location:
trunk
Files:
2 added
56 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r221084 r221110  
     12017-08-23  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [JSC] Optimize Map iteration with intrinsic
     4        https://bugs.webkit.org/show_bug.cgi?id=174355
     5
     6        Reviewed by Saam Barati.
     7
     8        * stress/map-iterator-result-should-have-expected-shape.js: Added.
     9        (shouldBe):
     10        (throw.new.Error):
     11        * stress/set-iterator-result-should-have-expected-shape.js: Added.
     12        (shouldBe):
     13        (throw.new.Error.let.iterator.set Symbol):
     14        (throw.new.Error.set add):
     15        (let.iterator.set Symbol):
     16
    1172017-08-23  Robin Morisset  <rmorisset@apple.com>
    218
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r221080 r221110  
    14771477    ${JAVASCRIPTCORE_DIR}/builtins/IteratorHelpers.js
    14781478    ${JAVASCRIPTCORE_DIR}/builtins/IteratorPrototype.js
     1479    ${JAVASCRIPTCORE_DIR}/builtins/MapIteratorPrototype.js
    14791480    ${JAVASCRIPTCORE_DIR}/builtins/MapPrototype.js
    14801481    ${JAVASCRIPTCORE_DIR}/builtins/ModuleLoaderPrototype.js
     
    14871488    ${JAVASCRIPTCORE_DIR}/builtins/ReflectObject.js
    14881489    ${JAVASCRIPTCORE_DIR}/builtins/RegExpPrototype.js
     1490    ${JAVASCRIPTCORE_DIR}/builtins/SetIteratorPrototype.js
    14891491    ${JAVASCRIPTCORE_DIR}/builtins/SetPrototype.js
    14901492    ${JAVASCRIPTCORE_DIR}/builtins/StringConstructor.js
  • trunk/Source/JavaScriptCore/ChangeLog

    r221097 r221110  
     12017-08-23  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [JSC] Optimize Map iteration with intrinsic
     4        https://bugs.webkit.org/show_bug.cgi?id=174355
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch optimizes Map/Set iteration by taking the approach similar to Array iteration.
     9        We create a simple iterator object instead of JSMapIterator and JSSetIterator. And we
     10        directly handles Map/Set buckets in JS builtins. We carefully create mapIteratorNext and
     11        setIteratorNext functions which should be inlined. This leads significant performance boost
     12        when they are inlined in for-of iteration.
     13
     14        This patch changes how DFG and FTL handles MapBucket if the bucket is not found.
     15        Previously, we use nullptr for that, and DFG and FTL specially handle this nullptr as bucket.
     16        Instead, this patch introduces sentinel buckets. They are marked as deleted, and not linked
     17        to any hash maps. And its key and value fields are filled with Undefined. By returning this
     18        sentinel bucket instead of returning nullptr, we simplify DFG and FTL's LoadXXXFromMapBucket
     19        code.
     20
     21        We still keep JSMapIterator and JSSetIterator because they are useful to serialize Map and Set
     22        in WebCore. So they are not used in user observable JS. We change them from JS objects to JS cells.
     23
     24        Existing microbenchmarks shows performance improvements.
     25
     26        large-map-iteration                           164.1622+-4.1618     ^     56.6284+-1.5355        ^ definitely 2.8989x faster
     27        set-for-of                                     15.4369+-1.0631     ^      9.2955+-0.5979        ^ definitely 1.6607x faster
     28        map-for-each                                    7.5889+-0.5792     ^      6.3011+-0.4816        ^ definitely 1.2044x faster
     29        map-for-of                                     32.3904+-1.3003     ^     12.6907+-0.6118        ^ definitely 2.5523x faster
     30        map-rehash                                     13.9275+-0.9187     ^     11.5367+-0.6430        ^ definitely 1.2072x faster
     31
     32        * CMakeLists.txt:
     33        * DerivedSources.make:
     34        * builtins/ArrayPrototype.js:
     35        (globalPrivate.createArrayIterator):
     36        * builtins/BuiltinNames.h:
     37        * builtins/MapIteratorPrototype.js: Copied from Source/JavaScriptCore/builtins/MapPrototype.js.
     38        (globalPrivate.mapIteratorNext):
     39        (next):
     40        * builtins/MapPrototype.js:
     41        (globalPrivate.createMapIterator):
     42        (values):
     43        (keys):
     44        (entries):
     45        (forEach):
     46        * builtins/SetIteratorPrototype.js: Copied from Source/JavaScriptCore/builtins/MapPrototype.js.
     47        (globalPrivate.setIteratorNext):
     48        (next):
     49        * builtins/SetPrototype.js:
     50        (globalPrivate.createSetIterator):
     51        (values):
     52        (entries):
     53        (forEach):
     54        * bytecode/BytecodeIntrinsicRegistry.cpp:
     55        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
     56        * bytecode/BytecodeIntrinsicRegistry.h:
     57        * bytecode/SpeculatedType.h:
     58        * dfg/DFGAbstractInterpreterInlines.h:
     59        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     60        * dfg/DFGByteCodeParser.cpp:
     61        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
     62        * dfg/DFGClobberize.h:
     63        (JSC::DFG::clobberize):
     64        * dfg/DFGDoesGC.cpp:
     65        (JSC::DFG::doesGC):
     66        * dfg/DFGFixupPhase.cpp:
     67        (JSC::DFG::FixupPhase::fixupNode):
     68        * dfg/DFGHeapLocation.cpp:
     69        (WTF::printInternal):
     70        * dfg/DFGHeapLocation.h:
     71        * dfg/DFGNode.h:
     72        (JSC::DFG::Node::hasHeapPrediction):
     73        (JSC::DFG::Node::hasBucketOwnerType):
     74        (JSC::DFG::Node::bucketOwnerType):
     75        (JSC::DFG::Node::OpInfoWrapper::as const):
     76        * dfg/DFGNodeType.h:
     77        * dfg/DFGOperations.cpp:
     78        * dfg/DFGPredictionPropagationPhase.cpp:
     79        * dfg/DFGSafeToExecute.h:
     80        (JSC::DFG::safeToExecute):
     81        * dfg/DFGSpeculativeJIT.cpp:
     82        (JSC::DFG::SpeculativeJIT::compileGetMapBucketHead):
     83        (JSC::DFG::SpeculativeJIT::compileGetMapBucketNext):
     84        (JSC::DFG::SpeculativeJIT::compileLoadKeyFromMapBucket):
     85        (JSC::DFG::SpeculativeJIT::compileLoadValueFromMapBucket):
     86        (JSC::DFG::SpeculativeJIT::compileCompareEqPtr): Deleted.
     87        * dfg/DFGSpeculativeJIT.h:
     88        * dfg/DFGSpeculativeJIT32_64.cpp:
     89        (JSC::DFG::SpeculativeJIT::compileCompareEqPtr):
     90        (JSC::DFG::SpeculativeJIT::compile):
     91        * dfg/DFGSpeculativeJIT64.cpp:
     92        (JSC::DFG::SpeculativeJIT::compileCompareEqPtr):
     93        (JSC::DFG::SpeculativeJIT::compile):
     94        * ftl/FTLAbstractHeapRepository.h:
     95        * ftl/FTLCapabilities.cpp:
     96        (JSC::FTL::canCompile):
     97        * ftl/FTLLowerDFGToB3.cpp:
     98        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
     99        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucket):
     100        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketHead):
     101        (JSC::FTL::DFG::LowerDFGToB3::compileGetMapBucketNext):
     102        (JSC::FTL::DFG::LowerDFGToB3::compileLoadValueFromMapBucket):
     103        (JSC::FTL::DFG::LowerDFGToB3::compileLoadKeyFromMapBucket):
     104        (JSC::FTL::DFG::LowerDFGToB3::setStorage):
     105        (JSC::FTL::DFG::LowerDFGToB3::compileLoadFromJSMapBucket): Deleted.
     106        (JSC::FTL::DFG::LowerDFGToB3::compileIsNonEmptyMapBucket): Deleted.
     107        (JSC::FTL::DFG::LowerDFGToB3::lowMapBucket): Deleted.
     108        (JSC::FTL::DFG::LowerDFGToB3::setMapBucket): Deleted.
     109        * inspector/JSInjectedScriptHost.cpp:
     110        (Inspector::JSInjectedScriptHost::subtype):
     111        (Inspector::JSInjectedScriptHost::getInternalProperties):
     112        (Inspector::cloneMapIteratorObject):
     113        (Inspector::cloneSetIteratorObject):
     114        (Inspector::JSInjectedScriptHost::iteratorEntries):
     115        * runtime/HashMapImpl.h:
     116        (JSC::HashMapBucket::createSentinel):
     117        (JSC::HashMapBucket::offsetOfNext):
     118        (JSC::HashMapBucket::offsetOfDeleted):
     119        (JSC::HashMapImpl::offsetOfHead):
     120        * runtime/Intrinsic.cpp:
     121        (JSC::intrinsicName):
     122        * runtime/Intrinsic.h:
     123        * runtime/JSGlobalObject.cpp:
     124        (JSC::JSGlobalObject::init):
     125        * runtime/JSGlobalObject.h:
     126        * runtime/JSMap.h:
     127        * runtime/JSMapIterator.cpp:
     128        (JSC::JSMapIterator::clone): Deleted.
     129        * runtime/JSMapIterator.h:
     130        (JSC::JSMapIterator::iteratedValue const):
     131        * runtime/JSSet.h:
     132        * runtime/JSSetIterator.cpp:
     133        (JSC::JSSetIterator::clone): Deleted.
     134        * runtime/JSSetIterator.h:
     135        (JSC::JSSetIterator::iteratedValue const):
     136        * runtime/MapConstructor.cpp:
     137        (JSC::mapPrivateFuncMapBucketHead):
     138        (JSC::mapPrivateFuncMapBucketNext):
     139        (JSC::mapPrivateFuncMapBucketKey):
     140        (JSC::mapPrivateFuncMapBucketValue):
     141        * runtime/MapConstructor.h:
     142        * runtime/MapIteratorPrototype.cpp:
     143        (JSC::MapIteratorPrototype::finishCreation):
     144        (JSC::MapIteratorPrototypeFuncNext): Deleted.
     145        * runtime/MapPrototype.cpp:
     146        (JSC::MapPrototype::finishCreation):
     147        (JSC::mapProtoFuncValues): Deleted.
     148        (JSC::mapProtoFuncEntries): Deleted.
     149        (JSC::mapProtoFuncKeys): Deleted.
     150        (JSC::privateFuncMapIterator): Deleted.
     151        (JSC::privateFuncMapIteratorNext): Deleted.
     152        * runtime/MapPrototype.h:
     153        * runtime/SetConstructor.cpp:
     154        (JSC::setPrivateFuncSetBucketHead):
     155        (JSC::setPrivateFuncSetBucketNext):
     156        (JSC::setPrivateFuncSetBucketKey):
     157        * runtime/SetConstructor.h:
     158        * runtime/SetIteratorPrototype.cpp:
     159        (JSC::SetIteratorPrototype::finishCreation):
     160        (JSC::SetIteratorPrototypeFuncNext): Deleted.
     161        * runtime/SetPrototype.cpp:
     162        (JSC::SetPrototype::finishCreation):
     163        (JSC::setProtoFuncSize):
     164        (JSC::setProtoFuncValues): Deleted.
     165        (JSC::setProtoFuncEntries): Deleted.
     166        (JSC::privateFuncSetIterator): Deleted.
     167        (JSC::privateFuncSetIteratorNext): Deleted.
     168        * runtime/SetPrototype.h:
     169        * runtime/VM.cpp:
     170        (JSC::VM::VM):
     171        * runtime/VM.h:
     172
    11732017-08-23  David Kilzer  <ddkilzer@apple.com>
    2174
  • trunk/Source/JavaScriptCore/DerivedSources.make

    r221080 r221110  
    106106    $(JavaScriptCore)/builtins/IteratorHelpers.js \
    107107    $(JavaScriptCore)/builtins/IteratorPrototype.js \
     108    $(JavaScriptCore)/builtins/MapIteratorPrototype.js \
    108109    $(JavaScriptCore)/builtins/MapPrototype.js \
    109110    $(JavaScriptCore)/builtins/ModuleLoaderPrototype.js \
     
    116117    $(JavaScriptCore)/builtins/ReflectObject.js \
    117118    $(JavaScriptCore)/builtins/RegExpPrototype.js \
     119    $(JavaScriptCore)/builtins/SetIteratorPrototype.js \
    118120    $(JavaScriptCore)/builtins/SetPrototype.js \
    119121    $(JavaScriptCore)/builtins/StringConstructor.js \
  • trunk/Source/JavaScriptCore/builtins/ArrayPrototype.js

    r218674 r221110  
    2929function createArrayIterator(iteratedObject, kind, iterationFunction)
    3030{
     31    "use strict";
     32
    3133    this.@iteratedObject = iteratedObject;
    3234    this.@arrayIteratorKind = kind;
  • trunk/Source/JavaScriptCore/builtins/BuiltinNames.h

    r221080 r221110  
    148148    macro(print) \
    149149    macro(regExpCreate) \
    150     macro(SetIterator) \
    151     macro(setIteratorNext) \
    152150    macro(replaceUsingRegExp) \
    153151    macro(replaceUsingStringSearch) \
    154     macro(MapIterator) \
    155     macro(mapIteratorNext) \
     152    macro(mapBucket) \
     153    macro(mapBucketHead) \
     154    macro(mapBucketNext) \
     155    macro(mapBucketKey) \
     156    macro(mapBucketValue) \
     157    macro(mapIteratorKind) \
     158    macro(setBucket) \
     159    macro(setBucketHead) \
     160    macro(setBucketNext) \
     161    macro(setBucketKey) \
     162    macro(setIteratorKind) \
    156163    macro(regExpBuiltinExec) \
    157164    macro(regExpMatchFast) \
  • trunk/Source/JavaScriptCore/builtins/MapIteratorPrototype.js

    r221109 r221110  
    11/*
    2  * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>.
     2 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 function forEach(callback /*, thisArg */)
     26// We keep this function small very carefully to encourage inlining.
     27@globalPrivate
     28function mapIteratorNext(bucket, kind)
     29{
     30    "use strict";
     31    var value;
     32
     33    bucket = @mapBucketNext(bucket);
     34    this.@mapBucket = bucket;
     35    var done = bucket === @sentinelMapBucket;
     36    if (!done) {
     37        var key = @mapBucketKey(bucket);
     38        value = @mapBucketValue(bucket);
     39        if (kind === @iterationKindKeyValue)
     40            value = [ key, value ]
     41        else if (kind === @iterationKindKey)
     42            value = key;
     43    }
     44    return { done, value };
     45}
     46
     47function next()
    2748{
    2849    "use strict";
    2950
    30     if (!@isMap(this))
    31         @throwTypeError("Map operation called on non-Map object");
     51    if (this == null)
     52        @throwTypeError("%MapIteratorPrototype%.next requires that |this| not be null or undefined");
    3253
    33     if (typeof callback !== 'function')
    34         @throwTypeError("Map.prototype.forEach callback must be a function");
    35 
    36     var thisArg = @argument(1);
    37     var iterator = @MapIterator(this);
    38 
    39     // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results.
    40     var value = [ @undefined, @undefined ];
    41     for (;;) {
    42         if (@mapIteratorNext.@call(iterator, value))
    43             break;
    44         callback.@call(thisArg, value[1], value[0], this);
    45     }
     54    var bucket = this.@mapBucket;
     55    if (bucket === @undefined)
     56        @throwTypeError("%MapIteratorPrototype%.next requires that |this| be a Map Iterator instance");
     57    return @mapIteratorNext.@call(this, bucket, this.@mapIteratorKind);
    4658}
  • trunk/Source/JavaScriptCore/builtins/MapPrototype.js

    r208524 r221110  
    11/*
    2  * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>.
     2 * Copyright (C) 2016-2017 Yusuke Suzuki <utatane.tea@gmail.com>.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
     26@constructor
     27@globalPrivate
     28function createMapIterator(iteratedObject, kind)
     29{
     30    "use strict";
     31
     32    @assert(@isMap(iteratedObject));
     33    this.@iteratedObject = iteratedObject;
     34    this.@mapIteratorKind = kind;
     35    this.@mapBucket = @mapBucketHead(iteratedObject);
     36}
     37
     38function values()
     39{
     40    "use strict";
     41
     42    if (!@isMap(this))
     43        @throwTypeError("Map.prototype.values requires that |this| be Map");
     44
     45    return new @createMapIterator(this, @iterationKindValue);
     46}
     47
     48function keys()
     49{
     50    "use strict";
     51
     52    if (!@isMap(this))
     53        @throwTypeError("Map.prototype.keys requires that |this| be Map");
     54
     55    return new @createMapIterator(this, @iterationKindKey);
     56}
     57
     58function entries()
     59{
     60    "use strict";
     61
     62    if (!@isMap(this))
     63        @throwTypeError("Map.prototype.entries requires that |this| be Map");
     64
     65    return new @createMapIterator(this, @iterationKindKeyValue);
     66}
     67
    2668function forEach(callback /*, thisArg */)
    2769{
     
    3577
    3678    var thisArg = @argument(1);
    37     var iterator = @MapIterator(this);
     79    var bucket = @mapBucketHead(this);
    3880
    39     // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results.
    40     var value = [ @undefined, @undefined ];
    41     for (;;) {
    42         if (@mapIteratorNext.@call(iterator, value))
     81    do {
     82        bucket = @mapBucketNext(bucket);
     83        if (bucket === @sentinelMapBucket)
    4384            break;
    44         callback.@call(thisArg, value[1], value[0], this);
    45     }
     85        callback.@call(thisArg, @mapBucketValue(bucket), @mapBucketKey(bucket), this);
     86    } while (true);
    4687}
  • trunk/Source/JavaScriptCore/builtins/SetIteratorPrototype.js

    r221109 r221110  
    11/*
    2  * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>.
     2 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 function forEach(callback /*, thisArg */)
     26// We keep this function small very carefully to encourage inlining.
     27@globalPrivate
     28function setIteratorNext(bucket, kind)
     29{
     30    "use strict";
     31    var value;
     32
     33    bucket = @setBucketNext(bucket);
     34    this.@setBucket = bucket;
     35    var done = bucket === @sentinelSetBucket;
     36    if (!done) {
     37        value = @setBucketKey(bucket);
     38        if (kind === @iterationKindKeyValue)
     39            value = [ value, value ]
     40    }
     41    return { done, value };
     42}
     43
     44function next()
    2745{
    2846    "use strict";
    2947
    30     if (!@isMap(this))
    31         @throwTypeError("Map operation called on non-Map object");
     48    if (this == null)
     49        @throwTypeError("%SetIteratorPrototype%.next requires that |this| not be null or undefined");
    3250
    33     if (typeof callback !== 'function')
    34         @throwTypeError("Map.prototype.forEach callback must be a function");
    35 
    36     var thisArg = @argument(1);
    37     var iterator = @MapIterator(this);
    38 
    39     // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results.
    40     var value = [ @undefined, @undefined ];
    41     for (;;) {
    42         if (@mapIteratorNext.@call(iterator, value))
    43             break;
    44         callback.@call(thisArg, value[1], value[0], this);
    45     }
     51    var bucket = this.@setBucket;
     52    if (bucket === @undefined)
     53        @throwTypeError("%SetIteratorPrototype%.next requires that |this| be a Set Iterator instance");
     54    return @setIteratorNext.@call(this, bucket, this.@setIteratorKind);
    4655}
  • trunk/Source/JavaScriptCore/builtins/SetPrototype.js

    r208524 r221110  
    2424 */
    2525
     26@constructor
     27@globalPrivate
     28function createSetIterator(iteratedObject, kind)
     29{
     30    "use strict";
     31
     32    @assert(@isSet(iteratedObject));
     33    this.@iteratedObject = iteratedObject;
     34    this.@setIteratorKind = kind;
     35    this.@setBucket = @setBucketHead(iteratedObject);
     36}
     37
     38function values()
     39{
     40    "use strict";
     41
     42    if (!@isSet(this))
     43        @throwTypeError("Set.prototype.values requires that |this| be Set");
     44
     45    return new @createSetIterator(this, @iterationKindValue);
     46}
     47
     48function entries()
     49{
     50    "use strict";
     51
     52    if (!@isSet(this))
     53        @throwTypeError("Set.prototype.entries requires that |this| be Set");
     54
     55    return new @createSetIterator(this, @iterationKindKeyValue);
     56}
     57
    2658function forEach(callback /*, thisArg */)
    2759{
     
    3567
    3668    var thisArg = @argument(1);
    37     var iterator = @SetIterator(this);
     69    var bucket = @setBucketHead(this);
    3870
    39     // To avoid object allocations for iterator result objects, we pass the placeholder to the special "next" function in order to fill the results.
    40     var value = [ @undefined ];
    41     for (;;) {
    42         if (@setIteratorNext.@call(iterator, value))
     71    do {
     72        bucket = @setBucketNext(bucket);
     73        if (bucket === @sentinelSetBucket)
    4374            break;
    44         callback.@call(thisArg, value[0], value[0], this);
    45     }
     75        var key = @setBucketKey(bucket);
     76        callback.@call(thisArg, key, key, this);
     77    } while (true);
    4678}
  • trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp

    r221080 r221110  
    7070    m_promiseStateFulfilled.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Fulfilled)));
    7171    m_promiseStateRejected.set(m_vm, jsNumber(static_cast<unsigned>(JSPromise::Status::Rejected)));
     72    m_sentinelMapBucket.set(m_vm, m_vm.sentinelMapBucket.get());
     73    m_sentinelSetBucket.set(m_vm, m_vm.sentinelSetBucket.get());
    7274    m_GeneratorResumeModeNormal.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::NormalMode)));
    7375    m_GeneratorResumeModeThrow.set(m_vm, jsNumber(static_cast<int32_t>(JSGeneratorFunction::GeneratorResumeMode::ThrowMode)));
  • trunk/Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h

    r221080 r221110  
    8181    macro(promiseStateFulfilled) \
    8282    macro(promiseStateRejected) \
     83    macro(sentinelMapBucket) \
     84    macro(sentinelSetBucket) \
    8385    macro(GeneratorResumeModeNormal) \
    8486    macro(GeneratorResumeModeThrow) \
  • trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h

    r220735 r221110  
    6767static const SpeculatedType SpecString             = SpecStringIdent | SpecStringVar; // It's definitely a JSString.
    6868static const SpeculatedType SpecSymbol             = 1ull << 23; // It's definitely a Symbol.
    69 static const SpeculatedType SpecCellOther          = 1ull << 24; // 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
     69static const SpeculatedType SpecCellOther          = 1ull << 24; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol.
    7070static const SpeculatedType SpecCell               = SpecObject | SpecString | SpecSymbol | SpecCellOther; // It's definitely a JSCell.
    7171static const SpeculatedType SpecBoolInt32          = 1ull << 25; // It's definitely an Int32 with value 0 or 1.
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r221080 r221110  
    10491049    }
    10501050
    1051     case LoadFromJSMapBucket:
     1051    case LoadKeyFromMapBucket:
     1052    case LoadValueFromMapBucket:
    10521053        forNode(node).makeHeapTop();
    10531054        break;
    10541055
    10551056    case GetMapBucket:
    1056         forNode(node).setType(m_graph, SpecCellOther);
    1057         break;
    1058 
    1059     case IsNonEmptyMapBucket:
    1060         forNode(node).setType(SpecBoolean);
     1057    case GetMapBucketHead:
     1058        if (node->child1().useKind() == MapObjectUse)
     1059            forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get());
     1060        else {
     1061            ASSERT(node->child1().useKind() == SetObjectUse);
     1062            forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get());
     1063        }
     1064        break;
     1065
     1066    case GetMapBucketNext:
     1067        if (node->bucketOwnerType() == BucketOwnerType::Map)
     1068            forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get());
     1069        else {
     1070            ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
     1071            forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get());
     1072        }
    10611073        break;
    10621074
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r221084 r221110  
    28692869        Node* hash = addToGraph(MapHash, key);
    28702870        Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash));
    2871         Node* result = addToGraph(LoadFromJSMapBucket, OpInfo(), OpInfo(prediction), bucket);
     2871        Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
    28722872        set(VirtualRegister(resultOperand), result);
    28732873        return true;
     
    28852885        UseKind useKind = intrinsic == JSSetHasIntrinsic ? SetObjectUse : MapObjectUse;
    28862886        Node* bucket = addToGraph(GetMapBucket, OpInfo(0), Edge(mapOrSet, useKind), Edge(key), Edge(hash));
    2887         Node* result = addToGraph(IsNonEmptyMapBucket, bucket);
     2887        JSCell* sentinel = nullptr;
     2888        if (intrinsic == JSMapHasIntrinsic)
     2889            sentinel = m_vm->sentinelMapBucket.get();
     2890        else
     2891            sentinel = m_vm->sentinelSetBucket.get();
     2892
     2893        FrozenValue* frozenPointer = m_graph.freeze(sentinel);
     2894        Node* invertedResult = addToGraph(CompareEqPtr, OpInfo(frozenPointer), bucket);
     2895        Node* result = addToGraph(LogicalNot, invertedResult);
     2896        set(VirtualRegister(resultOperand), result);
     2897        return true;
     2898    }
     2899
     2900    case JSSetBucketHeadIntrinsic:
     2901    case JSMapBucketHeadIntrinsic: {
     2902        ASSERT(argumentCountIncludingThis == 2);
     2903
     2904        insertChecks();
     2905        Node* map = get(virtualRegisterForArgument(1, registerOffset));
     2906        UseKind useKind = intrinsic == JSSetBucketHeadIntrinsic ? SetObjectUse : MapObjectUse;
     2907        Node* result = addToGraph(GetMapBucketHead, Edge(map, useKind));
     2908        set(VirtualRegister(resultOperand), result);
     2909        return true;
     2910    }
     2911
     2912    case JSSetBucketNextIntrinsic:
     2913    case JSMapBucketNextIntrinsic: {
     2914        ASSERT(argumentCountIncludingThis == 2);
     2915
     2916        insertChecks();
     2917        Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
     2918        BucketOwnerType type = intrinsic == JSSetBucketNextIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
     2919        Node* result = addToGraph(GetMapBucketNext, OpInfo(type), bucket);
     2920        set(VirtualRegister(resultOperand), result);
     2921        return true;
     2922    }
     2923
     2924    case JSSetBucketKeyIntrinsic:
     2925    case JSMapBucketKeyIntrinsic: {
     2926        ASSERT(argumentCountIncludingThis == 2);
     2927
     2928        insertChecks();
     2929        Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
     2930        Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
     2931        set(VirtualRegister(resultOperand), result);
     2932        return true;
     2933    }
     2934
     2935    case JSMapBucketValueIntrinsic: {
     2936        ASSERT(argumentCountIncludingThis == 2);
     2937
     2938        insertChecks();
     2939        Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
     2940        Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
    28882941        set(VirtualRegister(resultOperand), result);
    28892942        return true;
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r221080 r221110  
    149149        // more bits than we currently have in PureValue.
    150150        return;
     151
     152    case CompareEqPtr:
     153        def(PureValue(node, node->cellOperand()->cell()));
     154        return;
    151155       
    152156    case ArithIMul:
     
    159163    case StringCharCodeAt:
    160164    case CompareStrictEq:
    161     case CompareEqPtr:
    162165    case IsEmpty:
    163166    case IsUndefined:
     
    15521555        return;
    15531556    }
    1554     case LoadFromJSMapBucket: {
     1557    case GetMapBucketHead: {
     1558        read(MiscFields);
     1559        Edge& mapEdge = node->child1();
     1560        def(HeapLocation(MapBucketHeadLoc, MiscFields, mapEdge), LazyNode(node));
     1561        return;
     1562    }
     1563    case GetMapBucketNext: {
     1564        read(MiscFields);
     1565        LocationKind locationKind = MapBucketMapNextLoc;
     1566        if (node->bucketOwnerType() == BucketOwnerType::Set)
     1567            locationKind = MapBucketSetNextLoc;
     1568        Edge& bucketEdge = node->child1();
     1569        def(HeapLocation(locationKind, MiscFields, bucketEdge), LazyNode(node));
     1570        return;
     1571    }
     1572    case LoadKeyFromMapBucket: {
    15551573        read(MiscFields);
    15561574        Edge& bucketEdge = node->child1();
    1557         def(HeapLocation(JSMapGetLoc, MiscFields, bucketEdge), LazyNode(node));
    1558         return;
    1559     }
    1560     case IsNonEmptyMapBucket:
     1575        def(HeapLocation(MapBucketKeyLoc, MiscFields, bucketEdge), LazyNode(node));
     1576        return;
     1577    }
     1578    case LoadValueFromMapBucket: {
    15611579        read(MiscFields);
    1562         def(HeapLocation(MapHasLoc, MiscFields, node->child1()), LazyNode(node));
    1563         return;
     1580        Edge& bucketEdge = node->child1();
     1581        def(HeapLocation(MapBucketValueLoc, MiscFields, bucketEdge), LazyNode(node));
     1582        return;
     1583    }
    15641584
    15651585    case ToLowerCase:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r221080 r221110  
    195195    case MapHash:
    196196    case GetMapBucket:
    197     case LoadFromJSMapBucket:
    198     case IsNonEmptyMapBucket:
     197    case GetMapBucketHead:
     198    case GetMapBucketNext:
     199    case LoadKeyFromMapBucket:
     200    case LoadValueFromMapBucket:
    199201    case Unreachable:
    200202    case ExtractOSREntryLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r221080 r221110  
    17961796            break;
    17971797
    1798         case LoadFromJSMapBucket:
    1799             fixEdge<KnownCellUse>(node->child1());
    1800             break;
    1801 
    1802         case IsNonEmptyMapBucket:
    1803             fixEdge<KnownCellUse>(node->child1());
     1798        case GetMapBucketHead:
     1799            if (node->child1().useKind() == MapObjectUse)
     1800                fixEdge<MapObjectUse>(node->child1());
     1801            else if (node->child1().useKind() == SetObjectUse)
     1802                fixEdge<SetObjectUse>(node->child1());
     1803            else
     1804                RELEASE_ASSERT_NOT_REACHED();
     1805            break;
     1806
     1807        case GetMapBucketNext:
     1808        case LoadKeyFromMapBucket:
     1809        case LoadValueFromMapBucket:
     1810            fixEdge<CellUse>(node->child1());
    18041811            break;
    18051812
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp

    r220118 r221110  
    163163        out.print("MapBucketLoc");
    164164        return;
    165     case JSMapGetLoc:
    166         out.print("JSMapGetLoc");
     165    case MapBucketHeadLoc:
     166        out.print("MapBucketHeadLoc");
    167167        return;
    168     case MapHasLoc:
    169         out.print("MapHasLoc");
     168    case MapBucketKeyLoc:
     169        out.print("MapBucketKeyLoc");
     170        return;
     171    case MapBucketValueLoc:
     172        out.print("MapBucketValueLoc");
     173        return;
     174    case MapBucketMapNextLoc:
     175        out.print("MapBucketMapNextLoc");
     176        return;
     177    case MapBucketSetNextLoc:
     178        out.print("MapBucketSetNextLoc");
    170179        return;
    171180    case DOMStateLoc:
  • trunk/Source/JavaScriptCore/dfg/DFGHeapLocation.h

    r220118 r221110  
    6464    StackPayloadLoc,
    6565    MapBucketLoc,
    66     JSMapGetLoc,
    67     MapHasLoc,
     66    MapBucketHeadLoc,
     67    MapBucketValueLoc,
     68    MapBucketKeyLoc,
     69    MapBucketMapNextLoc,
     70    MapBucketSetNextLoc,
    6871    DOMStateLoc,
    6972};
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r221084 r221110  
    242242    DOMJIT::CallDOMGetterSnippet* snippet { nullptr };
    243243    unsigned identifierNumber { 0 };
     244};
     245
     246enum class BucketOwnerType : uint32_t {
     247    Map,
     248    Set
    244249};
    245250
     
    15161521        case StringReplaceRegExp:
    15171522        case ToNumber:
    1518         case LoadFromJSMapBucket:
     1523        case LoadKeyFromMapBucket:
     1524        case LoadValueFromMapBucket:
    15191525        case CallDOMGetter:
    15201526        case CallDOM:
     
    25452551    }
    25462552
     2553    bool hasBucketOwnerType()
     2554    {
     2555        return op() == GetMapBucketNext;
     2556    }
     2557
     2558    BucketOwnerType bucketOwnerType()
     2559    {
     2560        ASSERT(hasBucketOwnerType());
     2561        return m_opInfo.as<BucketOwnerType>();
     2562    }
     2563
    25472564    void dumpChildren(PrintStream& out)
    25482565    {
     
    26532670        }
    26542671        template <typename T>
    2655         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 4, T>::type
     2672        ALWAYS_INLINE auto as() const -> typename std::enable_if<(std::is_integral<T>::value || std::is_enum<T>::value) && sizeof(T) == 4, T>::type
    26562673        {
    2657             return u.int32;
     2674            return static_cast<T>(u.int32);
    26582675        }
    26592676        template <typename T>
    2660         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
     2677        ALWAYS_INLINE auto as() const -> typename std::enable_if<(std::is_integral<T>::value || std::is_enum<T>::value) && sizeof(T) == 8, T>::type
    26612678        {
    2662             return u.int64;
     2679            return static_cast<T>(u.int64);
    26632680        }
    26642681        ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r221080 r221110  
    432432    macro(MapHash, NodeResultInt32) \
    433433    macro(GetMapBucket, NodeResultJS) \
    434     macro(LoadFromJSMapBucket, NodeResultJS) \
    435     macro(IsNonEmptyMapBucket, NodeResultBoolean) \
     434    macro(GetMapBucketHead, NodeResultJS) \
     435    macro(GetMapBucketNext, NodeResultJS) \
     436    macro(LoadKeyFromMapBucket, NodeResultJS) \
     437    macro(LoadValueFromMapBucket, NodeResultJS) \
    436438    \
    437439    macro(ToLowerCase, NodeResultJS) \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r220306 r221110  
    23002300    JSMap::BucketType** bucket = jsCast<JSMap*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
    23012301    if (!bucket)
    2302         return nullptr;
     2302        return vm.sentinelMapBucket.get();
    23032303    return *bucket;
    23042304}
     
    23102310    JSSet::BucketType** bucket = jsCast<JSSet*>(map)->findBucket(exec, normalizeMapKey(JSValue::decode(key)), hash);
    23112311    if (!bucket)
    2312         return nullptr;
     2312        return vm.sentinelSetBucket.get();
    23132313    return *bucket;
    23142314}
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r221084 r221110  
    718718        case GetClosureVar:
    719719        case GetFromArguments:
    720         case LoadFromJSMapBucket:
     720        case LoadKeyFromMapBucket:
     721        case LoadValueFromMapBucket:
    721722        case ToNumber:
    722723        case GetArgument:
     
    757758            setPrediction(SpecInt32Only);
    758759            break;
     760
    759761        case GetMapBucket:
     762        case GetMapBucketHead:
     763        case GetMapBucketNext:
    760764            setPrediction(SpecCellOther);
    761             break;
    762         case IsNonEmptyMapBucket:
    763             setPrediction(SpecBoolean);
    764765            break;
    765766
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r221080 r221110  
    384384    case ToLowerCase:
    385385    case GetMapBucket:
    386     case LoadFromJSMapBucket:
    387     case IsNonEmptyMapBucket:
     386    case GetMapBucketHead:
     387    case GetMapBucketNext:
     388    case LoadKeyFromMapBucket:
     389    case LoadValueFromMapBucket:
    388390    case AtomicsAdd:
    389391    case AtomicsAnd:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r221080 r221110  
    1000910009}
    1001010010
    10011 void SpeculativeJIT::compileCompareEqPtr(Node* node)
    10012 {
    10013     JSValueOperand operand(this, node->child1());
    10014     GPRTemporary result(this);
    10015     JSValueRegs regs = operand.jsValueRegs();
    10016     GPRReg resultGPR = result.gpr();
    10017     m_jit.boxBooleanPayload(false, resultGPR);
    10018     JITCompiler::JumpList notEqual = m_jit.branchIfNotEqual(regs, node->cellOperand()->value());
    10019     m_jit.boxBooleanPayload(true, resultGPR);
    10020     notEqual.link(&m_jit);
    10021     blessedBooleanResult(resultGPR, node);
    10022 }
    10023 
    1002410011void SpeculativeJIT::compileDefineDataProperty(Node* node)
    1002510012{
     
    1019610183}
    1019710184
     10185void SpeculativeJIT::compileGetMapBucketHead(Node* node)
     10186{
     10187    SpeculateCellOperand map(this, node->child1());
     10188    GPRTemporary bucket(this);
     10189
     10190    GPRReg mapGPR = map.gpr();
     10191    GPRReg bucketGPR = bucket.gpr();
     10192
     10193    if (node->child1().useKind() == MapObjectUse)
     10194        speculateMapObject(node->child1(), mapGPR);
     10195    else if (node->child1().useKind() == SetObjectUse)
     10196        speculateSetObject(node->child1(), mapGPR);
     10197    else
     10198        RELEASE_ASSERT_NOT_REACHED();
     10199
     10200    ASSERT(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead() == HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>::offsetOfHead());
     10201    m_jit.loadPtr(MacroAssembler::Address(mapGPR, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead()), bucketGPR);
     10202    cellResult(bucketGPR, node);
     10203}
     10204
     10205void SpeculativeJIT::compileGetMapBucketNext(Node* node)
     10206{
     10207    SpeculateCellOperand bucket(this, node->child1());
     10208    GPRTemporary result(this);
     10209
     10210    GPRReg bucketGPR = bucket.gpr();
     10211    GPRReg resultGPR = result.gpr();
     10212
     10213    ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfNext() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext());
     10214    ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfDeleted() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted());
     10215    m_jit.loadPtr(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()), resultGPR);
     10216
     10217    MacroAssembler::Label loop = m_jit.label();
     10218    auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR);
     10219    auto done = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(resultGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted()));
     10220    m_jit.loadPtr(MacroAssembler::Address(resultGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()), resultGPR);
     10221    m_jit.jump().linkTo(loop, &m_jit);
     10222
     10223    notBucket.link(&m_jit);
     10224    JSCell* sentinel = nullptr;
     10225    if (node->bucketOwnerType() == BucketOwnerType::Map)
     10226        sentinel = m_jit.vm()->sentinelMapBucket.get();
     10227    else {
     10228        ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
     10229        sentinel = m_jit.vm()->sentinelSetBucket.get();
     10230    }
     10231    m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), sentinel), resultGPR);
     10232    done.link(&m_jit);
     10233
     10234    cellResult(resultGPR, node);
     10235}
     10236
     10237void SpeculativeJIT::compileLoadKeyFromMapBucket(Node* node)
     10238{
     10239    SpeculateCellOperand bucket(this, node->child1());
     10240    JSValueRegsTemporary result(this);
     10241
     10242    GPRReg bucketGPR = bucket.gpr();
     10243    JSValueRegs resultRegs = result.regs();
     10244
     10245    m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()), resultRegs);
     10246    jsValueResult(resultRegs, node);
     10247}
     10248
     10249void SpeculativeJIT::compileLoadValueFromMapBucket(Node* node)
     10250{
     10251    SpeculateCellOperand bucket(this, node->child1());
     10252    JSValueRegsTemporary result(this);
     10253
     10254    GPRReg bucketGPR = bucket.gpr();
     10255    JSValueRegs resultRegs = result.regs();
     10256
     10257    m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), resultRegs);
     10258    jsValueResult(resultRegs, node);
     10259}
     10260
    1019810261} } // namespace JSC::DFG
    1019910262
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r220890 r221110  
    27802780    void compileCallDOM(Node*);
    27812781    void compileCheckSubClass(Node*);
     2782    void compileGetMapBucketHead(Node*);
     2783    void compileGetMapBucketNext(Node*);
     2784    void compileLoadKeyFromMapBucket(Node*);
     2785    void compileLoadValueFromMapBucket(Node*);
    27822786   
    27832787#if USE(JSVALUE32_64)
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r221080 r221110  
    691691    notEqual.link(&m_jit);
    692692    booleanResult(result.gpr(), node);
     693}
     694
     695void SpeculativeJIT::compileCompareEqPtr(Node* node)
     696{
     697    JSValueOperand operand(this, node->child1());
     698    GPRTemporary result(this);
     699    JSValueRegs regs = operand.jsValueRegs();
     700    GPRReg resultGPR = result.gpr();
     701    m_jit.boxBooleanPayload(false, resultGPR);
     702    JITCompiler::JumpList notEqual = m_jit.branchIfNotEqual(regs, node->cellOperand()->value());
     703    m_jit.boxBooleanPayload(true, resultGPR);
     704    notEqual.link(&m_jit);
     705    blessedBooleanResult(resultGPR, node);
    693706}
    694707
     
    49034916    }
    49044917
    4905     case LoadFromJSMapBucket: {
    4906         SpeculateCellOperand bucket(this, node->child1());
    4907         GPRTemporary resultPayload(this);
    4908         GPRTemporary resultTag(this);
    4909 
    4910         GPRReg bucketGPR = bucket.gpr();
    4911         GPRReg resultPayloadGPR = resultPayload.gpr();
    4912         GPRReg resultTagGPR = resultTag.gpr();
    4913 
    4914         auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR);
    4915         m_jit.loadValue(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), JSValueRegs(resultTagGPR, resultPayloadGPR));
    4916         auto done = m_jit.jump();
    4917 
    4918         notBucket.link(&m_jit);
    4919         m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
    4920         m_jit.move(TrustedImm32(0), resultPayloadGPR);
    4921         done.link(&m_jit);
    4922         jsValueResult(resultTagGPR, resultPayloadGPR, node);
    4923         break;
    4924     }
    4925 
    4926     case IsNonEmptyMapBucket: {
    4927         SpeculateCellOperand bucket(this, node->child1());
    4928         GPRTemporary result(this);
    4929 
    4930         GPRReg bucketGPR = bucket.gpr();
    4931         GPRReg resultGPR = result.gpr();
    4932 
    4933         m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR);
    4934         booleanResult(resultGPR, node);
    4935         break;
    4936     }
     4918    case GetMapBucketHead:
     4919        compileGetMapBucketHead(node);
     4920        break;
     4921
     4922    case GetMapBucketNext:
     4923        compileGetMapBucketNext(node);
     4924        break;
     4925
     4926    case LoadKeyFromMapBucket:
     4927        compileLoadKeyFromMapBucket(node);
     4928        break;
     4929
     4930    case LoadValueFromMapBucket:
     4931        compileLoadValueFromMapBucket(node);
     4932        break;
    49374933
    49384934    case Flush:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r221080 r221110  
    18351835   
    18361836    jsValueResult(result.gpr(), node, DataFormatJSBoolean);
     1837}
     1838
     1839void SpeculativeJIT::compileCompareEqPtr(Node* node)
     1840{
     1841    JSValueOperand value(this, node->child1());
     1842    GPRTemporary result(this);
     1843    GPRReg valueGPR = value.gpr();
     1844    GPRReg resultGPR = result.gpr();
     1845
     1846    m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), node->cellOperand()->cell()), resultGPR);
     1847    m_jit.compare64(MacroAssembler::Equal, valueGPR, resultGPR, resultGPR);
     1848    unblessedBooleanResult(resultGPR, node);
    18371849}
    18381850
     
    52555267
    52565268        notPresentInTable.link(&m_jit);
    5257         m_jit.move(TrustedImmPtr(nullptr), resultGPR);
     5269        if (node->child1().useKind() == MapObjectUse)
     5270            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelMapBucket.get()), resultGPR);
     5271        else
     5272            m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.vm()->sentinelSetBucket.get()), resultGPR);
    52585273        done.link(&m_jit);
    52595274        cellResult(resultGPR, node);
     
    52615276    }
    52625277
    5263     case LoadFromJSMapBucket: {
    5264         SpeculateCellOperand bucket(this, node->child1());
    5265         GPRTemporary result(this);
    5266 
    5267         GPRReg bucketGPR = bucket.gpr();
    5268         GPRReg resultGPR = result.gpr();
    5269 
    5270         auto notBucket = m_jit.branchTestPtr(MacroAssembler::Zero, bucketGPR);
    5271         m_jit.load64(MacroAssembler::Address(bucketGPR, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()), resultGPR);
    5272         auto done = m_jit.jump();
    5273 
    5274         notBucket.link(&m_jit);
    5275         m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), resultGPR);
    5276         done.link(&m_jit);
    5277         jsValueResult(resultGPR, node);
    5278         break;
    5279     }
    5280 
    5281     case IsNonEmptyMapBucket: {
    5282         SpeculateCellOperand bucket(this, node->child1());
    5283         GPRTemporary result(this);
    5284 
    5285         GPRReg bucketGPR = bucket.gpr();
    5286         GPRReg resultGPR = result.gpr();
    5287 
    5288         m_jit.comparePtr(MacroAssembler::NotEqual, bucketGPR, TrustedImm32(0), resultGPR);
    5289         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
    5290         jsValueResult(resultGPR, node, DataFormatJSBoolean);
    5291         break;
    5292     }
     5278    case GetMapBucketHead:
     5279        compileGetMapBucketHead(node);
     5280        break;
     5281
     5282    case GetMapBucketNext:
     5283        compileGetMapBucketNext(node);
     5284        break;
     5285
     5286    case LoadKeyFromMapBucket:
     5287        compileLoadKeyFromMapBucket(node);
     5288        break;
     5289
     5290    case LoadValueFromMapBucket:
     5291        compileLoadValueFromMapBucket(node);
     5292        break;
    52935293
    52945294    case ToLowerCase: {
  • trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h

    r217202 r221110  
    114114    macro(HashMapImpl_capacity, HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfCapacity()) \
    115115    macro(HashMapImpl_buffer,  HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfBuffer()) \
     116    macro(HashMapImpl_head,  HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead()) \
    116117    macro(HashMapBucket_value, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfValue()) \
    117118    macro(HashMapBucket_key, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfKey()) \
     119    macro(HashMapBucket_next, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext()) \
     120    macro(HashMapBucket_deleted, HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted()) \
    118121    macro(Symbol_symbolImpl, Symbol::offsetOfSymbolImpl()) \
    119122    macro(JSFixedArray_size, JSFixedArray::offsetOfSize()) \
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r221080 r221110  
    196196    case MapHash:
    197197    case GetMapBucket:
    198     case LoadFromJSMapBucket:
    199     case IsNonEmptyMapBucket:
     198    case GetMapBucketHead:
     199    case GetMapBucketNext:
     200    case LoadKeyFromMapBucket:
     201    case LoadValueFromMapBucket:
    200202    case IsEmpty:
    201203    case IsUndefined:
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r221080 r221110  
    972972            compileGetMapBucket();
    973973            break;
    974         case LoadFromJSMapBucket:
    975             compileLoadFromJSMapBucket();
    976             break;
    977         case IsNonEmptyMapBucket:
    978             compileIsNonEmptyMapBucket();
     974        case GetMapBucketHead:
     975            compileGetMapBucketHead();
     976            break;
     977        case GetMapBucketNext:
     978            compileGetMapBucketNext();
     979            break;
     980        case LoadKeyFromMapBucket:
     981            compileLoadKeyFromMapBucket();
     982            break;
     983        case LoadValueFromMapBucket:
     984            compileLoadValueFromMapBucket();
    979985            break;
    980986        case IsObject:
     
    82378243
    82388244        m_out.appendTo(notPresentInTable, continuation);
    8239         ValueFromBlock notPresentResult = m_out.anchor(m_out.constIntPtr(0));
     8245        ValueFromBlock notPresentResult;
     8246        if (m_node->child1().useKind() == MapObjectUse)
     8247            notPresentResult = m_out.anchor(weakPointer(vm().sentinelMapBucket.get()));
     8248        else if (m_node->child1().useKind() == SetObjectUse)
     8249            notPresentResult = m_out.anchor(weakPointer(vm().sentinelSetBucket.get()));
     8250        else
     8251            RELEASE_ASSERT_NOT_REACHED();
    82408252        m_out.jump(continuation);
    82418253
    82428254        m_out.appendTo(continuation, lastNext);
    8243         setMapBucket(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult));
    8244     }
    8245 
    8246     void compileLoadFromJSMapBucket()
    8247     {
    8248         LValue mapBucket = lowMapBucket(m_node->child1());
    8249 
     8255        setJSValue(m_out.phi(pointerType(), bucketResult, slowPathResult, notPresentResult));
     8256    }
     8257
     8258    void compileGetMapBucketHead()
     8259    {
     8260        LValue map;
     8261        if (m_node->child1().useKind() == MapObjectUse)
     8262            map = lowMapObject(m_node->child1());
     8263        else if (m_node->child1().useKind() == SetObjectUse)
     8264            map = lowSetObject(m_node->child1());
     8265        else
     8266            RELEASE_ASSERT_NOT_REACHED();
     8267
     8268        ASSERT(HashMapImpl<HashMapBucket<HashMapBucketDataKey>>::offsetOfHead() == HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>::offsetOfHead());
     8269        setJSValue(m_out.loadPtr(map, m_heaps.HashMapImpl_head));
     8270    }
     8271
     8272    void compileGetMapBucketNext()
     8273    {
     8274        LBasicBlock loopStart = m_out.newBlock();
    82508275        LBasicBlock continuation = m_out.newBlock();
     8276        LBasicBlock noBucket = m_out.newBlock();
    82518277        LBasicBlock hasBucket = m_out.newBlock();
    8252 
    8253         ValueFromBlock noBucketResult = m_out.anchor(m_out.constInt64(JSValue::encode(jsUndefined())));
    8254 
    8255         m_out.branch(m_out.equal(mapBucket, m_out.constIntPtr(0)),
    8256             unsure(continuation), unsure(hasBucket));
    8257 
    8258         LBasicBlock lastNext = m_out.appendTo(hasBucket, continuation);
    8259         ValueFromBlock bucketResult = m_out.anchor(m_out.load64(mapBucket, m_heaps.HashMapBucket_value));
     8278        LBasicBlock nextBucket = m_out.newBlock();
     8279
     8280        LBasicBlock lastNext = m_out.insertNewBlocksBefore(loopStart);
     8281
     8282        ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfNext() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfNext());
     8283        ASSERT(HashMapBucket<HashMapBucketDataKey>::offsetOfDeleted() == HashMapBucket<HashMapBucketDataKeyValue>::offsetOfDeleted());
     8284        LValue mapBucketPrev = lowCell(m_node->child1());
     8285        ValueFromBlock mapBucketStart = m_out.anchor(m_out.loadPtr(mapBucketPrev, m_heaps.HashMapBucket_next));
     8286        m_out.jump(loopStart);
     8287
     8288        m_out.appendTo(loopStart, noBucket);
     8289        LValue mapBucket = m_out.phi(pointerType(), mapBucketStart);
     8290        m_out.branch(m_out.isNull(mapBucket), unsure(noBucket), unsure(hasBucket));
     8291
     8292        m_out.appendTo(noBucket, hasBucket);
     8293        ValueFromBlock noBucketResult;
     8294        if (m_node->bucketOwnerType() == BucketOwnerType::Map)
     8295            noBucketResult = m_out.anchor(weakPointer(vm().sentinelMapBucket.get()));
     8296        else {
     8297            ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
     8298            noBucketResult = m_out.anchor(weakPointer(vm().sentinelSetBucket.get()));
     8299        }
    82608300        m_out.jump(continuation);
    82618301
     8302        m_out.appendTo(hasBucket, nextBucket);
     8303        ValueFromBlock bucketResult = m_out.anchor(mapBucket);
     8304        m_out.branch(m_out.isZero32(m_out.load32(mapBucket, m_heaps.HashMapBucket_deleted)), unsure(continuation), unsure(nextBucket));
     8305
     8306        m_out.appendTo(nextBucket, continuation);
     8307        m_out.addIncomingToPhi(mapBucket, m_out.anchor(m_out.loadPtr(mapBucket, m_heaps.HashMapBucket_next)));
     8308        m_out.jump(loopStart);
     8309
    82628310        m_out.appendTo(continuation, lastNext);
    8263         setJSValue(m_out.phi(Int64, noBucketResult, bucketResult));
    8264     }
    8265 
    8266     void compileIsNonEmptyMapBucket()
    8267     {
    8268         LValue bucket = lowMapBucket(m_node->child1());
    8269         LValue result = m_out.notEqual(bucket, m_out.constIntPtr(0));
    8270         setBoolean(result);
     8311        setJSValue(m_out.phi(pointerType(), noBucketResult, bucketResult));
     8312    }
     8313
     8314    void compileLoadValueFromMapBucket()
     8315    {
     8316        LValue mapBucket = lowCell(m_node->child1());
     8317        setJSValue(m_out.load64(mapBucket, m_heaps.HashMapBucket_value));
     8318    }
     8319
     8320    void compileLoadKeyFromMapBucket()
     8321    {
     8322        LValue mapBucket = lowCell(m_node->child1());
     8323        setJSValue(m_out.load64(mapBucket, m_heaps.HashMapBucket_key));
    82718324    }
    82728325
     
    1286512918    }
    1286612919
    12867     LValue lowMapBucket(Edge edge)
    12868     {
    12869         LoweredNodeValue value = m_mapBucketValues.get(edge.node());
    12870         if (isValid(value))
    12871             return value.value();
    12872        
    12873         LValue result = lowCell(edge);
    12874         setStorage(edge.node(), result);
    12875         return result;
    12876     }
    12877    
    1287812920    LValue strictInt52ToInt32(Edge edge, LValue value)
    1287912921    {
     
    1438914431        m_storageValues.set(node, LoweredNodeValue(value, m_highBlock));
    1439014432    }
    14391     void setMapBucket(Node* node, LValue value)
    14392     {
    14393         m_mapBucketValues.set(node, LoweredNodeValue(value, m_highBlock));
    14394     }
    1439514433    void setDouble(Node* node, LValue value)
    1439614434    {
     
    1442514463    {
    1442614464        setStorage(m_node, value);
    14427     }
    14428     void setMapBucket(LValue value)
    14429     {
    14430         setMapBucket(m_node, value);
    1443114465    }
    1443214466    void setDouble(LValue value)
     
    1461914653    HashMap<Node*, LoweredNodeValue> m_booleanValues;
    1462014654    HashMap<Node*, LoweredNodeValue> m_storageValues;
    14621     HashMap<Node*, LoweredNodeValue> m_mapBucketValues;
    1462214655    HashMap<Node*, LoweredNodeValue> m_doubleValues;
    1462314656   
  • trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp

    r218836 r221110  
    3434#include "Error.h"
    3535#include "InjectedScriptHost.h"
     36#include "IterationKind.h"
    3637#include "IteratorOperations.h"
    3738#include "IteratorPrototype.h"
     
    4344#include "JSInjectedScriptHostPrototype.h"
    4445#include "JSMap.h"
    45 #include "JSMapIterator.h"
    4646#include "JSPromise.h"
    4747#include "JSSet.h"
    48 #include "JSSetIterator.h"
    4948#include "JSStringIterator.h"
    5049#include "JSTypedArrays.h"
     
    5251#include "JSWeakSet.h"
    5352#include "JSWithScope.h"
     53#include "MapIteratorPrototype.h"
    5454#include "ObjectConstructor.h"
    5555#include "ProxyObject.h"
    5656#include "RegExpObject.h"
    5757#include "ScopedArguments.h"
     58#include "SetIteratorPrototype.h"
    5859#include "SourceCode.h"
    5960#include "TypedArrayInlines.h"
     
    183184        return jsNontrivialString(exec, ASCIILiteral("weakset"));
    184185
    185     if (value.inherits(vm, JSMapIterator::info())
    186         || value.inherits(vm, JSSetIterator::info())
    187         || value.inherits(vm, JSStringIterator::info()))
     186    if (value.inherits(vm, JSStringIterator::info()))
    188187        return jsNontrivialString(exec, ASCIILiteral("iterator"));
    189188
    190     if (object && object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName()))
    191         return jsNontrivialString(exec, ASCIILiteral("iterator"));
     189    if (object) {
     190        if (object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())
     191            || object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().mapBucketPrivateName())
     192            || object->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().setBucketPrivateName()))
     193            return jsNontrivialString(exec, ASCIILiteral("iterator"));
     194    }
    192195
    193196    if (value.inherits(vm, JSInt8Array::info())
     
    336339            return array;
    337340        }
    338     }
    339 
    340     if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(vm, value)) {
    341         String kind;
    342         switch (mapIterator->kind()) {
    343         case IterateKey:
    344             kind = ASCIILiteral("key");
    345             break;
    346         case IterateValue:
    347             kind = ASCIILiteral("value");
    348             break;
    349         case IterateKeyValue:
    350             kind = ASCIILiteral("key+value");
    351             break;
     341
     342        if (iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().mapBucketPrivateName())) {
     343            JSValue iteratedValue = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().iteratedObjectPrivateName());
     344            String kind;
     345            switch (static_cast<IterationKind>(iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().mapIteratorKindPrivateName()).asInt32())) {
     346            case IterateKey:
     347                kind = ASCIILiteral("key");
     348                break;
     349            case IterateValue:
     350                kind = ASCIILiteral("value");
     351                break;
     352            case IterateKeyValue:
     353                kind = ASCIILiteral("key+value");
     354                break;
     355            }
     356            unsigned index = 0;
     357            JSArray* array = constructEmptyArray(exec, nullptr, 2);
     358            RETURN_IF_EXCEPTION(scope, JSValue());
     359            array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", iteratedValue));
     360            RETURN_IF_EXCEPTION(scope, JSValue());
     361            scope.release();
     362            array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
     363            return array;
    352364        }
    353         unsigned index = 0;
    354         JSArray* array = constructEmptyArray(exec, nullptr, 2);
    355         RETURN_IF_EXCEPTION(scope, JSValue());
    356         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "map", mapIterator->iteratedValue()));
    357         RETURN_IF_EXCEPTION(scope, JSValue());
    358         scope.release();
    359         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
    360         return array;
    361     }
    362 
    363     if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value)) {
    364         String kind;
    365         switch (setIterator->kind()) {
    366         case IterateKey:
    367             kind = ASCIILiteral("key");
    368             break;
    369         case IterateValue:
    370             kind = ASCIILiteral("value");
    371             break;
    372         case IterateKeyValue:
    373             kind = ASCIILiteral("key+value");
    374             break;
     365
     366        if (iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().setBucketPrivateName())) {
     367            JSValue iteratedValue = iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().iteratedObjectPrivateName());
     368            String kind;
     369            switch (static_cast<IterationKind>(iteratorObject->getDirect(exec->vm(), exec->vm().propertyNames->builtinNames().setIteratorKindPrivateName()).asInt32())) {
     370            case IterateKey:
     371                kind = ASCIILiteral("key");
     372                break;
     373            case IterateValue:
     374                kind = ASCIILiteral("value");
     375                break;
     376            case IterateKeyValue:
     377                kind = ASCIILiteral("key+value");
     378                break;
     379            }
     380            unsigned index = 0;
     381            JSArray* array = constructEmptyArray(exec, nullptr, 2);
     382            RETURN_IF_EXCEPTION(scope, JSValue());
     383            array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", iteratedValue));
     384            RETURN_IF_EXCEPTION(scope, JSValue());
     385            scope.release();
     386            array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
     387            return array;
    375388        }
    376         unsigned index = 0;
    377         JSArray* array = constructEmptyArray(exec, nullptr, 2);
    378         RETURN_IF_EXCEPTION(scope, JSValue());
    379         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "set", setIterator->iteratedValue()));
    380         RETURN_IF_EXCEPTION(scope, JSValue());
    381         scope.release();
    382         array->putDirectIndex(exec, index++, constructInternalProperty(exec, "kind", jsNontrivialString(exec, kind)));
    383         return array;
    384389    }
    385390
     
    523528}
    524529
     530static JSObject* cloneMapIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSGlobalObject* globalObject, JSValue mapBucket, JSValue iteratedObject)
     531{
     532    ASSERT(iteratorObject->type() == FinalObjectType);
     533    JSObject* clone = constructEmptyObject(exec, MapIteratorPrototype::create(vm, globalObject, MapIteratorPrototype::createStructure(vm, globalObject, globalObject->iteratorPrototype())));
     534    clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratedObject);
     535    clone->putDirect(vm, vm.propertyNames->builtinNames().mapIteratorKindPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapIteratorKindPrivateName()));
     536    clone->putDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName(), mapBucket);
     537    return clone;
     538}
     539
     540static JSObject* cloneSetIteratorObject(ExecState* exec, VM& vm, JSObject* iteratorObject, JSGlobalObject* globalObject, JSValue setBucket, JSValue iteratedObject)
     541{
     542    ASSERT(iteratorObject->type() == FinalObjectType);
     543    JSObject* clone = constructEmptyObject(exec, SetIteratorPrototype::create(vm, globalObject, SetIteratorPrototype::createStructure(vm, globalObject, globalObject->iteratorPrototype())));
     544    clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratedObject);
     545    clone->putDirect(vm, vm.propertyNames->builtinNames().setIteratorKindPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setIteratorKindPrivateName()));
     546    clone->putDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName(), setBucket);
     547    return clone;
     548}
     549
    525550JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec)
    526551{
     
    534559    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    535560    JSValue value = exec->uncheckedArgument(0);
    536     if (JSMapIterator* mapIterator = jsDynamicCast<JSMapIterator*>(vm, value)) {
    537         if (jsCast<JSMap*>(mapIterator->iteratedValue())->isIteratorProtocolFastAndNonObservable())
    538             iterator = mapIterator->clone(exec);
    539     } else if (JSSetIterator* setIterator = jsDynamicCast<JSSetIterator*>(vm, value)) {
    540         if (jsCast<JSSet*>(setIterator->iteratedValue())->isIteratorProtocolFastAndNonObservable())
    541             iterator = setIterator->clone(exec);
    542     } else if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(vm, value)) {
     561    if (JSStringIterator* stringIterator = jsDynamicCast<JSStringIterator*>(vm, value)) {
    543562        if (globalObject->isStringPrototypeIteratorProtocolFastAndNonObservable())
    544563            iterator = stringIterator->clone(exec);
    545564    } else if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(vm, value)) {
    546565        // Detect an ArrayIterator by checking for one of its unique private properties.
     566        JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
    547567        if (JSValue nextIndex = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) {
    548             JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
    549568            if (isJSArray(iteratedObject)) {
    550569                JSArray* array = jsCast<JSArray*>(iteratedObject);
     
    555574                    iterator = cloneArrayIteratorObject(exec, vm, iteratorObject, globalObject, nextIndex, iteratedObject);
    556575            }
     576        } else if (JSValue mapBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())) {
     577            if (jsCast<JSMap*>(iteratedObject)->isIteratorProtocolFastAndNonObservable())
     578                iterator = cloneMapIteratorObject(exec, vm, iteratorObject, globalObject, mapBucket, iteratedObject);
     579        } else if (JSValue setBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName())) {
     580            if (jsCast<JSSet*>(iteratedObject)->isIteratorProtocolFastAndNonObservable())
     581                iterator = cloneSetIteratorObject(exec, vm, iteratorObject, globalObject, setBucket, iteratedObject);
    557582        }
    558583    }
  • trunk/Source/JavaScriptCore/runtime/HashMapImpl.h

    r220500 r221110  
    9898    }
    9999
     100    static HashMapBucket* createSentinel(VM& vm)
     101    {
     102        auto* bucket = create(vm);
     103        bucket->setDeleted(true);
     104        bucket->setKey(vm, jsUndefined());
     105        bucket->setValue(vm, jsUndefined());
     106        return bucket;
     107    }
     108
    100109    HashMapBucket(VM& vm, Structure* structure)
    101110        : Base(vm, structure)
     
    151160    }
    152161
     162    static ptrdiff_t offsetOfNext()
     163    {
     164        return OBJECT_OFFSETOF(HashMapBucket, m_next);
     165    }
     166
     167    static ptrdiff_t offsetOfDeleted()
     168    {
     169        return OBJECT_OFFSETOF(HashMapBucket, m_deleted);
     170    }
     171
    153172    template <typename T = Data>
    154173    ALWAYS_INLINE static typename std::enable_if<std::is_same<T, HashMapBucketDataKeyValue>::value, JSValue>::type extractValue(const HashMapBucket& bucket)
     
    164183
    165184private:
    166     Data m_data;
    167185    WriteBarrier<HashMapBucket> m_next;
    168186    WriteBarrier<HashMapBucket> m_prev;
    169     bool m_deleted { false };
     187    uint32_t m_deleted { false };
     188    Data m_data;
    170189};
    171190
     
    468487    {
    469488        return m_capacity * sizeof(HashMapBucketType*);
     489    }
     490
     491    static ptrdiff_t offsetOfHead()
     492    {
     493        return OBJECT_OFFSETOF(HashMapImpl<HashMapBucketType>, m_head);
    470494    }
    471495
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp

    r218084 r221110  
    138138    case JSMapHasIntrinsic:
    139139        return "JSMapHasIntrinsic";
     140    case JSMapBucketHeadIntrinsic:
     141        return "JSMapBucketHeadIntrinsic";
     142    case JSMapBucketNextIntrinsic:
     143        return "JSMapBucketNextIntrinsic";
     144    case JSMapBucketKeyIntrinsic:
     145        return "JSMapBucketKeyIntrinsic";
     146    case JSMapBucketValueIntrinsic:
     147        return "JSMapBucketValueIntrinsic";
    140148    case JSSetHasIntrinsic:
    141149        return "JSSetHasIntrinsic";
     150    case JSSetBucketHeadIntrinsic:
     151        return "JSSetBucketHeadIntrinsic";
     152    case JSSetBucketNextIntrinsic:
     153        return "JSSetBucketNextIntrinsic";
     154    case JSSetBucketKeyIntrinsic:
     155        return "JSSetBucketKeyIntrinsic";
    142156    case HasOwnPropertyIntrinsic:
    143157        return "HasOwnPropertyIntrinsic";
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r218084 r221110  
    8282    JSMapGetIntrinsic,
    8383    JSMapHasIntrinsic,
     84    JSMapBucketHeadIntrinsic,
     85    JSMapBucketNextIntrinsic,
     86    JSMapBucketKeyIntrinsic,
     87    JSMapBucketValueIntrinsic,
    8488    JSSetHasIntrinsic,
     89    JSSetBucketHeadIntrinsic,
     90    JSSetBucketNextIntrinsic,
     91    JSSetBucketKeyIntrinsic,
    8592    HasOwnPropertyIntrinsic,
    8693    AtomicsAddIntrinsic,
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r221080 r221110  
    100100#include "JSLock.h"
    101101#include "JSMap.h"
    102 #include "JSMapIterator.h"
    103102#include "JSModuleEnvironment.h"
    104103#include "JSModuleLoader.h"
     
    111110#include "JSPromisePrototype.h"
    112111#include "JSSet.h"
    113 #include "JSSetIterator.h"
    114112#include "JSStringIterator.h"
    115113#include "JSTemplateRegistryKey.h"
     
    753751    JSFunction* privateFuncConcatMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncConcatMemcpy);
    754752    JSFunction* privateFuncAppendMemcpy = JSFunction::create(vm, this, 0, String(), arrayProtoPrivateFuncAppendMemcpy);
     753    JSFunction* privateFuncMapBucketHead = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketHead, JSMapBucketHeadIntrinsic);
     754    JSFunction* privateFuncMapBucketNext = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketNext, JSMapBucketNextIntrinsic);
     755    JSFunction* privateFuncMapBucketKey = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketKey, JSMapBucketKeyIntrinsic);
     756    JSFunction* privateFuncMapBucketValue = JSFunction::create(vm, this, 0, String(), mapPrivateFuncMapBucketValue, JSMapBucketValueIntrinsic);
     757    JSFunction* privateFuncSetBucketHead = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketHead, JSSetBucketHeadIntrinsic);
     758    JSFunction* privateFuncSetBucketNext = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketNext, JSSetBucketNextIntrinsic);
     759    JSFunction* privateFuncSetBucketKey = JSFunction::create(vm, this, 0, String(), setPrivateFuncSetBucketKey, JSSetBucketKeyIntrinsic);
    755760
    756761    JSObject* regExpProtoFlagsGetterObject = getGetterById(exec, m_regExpPrototype.get(), vm.propertyNames->flags);
     
    784789    JSObject* asyncFromSyncIteratorPrototype = AsyncFromSyncIteratorPrototype::create(vm, this, AsyncFromSyncIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
    785790    AsyncFromSyncIteratorConstructorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, asyncFromSyncIteratorPrototype);
     791
     792    JSObject* mapIteratorPrototype = MapIteratorPrototype::create(vm, this, MapIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
     793    createMapIteratorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, mapIteratorPrototype);
     794
     795    JSObject* setIteratorPrototype = SetIteratorPrototype::create(vm, this, SetIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
     796    createSetIteratorPrivateFunction->putDirect(vm, vm.propertyNames->prototype, setIteratorPrototype);
    786797
    787798    GlobalPropertyInfo staticGlobals[] = {
     
    819830
    820831        GlobalPropertyInfo(vm.propertyNames->builtinNames().repeatCharacterPrivateName(), JSFunction::create(vm, this, 2, String(), stringProtoFuncRepeatCharacter), DontEnum | DontDelete | ReadOnly),
    821         GlobalPropertyInfo(vm.propertyNames->builtinNames().SetIteratorPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncSetIterator), DontEnum | DontDelete | ReadOnly),
    822         GlobalPropertyInfo(vm.propertyNames->builtinNames().setIteratorNextPrivateName(), JSFunction::create(vm, this, 0, String(), privateFuncSetIteratorNext), DontEnum | DontDelete | ReadOnly),
    823832        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArrayPrivateName(), arrayConstructor->getDirect(vm, vm.propertyNames->isArray), DontEnum | DontDelete | ReadOnly),
    824833        GlobalPropertyInfo(vm.propertyNames->builtinNames().isArraySlowPrivateName(), privateFuncIsArraySlow, DontEnum | DontDelete | ReadOnly),
     
    826835        GlobalPropertyInfo(vm.propertyNames->builtinNames().concatMemcpyPrivateName(), privateFuncConcatMemcpy, DontEnum | DontDelete | ReadOnly),
    827836        GlobalPropertyInfo(vm.propertyNames->builtinNames().appendMemcpyPrivateName(), privateFuncAppendMemcpy, DontEnum | DontDelete | ReadOnly),
    828         GlobalPropertyInfo(vm.propertyNames->builtinNames().MapIteratorPrivateName(), JSFunction::create(vm, this, 1, String(), privateFuncMapIterator), DontEnum | DontDelete | ReadOnly),
    829         GlobalPropertyInfo(vm.propertyNames->builtinNames().mapIteratorNextPrivateName(), JSFunction::create(vm, this, 0, String(), privateFuncMapIteratorNext), DontEnum | DontDelete | ReadOnly),
    830837
    831838        GlobalPropertyInfo(vm.propertyNames->builtinNames().hostPromiseRejectionTrackerPrivateName(), JSFunction::create(vm, this, 2, String(), globalFuncHostPromiseRejectionTracker), DontEnum | DontDelete | ReadOnly),
     
    868875        GlobalPropertyInfo(vm.propertyNames->builtinNames().makeBoundFunctionPrivateName(), JSFunction::create(vm, this, 5, String(), makeBoundFunction), DontEnum | DontDelete | ReadOnly),
    869876        GlobalPropertyInfo(vm.propertyNames->builtinNames().hasOwnLengthPropertyPrivateName(), JSFunction::create(vm, this, 1, String(), hasOwnLengthProperty), DontEnum | DontDelete | ReadOnly),
     877
     878        // Map and Set helpers.
     879        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketHeadPrivateName(), privateFuncMapBucketHead, DontEnum | DontDelete | ReadOnly),
     880        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketNextPrivateName(), privateFuncMapBucketNext, DontEnum | DontDelete | ReadOnly),
     881        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketKeyPrivateName(), privateFuncMapBucketKey, DontEnum | DontDelete | ReadOnly),
     882        GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketValuePrivateName(), privateFuncMapBucketValue, DontEnum | DontDelete | ReadOnly),
     883        GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketHeadPrivateName(), privateFuncSetBucketHead, DontEnum | DontDelete | ReadOnly),
     884        GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketNextPrivateName(), privateFuncSetBucketNext, DontEnum | DontDelete | ReadOnly),
     885        GlobalPropertyInfo(vm.propertyNames->builtinNames().setBucketKeyPrivateName(), privateFuncSetBucketKey, DontEnum | DontDelete | ReadOnly),
    870886    };
    871887    addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
     
    957973
    958974        {
    959             ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m_mapIteratorPrototype.get(), m_vm.propertyNames->next);
     975            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(mapIteratorPrototype, m_vm.propertyNames->next);
    960976            m_mapIteratorPrototypeNextWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_mapIteratorProtocolWatchpoint);
    961977            m_mapIteratorPrototypeNextWatchpoint->install();
     
    968984
    969985        {
    970             ObjectPropertyCondition condition = setupAdaptiveWatchpoint(m_setIteratorPrototype.get(), m_vm.propertyNames->next);
     986            ObjectPropertyCondition condition = setupAdaptiveWatchpoint(setIteratorPrototype, m_vm.propertyNames->next);
    971987            m_setIteratorPrototypeNextWatchpoint = std::make_unique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(vm, condition, m_setIteratorProtocolWatchpoint);
    972988            m_setIteratorPrototypeNextWatchpoint->install();
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r221080 r221110  
    127127
    128128#define FOR_EACH_BUILTIN_DERIVED_ITERATOR_TYPE(macro) \
    129     macro(MapIterator, mapIterator, mapIterator, JSMapIterator, MapIterator, iterator) \
    130     macro(SetIterator, setIterator, setIterator, JSSetIterator, SetIterator, iterator) \
    131129    macro(StringIterator, stringIterator, stringIterator, JSStringIterator, StringIterator, iterator) \
    132130
  • trunk/Source/JavaScriptCore/runtime/JSMap.h

    r218836 r221110  
    3131namespace JSC {
    3232
    33 class JSMapIterator;
    34 
    3533class JSMap final : public HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>> {
    3634    using Base = HashMapImpl<HashMapBucket<HashMapBucketDataKeyValue>>;
    3735public:
    38     friend class JSMapIterator;
    3936
    4037    DECLARE_EXPORT_INFO;
  • trunk/Source/JavaScriptCore/runtime/JSMapIterator.cpp

    r217192 r221110  
    3232namespace JSC {
    3333
    34 const ClassInfo JSMapIterator::s_info = { "Map Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSMapIterator) };
     34const ClassInfo JSMapIterator::s_info = { "Map Iterator", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSMapIterator) };
    3535
    3636void JSMapIterator::finishCreation(VM& vm, JSMap* iteratedObject)
     
    5959}
    6060
    61 JSMapIterator* JSMapIterator::clone(ExecState* exec)
    62 {
    63     VM& vm = exec->vm();
    64     auto clone = JSMapIterator::create(vm, exec->jsCallee()->globalObject()->mapIteratorStructure(), m_map.get(), m_kind);
    65     clone->setIterator(vm, m_iter.get());
    66     return clone;
    6761}
    68 
    69 }
  • trunk/Source/JavaScriptCore/runtime/JSMapIterator.h

    r211675 r221110  
    3232namespace JSC {
    3333
    34 class JSMapIterator : public JSNonFinalObject {
     34// Now, it is only used for serialization.
     35class JSMapIterator : public JSCell {
    3536    typedef HashMapBucket<HashMapBucketDataKeyValue> HashMapBucketType;
    3637public:
    37     typedef JSNonFinalObject Base;
     38    using Base = JSCell;
    3839
    3940    DECLARE_EXPORT_INFO;
     
    9495    IterationKind kind() const { return m_kind; }
    9596    JSValue iteratedValue() const { return m_map.get(); }
    96     JSMapIterator* clone(ExecState*);
    9797
    9898private:
  • trunk/Source/JavaScriptCore/runtime/JSSet.h

    r220500 r221110  
    3131namespace JSC {
    3232
    33 class JSSetIterator;
    34 
    3533class JSSet final : public HashMapImpl<HashMapBucket<HashMapBucketDataKey>> {
    3634    using Base = HashMapImpl<HashMapBucket<HashMapBucketDataKey>>;
    3735public:
    38 
    39     friend class JSSetIterator;
    4036
    4137    DECLARE_EXPORT_INFO;
  • trunk/Source/JavaScriptCore/runtime/JSSetIterator.cpp

    r217192 r221110  
    3232namespace JSC {
    3333
    34 const ClassInfo JSSetIterator::s_info = { "Set Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSSetIterator) };
     34const ClassInfo JSSetIterator::s_info = { "Set Iterator", nullptr, nullptr, nullptr, CREATE_METHOD_TABLE(JSSetIterator) };
    3535
    3636void JSSetIterator::finishCreation(VM& vm, JSSet* iteratedObject)
     
    5959}
    6060
    61 JSSetIterator* JSSetIterator::clone(ExecState* exec)
    62 {
    63     VM& vm = exec->vm();
    64     auto clone = JSSetIterator::create(vm, exec->jsCallee()->globalObject()->setIteratorStructure(), m_set.get(), m_kind);
    65     clone->setIterator(vm, m_iter.get());
    66     return clone;
    6761}
    68 
    69 }
  • trunk/Source/JavaScriptCore/runtime/JSSetIterator.h

    r211675 r221110  
    3232namespace JSC {
    3333
    34 class JSSetIterator : public JSNonFinalObject {
     34// Now, it is only used for serialization.
     35class JSSetIterator : public JSCell {
    3536    typedef HashMapBucket<HashMapBucketDataKey> HashMapBucketType;
    3637public:
    37     typedef JSNonFinalObject Base;
     38    using Base = JSCell;
    3839
    3940    DECLARE_EXPORT_INFO;
     
    8283    IterationKind kind() const { return m_kind; }
    8384    JSValue iteratedValue() const { return m_set.get(); }
    84     JSSetIterator* clone(ExecState*);
    8585
    8686private:
  • trunk/Source/JavaScriptCore/runtime/MapConstructor.cpp

    r217527 r221110  
    121121}
    122122
     123EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketHead(ExecState* exec)
     124{
     125    ASSERT(isJSMap(exec->argument(0)));
     126    JSMap* map = jsCast<JSMap*>(exec->uncheckedArgument(0));
     127    auto* head = map->head();
     128    ASSERT(head);
     129    return JSValue::encode(head);
    123130}
     131
     132EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketNext(ExecState* exec)
     133{
     134    ASSERT(jsDynamicCast<JSMap::BucketType*>(exec->vm(), exec->argument(0)));
     135    auto* bucket = jsCast<JSMap::BucketType*>(exec->uncheckedArgument(0));
     136    ASSERT(bucket);
     137    bucket = bucket->next();
     138    while (bucket) {
     139        if (!bucket->deleted())
     140            return JSValue::encode(bucket);
     141        bucket = bucket->next();
     142    }
     143    return JSValue::encode(exec->vm().sentinelMapBucket.get());
     144}
     145
     146EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketKey(ExecState* exec)
     147{
     148    ASSERT(jsDynamicCast<JSMap::BucketType*>(exec->vm(), exec->argument(0)));
     149    auto* bucket = jsCast<JSMap::BucketType*>(exec->uncheckedArgument(0));
     150    ASSERT(bucket);
     151    return JSValue::encode(bucket->key());
     152}
     153
     154EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketValue(ExecState* exec)
     155{
     156    ASSERT(jsDynamicCast<JSMap::BucketType*>(exec->vm(), exec->argument(0)));
     157    auto* bucket = jsCast<JSMap::BucketType*>(exec->uncheckedArgument(0));
     158    ASSERT(bucket);
     159    return JSValue::encode(bucket->value());
     160}
     161
     162}
  • trunk/Source/JavaScriptCore/runtime/MapConstructor.h

    r206525 r221110  
    6161};
    6262
     63EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketHead(ExecState*);
     64EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketNext(ExecState*);
     65EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketKey(ExecState*);
     66EncodedJSValue JSC_HOST_CALL mapPrivateFuncMapBucketValue(ExecState*);
     67
    6368} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/MapIteratorPrototype.cpp

    r217108 r221110  
    2727#include "MapIteratorPrototype.h"
    2828
    29 #include "IteratorOperations.h"
     29#include "JSCBuiltins.h"
    3030#include "JSCInlines.h"
    31 #include "JSMapIterator.h"
    3231
    3332namespace JSC {
    3433
    3534const ClassInfo MapIteratorPrototype::s_info = { "Map Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(MapIteratorPrototype) };
    36 
    37 static EncodedJSValue JSC_HOST_CALL MapIteratorPrototypeFuncNext(ExecState*);
    3835
    3936void MapIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     
    4340    vm.prototypeMap.addPrototype(this);
    4441
    45     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, MapIteratorPrototypeFuncNext, DontEnum, 0);
     42    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", mapIteratorPrototypeNextCodeGenerator, DontEnum);
    4643    putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Map Iterator"), DontEnum | ReadOnly);
    4744}
    4845
    49 EncodedJSValue JSC_HOST_CALL MapIteratorPrototypeFuncNext(CallFrame* callFrame)
    50 {
    51     VM& vm = callFrame->vm();
    52     auto scope = DECLARE_THROW_SCOPE(vm);
    53 
    54     JSMapIterator* iterator = jsDynamicCast<JSMapIterator*>(vm, callFrame->thisValue());
    55     if (!iterator)
    56         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot call MapIterator.next() on a non-MapIterator object")));
    57 
    58     JSValue result;
    59     if (iterator->next(callFrame, result)) {
    60         scope.release();
    61         return JSValue::encode(createIteratorResultObject(callFrame, result, false));
    62     }
    63     scope.release();
    64     return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true));
    6546}
    66 
    67 
    68 }
  • trunk/Source/JavaScriptCore/runtime/MapPrototype.cpp

    r217192 r221110  
    3333#include "JSCInlines.h"
    3434#include "JSMap.h"
    35 #include "JSMapIterator.h"
    3635#include "Lookup.h"
    3736
     
    4544@begin mapPrototypeTable
    4645  forEach   JSBuiltin  DontEnum|Function 0
     46  values    JSBuiltin  DontEnum|Function 0
     47  keys      JSBuiltin  DontEnum|Function 0
    4748@end
    4849*/
     
    5354static EncodedJSValue JSC_HOST_CALL mapProtoFuncHas(ExecState*);
    5455static EncodedJSValue JSC_HOST_CALL mapProtoFuncSet(ExecState*);
    55 static EncodedJSValue JSC_HOST_CALL mapProtoFuncKeys(ExecState*);
    56 static EncodedJSValue JSC_HOST_CALL mapProtoFuncValues(ExecState*);
    57 static EncodedJSValue JSC_HOST_CALL mapProtoFuncEntries(ExecState*);
    5856
    5957static EncodedJSValue JSC_HOST_CALL mapProtoFuncSize(ExecState*);
     
    7068    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->has, mapProtoFuncHas, DontEnum, 1, JSMapHasIntrinsic);
    7169    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->set, mapProtoFuncSet, DontEnum, 2);
    72     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), mapProtoFuncKeys, DontEnum, 0);
    73     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().valuesPublicName(), mapProtoFuncValues, DontEnum, 0);
    7470
    7571    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrivateName(), mapProtoFuncGet, DontEnum, 1, JSMapGetIntrinsic);
    7672    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().setPrivateName(), mapProtoFuncSet, DontEnum, 2);
    7773
    78     JSFunction* entries = JSFunction::create(vm, globalObject, 0, vm.propertyNames->builtinNames().entriesPublicName().string(), mapProtoFuncEntries);
     74    JSFunction* entries = JSFunction::create(vm, mapPrototypeEntriesCodeGenerator(vm), globalObject);
    7975    putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().entriesPublicName(), entries, DontEnum);
    8076    putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, entries, DontEnum);
     
    151147}
    152148
    153 EncodedJSValue JSC_HOST_CALL mapProtoFuncValues(CallFrame* callFrame)
    154 {
    155     VM& vm = callFrame->vm();
    156     auto scope = DECLARE_THROW_SCOPE(vm);
    157 
    158     JSMap* thisObj = jsDynamicCast<JSMap*>(vm, callFrame->thisValue());
    159     if (!thisObj)
    160         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Map value iterator for a non-Map object.")));
    161     return JSValue::encode(JSMapIterator::create(vm, callFrame->jsCallee()->globalObject()->mapIteratorStructure(), thisObj, IterateValue));
    162149}
    163 
    164 EncodedJSValue JSC_HOST_CALL mapProtoFuncEntries(CallFrame* callFrame)
    165 {
    166     VM& vm = callFrame->vm();
    167     auto scope = DECLARE_THROW_SCOPE(vm);
    168 
    169     JSMap* thisObj = jsDynamicCast<JSMap*>(vm, callFrame->thisValue());
    170     if (!thisObj)
    171         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Map entry iterator for a non-Map object.")));
    172     return JSValue::encode(JSMapIterator::create(vm, callFrame->jsCallee()->globalObject()->mapIteratorStructure(), thisObj, IterateKeyValue));
    173 }
    174 
    175 EncodedJSValue JSC_HOST_CALL mapProtoFuncKeys(CallFrame* callFrame)
    176 {
    177     VM& vm = callFrame->vm();
    178     auto scope = DECLARE_THROW_SCOPE(vm);
    179 
    180     JSMap* thisObj = jsDynamicCast<JSMap*>(vm, callFrame->thisValue());
    181     if (!thisObj)
    182         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Map key iterator for a non-Map object.")));
    183     return JSValue::encode(JSMapIterator::create(vm, callFrame->jsCallee()->globalObject()->mapIteratorStructure(), thisObj, IterateKey));
    184 }
    185 
    186 EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState* exec)
    187 {
    188     ASSERT(jsDynamicCast<JSMap*>(exec->vm(), exec->uncheckedArgument(0)));
    189     JSMap* map = jsCast<JSMap*>(exec->uncheckedArgument(0));
    190     return JSValue::encode(JSMapIterator::create(exec->vm(), exec->jsCallee()->globalObject()->mapIteratorStructure(), map, IterateKeyValue));
    191 }
    192 
    193 EncodedJSValue JSC_HOST_CALL privateFuncMapIteratorNext(ExecState* exec)
    194 {
    195     VM& vm = exec->vm();
    196     auto scope = DECLARE_THROW_SCOPE(vm);
    197     ASSERT(jsDynamicCast<JSMapIterator*>(vm, exec->thisValue()));
    198     JSMapIterator* iterator = jsCast<JSMapIterator*>(exec->thisValue());
    199     JSValue key, value;
    200     if (iterator->nextKeyValue(exec, key, value)) {
    201         JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0));
    202         resultArray->putDirectIndex(exec, 0, key);
    203         RETURN_IF_EXCEPTION(scope, encodedJSValue());
    204         scope.release();
    205         resultArray->putDirectIndex(exec, 1, value);
    206         return JSValue::encode(jsBoolean(false));
    207     }
    208     return JSValue::encode(jsBoolean(true));
    209 }
    210 
    211 }
  • trunk/Source/JavaScriptCore/runtime/MapPrototype.h

    r206525 r221110  
    5858};
    5959
    60 EncodedJSValue JSC_HOST_CALL privateFuncMapIterator(ExecState*);
    61 EncodedJSValue JSC_HOST_CALL privateFuncMapIteratorNext(ExecState*);
    62 
    6360} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/SetConstructor.cpp

    r217527 r221110  
    107107}
    108108
     109EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketHead(ExecState* exec)
     110{
     111    ASSERT(isJSSet(exec->argument(0)));
     112    JSSet* set = jsCast<JSSet*>(exec->uncheckedArgument(0));
     113    auto* head = set->head();
     114    ASSERT(head);
     115    return JSValue::encode(head);
    109116}
     117
     118EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketNext(ExecState* exec)
     119{
     120    ASSERT(jsDynamicCast<JSSet::BucketType*>(exec->vm(), exec->argument(0)));
     121    auto* bucket = jsCast<JSSet::BucketType*>(exec->uncheckedArgument(0));
     122    ASSERT(bucket);
     123    bucket = bucket->next();
     124    while (bucket) {
     125        if (!bucket->deleted())
     126            return JSValue::encode(bucket);
     127        bucket = bucket->next();
     128    }
     129    return JSValue::encode(exec->vm().sentinelSetBucket.get());
     130}
     131
     132EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketKey(ExecState* exec)
     133{
     134    ASSERT(jsDynamicCast<JSSet::BucketType*>(exec->vm(), exec->argument(0)));
     135    auto* bucket = jsCast<JSSet::BucketType*>(exec->uncheckedArgument(0));
     136    ASSERT(bucket);
     137    return JSValue::encode(bucket->key());
     138}
     139
     140}
  • trunk/Source/JavaScriptCore/runtime/SetConstructor.h

    r206525 r221110  
    6161};
    6262
     63EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketHead(ExecState*);
     64EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketNext(ExecState*);
     65EncodedJSValue JSC_HOST_CALL setPrivateFuncSetBucketKey(ExecState*);
     66
    6367} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/SetIteratorPrototype.cpp

    r217108 r221110  
    2727#include "SetIteratorPrototype.h"
    2828
    29 #include "IteratorOperations.h"
     29#include "JSCBuiltins.h"
    3030#include "JSCInlines.h"
    31 #include "JSSetIterator.h"
    3231
    3332namespace JSC {
    3433
    3534const ClassInfo SetIteratorPrototype::s_info = { "Set Iterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(SetIteratorPrototype) };
    36 
    37 static EncodedJSValue JSC_HOST_CALL SetIteratorPrototypeFuncNext(ExecState*);
    3835
    3936void SetIteratorPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     
    4340    vm.prototypeMap.addPrototype(this);
    4441
    45     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, SetIteratorPrototypeFuncNext, DontEnum, 0);
     42    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("next", setIteratorPrototypeNextCodeGenerator, DontEnum);
    4643    putDirectWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, jsString(&vm, "Set Iterator"), DontEnum | ReadOnly);
    4744}
    4845
    49 EncodedJSValue JSC_HOST_CALL SetIteratorPrototypeFuncNext(CallFrame* callFrame)
    50 {
    51     VM& vm = callFrame->vm();
    52     auto scope = DECLARE_THROW_SCOPE(vm);
    53 
    54     JSValue result;
    55     JSSetIterator* iterator = jsDynamicCast<JSSetIterator*>(vm, callFrame->thisValue());
    56     if (!iterator)
    57         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot call SetIterator.next() on a non-SetIterator object")));
    58 
    59     if (iterator->next(callFrame, result)) {
    60         scope.release();
    61         return JSValue::encode(createIteratorResultObject(callFrame, result, false));
    62     }
    63     scope.release();
    64     return JSValue::encode(createIteratorResultObject(callFrame, jsUndefined(), true));
    6546}
    66 
    67 }
  • trunk/Source/JavaScriptCore/runtime/SetPrototype.cpp

    r218861 r221110  
    3333#include "JSCInlines.h"
    3434#include "JSSet.h"
    35 #include "JSSetIterator.h"
    3635#include "Lookup.h"
    3736
     
    4544@begin setPrototypeTable
    4645  forEach   JSBuiltin  DontEnum|Function 0
     46  entries   JSBuiltin  DontEnum|Function 0
    4747@end
    4848*/
     
    5252static EncodedJSValue JSC_HOST_CALL setProtoFuncDelete(ExecState*);
    5353static EncodedJSValue JSC_HOST_CALL setProtoFuncHas(ExecState*);
    54 static EncodedJSValue JSC_HOST_CALL setProtoFuncValues(ExecState*);
    55 static EncodedJSValue JSC_HOST_CALL setProtoFuncEntries(ExecState*);
    5654
    5755
     
    7068    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().hasPrivateName(), setProtoFuncHas, DontEnum, 1, JSSetHasIntrinsic);
    7169    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().addPrivateName(), setProtoFuncAdd, DontEnum, 1);
    72     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), setProtoFuncEntries, DontEnum, 0);
    7370
    74     JSFunction* values = JSFunction::create(vm, globalObject, 0, vm.propertyNames->builtinNames().valuesPublicName().string(), setProtoFuncValues);
     71    JSFunction* values = JSFunction::create(vm, setPrototypeValuesCodeGenerator(vm), globalObject);
    7572    putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), values, DontEnum);
    7673    putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().keysPublicName(), values, DontEnum);
     
    138135    return JSValue::encode(jsNumber(set->size()));
    139136}
    140    
    141 EncodedJSValue JSC_HOST_CALL setProtoFuncValues(CallFrame* callFrame)
    142 {
    143     VM& vm = callFrame->vm();
    144     auto scope = DECLARE_THROW_SCOPE(vm);
    145 
    146     JSSet* thisObj = jsDynamicCast<JSSet*>(vm, callFrame->thisValue());
    147     if (!thisObj)
    148         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Set value iterator for a non-Set object.")));
    149     return JSValue::encode(JSSetIterator::create(vm, callFrame->jsCallee()->globalObject()->setIteratorStructure(), thisObj, IterateValue));
    150 }
    151 
    152 EncodedJSValue JSC_HOST_CALL setProtoFuncEntries(CallFrame* callFrame)
    153 {
    154     VM& vm = callFrame->vm();
    155     auto scope = DECLARE_THROW_SCOPE(vm);
    156 
    157     JSSet* thisObj = jsDynamicCast<JSSet*>(vm, callFrame->thisValue());
    158     if (!thisObj)
    159         return JSValue::encode(throwTypeError(callFrame, scope, ASCIILiteral("Cannot create a Set entry iterator for a non-Set object.")));
    160     return JSValue::encode(JSSetIterator::create(vm, callFrame->jsCallee()->globalObject()->setIteratorStructure(), thisObj, IterateKeyValue));
    161 }
    162 
    163 EncodedJSValue JSC_HOST_CALL privateFuncSetIterator(ExecState* exec)
    164 {
    165 
    166     ASSERT(jsDynamicCast<JSSet*>(exec->vm(), exec->uncheckedArgument(0)));
    167     JSSet* set = jsCast<JSSet*>(exec->uncheckedArgument(0));
    168     return JSValue::encode(JSSetIterator::create(exec->vm(), exec->jsCallee()->globalObject()->setIteratorStructure(), set, IterateKey));
    169 }
    170 
    171 EncodedJSValue JSC_HOST_CALL privateFuncSetIteratorNext(ExecState* exec)
    172 {
    173     ASSERT(jsDynamicCast<JSSetIterator*>(exec->vm(), exec->thisValue()));
    174     JSSetIterator* iterator = jsCast<JSSetIterator*>(exec->thisValue());
    175     JSValue result;
    176     if (iterator->next(exec, result)) {
    177         JSArray* resultArray = jsCast<JSArray*>(exec->uncheckedArgument(0));
    178         resultArray->putDirectIndex(exec, 0, result);
    179         return JSValue::encode(jsBoolean(false));
    180     }
    181     return JSValue::encode(jsBoolean(true));
    182 }
    183137
    184138}
  • trunk/Source/JavaScriptCore/runtime/SetPrototype.h

    r206525 r221110  
    5858};
    5959
    60 EncodedJSValue JSC_HOST_CALL privateFuncSetIterator(ExecState*);
    61 EncodedJSValue JSC_HOST_CALL privateFuncSetIteratorNext(ExecState*);
    62 
    6360} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r220777 r221110  
    7171#include "JSLock.h"
    7272#include "JSMap.h"
     73#include "JSMapIterator.h"
    7374#include "JSPromiseDeferred.h"
    7475#include "JSPropertyNameEnumerator.h"
    7576#include "JSScriptFetcher.h"
     77#include "JSSet.h"
     78#include "JSSetIterator.h"
    7679#include "JSSourceCode.h"
    7780#include "JSTemplateRegistryKey.h"
     
    276279    hashMapBucketSetStructure.set(*this, HashMapBucket<HashMapBucketDataKey>::createStructure(*this, 0, jsNull()));
    277280    hashMapBucketMapStructure.set(*this, HashMapBucket<HashMapBucketDataKeyValue>::createStructure(*this, 0, jsNull()));
     281    setIteratorStructure.set(*this, JSSetIterator::createStructure(*this, 0, jsNull()));
     282    mapIteratorStructure.set(*this, JSMapIterator::createStructure(*this, 0, jsNull()));
     283
     284    sentinelSetBucket.set(*this, JSSet::BucketType::createSentinel(*this));
     285    sentinelMapBucket.set(*this, JSMap::BucketType::createSentinel(*this));
    278286
    279287    nativeStdFunctionCellStructure.set(*this, NativeStdFunctionCell::createStructure(*this, 0, jsNull()));
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r220777 r221110  
    385385    Strong<Structure> hashMapBucketSetStructure;
    386386    Strong<Structure> hashMapBucketMapStructure;
     387    Strong<Structure> setIteratorStructure;
     388    Strong<Structure> mapIteratorStructure;
    387389
    388390    Strong<JSCell> emptyPropertyNameEnumerator;
     391    Strong<JSCell> sentinelSetBucket;
     392    Strong<JSCell> sentinelMapBucket;
    389393
    390394    std::unique_ptr<PromiseDeferredTimer> promiseDeferredTimer;
  • trunk/Source/WebCore/ChangeLog

    r221109 r221110  
     12017-08-23  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [JSC] Optimize Map iteration with intrinsic
     4        https://bugs.webkit.org/show_bug.cgi?id=174355
     5
     6        Reviewed by Saam Barati.
     7
     8        * bindings/js/SerializedScriptValue.cpp:
     9        (WebCore::CloneSerializer::serialize):
     10
    1112017-08-23  Alex Christensen  <achristensen@webkit.org>
    212
  • trunk/Source/WebCore/bindings/js/SerializedScriptValue.cpp

    r220949 r221110  
    15941594                if (!startMap(inMap))
    15951595                    break;
    1596                 JSMapIterator* iterator = JSMapIterator::create(vm, m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, IterateKeyValue);
     1596                JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure.get(), inMap, IterateKeyValue);
    15971597                m_gcBuffer.append(inMap);
    15981598                m_gcBuffer.append(iterator);
     
    16381638                if (!startSet(inSet))
    16391639                    break;
    1640                 JSSetIterator* iterator = JSSetIterator::create(vm, m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, IterateKey);
     1640                JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure.get(), inSet, IterateKey);
    16411641                m_gcBuffer.append(inSet);
    16421642                m_gcBuffer.append(iterator);
Note: See TracChangeset for help on using the changeset viewer.