[JSC] Introduce JSArrayIterator
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Jan 2020 06:07:29 +0000 (06:07 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Jan 2020 06:07:29 +0000 (06:07 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204043

Reviewed by Yusuke Suzuki.

JSTests:

* stress/array-iterator-materialize-at-osr-exit.js: Added.
(shouldBe):
(test):
* stress/array-iterator-materialize-one-path.js: Added.
(shouldBe):
(test):
* stress/array-iterator-materialize.js: Added.
(shouldBe):
(test):
* stress/array-iterator-sinking.js: Added.
(shouldBe):
(test):
* stress/array-iterators-next-error-messages.js:
(catch):
* stress/array-iterators-next-with-call.js:
* stress/for-of-iteration.js: Added.
(shouldBe):
(test1):
(test2):
(test3):
* stress/typedarray-functions-with-neutered.js:
(checkProtoFunc):

Source/JavaScriptCore:

This patch introduces JSArrayIterator that changes the iterator object
from a JSFinalObject to an InternalFieldsObject. This makes accessing it
much easier from C++ code and makes the iterator object smaller. It also
means that the JS code for the next function is much simpler and can *almost*
be inlined without shenanigans.

As part of this patch the keys/values/entries functions have been converted to
C++ with intrinsics since that's slightly more efficient in the LLInt/Baseline.

Lastly, this patch also add a custom ISOSubspace for JSArrayIterator objects.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* builtins/ArrayIteratorPrototype.js:
(next):
(globalPrivate.arrayIteratorNextHelper):
(globalPrivate.arrayIteratorValueNext): Deleted.
(globalPrivate.arrayIteratorKeyNext): Deleted.
(globalPrivate.arrayIteratorKeyValueNext): Deleted.
* builtins/ArrayPrototype.js:
(globalPrivate.ArrayIterator): Deleted.
(values): Deleted.
(keys): Deleted.
(entries): Deleted.
* builtins/TypedArrayPrototype.js:
(values): Deleted.
(keys): Deleted.
(entries): Deleted.
* bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
* bytecode/BytecodeIntrinsicRegistry.h:
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitIsArrayIterator):
* bytecompiler/NodesCodegen.cpp:
(JSC::arrayIteratorInternalFieldIndex):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_getArrayIteratorInternalField):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putArrayIteratorInternalField):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isGenerator): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isAsyncGenerator): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isJSArray): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isPromise): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isProxyObject): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isObject): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isMap): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isSet): Deleted.
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isUndefinedOrNull): Deleted.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGClobbersExitState.cpp:
(JSC::DFG::clobbersExitState):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGHeapLocation.h:
* dfg/DFGMayExit.cpp:
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToPhantomNewObject):
(JSC::DFG::Node::convertToPhantomNewArrayIterator):
(JSC::DFG::Node::convertToPhantomCreateActivation):
(JSC::DFG::Node::hasStructure):
(JSC::DFG::Node::hasObjectMaterializationData):
(JSC::DFG::Node::isPhantomAllocation):
* dfg/DFGNodeType.h:
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGPromotedHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGPromotedHeapLocation.h:
(JSC::DFG::PromotedLocationDescriptor::neededForMaterialization const):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCheckNeutered):
(JSC::DFG::SpeculativeJIT::compileToObjectOrCallObjectConstructor):
(JSC::DFG::SpeculativeJIT::compileNewInternalFieldObject):
(JSC::DFG::SpeculativeJIT::compileNewArrayIterator):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* dfg/DFGTypeCheckHoistingPhase.cpp:
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
* dfg/DFGValidate.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileToObjectOrCallObjectConstructor):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckArray):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckNeutered):
(JSC::FTL::DFG::LowerDFGToB3::compileNewInternalFieldObject):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayIterator):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateInternalFieldObject):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewInternalFieldObjectImpl):
(JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewInternalFieldObject):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationPopulateObjectInOSR):
(JSC::FTL::operationMaterializeObjectInOSR):
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::subtype):
(Inspector::JSInjectedScriptHost::getInternalProperties):
(Inspector::cloneArrayIteratorObject):
(Inspector::JSInjectedScriptHost::iteratorEntries):
* runtime/ArrayPrototype.cpp:
(JSC::ArrayPrototype::finishCreation):
(JSC::createArrayIteratorObject):
(JSC::arrayProtoFuncValues):
(JSC::arrayProtoFuncEntries):
(JSC::arrayProtoFuncKeys):
* runtime/CommonIdentifiers.h:
* runtime/Intrinsic.cpp:
(JSC::intrinsicName):
* runtime/Intrinsic.h:
* runtime/IterationKind.h:
(): Deleted.
* runtime/JSArrayIterator.cpp: Added.
(JSC::JSArrayIterator::create):
(JSC::JSArrayIterator::createWithInitialValues):
(JSC::JSArrayIterator::createStructure):
(JSC::JSArrayIterator::JSArrayIterator):
(JSC::JSArrayIterator::finishCreation):
(JSC::JSArrayIterator::visitChildren):
* runtime/JSArrayIterator.h: Added.
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::arrayIteratorPrototype const):
(JSC::JSGlobalObject::arrayIteratorStructure const):
* runtime/JSMapIterator.h:
* runtime/JSSetIterator.h:
* runtime/JSType.cpp:
(WTF::printInternal):
* runtime/JSType.h:
* runtime/JSTypedArrayViewPrototype.cpp:
(JSC::createTypedArrayIteratorObject):
(JSC::typedArrayViewProtoFuncValues):
(JSC::typedArrayProtoViewFuncEntries):
(JSC::typedArrayViewProtoFuncKeys):
(JSC::JSTypedArrayViewPrototype::finishCreation):
* runtime/VM.cpp:
* runtime/VM.h:

Source/WebCore:

JSDOMIterator should just use the JSC IterationKind enum. Also,
update other files for the enum member name changes.

* bindings/js/JSDOMIterator.h:
(WebCore::IteratorTraits>::asJS):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::serialize):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateIterableDefinition):
* bindings/scripts/test/JS/JSTestInterface.cpp:
(WebCore::jsTestInterfacePrototypeFunctionEntriesCaller):
(WebCore::jsTestInterfacePrototypeFunctionKeysCaller):
(WebCore::jsTestInterfacePrototypeFunctionValuesCaller):
* bindings/scripts/test/JS/JSTestIterable.cpp:
(WebCore::jsTestIterablePrototypeFunctionEntriesCaller):
(WebCore::jsTestIterablePrototypeFunctionKeysCaller):
(WebCore::jsTestIterablePrototypeFunctionValuesCaller):
* bindings/scripts/test/JS/JSTestNode.cpp:
(WebCore::jsTestNodePrototypeFunctionEntriesCaller):
(WebCore::jsTestNodePrototypeFunctionKeysCaller):
(WebCore::jsTestNodePrototypeFunctionValuesCaller):

LayoutTests:

Change the labels of iteration kinds to match what JS refers to them as.

* inspector/model/remote-object/iterator-expected.txt:
* inspector/model/remote-object/iterator-large-expected.txt:
* inspector/model/remote-object/iterators-mutated-expected.txt:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@254252 268f45cc-cd09-0410-ab3c-d52691b4dbfc

78 files changed:
JSTests/ChangeLog
JSTests/stress/array-iterator-materialize-at-osr-exit.js [new file with mode: 0644]
JSTests/stress/array-iterator-materialize-one-path.js [new file with mode: 0644]
JSTests/stress/array-iterator-materialize.js [new file with mode: 0644]
JSTests/stress/array-iterator-sinking.js [new file with mode: 0644]
JSTests/stress/array-iterators-next-error-messages.js
JSTests/stress/array-iterators-next-with-call.js
JSTests/stress/for-of-iteration.js [new file with mode: 0644]
JSTests/stress/typedarray-functions-with-neutered.js
LayoutTests/ChangeLog
LayoutTests/inspector/model/remote-object-get-properties-expected.txt
LayoutTests/inspector/model/remote-object/iterator-expected.txt
LayoutTests/inspector/model/remote-object/iterator-large-expected.txt
LayoutTests/inspector/model/remote-object/iterators-mutated-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js
Source/JavaScriptCore/builtins/ArrayPrototype.js
Source/JavaScriptCore/builtins/TypedArrayPrototype.js
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGHeapLocation.cpp
Source/JavaScriptCore/dfg/DFGHeapLocation.h
Source/JavaScriptCore/dfg/DFGMayExit.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp
Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp
Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLOperations.cpp
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/CommonIdentifiers.h
Source/JavaScriptCore/runtime/Intrinsic.cpp
Source/JavaScriptCore/runtime/Intrinsic.h
Source/JavaScriptCore/runtime/IterationKind.h
Source/JavaScriptCore/runtime/JSArrayIterator.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSArrayIterator.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSMapIterator.h
Source/JavaScriptCore/runtime/JSSetIterator.h
Source/JavaScriptCore/runtime/JSType.cpp
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSDOMIterator.h
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestIterable.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestNode.cpp

index ff60ea0..e0937d4 100644 (file)
@@ -1,3 +1,33 @@
+2020-01-08  Keith Miller  <keith_miller@apple.com>
+
+        [JSC] Introduce JSArrayIterator
+        https://bugs.webkit.org/show_bug.cgi?id=204043
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/array-iterator-materialize-at-osr-exit.js: Added.
+        (shouldBe):
+        (test):
+        * stress/array-iterator-materialize-one-path.js: Added.
+        (shouldBe):
+        (test):
+        * stress/array-iterator-materialize.js: Added.
+        (shouldBe):
+        (test):
+        * stress/array-iterator-sinking.js: Added.
+        (shouldBe):
+        (test):
+        * stress/array-iterators-next-error-messages.js:
+        (catch):
+        * stress/array-iterators-next-with-call.js:
+        * stress/for-of-iteration.js: Added.
+        (shouldBe):
+        (test1):
+        (test2):
+        (test3):
+        * stress/typedarray-functions-with-neutered.js:
+        (checkProtoFunc):
+
 2020-01-08  Saam Barati  <sbarati@apple.com>
 
         Unreviewed follow up on r254188. I accidentally included the same test
diff --git a/JSTests/stress/array-iterator-materialize-at-osr-exit.js b/JSTests/stress/array-iterator-materialize-at-osr-exit.js
new file mode 100644 (file)
index 0000000..4971e5c
--- /dev/null
@@ -0,0 +1,25 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+ function test(array, flag)
+{
+    var iterator = array.values();
+    iterator.next();
+    if (flag) {
+        OSRExit();
+        return iterator;
+    }
+    return iterator.next().done;
+}
+noInline(test);
+
+ var array = [0];
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(test(array, false), true);
+
+ var iterator = test(array, true);
+shouldBe(iterator.__proto__, [].values().__proto__);
+shouldBe(iterator.next().done, true);
\ No newline at end of file
diff --git a/JSTests/stress/array-iterator-materialize-one-path.js b/JSTests/stress/array-iterator-materialize-one-path.js
new file mode 100644 (file)
index 0000000..09408b6
--- /dev/null
@@ -0,0 +1,30 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+ function test(array, index, flag)
+{
+    var iterator = array.values();
+    var result = iterator.next().value;
+    if (index % 100 === 0)
+        iterator.next();
+    if (flag)
+        return iterator;
+    return result;
+}
+noInline(test);
+
+ var array = [1, 2, 3];
+var iterator = array.values();
+var ArrayIteratorPrototype = iterator.__proto__;
+for (var i = 0; i < 1e6; ++i) {
+    var flag = i % 10000 === 0;
+    var result = test(array, i, flag);
+    if (flag) {
+        shouldBe(typeof result, "object");
+        shouldBe(result.next().value, 3);
+        shouldBe(result.__proto__, ArrayIteratorPrototype);
+    } else
+        shouldBe(result, 1);
+}
\ No newline at end of file
diff --git a/JSTests/stress/array-iterator-materialize.js b/JSTests/stress/array-iterator-materialize.js
new file mode 100644 (file)
index 0000000..2a16930
--- /dev/null
@@ -0,0 +1,28 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+ function test(array, flag)
+{
+    var iterator = array.values();
+    var result = iterator.next().value;
+    if (flag)
+        return iterator;
+    return result;
+}
+noInline(test);
+
+ var array = [1, 2, 3];
+var iterator = array.values();
+var ArrayIteratorPrototype = iterator.__proto__;
+for (var i = 0; i < 1e6; ++i) {
+    var flag = i % 10000 === 0;
+    var result = test(array, flag);
+    if (flag) {
+        shouldBe(typeof result, "object");
+        shouldBe(result.next().value, 2);
+        shouldBe(result.__proto__, ArrayIteratorPrototype);
+    } else
+        shouldBe(result, 1);
+}
\ No newline at end of file
diff --git a/JSTests/stress/array-iterator-sinking.js b/JSTests/stress/array-iterator-sinking.js
new file mode 100644 (file)
index 0000000..e38438a
--- /dev/null
@@ -0,0 +1,15 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+ function test(array)
+{
+    var iterator = array.values();
+    return iterator.next().value;
+}
+noInline(test);
+
+ var array = [1, 2, 3];
+for (var i = 0; i < 1e6; ++i)
+    shouldBe(test(array), 1);
\ No newline at end of file
index c0316e6..3c297ef 100644 (file)
@@ -8,11 +8,11 @@ next = [].values().next;
 try {
     next.call(null);
 } catch(e) {
-    assert(e, "TypeError: %ArrayIteratorPrototype%.next requires that |this| not be null or undefined");
+    assert(e, "TypeError: %ArrayIteratorPrototype%.next requires that |this| be an Array Iterator instance");
 }
 
 try {
     next.call(undefined);
 } catch(e) {
-    assert(e, "TypeError: %ArrayIteratorPrototype%.next requires that |this| not be null or undefined");
+    assert(e, "TypeError: %ArrayIteratorPrototype%.next requires that |this| be an Array Iterator instance");
 }
index ab7f87d..2383b69 100644 (file)
@@ -84,12 +84,8 @@ for (var primitive of primitives) {
     if (!didThrow)
         throw "Error: no error thrown";
     var expectedMessage = 'TypeError: %ArrayIteratorPrototype%.next requires that |this| be an Array Iterator instance';
-    if (primitive === null)
-        expectedMessage = 'TypeError: %ArrayIteratorPrototype%.next requires that |this| not be null or undefined';
-    if (primitive === undefined)
-        expectedMessage = 'TypeError: %ArrayIteratorPrototype%.next requires that |this| not be null or undefined';
     if (String(didThrow) !== expectedMessage)
-        throw "Error: bad error thrown: " + didThrow;
+        throw new Error("bad error thrown: " + didThrow + " expected: " + expectedMessage);
 }
 
 var nonRelatedObjects = [
@@ -113,5 +109,5 @@ for (var object of nonRelatedObjects) {
     if (!didThrow)
         throw "Error: no error thrown";
     if (String(didThrow) !== 'TypeError: %ArrayIteratorPrototype%.next requires that |this| be an Array Iterator instance')
-        throw "Error: bad error thrown: " + didThrow;
+        throw new Error("bad error thrown: " + didThrow);
 }
diff --git a/JSTests/stress/for-of-iteration.js b/JSTests/stress/for-of-iteration.js
new file mode 100644 (file)
index 0000000..6c4eb63
--- /dev/null
@@ -0,0 +1,38 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+ function test1(array)
+{
+    var sum = 0;
+    for (var value of array)
+        sum += value;
+    return sum;
+}
+noInline(test1);
+
+ function test2(array)
+{
+    var sum = 0;
+    for (var value of array.keys())
+        sum += value;
+    return sum;
+}
+noInline(test2);
+
+ function test3(array)
+{
+    var sum = 0;
+    for (var [key, value] of array.entries())
+        sum += (value + key);
+    return sum;
+}
+noInline(test3);
+
+ var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+for (var i = 0; i < 1e5; ++i) {
+    shouldBe(test1(array), 55);
+    shouldBe(test2(array), 55);
+    shouldBe(test3(array), 110);
+}
\ No newline at end of file
index 0e66ec9..94fd915 100644 (file)
@@ -63,7 +63,7 @@ function checkProtoFunc(testArgs) {
     }
 
     if (!arrays.every(throwsCorrectError))
-        throw "bad" + testArgs.func.name;
+        throw new Error("bad " + testArgs.func.name);
 }
 
 function test() {
index 4c176d4..a900b3a 100644 (file)
@@ -1,3 +1,16 @@
+2020-01-08  Keith Miller  <keith_miller@apple.com>
+
+        [JSC] Introduce JSArrayIterator
+        https://bugs.webkit.org/show_bug.cgi?id=204043
+
+        Reviewed by Yusuke Suzuki.
+
+        Change the labels of iteration kinds to match what JS refers to them as.
+
+        * inspector/model/remote-object/iterator-expected.txt:
+        * inspector/model/remote-object/iterator-large-expected.txt:
+        * inspector/model/remote-object/iterators-mutated-expected.txt:
+
 2020-01-08  Ryan Haddad  <ryanhaddad@apple.com>
 
         few web-platform-tests are failing on iOS
index 8e0e2d7..ffbd105 100644 (file)
@@ -79,8 +79,8 @@ ALL PROPERTIES:
     reduce
     reduceRight
     map
-    entries
     keys
+    entries
     find
     findIndex
     includes
@@ -132,8 +132,8 @@ OWN PROPERTIES:
     reduce
     reduceRight
     map
-    entries
     keys
+    entries
     find
     findIndex
     includes
@@ -170,8 +170,8 @@ DISPLAYABLE PROPERTIES:
     reduce
     reduceRight
     map
-    entries
     keys
+    entries
     find
     findIndex
     includes
@@ -208,8 +208,8 @@ ALL PROPERTIES:
     reduce
     reduceRight
     map
-    entries
     keys
+    entries
     find
     findIndex
     includes
index dff4673..67113d9 100644 (file)
@@ -144,7 +144,7 @@ EXPRESSION: [][Symbol.iterator]()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -191,7 +191,7 @@ EXPRESSION: [1][Symbol.iterator]()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -234,7 +234,7 @@ EXPRESSION: [1, "two", 3, "four", 5, "size"][Symbol.iterator]()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -317,7 +317,7 @@ EXPRESSION: [1, "two", 3, "four", 5, "size"].keys()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key",
+        "_value": "keys",
         "_internal": true
       }
     ],
@@ -400,7 +400,7 @@ EXPRESSION: [1, "two", 3, "four", 5, "size"].entries()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key+value",
+        "_value": "entries",
         "_internal": true
       }
     ],
@@ -548,7 +548,7 @@ EXPRESSION: map = new Map; map.set(1, 2); map.set("key", "value"); map.values()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -601,7 +601,7 @@ EXPRESSION: map.keys()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key",
+        "_value": "keys",
         "_internal": true
       }
     ],
@@ -654,7 +654,7 @@ EXPRESSION: map.entries()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key+value",
+        "_value": "entries",
         "_internal": true
       }
     ],
@@ -733,7 +733,7 @@ EXPRESSION: set = new Set; for (var i = 0; i <= 100; i++) set.add(i); set.values
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -816,7 +816,7 @@ EXPRESSION: map.entries()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key+value",
+        "_value": "entries",
         "_internal": true
       }
     ],
@@ -915,7 +915,7 @@ EXPRESSION: x = undefined; (function() { x = arguments; })(1, "two"); x[Symbol.i
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -988,7 +988,7 @@ EXPRESSION: iter = [1, 2][Symbol.iterator](); iter["return"] = function(){}; ite
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
index 6dee12e..4bbefbe 100644 (file)
@@ -99,7 +99,7 @@ EXPRESSION: arr = new Int8Array(new ArrayBuffer(1000000)); arr[Symbol.iterator](
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -131,7 +131,7 @@ EXPRESSION: map = new Map; for (var i = 0; i < 1000000; i++) map.set(i, i); map[
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key+value",
+        "_value": "entries",
         "_internal": true
       }
     ],
@@ -279,7 +279,7 @@ EXPRESSION: set = new Set; for (var i = 0; i < 1000000; i++) set.add(i); set[Sym
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
index d72fcef..267a44a 100644 (file)
@@ -124,7 +124,7 @@ EXPRESSION: map = new Map; map.set(1, 2); map.set('key', 'value'); iter = map[Sy
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key+value",
+        "_value": "entries",
         "_internal": true
       }
     ],
@@ -203,7 +203,7 @@ EXPRESSION: iter.__proto__.next = function(){}; iter
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "key+value",
+        "_value": "entries",
         "_internal": true
       }
     ],
@@ -235,7 +235,7 @@ EXPRESSION: set = new Set; for (var i = 0; i <= 100; i++) set.add(i); iter = set
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -318,7 +318,7 @@ EXPRESSION: iter.__proto__.next = function(){}; iter
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -375,7 +375,7 @@ EXPRESSION: arrayIter = [1,2,3][Symbol.iterator]()
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -458,7 +458,7 @@ EXPRESSION: x = undefined; (function() { x = arguments; })(3, 'arg'); argumentsI
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -536,7 +536,7 @@ EXPRESSION: arrayIter.__proto__.next = function(){}; arrayIter
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
@@ -588,7 +588,7 @@ EXPRESSION: argumentsIter.__proto__.next = function(){}; argumentsIter
       {
         "_name": "kind",
         "_type": "string",
-        "_value": "value",
+        "_value": "values",
         "_internal": true
       }
     ],
index 2cc1b6d..41c8e6b 100644 (file)
@@ -1,3 +1,171 @@
+2020-01-08  Keith Miller  <keith_miller@apple.com>
+
+        [JSC] Introduce JSArrayIterator
+        https://bugs.webkit.org/show_bug.cgi?id=204043
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch introduces JSArrayIterator that changes the iterator object
+        from a JSFinalObject to an InternalFieldsObject. This makes accessing it
+        much easier from C++ code and makes the iterator object smaller. It also
+        means that the JS code for the next function is much simpler and can *almost*
+        be inlined without shenanigans.
+
+        As part of this patch the keys/values/entries functions have been converted to
+        C++ with intrinsics since that's slightly more efficient in the LLInt/Baseline.
+
+        Lastly, this patch also add a custom ISOSubspace for JSArrayIterator objects.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * builtins/ArrayIteratorPrototype.js:
+        (next):
+        (globalPrivate.arrayIteratorNextHelper):
+        (globalPrivate.arrayIteratorValueNext): Deleted.
+        (globalPrivate.arrayIteratorKeyNext): Deleted.
+        (globalPrivate.arrayIteratorKeyValueNext): Deleted.
+        * builtins/ArrayPrototype.js:
+        (globalPrivate.ArrayIterator): Deleted.
+        (values): Deleted.
+        (keys): Deleted.
+        (entries): Deleted.
+        * builtins/TypedArrayPrototype.js:
+        (values): Deleted.
+        (keys): Deleted.
+        (entries): Deleted.
+        * bytecode/BytecodeIntrinsicRegistry.cpp:
+        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitIsArrayIterator):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::arrayIteratorInternalFieldIndex):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_getArrayIteratorInternalField):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_putArrayIteratorInternalField):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isGenerator): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isAsyncGenerator): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isJSArray): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isPromise): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isProxyObject): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isObject): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isMap): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isSet): Deleted.
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isUndefinedOrNull): Deleted.
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGClobbersExitState.cpp:
+        (JSC::DFG::clobbersExitState):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGHeapLocation.h:
+        * dfg/DFGMayExit.cpp:
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToPhantomNewObject):
+        (JSC::DFG::Node::convertToPhantomNewArrayIterator):
+        (JSC::DFG::Node::convertToPhantomCreateActivation):
+        (JSC::DFG::Node::hasStructure):
+        (JSC::DFG::Node::hasObjectMaterializationData):
+        (JSC::DFG::Node::isPhantomAllocation):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGPromotedHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGPromotedHeapLocation.h:
+        (JSC::DFG::PromotedLocationDescriptor::neededForMaterialization const):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCheckNeutered):
+        (JSC::DFG::SpeculativeJIT::compileToObjectOrCallObjectConstructor):
+        (JSC::DFG::SpeculativeJIT::compileNewInternalFieldObject):
+        (JSC::DFG::SpeculativeJIT::compileNewArrayIterator):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStoreBarrierInsertionPhase.cpp:
+        * dfg/DFGTypeCheckHoistingPhase.cpp:
+        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
+        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
+        * dfg/DFGValidate.cpp:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileToObjectOrCallObjectConstructor):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckArray):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckNeutered):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewInternalFieldObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayIterator):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateInternalFieldObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewInternalFieldObjectImpl):
+        (JSC::FTL::DFG::LowerDFGToB3::compileMaterializeNewInternalFieldObject):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationPopulateObjectInOSR):
+        (JSC::FTL::operationMaterializeObjectInOSR):
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::subtype):
+        (Inspector::JSInjectedScriptHost::getInternalProperties):
+        (Inspector::cloneArrayIteratorObject):
+        (Inspector::JSInjectedScriptHost::iteratorEntries):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::ArrayPrototype::finishCreation):
+        (JSC::createArrayIteratorObject):
+        (JSC::arrayProtoFuncValues):
+        (JSC::arrayProtoFuncEntries):
+        (JSC::arrayProtoFuncKeys):
+        * runtime/CommonIdentifiers.h:
+        * runtime/Intrinsic.cpp:
+        (JSC::intrinsicName):
+        * runtime/Intrinsic.h:
+        * runtime/IterationKind.h:
+        (): Deleted.
+        * runtime/JSArrayIterator.cpp: Added.
+        (JSC::JSArrayIterator::create):
+        (JSC::JSArrayIterator::createWithInitialValues):
+        (JSC::JSArrayIterator::createStructure):
+        (JSC::JSArrayIterator::JSArrayIterator):
+        (JSC::JSArrayIterator::finishCreation):
+        (JSC::JSArrayIterator::visitChildren):
+        * runtime/JSArrayIterator.h: Added.
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::arrayIteratorPrototype const):
+        (JSC::JSGlobalObject::arrayIteratorStructure const):
+        * runtime/JSMapIterator.h:
+        * runtime/JSSetIterator.h:
+        * runtime/JSType.cpp:
+        (WTF::printInternal):
+        * runtime/JSType.h:
+        * runtime/JSTypedArrayViewPrototype.cpp:
+        (JSC::createTypedArrayIteratorObject):
+        (JSC::typedArrayViewProtoFuncValues):
+        (JSC::typedArrayProtoViewFuncEntries):
+        (JSC::typedArrayViewProtoFuncKeys):
+        (JSC::JSTypedArrayViewPrototype::finishCreation):
+        * runtime/VM.cpp:
+        * runtime/VM.h:
+
 2020-01-08  Michael Saboff  <msaboff@apple.com>
 
         Instruction.h: Multiplication result converted to larger type
index 2a15f2d..49e4481 100644 (file)
                539930C822AD3B9A0051CDE2 /* WeakObjectRefConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 539930C722AD3B9A0051CDE2 /* WeakObjectRefConstructor.h */; };
                539BFBAE22AD3C3A0023F4C0 /* WeakObjectRefPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 539BFBAD22AD3C3A0023F4C0 /* WeakObjectRefPrototype.h */; };
                539BFBB022AD3CDC0023F4C0 /* JSWeakObjectRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 539BFBAF22AD3CDC0023F4C0 /* JSWeakObjectRef.h */; };
+               539DD7F523C1BBB500905F13 /* JSArrayIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 539DD7F423C1BBA900905F13 /* JSArrayIterator.h */; };
                539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
                53B4BD121F68B32500D2BEA3 /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
                53B601EC2034B8C5006BE667 /* JSCast.h in Headers */ = {isa = PBXBuildFile; fileRef = 53B601EB2034B8C5006BE667 /* JSCast.h */; settings = {ATTRIBUTES = (Private, ); }; };
                539BFBAD22AD3C3A0023F4C0 /* WeakObjectRefPrototype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakObjectRefPrototype.h; sourceTree = "<group>"; };
                539BFBAF22AD3CDC0023F4C0 /* JSWeakObjectRef.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectRef.h; sourceTree = "<group>"; };
                539BFBB122AD3D8C0023F4C0 /* JSWeakObjectRef.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSWeakObjectRef.cpp; sourceTree = "<group>"; };
+               539DD7F323C1BBA900905F13 /* JSArrayIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSArrayIterator.cpp; sourceTree = "<group>"; };
+               539DD7F423C1BBA900905F13 /* JSArrayIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArrayIterator.h; sourceTree = "<group>"; };
                539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArrayInlines.h; sourceTree = "<group>"; };
                53B0BE331E561AC900A8FC29 /* GetterSetterAccessCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetterSetterAccessCase.cpp; sourceTree = "<group>"; };
                53B0BE351E561B0900A8FC29 /* ProxyableAccessCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyableAccessCase.cpp; sourceTree = "<group>"; };
                                0F2B66BB17B6B5AB00A7AE3F /* JSArrayBufferView.h */,
                                0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
                                539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */,
+                               539DD7F323C1BBA900905F13 /* JSArrayIterator.cpp */,
+                               539DD7F423C1BBA900905F13 /* JSArrayIterator.h */,
                                5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */,
                                5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */,
                                E39FEBE12339C5D400B40AB0 /* JSAsyncGenerator.cpp */,
                                0F2B66E917B6B5AB00A7AE3F /* JSArrayBufferView.h in Headers */,
                                0F2B66EA17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h in Headers */,
                                539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */,
+                               539DD7F523C1BBB500905F13 /* JSArrayIterator.h in Headers */,
                                5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */,
                                E39FEBE32339C5D900B40AB0 /* JSAsyncGenerator.h in Headers */,
                                8BC064891E1ABA6400B2B8CA /* JSAsyncGeneratorFunction.h in Headers */,
index ca284e5..d242ef6 100644 (file)
@@ -820,6 +820,7 @@ runtime/JSArrayBufferView.cpp
 runtime/JSAsyncFunction.cpp
 runtime/JSAsyncGenerator.cpp
 runtime/JSAsyncGeneratorFunction.cpp
+runtime/JSArrayIterator.cpp
 runtime/JSBigInt.cpp
 runtime/JSBoundFunction.cpp
 runtime/JSCConfig.cpp
index 94eb5f4..b416fbd 100644 (file)
@@ -28,81 +28,38 @@ function next()
 {
     "use strict";
 
-    if (@isUndefinedOrNull(this))
-        @throwTypeError("%ArrayIteratorPrototype%.next requires that |this| not be null or undefined");
-
-    let next = @getByIdDirectPrivate(this, "arrayIteratorNext");
-    if (next === @undefined)
+    if (!@isArrayIterator(this))
         @throwTypeError("%ArrayIteratorPrototype%.next requires that |this| be an Array Iterator instance");
 
-    return next.@call(this);
-}
-
-@globalPrivate
-function arrayIteratorValueNext()
-{
-    "use strict";
-    var done = true;
-    var value;
-
-    var array = @getByIdDirectPrivate(this, "iteratedObject");
-    if (!@getByIdDirectPrivate(this, "arrayIteratorIsDone")) {
-        var index = @getByIdDirectPrivate(this, "arrayIteratorNextIndex");
-        var length = array.length >>> 0;
-        if (index >= length)
-            @putByIdDirectPrivate(this, "arrayIteratorIsDone", true);
-        else {
-            @putByIdDirectPrivate(this, "arrayIteratorNextIndex", index + 1);
-            done = false;
-            value = array[index];
-        }
-    }
-
-    return { value, done };
-}
-
-@globalPrivate
-function arrayIteratorKeyNext()
-{
-    "use strict";
-    var done = true;
-    var value;
-
-    var array = @getByIdDirectPrivate(this, "iteratedObject");
-    if (!@getByIdDirectPrivate(this, "arrayIteratorIsDone")) {
-        var index = @getByIdDirectPrivate(this, "arrayIteratorNextIndex");
-        var length = array.length >>> 0;
-        if (index >= length)
-            @putByIdDirectPrivate(this, "arrayIteratorIsDone", true);
-        else {
-            @putByIdDirectPrivate(this, "arrayIteratorNextIndex", index + 1);
-            done = false;
-            value = index;
-        }
-    }
-
-    return { value, done };
+    var array = @getArrayIteratorInternalField(this, @arrayIteratorFieldIteratedObject);
+    var kind = @getArrayIteratorInternalField(this, @arrayIteratorFieldKind);
+    return @arrayIteratorNextHelper.@call(this, array, kind);
 }
 
+// FIXME: We have to have this because we can't implement this all as one function and meet our inlining heuristics.
+// Collectively, next and this have ~130 bytes of bytecodes but our limit is 120.
 @globalPrivate
-function arrayIteratorKeyValueNext()
+function arrayIteratorNextHelper(array, kind)
 {
     "use strict";
     var done = true;
     var value;
 
-    var array = @getByIdDirectPrivate(this, "iteratedObject");
-    if (!@getByIdDirectPrivate(this, "arrayIteratorIsDone")) {
-        var index = @getByIdDirectPrivate(this, "arrayIteratorNextIndex");
+    if (!@getArrayIteratorInternalField(this, @arrayIteratorFieldIsDone)) {
+        var index = @getArrayIteratorInternalField(this, @arrayIteratorFieldIndex);
         var length = array.length >>> 0;
-        if (index >= length)
-            @putByIdDirectPrivate(this, "arrayIteratorIsDone", true);
-        else {
-            @putByIdDirectPrivate(this, "arrayIteratorNextIndex", index + 1);
+        if (index < length) {
+            @putArrayIteratorInternalField(this, @arrayIteratorFieldIndex, index + 1);
             done = false;
-            value = [ index, array[index] ];
+            if (kind === @iterationKindKey)
+                value = index;
+            else { 
+                value = array[index];
+                value = kind === @iterationKindValue ? value : [index, value];
+            }
         }
     }
+    @putArrayIteratorInternalField(this, @arrayIteratorFieldIsDone, done);
 
     return { value, done };
 }
index bf9b741..d90c7a1 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-@constructor
-@globalPrivate
-function ArrayIterator(iteratedObject, kind, iterationFunction)
-{
-    "use strict";
-
-    @putByIdDirectPrivate(this, "iteratedObject", iteratedObject);
-    @putByIdDirectPrivate(this, "arrayIteratorKind", kind);
-    @putByIdDirectPrivate(this, "arrayIteratorNextIndex", 0);
-    @putByIdDirectPrivate(this, "arrayIteratorNext", iterationFunction);
-    @putByIdDirectPrivate(this, "arrayIteratorIsDone", false);
-}
-
-function values()
-{
-    "use strict";
-
-    return new @ArrayIterator(@toObject(this, "Array.prototype.values requires that |this| not be null or undefined"), "value", @arrayIteratorValueNext);
-}
-
-function keys()
-{
-    "use strict";
-
-    return new @ArrayIterator(@toObject(this, "Array.prototype.keys requires that |this| not be null or undefined"), "key", @arrayIteratorKeyNext);
-}
-
-function entries()
-{
-    "use strict";
-
-    return new @ArrayIterator(@toObject(this, "Array.prototype.entries requires that |this| not be null or undefined"), "key+value", @arrayIteratorKeyValueNext);
-}
-
 function reduce(callback /*, initialValue */)
 {
     "use strict";
index bf86432..83d7511 100644 (file)
@@ -68,27 +68,6 @@ function typedArrayClampArgumentToStartOrEnd(value, length, undefinedValue)
     return int > length ? length : int;
 }
 
-function values()
-{
-    "use strict";
-    @typedArrayLength(this);
-    return new @ArrayIterator(this, "value", @arrayIteratorValueNext);
-}
-
-function keys()
-{
-    "use strict";
-    @typedArrayLength(this);
-    return new @ArrayIterator(this, "key", @arrayIteratorKeyNext);
-}
-
-function entries()
-{
-    "use strict";
-    @typedArrayLength(this);
-    return new @ArrayIterator(this, "key+value", @arrayIteratorKeyValueNext);
-}
-
 function every(callback /*, thisArg */)
 {
     "use strict";
index 99f3ebb..00f1379 100644 (file)
@@ -31,6 +31,7 @@
 #include "BuiltinNames.h"
 #include "BytecodeGenerator.h"
 #include "IterationKind.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncGenerator.h"
 #include "JSCInlines.h"
 #include "JSGenerator.h"
@@ -55,9 +56,9 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
 
     m_undefined.set(m_vm, jsUndefined());
     m_Infinity.set(m_vm, jsDoubleNumber(std::numeric_limits<double>::infinity()));
-    m_iterationKindKey.set(m_vm, jsNumber(IterateKey));
-    m_iterationKindValue.set(m_vm, jsNumber(IterateValue));
-    m_iterationKindKeyValue.set(m_vm, jsNumber(IterateKeyValue));
+    m_iterationKindKey.set(m_vm, jsNumber(static_cast<unsigned>(IterationKind::Keys)));
+    m_iterationKindValue.set(m_vm, jsNumber(static_cast<unsigned>(IterationKind::Values)));
+    m_iterationKindKeyValue.set(m_vm, jsNumber(static_cast<unsigned>(IterationKind::Entries)));
     m_MAX_ARRAY_INDEX.set(m_vm, jsNumber(MAX_ARRAY_INDEX));
     m_MAX_STRING_LENGTH.set(m_vm, jsNumber(JSString::MaxLength));
     m_MAX_SAFE_INTEGER.set(m_vm, jsDoubleNumber(maxSafeInteger()));
@@ -87,6 +88,10 @@ BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry(VM& vm)
     m_GeneratorResumeModeReturn.set(m_vm, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorResumeMode::ReturnMode)));
     m_GeneratorStateCompleted.set(m_vm, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorState::Completed)));
     m_GeneratorStateExecuting.set(m_vm, jsNumber(static_cast<int32_t>(JSGenerator::GeneratorState::Executing)));
+    m_arrayIteratorFieldIteratedObject.set(m_vm, jsNumber(static_cast<int32_t>(JSArrayIterator::Field::IteratedObject)));
+    m_arrayIteratorFieldIndex.set(m_vm, jsNumber(static_cast<int32_t>(JSArrayIterator::Field::Index)));
+    m_arrayIteratorFieldIsDone.set(m_vm, jsNumber(static_cast<int32_t>(JSArrayIterator::Field::IsDone)));
+    m_arrayIteratorFieldKind.set(m_vm, jsNumber(static_cast<int32_t>(JSArrayIterator::Field::Kind)));
     m_asyncGeneratorFieldSuspendReason.set(m_vm, jsNumber(static_cast<unsigned>(JSAsyncGenerator::Field::SuspendReason)));
     m_asyncGeneratorFieldQueueFirst.set(m_vm, jsNumber(static_cast<unsigned>(JSAsyncGenerator::Field::QueueFirst)));
     m_asyncGeneratorFieldQueueLast.set(m_vm, jsNumber(static_cast<unsigned>(JSAsyncGenerator::Field::QueueLast)));
index 849e34b..b5c5f51 100644 (file)
@@ -45,6 +45,7 @@ enum class LinkTimeConstant : int32_t;
     macro(getPromiseInternalField) \
     macro(getGeneratorInternalField) \
     macro(getAsyncGeneratorInternalField) \
+    macro(getArrayIteratorInternalField) \
     macro(idWithProfile) \
     macro(isObject) \
     macro(isJSArray) \
@@ -56,6 +57,7 @@ enum class LinkTimeConstant : int32_t;
     macro(isRegExpObject) \
     macro(isMap) \
     macro(isSet) \
+    macro(isArrayIterator) \
     macro(isUndefinedOrNull) \
     macro(tailCallForwardArguments) \
     macro(throwTypeError) \
@@ -68,6 +70,7 @@ enum class LinkTimeConstant : int32_t;
     macro(putPromiseInternalField) \
     macro(putGeneratorInternalField) \
     macro(putAsyncGeneratorInternalField) \
+    macro(putArrayIteratorInternalField) \
     macro(toNumber) \
     macro(toString) \
     macro(toObject) \
@@ -115,6 +118,10 @@ enum class LinkTimeConstant : int32_t;
     macro(GeneratorResumeModeReturn) \
     macro(GeneratorStateCompleted) \
     macro(GeneratorStateExecuting) \
+    macro(arrayIteratorFieldIndex) \
+    macro(arrayIteratorFieldIsDone) \
+    macro(arrayIteratorFieldIteratedObject) \
+    macro(arrayIteratorFieldKind) \
     macro(asyncGeneratorFieldSuspendReason) \
     macro(asyncGeneratorFieldQueueFirst) \
     macro(asyncGeneratorFieldQueueLast) \
index bc5bbae..62d5cbb 100644 (file)
@@ -878,6 +878,7 @@ namespace JSC {
         RegisterID* emitIsRegExpObject(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, RegExpObjectType); }
         RegisterID* emitIsMap(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSMapType); }
         RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); }
+        RegisterID* emitIsArrayIterator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSArrayIteratorType); }
         RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsNumber(RegisterID* dst, RegisterID* src);
         RegisterID* emitIsUndefined(RegisterID* dst, RegisterID* src);
index f4a1efe..8c82f57 100644 (file)
@@ -33,6 +33,7 @@
 #include "BytecodeGeneratorBaseInlines.h"
 #include "CallFrame.h"
 #include "JIT.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncGenerator.h"
 #include "JSCInlines.h"
 #include "JSFunction.h"
@@ -1063,6 +1064,21 @@ static JSAsyncGenerator::Field asyncGeneratorInternalFieldIndex(BytecodeIntrinsi
     return JSAsyncGenerator::Field::State;
 }
 
+static JSArrayIterator::Field arrayIteratorInternalFieldIndex(BytecodeIntrinsicNode* node)
+{
+    ASSERT(node->entry().type() == BytecodeIntrinsicRegistry::Type::Emitter);
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_arrayIteratorFieldIndex)
+        return JSArrayIterator::Field::Index;
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_arrayIteratorFieldIsDone)
+        return JSArrayIterator::Field::IsDone;
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_arrayIteratorFieldIteratedObject)
+        return JSArrayIterator::Field::IteratedObject;
+    if (node->entry().emitter() == &BytecodeIntrinsicNode::emit_intrinsic_arrayIteratorFieldKind)
+        return JSArrayIterator::Field::Kind;
+    RELEASE_ASSERT_NOT_REACHED();
+    return JSArrayIterator::Field::Index;
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getPromiseInternalField(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;
@@ -1102,6 +1118,19 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getAsyncGeneratorInternalField
     return generator.emitGetInternalField(generator.finalDestination(dst), base.get(), index);
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getArrayIteratorInternalField(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> base = generator.emitNode(node);
+    node = node->m_next;
+    RELEASE_ASSERT(node->m_expr->isBytecodeIntrinsicNode());
+    unsigned index = static_cast<unsigned>(arrayIteratorInternalFieldIndex(static_cast<BytecodeIntrinsicNode*>(node->m_expr)));
+    ASSERT(index < JSArrayIterator::numberOfInternalFields);
+    ASSERT(!node->m_next);
+
+    return generator.emitGetInternalField(generator.finalDestination(dst), base.get(), index);
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_argument(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;
@@ -1219,6 +1248,22 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putAsyncGeneratorInternalField
     return generator.move(dst, generator.emitPutInternalField(base.get(), index, value.get()));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putArrayIteratorInternalField(BytecodeGenerator& generator, RegisterID* dst)
+{
+    ArgumentListNode* node = m_args->m_listNode;
+    RefPtr<RegisterID> base = generator.emitNode(node);
+    node = node->m_next;
+    RELEASE_ASSERT(node->m_expr->isBytecodeIntrinsicNode());
+    unsigned index = static_cast<unsigned>(arrayIteratorInternalFieldIndex(static_cast<BytecodeIntrinsicNode*>(node->m_expr)));
+    ASSERT(index < JSArrayIterator::numberOfInternalFields);
+    node = node->m_next;
+    RefPtr<RegisterID> value = generator.emitNode(node);
+
+    ASSERT(!node->m_next);
+
+    return generator.move(dst, generator.emitPutInternalField(base.get(), index, value.get()));
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_tailCallForwardArguments(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;
@@ -1333,104 +1378,29 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_idWithProfile(BytecodeGenerato
     return generator.move(dst, generator.emitIdWithProfile(idValue.get(), speculation));
 }
 
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isGenerator(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsGenerator(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isAsyncGenerator(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsAsyncGenerator(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isJSArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsJSArray(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isPromise(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsPromise(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isProxyObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsProxyObject(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isRegExpObject(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsRegExpObject(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isObject(BytecodeGenerator& generator, RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsObject(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isDerivedArray(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsDerivedArray(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isMap(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsMap(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isSet(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsSet(generator.tempDestination(dst), src.get()));
-}
-
-RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isUndefinedOrNull(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
-{
-    ArgumentListNode* node = m_args->m_listNode;
-    RefPtr<RegisterID> src = generator.emitNode(node);
-    ASSERT(!node->m_next);
-
-    return generator.move(dst, generator.emitIsUndefinedOrNull(generator.tempDestination(dst), src.get()));
-}
+#define CREATE_INTRINSIC_FOR_BRAND_CHECK(lowerName, upperName) \
+    RegisterID* BytecodeIntrinsicNode::emit_intrinsic_##lowerName(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst) \
+    {                                                                                                                      \
+        ArgumentListNode* node = m_args->m_listNode;                                                                       \
+        RefPtr<RegisterID> src = generator.emitNode(node);                                                                 \
+        ASSERT(!node->m_next);                                                                                             \
+        return generator.move(dst, generator.emit##upperName(generator.tempDestination(dst), src.get()));                  \
+    }
+
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isObject, IsObject)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isJSArray, IsJSArray)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isProxyObject, IsProxyObject)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isDerivedArray, IsDerivedArray)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isGenerator, IsGenerator)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isAsyncGenerator, IsAsyncGenerator)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isPromise, IsPromise)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isRegExpObject, IsRegExpObject)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isMap, IsMap)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isSet, IsSet)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isArrayIterator, IsArrayIterator)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isUndefinedOrNull, IsUndefinedOrNull)
+
+#undef CREATE_INTRINSIC_FOR_BRAND_CHECK
 
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_newArrayWithSize(JSC::BytecodeGenerator& generator, JSC::RegisterID* dst)
 {
index 23ec63a..b42b0cf 100644 (file)
@@ -1466,7 +1466,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     bool ok = true;
                     Optional<bool> result;
                     child.m_structure.forEach(
-                        [&](RegisteredStructure structure) {
+                        [&] (RegisteredStructure structure) {
                             bool matched = structure->typeInfo().type() == node->queriedType();
                             if (!result)
                                 result = matched;
@@ -1488,7 +1488,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     break;
             }
         }
-        
+
         // FIXME: This code should really use AbstractValue::isType() and
         // AbstractValue::couldBeType().
         // https://bugs.webkit.org/show_bug.cgi?id=146870
@@ -2844,17 +2844,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
 
     case NewPromise:
-        ASSERT(!!node->structure().get());
-        setForNode(node, node->structure());
-        break;
-
     case NewGenerator:
-    case NewAsyncGenerator:
-        ASSERT(!!node->structure().get());
-        setForNode(node, node->structure());
-        break;
-        
+    case NewAsyncGenerator:    
+    case NewArrayIterator:
     case NewObject:
+    case MaterializeNewInternalFieldObject:
         ASSERT(!!node->structure().get());
         setForNode(node, node->structure());
         break;
@@ -2936,6 +2930,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case PhantomSpread:
     case PhantomNewArrayWithSpread:
     case PhantomNewArrayBuffer:
+    case PhantomNewArrayIterator:
     case PhantomNewRegexp:
     case BottomValue: {
         clearForNode(node);
@@ -3364,6 +3359,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         setTypeForNode(node, signature->result);
         break;
     }
+
+    case CheckNeutered: {
+        break;
+    }
+
     case CheckArray: {
         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
             m_state.setShouldTryConstantFolding(true);
@@ -3423,6 +3423,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
         break;
     }
+
     case Arrayify: {
         if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
             didFoldClobberStructures();
index ebb46da..7215965 100644 (file)
@@ -52,6 +52,7 @@
 #include "Heap.h"
 #include "InByIdStatus.h"
 #include "InstanceOfStatus.h"
+#include "JSArrayIterator.h"
 #include "JSCInlines.h"
 #include "JSImmutableButterfly.h"
 #include "JSInternalPromise.h"
@@ -2360,6 +2361,63 @@ bool ByteCodeParser::handleIntrinsicCall(Node* callee, VirtualRegister result, I
             setResult(addToGraph(ArithPow, get(xOperand), get(yOperand)));
             return true;
         }
+
+        case TypedArrayEntriesIntrinsic:
+        case TypedArrayKeysIntrinsic:
+        case TypedArrayValuesIntrinsic: {
+            if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType)
+                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
+                return false;
+
+            ArrayMode mode = getArrayMode(Array::Read);
+            if (!mode.isSomeTypedArrayView())
+                return false;
+
+            addToGraph(CheckArray, OpInfo(mode.asWord()), get(virtualRegisterForArgument(0, registerOffset)));
+            addToGraph(CheckNeutered, get(virtualRegisterForArgument(0, registerOffset)));
+            FALLTHROUGH;
+        }
+
+        case ArrayEntriesIntrinsic:
+        case ArrayKeysIntrinsic:
+        case ArrayValuesIntrinsic: {
+            insertChecks();
+
+            IterationKind kind;
+            switch (intrinsic) {
+            case ArrayValuesIntrinsic:
+            case TypedArrayValuesIntrinsic:
+                kind = IterationKind::Values;
+                break;
+            case ArrayKeysIntrinsic:
+            case TypedArrayKeysIntrinsic:
+                kind = IterationKind::Keys;
+                break;
+            case ArrayEntriesIntrinsic:
+            case TypedArrayEntriesIntrinsic:
+                kind = IterationKind::Entries;
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+                break;
+            }
+
+            // Add the constant before exit becomes invalid because we may want to insert (redundant) checks on it in Fixup.
+            Node* kindNode = jsConstant(jsNumber(static_cast<uint32_t>(kind)));
+
+            // We don't have an existing error string.
+            unsigned errorStringIndex = UINT32_MAX;
+            Node* object = addToGraph(ToObject, OpInfo(errorStringIndex), OpInfo(SpecNone), get(virtualRegisterForArgument(0, registerOffset)));
+
+            JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
+            Node* iterator = addToGraph(NewArrayIterator, OpInfo(m_graph.registerStructure(globalObject->arrayIteratorStructure())));
+
+            addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSArrayIterator::Field::IteratedObject)), iterator, object);
+            addToGraph(PutInternalField, OpInfo(static_cast<uint32_t>(JSArrayIterator::Field::Kind)), iterator, kindNode);
+
+            setResult(iterator);
+            return true;
+        }
             
         case ArrayPushIntrinsic: {
             if (static_cast<unsigned>(argumentCountIncludingThis) >= MIN_SPARSE_ARRAY_INDEX)
index d6a4635..d4ec7b7 100644 (file)
@@ -1101,6 +1101,10 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
         read(JSCell_structureID);
         return;
 
+    case CheckNeutered:
+        read(MiscFields);
+        return; 
+        
     case CheckTypeInfoFlags:
         read(JSCell_typeInfoFlags);
         def(HeapLocation(CheckTypeInfoFlagsLoc, JSCell_typeInfoFlags, node->child1()), LazyNode(node));
@@ -1348,14 +1352,14 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case GetInternalField: {
         AbstractHeap heap(JSPromiseFields, node->internalFieldIndex());
         read(heap);
-        def(HeapLocation(PromiseInternalFieldLoc, heap, node->child1()), LazyNode(node));
+        def(HeapLocation(InternalFieldObjectLoc, heap, node->child1()), LazyNode(node));
         return;
     }
 
     case PutInternalField: {
         AbstractHeap heap(JSPromiseFields, node->internalFieldIndex());
         write(heap);
-        def(HeapLocation(PromiseInternalFieldLoc, heap, node->child1()), LazyNode(node->child2().node()));
+        def(HeapLocation(InternalFieldObjectLoc, heap, node->child1()), LazyNode(node->child2().node()));
         return;
     }
 
@@ -1595,6 +1599,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case NewPromise:
     case NewGenerator:
     case NewAsyncGenerator:
+    case NewArrayIterator:
     case NewRegexp:
     case NewSymbol:
     case NewStringObject:
@@ -1604,6 +1609,8 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case PhantomNewGeneratorFunction:
     case PhantomNewAsyncFunction:
     case PhantomNewAsyncGeneratorFunction:
+    case PhantomNewArrayIterator:
+    case MaterializeNewInternalFieldObject:
     case PhantomCreateActivation:
     case MaterializeCreateActivation:
     case PhantomNewRegexp:
index 0f81a8e..ee98fac 100644 (file)
@@ -60,6 +60,7 @@ bool clobbersExitState(Graph& graph, Node* node)
     case NewPromise:
     case NewGenerator:
     case NewAsyncGenerator:
+    case NewArrayIterator:
     case NewRegexp:
     case NewSymbol:
     case NewStringObject:
@@ -69,6 +70,8 @@ bool clobbersExitState(Graph& graph, Node* node)
     case PhantomNewGeneratorFunction:
     case PhantomNewAsyncGeneratorFunction:
     case PhantomNewAsyncFunction:
+    case PhantomNewArrayIterator:
+    case MaterializeNewInternalFieldObject:
     case PhantomCreateActivation:
     case MaterializeCreateActivation:
     case PhantomNewRegexp:
index b8af520..6d447d3 100644 (file)
@@ -1074,6 +1074,7 @@ private:
             case PhantomNewGeneratorFunction:
             case PhantomNewAsyncGeneratorFunction:
             case PhantomNewAsyncFunction:
+            case PhantomNewArrayIterator:
             case PhantomCreateActivation:
             case PhantomDirectArguments:
             case PhantomClonedArguments:
index 6eb8402..1f30dff 100644 (file)
@@ -117,6 +117,7 @@ bool doesGC(Graph& graph, Node* node)
     case GetButterfly:
     case CheckSubClass:
     case CheckArray:
+    case CheckNeutered:
     case GetScope:
     case SkipScope:
     case GetGlobalObject:
@@ -208,6 +209,7 @@ bool doesGC(Graph& graph, Node* node)
     case PhantomNewGeneratorFunction:
     case PhantomNewAsyncFunction:
     case PhantomNewAsyncGeneratorFunction:
+    case PhantomNewArrayIterator:
     case PhantomCreateActivation:
     case PhantomDirectArguments:
     case PhantomCreateRest:
@@ -352,6 +354,7 @@ bool doesGC(Graph& graph, Node* node)
     case NewAsyncGenerator:
     case NewArray:
     case NewArrayWithSpread:
+    case NewArrayIterator:
     case Spread:
     case NewArrayWithSize:
     case NewArrayBuffer:
@@ -370,6 +373,7 @@ bool doesGC(Graph& graph, Node* node)
     case GetEnumeratorGenericPname:
     case ToIndexString:
     case MaterializeNewObject:
+    case MaterializeNewInternalFieldObject:
     case MaterializeCreateActivation:
     case SetFunctionName:
     case StrCat:
index dce8e3f..922d35b 100644 (file)
@@ -1869,6 +1869,12 @@ private:
             break;
         }
 
+        case CheckNeutered:
+        case CheckArray: {
+            fixEdge<CellUse>(node->child1());
+            break;
+        }
+
         case Phi:
         case Upsilon:
         case EntrySwitch:
@@ -1877,7 +1883,6 @@ private:
         case CheckTierUpInLoop:
         case CheckTierUpAtReturn:
         case CheckTierUpAndOSREnter:
-        case CheckArray:
         case CheckInBounds:
         case ConstantStoragePointer:
         case DoubleAsInt32:
@@ -1893,6 +1898,7 @@ private:
         case PhantomNewGeneratorFunction:
         case PhantomNewAsyncGeneratorFunction:
         case PhantomNewAsyncFunction:
+        case PhantomNewArrayIterator:
         case PhantomCreateActivation:
         case PhantomDirectArguments:
         case PhantomCreateRest:
@@ -1909,6 +1915,7 @@ private:
         case CheckStructureOrEmpty:
         case MaterializeNewObject:
         case MaterializeCreateActivation:
+        case MaterializeNewInternalFieldObject:
         case PutStack:
         case KillStack:
         case GetStack:
@@ -2476,6 +2483,7 @@ private:
         case NewPromise:
         case NewGenerator:
         case NewAsyncGenerator:
+        case NewArrayIterator:
         case NewRegexp:
         case DeleteById:
         case DeleteByVal:
index 418696a..b9f8572 100644 (file)
@@ -243,7 +243,7 @@ void Graph::dump(PrintStream& out, const char* prefixStr, Node* node, DumpContex
         out.print(comma, node->argumentIndex());
     if (node->hasRegisterPointer())
         out.print(comma, "global", "(", RawPointer(node->variablePointer()), ")");
-    if (node->hasIdentifier())
+    if (node->hasIdentifier() && node->identifierNumber() != UINT32_MAX)
         out.print(comma, "id", node->identifierNumber(), "{", identifiers()[node->identifierNumber()], "}");
     if (node->hasPromotedLocationDescriptor())
         out.print(comma, node->promotedLocationDescriptor());
index c2b96b5..fcb0f86 100644 (file)
@@ -196,8 +196,8 @@ void printInternal(PrintStream& out, LocationKind kind)
         out.print("WeakMapGetLoc");
         return;
 
-    case PromiseInternalFieldLoc:
-        out.print("PromiseInternalFieldLoc");
+    case InternalFieldObjectLoc:
+        out.print("InternalFieldObjectLoc");
         return;
 
     case DOMStateLoc:
index a8e7381..b78f0c8 100644 (file)
@@ -71,7 +71,7 @@ enum LocationKind {
     MapBucketKeyLoc,
     MapBucketNextLoc,
     WeakMapGetLoc,
-    PromiseInternalFieldLoc,
+    InternalFieldObjectLoc,
     DOMStateLoc,
 };
 
index ae224cc..b928810 100644 (file)
@@ -71,6 +71,7 @@ ExitMode mayExitImpl(Graph& graph, Node* node, StateType& state)
     case BottomValue:
     case PutHint:
     case PhantomNewObject:
+    case PhantomNewArrayIterator:
     case PutStack:
     case KillStack:
     case GetStack:
@@ -121,12 +122,14 @@ ExitMode mayExitImpl(Graph& graph, Node* node, StateType& state)
     case CreateActivation:
     case MaterializeCreateActivation:
     case MaterializeNewObject:
+    case MaterializeNewInternalFieldObject:
     case NewFunction:
     case NewGeneratorFunction:
     case NewAsyncFunction:
     case NewAsyncGeneratorFunction:
     case NewStringObject:
     case NewSymbol:
+    case NewArrayIterator:
     case NewRegexp:
     case ToNumber:
     case ToNumeric:
index 7f6e595..517af10 100644 (file)
@@ -614,7 +614,7 @@ public:
     
     void convertToPhantomNewObject()
     {
-        ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
+        ASSERT(m_op == NewObject);
         m_op = PhantomNewObject;
         m_flags &= ~NodeHasVarArgs;
         m_flags |= NodeMustGenerate;
@@ -643,6 +643,17 @@ public:
         children = AdjacencyList();
     }
 
+    void convertToPhantomNewArrayIterator()
+    {
+        ASSERT(m_op == NewArrayIterator);
+        m_op = PhantomNewArrayIterator;
+        m_flags &= ~NodeHasVarArgs;
+        m_flags |= NodeMustGenerate;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
+        children = AdjacencyList();
+    }
+
     void convertToPhantomNewAsyncFunction()
     {
         ASSERT(m_op == NewAsyncFunction);
@@ -665,7 +676,7 @@ public:
     
     void convertToPhantomCreateActivation()
     {
-        ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
+        ASSERT(m_op == CreateActivation);
         m_op = PhantomCreateActivation;
         m_flags &= ~NodeHasVarArgs;
         m_flags |= NodeMustGenerate;
@@ -1939,10 +1950,12 @@ public:
     {
         switch (op()) {
         case ArrayifyToStructure:
+        case MaterializeNewInternalFieldObject:
         case NewObject:
         case NewPromise:
         case NewGenerator:
         case NewAsyncGenerator:
+        case NewArrayIterator:
         case NewStringObject:
             return true;
         default:
@@ -2011,6 +2024,7 @@ public:
     {
         switch (op()) {
         case MaterializeNewObject:
+        case MaterializeNewInternalFieldObject:
         case MaterializeCreateActivation:
             return true;
 
@@ -2107,6 +2121,7 @@ public:
         case PhantomNewGeneratorFunction:
         case PhantomNewAsyncFunction:
         case PhantomNewAsyncGeneratorFunction:
+        case PhantomNewArrayIterator:
         case PhantomCreateActivation:
         case PhantomNewRegexp:
             return true;
index c3868c0..7c6d1b2 100644 (file)
@@ -238,6 +238,8 @@ namespace JSC { namespace DFG {
     macro(GetButterfly, NodeResultStorage) \
     macro(NukeStructureAndSetButterfly, NodeMustGenerate) \
     macro(CheckArray, NodeMustGenerate) \
+    /* This checks if the edge is a typed array and if it is neutered. */ \
+    macro(CheckNeutered, NodeMustGenerate) \
     macro(Arrayify, NodeMustGenerate) \
     macro(ArrayifyToStructure, NodeMustGenerate) \
     macro(GetIndexedPropertyStorage, NodeResultStorage) \
@@ -355,6 +357,7 @@ namespace JSC { namespace DFG {
     macro(NewArrayWithSpread, NodeResultJS | NodeHasVarArgs) \
     macro(NewArrayWithSize, NodeResultJS | NodeMustGenerate) \
     macro(NewArrayBuffer, NodeResultJS) \
+    macro(NewArrayIterator, NodeResultJS) \
     macro(NewTypedArray, NodeResultJS | NodeMustGenerate) \
     macro(NewRegexp, NodeResultJS) \
     macro(NewSymbol, NodeResultJS) \
@@ -373,6 +376,8 @@ namespace JSC { namespace DFG {
     macro(PhantomNewGeneratorFunction, NodeResultJS | NodeMustGenerate) \
     macro(PhantomNewAsyncFunction, NodeResultJS | NodeMustGenerate) \
     macro(PhantomNewAsyncGeneratorFunction, NodeResultJS | NodeMustGenerate) \
+    macro(PhantomNewArrayIterator, NodeResultJS | NodeMustGenerate) \
+    macro(MaterializeNewInternalFieldObject, NodeResultJS | NodeHasVarArgs) \
     macro(PhantomCreateActivation, NodeResultJS | NodeMustGenerate) \
     macro(MaterializeCreateActivation, NodeResultJS | NodeHasVarArgs) \
     macro(PhantomNewRegexp, NodeResultJS | NodeMustGenerate) \
index 335034b..6379bb5 100644 (file)
@@ -40,6 +40,7 @@
 #include "DFGPromotedHeapLocation.h"
 #include "DFGSSACalculator.h"
 #include "DFGValidate.h"
+#include "JSArrayIterator.h"
 #include "JSCInlines.h"
 #include <wtf/StdList.h>
 
@@ -140,7 +141,7 @@ public:
     // once it is escaped if it still has pointers to it in order to
     // replace any use of those pointers by the corresponding
     // materialization
-    enum class Kind { Escaped, Object, Activation, Function, GeneratorFunction, AsyncFunction, AsyncGeneratorFunction, RegExpObject };
+    enum class Kind { Escaped, Object, Activation, Function, GeneratorFunction, AsyncFunction, AsyncGeneratorFunction, InternalFieldObject, RegExpObject };
 
     using Fields = HashMap<PromotedLocationDescriptor, Node*>;
 
@@ -245,6 +246,11 @@ public:
         return m_kind == Kind::Function || m_kind == Kind::GeneratorFunction || m_kind == Kind::AsyncFunction;
     }
 
+    bool isInternalFieldObjectAllocation() const
+    {
+        return m_kind == Kind::InternalFieldObject;
+    }
+
     bool isRegExpObjectAllocation() const
     {
         return m_kind == Kind::RegExpObject;
@@ -291,6 +297,10 @@ public:
             out.print("AsyncFunction");
             break;
 
+        case Kind::InternalFieldObject:
+            out.print("InternalFieldObject");
+            break;
+
         case Kind::AsyncGeneratorFunction:
             out.print("AsyncGeneratorFunction");
             break;
@@ -815,6 +825,19 @@ private:
         } while (changed);
     }
 
+    template<typename InternalFieldClass>
+    Allocation* handleInternalFieldClass(Node* node, HashMap<PromotedLocationDescriptor, LazyNode>& writes)
+    {
+        Allocation* result = &m_heap.newAllocation(node, Allocation::Kind::InternalFieldObject);
+        writes.add(StructurePLoc, LazyNode(m_graph.freeze(node->structure().get())));
+        auto initialValues = InternalFieldClass::initialValues();
+        static_assert(initialValues.size() == InternalFieldClass::numberOfInternalFields);        
+        for (unsigned index = 0; index < initialValues.size(); ++index)
+            writes.add(PromotedLocationDescriptor(InternalFieldObjectPLoc, index), LazyNode(m_graph.freeze(initialValues[index])));
+
+        return result;
+    }
+
     template<typename WriteFunctor, typename ResolveFunctor>
     void handleNode(
         Node* node,
@@ -859,6 +882,11 @@ private:
             break;
         }
 
+        case NewArrayIterator: {
+            target = handleInternalFieldClass<JSArrayIterator>(node, writes);
+            break;
+        }
+
         case NewRegexp: {
             target = &m_heap.newAllocation(node, Allocation::Kind::RegExpObject);
 
@@ -1069,6 +1097,26 @@ private:
             }
             break;
 
+        case GetInternalField: {
+            target = m_heap.onlyLocalAllocation(node->child1().node());
+            if (target && target->isInternalFieldObjectAllocation())
+                exactRead = PromotedLocationDescriptor(InternalFieldObjectPLoc, node->internalFieldIndex());
+            else
+                m_heap.escape(node->child1().node());
+            break;
+        }
+
+        case PutInternalField: {
+            target = m_heap.onlyLocalAllocation(node->child1().node());
+            if (target && target->isInternalFieldObjectAllocation())
+                writes.add(PromotedLocationDescriptor(InternalFieldObjectPLoc, node->internalFieldIndex()), LazyNode(node->child2().node()));
+            else {
+                m_heap.escape(node->child1().node());
+                m_heap.escape(node->child2().node());
+            }
+            break;
+        }
+
         case Check:
         case CheckVarargs:
             m_graph.doToChildren(
@@ -1561,6 +1609,15 @@ private:
                 OpInfo(executable));
         }
 
+        case Allocation::Kind::InternalFieldObject: {
+            ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
+            return m_graph.addNode(
+                allocation.identifier()->prediction(), Node::VarArg, MaterializeNewInternalFieldObject,
+                where->origin.withSemantic(
+                    allocation.identifier()->origin.semantic),
+                OpInfo(allocation.identifier()->structure()), OpInfo(data), 0, 0);
+        }
+
         case Allocation::Kind::Activation: {
             ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
             FrozenValue* symbolTable = allocation.identifier()->cellOperand();
@@ -1948,6 +2005,10 @@ private:
                         node->convertToPhantomNewAsyncFunction();
                         break;
 
+                    case NewArrayIterator:
+                        node->convertToPhantomNewArrayIterator();
+                        break;
+
                     case CreateActivation:
                         node->convertToPhantomCreateActivation();
                         break;
@@ -2224,6 +2285,46 @@ private:
             break;
         }
 
+        case MaterializeNewInternalFieldObject: {
+            ObjectMaterializationData& data = node->objectMaterializationData();
+
+            unsigned firstChild = m_graph.m_varArgChildren.size();
+
+            Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
+
+            PromotedHeapLocation structure(StructurePLoc, allocation.identifier());
+            ASSERT(locations.contains(structure));
+            m_graph.m_varArgChildren.append(Edge(resolve(block, structure), KnownCellUse));
+
+            for (PromotedHeapLocation location : locations) {
+                switch (location.kind()) {
+                case StructurePLoc: {
+                    ASSERT(location == structure);
+                    break;
+                }
+
+                case InternalFieldObjectPLoc: {
+                    ASSERT(location.base() == allocation.identifier());
+                    data.m_properties.append(location.descriptor());
+                    Node* value = resolve(block, location);
+                    if (m_sinkCandidates.contains(value))
+                        m_graph.m_varArgChildren.append(m_bottom);
+                    else
+                        m_graph.m_varArgChildren.append(value);
+                    break;
+                }
+
+                default:
+                    DFG_CRASH(m_graph, node, "Bad location kind");
+                }
+            }
+
+            node->children = AdjacencyList(
+                AdjacencyList::Variable,
+                firstChild, m_graph.m_varArgChildren.size() - firstChild);
+            break;
+        }
+
         case NewRegexp: {
             Vector<PromotedHeapLocation> locations = m_locationsForAllocation.get(escapee);
             ASSERT(locations.size() == 2);
@@ -2355,6 +2456,15 @@ private:
                 value->defaultEdge());
         }
 
+        case InternalFieldObjectPLoc: {
+            return m_graph.addNode(
+                PutInternalField,
+                origin.takeValidExit(canExit),
+                OpInfo(location.info()),
+                Edge(base, KnownCellUse),
+                value->defaultEdge());
+        }
+
         case RegExpObjectLastIndexPLoc: {
             return m_graph.addNode(
                 SetRegExpObjectLastIndex,
index 6481a79..b2b6aa7 100644 (file)
@@ -51,6 +51,7 @@
 #include "JIT.h"
 #include "JITExceptions.h"
 #include "JSArrayInlines.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncGenerator.h"
 #include "JSBigInt.h"
 #include "JSCInlines.h"
@@ -2087,6 +2088,15 @@ char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(
     return reinterpret_cast<char*>(constructGenericTypedArrayViewWithArguments<JSFloat64Array>(globalObject, structure, encodedValue, 0, WTF::nullopt));
 }
 
+JSCell* JIT_OPERATION operationNewArrayIterator(VM* vmPointer, Structure* structure)
+{
+    VM& vm = *vmPointer;
+    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
+    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+
+    return JSArrayIterator::createWithInitialValues(vm, structure);
+}
+
 JSCell* JIT_OPERATION operationCreateActivationDirect(VM* vmPointer, Structure* structure, JSScope* scope, SymbolTable* table, EncodedJSValue initialValueEncoded)
 {
     VM& vm = *vmPointer;
index 339f918..a33ede9 100644 (file)
@@ -124,6 +124,8 @@ char* JIT_OPERATION operationNewFloat32ArrayWithSize(JSGlobalObject*, Structure*
 char* JIT_OPERATION operationNewFloat32ArrayWithOneArgument(JSGlobalObject*, Structure*, EncodedJSValue) WTF_INTERNAL;
 char* JIT_OPERATION operationNewFloat64ArrayWithSize(JSGlobalObject*, Structure*, int32_t, char*) WTF_INTERNAL;
 char* JIT_OPERATION operationNewFloat64ArrayWithOneArgument(JSGlobalObject*, Structure*, EncodedJSValue) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationNewArrayIterator(VM*, Structure*) WTF_INTERNAL;
+
 void JIT_OPERATION operationPutByValStrict(JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
 void JIT_OPERATION operationPutByValNonStrict(JSGlobalObject*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
 void JIT_OPERATION operationPutByValCellStrict(JSGlobalObject*, JSCell*, EncodedJSValue encodedProperty, EncodedJSValue encodedValue) WTF_INTERNAL;
index bbc551d..f92ae9d 100644 (file)
@@ -1053,6 +1053,7 @@ private:
         case NewGenerator:
         case CreateAsyncGenerator:
         case NewAsyncGenerator:
+        case NewArrayIterator:
             setPrediction(SpecObjectOther);
             break;
             
@@ -1250,7 +1251,6 @@ private:
 
         case PutByValAlias:
         case DoubleAsInt32:
-        case CheckArray:
         case CheckTypeInfoFlags:
         case Arrayify:
         case ArrayifyToStructure:
@@ -1276,6 +1276,7 @@ private:
         case PhantomSpread:
         case PhantomNewArrayWithSpread:
         case PhantomNewArrayBuffer:
+        case PhantomNewArrayIterator:
         case PhantomClonedArguments:
         case PhantomNewRegexp:
         case GetMyArgumentByVal:
@@ -1285,6 +1286,7 @@ private:
         case CheckStructureOrEmpty:
         case MaterializeNewObject:
         case MaterializeCreateActivation:
+        case MaterializeNewInternalFieldObject:
         case PutStack:
         case KillStack:
         case StoreBarrier:
@@ -1358,6 +1360,8 @@ private:
         case PutStructure:
         case Phantom:
         case Check:
+        case CheckArray:
+        case CheckNeutered:
         case CheckVarargs:
         case PutGlobalVariable:
         case CheckTraps:
index 850710e..3b0ae66 100644 (file)
@@ -135,8 +135,8 @@ void printInternal(PrintStream& out, PromotedLocationKind kind)
         out.print("RegExpObjectLastIndexPLoc");
         return;
 
-    case PromiseInternalFieldPLoc:
-        out.print("PromiseInternalFieldPLoc");
+    case InternalFieldObjectPLoc:
+        out.print("InternalFieldObjectPLoc");
         return;
     }
     
index 07e6d89..e0c31c2 100644 (file)
@@ -54,7 +54,7 @@ enum PromotedLocationKind {
     ArgumentPLoc,
     ArgumentsCalleePLoc,
     ClosureVarPLoc,
-    PromiseInternalFieldPLoc,
+    InternalFieldObjectPLoc,
     FunctionActivationPLoc,
     FunctionExecutablePLoc,
     IndexedPropertyPLoc,
@@ -121,6 +121,7 @@ public:
         case NamedPropertyPLoc:
         case ClosureVarPLoc:
         case RegExpObjectLastIndexPLoc:
+        case InternalFieldObjectPLoc:
             return false;
 
         default:
index 8830c68..203387b 100644 (file)
@@ -278,6 +278,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case CallDOM:
     case CheckSubClass:
     case CheckArray:
+    case CheckNeutered:
     case Arrayify:
     case ArrayifyToStructure:
     case GetScope:
@@ -334,6 +335,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case NewArrayWithSize:
     case NewArrayBuffer:
     case NewArrayWithSpread:
+    case NewArrayIterator:
     case Spread:
     case NewRegexp:
     case NewSymbol:
@@ -443,12 +445,14 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case PhantomNewGeneratorFunction:
     case PhantomNewAsyncGeneratorFunction:
     case PhantomNewAsyncFunction:
+    case PhantomNewArrayIterator:
     case PhantomCreateActivation:
     case PhantomNewRegexp:
     case PutHint:
     case CheckStructureImmediate:
     case MaterializeNewObject:
     case MaterializeCreateActivation:
+    case MaterializeNewInternalFieldObject:
     case PhantomDirectArguments:
     case PhantomCreateRest:
     case PhantomSpread:
index 91f338f..07024cd 100644 (file)
@@ -51,6 +51,7 @@
 #include "JITMulGenerator.h"
 #include "JITRightShiftGenerator.h"
 #include "JITSubGenerator.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncFunction.h"
 #include "JSAsyncGeneratorFunction.h"
 #include "JSCInlines.h"
@@ -1780,6 +1781,21 @@ void SpeculativeJIT::compileMovHint(Node* node)
     m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->unlinkedOperand()));
 }
 
+void SpeculativeJIT::compileCheckNeutered(Node* node)
+{
+    SpeculateCellOperand base(this, node->child1());
+    GPRReg baseReg = base.gpr();
+
+    // We only emit this node after we have checked this is a typed array so that better be true now.
+    DFG_ASSERT(m_graph, node, speculationChecked(m_state.forNode(node->child1()).m_type, SpecTypedArrayView));
+
+    speculationCheck(
+        BadIndexingType, JSValueSource::unboxedCell(baseReg), node->child1(), 
+        m_jit.branchTestPtr(MacroAssembler::Zero, MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfVector())));
+
+    noResult(node);
+}
+
 void SpeculativeJIT::bail(AbortReason reason)
 {
     if (verboseCompilationEnabled())
@@ -4307,9 +4323,12 @@ void SpeculativeJIT::compileToObjectOrCallObjectConstructor(Node* node)
     slowCases.append(m_jit.branchIfNotObject(valueRegs.payloadGPR()));
     m_jit.move(valueRegs.payloadGPR(), resultGPR);
 
-    if (node->op() == ToObject)
-        addSlowPathGenerator(slowPathCall(slowCases, this, operationToObject, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), valueRegs, identifierUID(node->identifierNumber())));
-    else
+    if (node->op() == ToObject) {
+        UniquedStringImpl* errorMessage = nullptr;
+        if (node->identifierNumber() != UINT32_MAX)
+            errorMessage = identifierUID(node->identifierNumber());
+        addSlowPathGenerator(slowPathCall(slowCases, this, operationToObject, resultGPR, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), valueRegs, errorMessage));
+    } else
         addSlowPathGenerator(slowPathCall(slowCases, this, operationCallObjectConstructor, resultGPR, TrustedImmPtr(node->cellOperand()), valueRegs));
 
     cellResult(resultGPR, node);
@@ -12987,7 +13006,7 @@ void SpeculativeJIT::compileNewInternalFieldObject(Node* node, Operation operati
     auto butterfly = TrustedImmPtr(nullptr);
     emitAllocateJSObjectWithKnownSize<JSClass>(resultGPR, TrustedImmPtr(structure), butterfly, scratch1GPR, scratch2GPR, slowCases, sizeof(JSClass));
     auto initialValues = JSClass::initialValues();
-    ASSERT(initialValues.size() == JSClass::numberOfInternalFields);
+    static_assert(initialValues.size() == JSClass::numberOfInternalFields);
     for (unsigned index = 0; index < initialValues.size(); ++index)
         m_jit.storeTrustedValue(initialValues[index], CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(index)));
     m_jit.mutatorFence(m_jit.vm());
@@ -13007,6 +13026,11 @@ void SpeculativeJIT::compileNewAsyncGenerator(Node* node)
     compileNewInternalFieldObject<JSAsyncGenerator>(node, operationNewAsyncGenerator);
 }
 
+void SpeculativeJIT::compileNewArrayIterator(Node* node)
+{
+    compileNewInternalFieldObject<JSArrayIterator>(node, operationNewArrayIterator);
+}
+
 void SpeculativeJIT::compileToPrimitive(Node* node)
 {
     DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse, node->child1().useKind());
index 4b90a05..4a2f0f7 100644 (file)
@@ -714,6 +714,8 @@ public:
     void compileMovHint(Node*);
     void compileMovHintAndCheck(Node*);
 
+    void compileCheckNeutered(Node*);
+
     void cachedGetById(CodeOrigin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode, AccessType);
     void cachedPutById(CodeOrigin, GPRReg baseGPR, JSValueRegs valueRegs, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
     void cachedGetByVal(CodeOrigin, JSValueRegs base, JSValueRegs property, JSValueRegs result, JITCompiler::Jump slowPathTarget);
@@ -1485,6 +1487,7 @@ public:
     void compileNewPromise(Node*);
     void compileNewGenerator(Node*);
     void compileNewAsyncGenerator(Node*);
+    void compileNewArrayIterator(Node*);
     void compileToPrimitive(Node*);
     void compileToNumeric(Node*);
     void compileLogShadowChickenPrologue(Node*);
index 80626b0..5162917 100644 (file)
@@ -2218,6 +2218,11 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
         
+    case CheckNeutered: {
+        compileCheckNeutered(node);
+        break;
+    }
+
     case CheckArray: {
         checkArray(node);
         break;
@@ -3250,6 +3255,11 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case NewArrayIterator: {
+        compileNewArrayIterator(node);
+        break;
+    }
+
     case GetCallee: {
         compileGetCallee(node);
         break;
@@ -4197,10 +4207,12 @@ void SpeculativeJIT::compile(Node* node)
     case PhantomNewAsyncFunction:
     case PhantomNewAsyncGeneratorFunction:
     case PhantomCreateActivation:
+    case PhantomNewArrayIterator:
     case PhantomNewRegexp:
     case PutHint:
     case CheckStructureImmediate:
     case MaterializeCreateActivation:
+    case MaterializeNewInternalFieldObject:
     case PutStack:
     case KillStack:
     case GetStack:
index adf6714..46b11da 100644 (file)
@@ -2370,6 +2370,11 @@ void SpeculativeJIT::compile(Node* node)
         compileFromCharCode(node);
         break;
     }
+
+    case CheckNeutered: {
+        compileCheckNeutered(node);
+        break;
+    }
         
     case CheckArray: {
         checkArray(node);
@@ -3578,6 +3583,11 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case NewArrayIterator: {
+        compileNewArrayIterator(node);
+        break;
+    }
+
     case GetCallee: {
         compileGetCallee(node);
         break;
@@ -5261,6 +5271,7 @@ void SpeculativeJIT::compile(Node* node)
     case PhantomNewGeneratorFunction:
     case PhantomNewAsyncFunction:
     case PhantomNewAsyncGeneratorFunction:
+    case PhantomNewArrayIterator:
     case PhantomCreateActivation:
     case PhantomNewRegexp:
     case GetMyArgumentByVal:
@@ -5269,6 +5280,7 @@ void SpeculativeJIT::compile(Node* node)
     case PutHint:
     case CheckStructureImmediate:
     case MaterializeCreateActivation:
+    case MaterializeNewInternalFieldObject:
     case PutStack:
     case KillStack:
     case GetStack:
index 69e68cc..2e80004 100644 (file)
@@ -327,6 +327,7 @@ private:
             case NewArray:
             case NewArrayWithSize:
             case NewArrayBuffer:
+            case NewArrayIterator:
             case NewTypedArray:
             case NewRegexp:
             case NewStringObject:
index 79665f8..7528e5e 100644 (file)
@@ -271,6 +271,7 @@ private:
                 case PutByValAlias:
                 case GetArrayLength:
                 case CheckArray:
+                case CheckNeutered:
                 case GetIndexedPropertyStorage:
                 case GetTypedArrayByteOffset:
                 case Phantom:
@@ -336,6 +337,7 @@ private:
                 }
 
                 case CheckStructure:
+                case CheckNeutered:
                 case GetByOffset:
                 case PutByOffset:
                 case PutStructure:
index a2d6cfc..3715f72 100644 (file)
@@ -473,7 +473,7 @@ private:
                     Node* node = block->at(i);
                     m_graph.doToChildren(node, [&] (const Edge& edge) {
                         Node* child = edge.node();
-                        VALIDATE((node), block->isInPhis(child) || seenNodes.contains(child));
+                        VALIDATE((node, edge), block->isInPhis(child) || seenNodes.contains(child));
                     });
                     seenNodes.add(node);
                 }
index 7ca825d..b953cfe 100644 (file)
@@ -81,6 +81,7 @@ inline CapabilityLevel canCompile(Node* node)
     case NewSymbol:
     case NewArray:
     case NewArrayWithSpread:
+    case NewArrayIterator:
     case Spread:
     case NewArrayBuffer:
     case NewTypedArray:
@@ -202,6 +203,7 @@ inline CapabilityLevel canCompile(Node* node)
     case Check:
     case CheckVarargs:
     case CheckArray:
+    case CheckNeutered:
     case CountExecution:
     case SuperSamplerBegin:
     case SuperSamplerEnd:
@@ -287,12 +289,14 @@ inline CapabilityLevel canCompile(Node* node)
     case PhantomNewGeneratorFunction:
     case PhantomNewAsyncGeneratorFunction:
     case PhantomNewAsyncFunction:
+    case PhantomNewArrayIterator:
     case PhantomCreateActivation:
     case PhantomNewRegexp:
     case PutHint:
     case CheckStructureImmediate:
     case MaterializeNewObject:
     case MaterializeCreateActivation:
+    case MaterializeNewInternalFieldObject:
     case PhantomDirectArguments:
     case PhantomCreateRest:
     case PhantomSpread:
index eec481e..d98454e 100644 (file)
@@ -76,6 +76,7 @@
 #include "JITMulGenerator.h"
 #include "JITRightShiftGenerator.h"
 #include "JITSubGenerator.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncFunction.h"
 #include "JSAsyncGenerator.h"
 #include "JSAsyncGeneratorFunction.h"
@@ -966,6 +967,9 @@ private:
         case CheckArray:
             compileCheckArray();
             break;
+        case CheckNeutered:
+            compileCheckNeutered();
+            break;
         case GetArrayLength:
             compileGetArrayLength();
             break;
@@ -1067,6 +1071,9 @@ private:
         case NewAsyncGenerator:
             compileNewAsyncGenerator();
             break;
+        case NewArrayIterator:
+            compileNewArrayIterator();
+            break;
         case NewStringObject:
             compileNewStringObject();
             break;
@@ -1466,6 +1473,9 @@ private:
         case MaterializeCreateActivation:
             compileMaterializeCreateActivation();
             break;
+        case MaterializeNewInternalFieldObject:
+            compileMaterializeNewInternalFieldObject();
+            break;
         case CheckTraps:
             compileCheckTraps();
             break;
@@ -1579,6 +1589,7 @@ private:
         case PhantomNewGeneratorFunction:
         case PhantomNewAsyncGeneratorFunction:
         case PhantomNewAsyncFunction:
+        case PhantomNewArrayIterator:
         case PhantomCreateActivation:
         case PhantomDirectArguments:
         case PhantomCreateRest:
@@ -2069,8 +2080,11 @@ private:
 
         ValueFromBlock slowResult;
         if (m_node->op() == ToObject) {
+            UniquedStringImpl* errorMessage = nullptr;
+            if (m_node->identifierNumber() != UINT32_MAX)
+                errorMessage = m_graph.identifiers()[m_node->identifierNumber()];
             auto* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
-            slowResult = m_out.anchor(vmCall(Int64, operationToObject, weakPointer(globalObject), value, m_out.constIntPtr(m_graph.identifiers()[m_node->identifierNumber()])));
+            slowResult = m_out.anchor(vmCall(Int64, operationToObject, weakPointer(globalObject), value, m_out.constIntPtr(errorMessage)));
         } else
             slowResult = m_out.anchor(vmCall(Int64, operationCallObjectConstructor, frozenPointer(m_node->cellOperand()), value));
         m_out.jump(continuation);
@@ -4042,7 +4056,7 @@ private:
     {
         Edge edge = m_node->child1();
         LValue cell = lowCell(edge);
-        
+
         if (m_node->arrayMode().alreadyChecked(m_graph, m_node, abstractValue(edge)))
             return;
         
@@ -4051,6 +4065,19 @@ private:
             m_out.logicalNot(isArrayTypeForCheckArray(cell, m_node->arrayMode())));
     }
 
+    void compileCheckNeutered()
+    {
+        Edge edge = m_node->child1();
+        LValue cell = lowCell(edge);
+        
+        // We only emit this node after we have checked this is a typed array so that better be true now.
+        DFG_ASSERT(m_graph, m_node, speculationChecked(abstractValue(edge).m_type, SpecTypedArrayView));
+
+        speculate(
+            BadIndexingType, jsValueValue(cell), edge.node(),
+            m_out.isNull(m_out.loadPtr(cell, m_heaps.JSArrayBufferView_vector)));
+    }
+
     void compileGetTypedArrayByteOffset()
     {
         LValue basePtr = lowCell(m_node->child1());    
@@ -6142,7 +6169,7 @@ private:
 
         LValue object = allocateObject<JSClass>(m_node->structure(), m_out.intPtrZero, slowCase);
         auto initialValues = JSClass::initialValues();
-        ASSERT(initialValues.size() == JSClass::numberOfInternalFields);
+        static_assert(initialValues.size() == JSClass::numberOfInternalFields);
         for (unsigned index = 0; index < initialValues.size(); ++index)
             m_out.store64(m_out.constInt64(JSValue::encode(initialValues[index])), object, m_heaps.JSInternalFieldObjectImpl_internalFields[index]);
         mutatorFence();
@@ -6167,6 +6194,11 @@ private:
         compileNewInternalFieldObject<JSAsyncGenerator>(operationNewAsyncGenerator);
     }
 
+    void compileNewArrayIterator()
+    {
+        compileNewInternalFieldObject<JSArrayIterator>(operationNewArrayIterator);
+    }
+
     void compileNewStringObject()
     {
         RegisteredStructure structure = m_node->structure();
@@ -6675,7 +6707,7 @@ private:
         m_out.appendTo(fastAllocationCase, slowCase);
         LValue object = allocateObject<JSClass>(structure, m_out.intPtrZero, slowCase);
         auto initialValues = JSClass::initialValues();
-        ASSERT(initialValues.size() == JSClass::numberOfInternalFields);
+        static_assert(initialValues.size() == JSClass::numberOfInternalFields, "We don't support non-constant fields in create yet.");
         for (unsigned index = 0; index < initialValues.size(); ++index)
             m_out.store64(m_out.constInt64(JSValue::encode(initialValues[index])), object, m_heaps.JSInternalFieldObjectImpl_internalFields[index]);
         mutatorFence();
@@ -11991,6 +12023,63 @@ private:
         setJSValue(activation);
     }
 
+    template<typename JSClass, typename Operation>
+    void compileMaterializeNewInternalFieldObjectImpl(Operation operation)
+    {
+        ObjectMaterializationData& data = m_node->objectMaterializationData();
+
+        Vector<LValue, JSClass::numberOfInternalFields> values;
+        ASSERT(data.m_properties.size() == JSClass::numberOfInternalFields);
+        for (unsigned i = 0; i < data.m_properties.size(); ++i)
+            values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
+
+        RegisteredStructure structure = m_node->structure();
+
+        LBasicBlock slowPath = m_out.newBlock();
+        LBasicBlock continuation = m_out.newBlock();
+
+        LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowPath);
+
+        RELEASE_ASSERT(data.m_properties.size() == JSClass::numberOfInternalFields);
+        LValue fastObject = allocateObject<JSClass>(structure, m_out.intPtrZero, slowPath);
+        ValueFromBlock fastResult = m_out.anchor(fastObject);
+        m_out.jump(continuation);
+
+        m_out.appendTo(slowPath, continuation);
+        VM& vm = this->vm();
+        LValue callResult = lazySlowPath(
+            [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
+                return createLazyCallGenerator(vm,
+                    operation, locations[0].directGPR(), &vm,
+                    CCallHelpers::TrustedImmPtr(structure.get()));
+            });
+        ValueFromBlock slowResult = m_out.anchor(callResult);
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        LValue object = m_out.phi(pointerType(), fastResult, slowResult);
+        for (unsigned i = 0; i < data.m_properties.size(); ++i) {
+            PromotedLocationDescriptor descriptor = data.m_properties[i];
+            ASSERT(descriptor.kind() == InternalFieldObjectPLoc);
+            RELEASE_ASSERT(descriptor.info() < JSClass::numberOfInternalFields);
+            m_out.store64(values[i], object, m_heaps.JSInternalFieldObjectImpl_internalFields[descriptor.info()]);
+        }
+
+        mutatorFence();
+        setJSValue(object);
+    }
+
+    void compileMaterializeNewInternalFieldObject()
+    {
+        switch (m_node->structure()->typeInfo().type()) {
+        case JSArrayIteratorType:
+            compileMaterializeNewInternalFieldObjectImpl<JSArrayIterator>(operationNewArrayIterator);
+            break;
+        default:
+            DFG_CRASH(m_graph, m_node, "Bad structure");
+        }
+    }
+
     void compileCheckTraps()
     {
         ASSERT(Options::usePollingTraps());
index 71f74dd..0069a3a 100644 (file)
@@ -37,6 +37,7 @@
 #include "FrameTracers.h"
 #include "InlineCallFrame.h"
 #include "Interpreter.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncFunction.h"
 #include "JSAsyncGeneratorFunction.h"
 #include "JSCInlines.h"
@@ -117,6 +118,19 @@ extern "C" void JIT_OPERATION operationPopulateObjectInOSR(JSGlobalObject* globa
         break;
     }
 
+    case PhantomNewArrayIterator: {
+        JSArrayIterator* arrayIterator = jsCast<JSArrayIterator*>(JSValue::decode(*encodedValue));
+
+        // Figure out what to populate the iterator with
+        for (unsigned i = materialization->properties().size(); i--;) {
+            const ExitPropertyValue& property = materialization->properties()[i];
+            if (property.location().kind() != InternalFieldObjectPLoc)
+                continue;
+            arrayIterator->internalField(static_cast<JSArrayIterator::Field>(property.location().info())).set(vm, arrayIterator, JSValue::decode(values[i]));
+        }
+        break;
+    }
+
     case PhantomNewRegexp: {
         RegExpObject* regExpObject = jsCast<RegExpObject*>(JSValue::decode(*encodedValue));
 
@@ -279,6 +293,28 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(JSGlobalObject*
         return result;
     }
 
+    case PhantomNewArrayIterator: {
+        // Figure out what structure.
+        Structure* structure = nullptr;
+        for (unsigned i = materialization->properties().size(); i--;) {
+            const ExitPropertyValue& property = materialization->properties()[i];
+            if (property.location() == PromotedLocationDescriptor(StructurePLoc)) {
+                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<Structure>(vm));
+                structure = jsCast<Structure*>(JSValue::decode(values[i]));
+            }
+        }
+        RELEASE_ASSERT(structure);
+
+        JSArrayIterator* result = JSArrayIterator::createWithInitialValues(vm, structure);
+
+        RELEASE_ASSERT(materialization->properties().size() - 1 == JSArrayIterator::numberOfInternalFields);
+
+        // The real values will be put subsequently by
+        // operationPopulateNewObjectInOSR. See the PhantomNewObject
+        // case for details.
+        return result;
+    }
+
     case PhantomCreateRest:
     case PhantomDirectArguments:
     case PhantomClonedArguments: {
index 3ec6fe7..3f19474 100644 (file)
@@ -43,6 +43,7 @@
 #include "IteratorOperations.h"
 #include "IteratorPrototype.h"
 #include "JSArray.h"
+#include "JSArrayIterator.h"
 #include "JSBoundFunction.h"
 #include "JSCInlines.h"
 #include "JSFunction.h"
@@ -227,7 +228,7 @@ JSValue JSInjectedScriptHost::subtype(JSGlobalObject* globalObject, CallFrame* c
         if (object->inherits<JSStringIterator>(vm))
             return jsNontrivialString(vm, "iterator"_s);
 
-        if (object->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())
+        if (object->inherits<JSArrayIterator>(vm)
             || object->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())
             || object->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName()))
             return jsNontrivialString(vm, "iterator"_s);
@@ -370,9 +371,21 @@ JSValue JSInjectedScriptHost::getInternalProperties(JSGlobalObject* globalObject
     }
 
     if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(vm, value)) {
-        if (iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) {
-            JSValue iteratedValue = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
-            JSValue kind = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorKindPrivateName());
+        auto toString = [&] (IterationKind kind) {
+            switch (kind) {
+            case IterationKind::Keys:
+                return jsNontrivialString(vm, "keys"_s);
+            case IterationKind::Values:
+                return jsNontrivialString(vm, "values"_s);
+            case IterationKind::Entries:
+                return jsNontrivialString(vm, "entries"_s);
+            }
+            return jsNontrivialString(vm, ""_s);
+        };
+        
+        if (auto* arrayIterator = jsDynamicCast<JSArrayIterator*>(vm, iteratorObject)) {
+            JSValue iteratedValue = arrayIterator->iteratedObject();
+            IterationKind kind = arrayIterator->kind();
 
             unsigned index = 0;
             JSArray* array = constructEmptyArray(globalObject, nullptr, 2);
@@ -380,55 +393,35 @@ JSValue JSInjectedScriptHost::getInternalProperties(JSGlobalObject* globalObject
             array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "array", iteratedValue));
             RETURN_IF_EXCEPTION(scope, JSValue());
             scope.release();
-            array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "kind", kind));
+            array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "kind", toString(kind)));
             return array;
         }
 
         if (iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())) {
             JSValue iteratedValue = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
-            String kind;
-            switch (static_cast<IterationKind>(iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapIteratorKindPrivateName()).asInt32())) {
-            case IterateKey:
-                kind = "key"_s;
-                break;
-            case IterateValue:
-                kind = "value"_s;
-                break;
-            case IterateKeyValue:
-                kind = "key+value"_s;
-                break;
-            }
+            IterationKind kind = static_cast<IterationKind>(iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapIteratorKindPrivateName()).asInt32());
+
             unsigned index = 0;
             JSArray* array = constructEmptyArray(globalObject, nullptr, 2);
             RETURN_IF_EXCEPTION(scope, JSValue());
             array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "map", iteratedValue));
             RETURN_IF_EXCEPTION(scope, JSValue());
             scope.release();
-            array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "kind", jsNontrivialString(vm, kind)));
+            array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "kind", toString(kind)));
             return array;
         }
 
         if (iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName())) {
             JSValue iteratedValue = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
-            String kind;
-            switch (static_cast<IterationKind>(iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setIteratorKindPrivateName()).asInt32())) {
-            case IterateKey:
-                kind = "key"_s;
-                break;
-            case IterateValue:
-                kind = "value"_s;
-                break;
-            case IterateKeyValue:
-                kind = "key+value"_s;
-                break;
-            }
+            IterationKind kind = static_cast<IterationKind>(iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setIteratorKindPrivateName()).asInt32());
+
             unsigned index = 0;
             JSArray* array = constructEmptyArray(globalObject, nullptr, 2);
             RETURN_IF_EXCEPTION(scope, JSValue());
             array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "set", iteratedValue));
             RETURN_IF_EXCEPTION(scope, JSValue());
             scope.release();
-            array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "kind", jsNontrivialString(vm, kind)));
+            array->putDirectIndex(globalObject, index++, constructInternalProperty(globalObject, "kind", toString(kind)));
             return array;
         }
     }
@@ -549,15 +542,11 @@ JSValue JSInjectedScriptHost::weakSetEntries(JSGlobalObject* globalObject, CallF
     return array;
 }
 
-static JSObject* cloneArrayIteratorObject(JSGlobalObject* globalObject, VM& vm, JSObject* iteratorObject, JSValue nextIndex, JSValue iteratedObject)
+static JSObject* cloneArrayIteratorObject(JSGlobalObject* globalObject, VM& vm, JSArrayIterator* iteratorObject)
 {
-    ASSERT(iteratorObject->type() == FinalObjectType);
-    JSObject* clone = constructEmptyObject(globalObject, ArrayIteratorPrototype::create(vm, globalObject, ArrayIteratorPrototype::createStructure(vm, globalObject, globalObject->iteratorPrototype())));
-    clone->putDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName(), iteratedObject);
-    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorKindPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorKindPrivateName()));
-    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName(), nextIndex);
-    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextPrivateName()));
-    clone->putDirect(vm, vm.propertyNames->builtinNames().arrayIteratorIsDonePrivateName(), iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorIsDonePrivateName()));
+    JSArrayIterator* clone = JSArrayIterator::create(vm, globalObject->arrayIteratorStructure(), iteratorObject->iteratedObject(), iteratorObject->internalField(JSArrayIterator::Field::Kind).get());
+    clone->internalField(JSArrayIterator::Field::Index).set(vm, clone, iteratorObject->internalField(JSArrayIterator::Field::Index).get());
+    clone->internalField(JSArrayIterator::Field::IsDone).set(vm, clone, iteratorObject->internalField(JSArrayIterator::Field::IsDone).get());
     return clone;
 }
 
@@ -595,23 +584,25 @@ JSValue JSInjectedScriptHost::iteratorEntries(JSGlobalObject* globalObject, Call
         if (globalObject->isStringPrototypeIteratorProtocolFastAndNonObservable())
             iterator = stringIterator->clone(globalObject);
     } else if (JSObject* iteratorObject = jsDynamicCast<JSObject*>(vm, value)) {
-        // Detect an ArrayIterator by checking for one of its unique private properties.
-        JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
-        if (JSValue nextIndex = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())) {
+        if (auto* arrayIterator = jsDynamicCast<JSArrayIterator*>(vm, iteratorObject)) {
+            JSObject* iteratedObject = arrayIterator->iteratedObject();
             if (isJSArray(iteratedObject)) {
                 JSArray* array = jsCast<JSArray*>(iteratedObject);
                 if (array->isIteratorProtocolFastAndNonObservable())
-                    iterator = cloneArrayIteratorObject(globalObject, vm, iteratorObject, nextIndex, iteratedObject);
-            } else if (iteratedObject.isObject() && TypeInfo::isArgumentsType(asObject(iteratedObject)->type())) {
+                    iterator = cloneArrayIteratorObject(globalObject, vm, arrayIterator);
+            } else if (TypeInfo::isArgumentsType(iteratedObject->type())) {
                 if (globalObject->isArrayPrototypeIteratorProtocolFastAndNonObservable())
-                    iterator = cloneArrayIteratorObject(globalObject, vm, iteratorObject, nextIndex, iteratedObject);
+                    iterator = cloneArrayIteratorObject(globalObject, vm, arrayIterator);
+            }
+        } else {
+            JSValue iteratedObject = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().iteratedObjectPrivateName());
+            if (JSValue mapBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())) {
+                if (jsCast<JSMap*>(iteratedObject)->isIteratorProtocolFastAndNonObservable())
+                    iterator = cloneMapIteratorObject(globalObject, vm, iteratorObject, mapBucket, iteratedObject);
+            } else if (JSValue setBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName())) {
+                if (jsCast<JSSet*>(iteratedObject)->isIteratorProtocolFastAndNonObservable())
+                    iterator = cloneSetIteratorObject(globalObject, vm, iteratorObject, setBucket, iteratedObject);
             }
-        } else if (JSValue mapBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())) {
-            if (jsCast<JSMap*>(iteratedObject)->isIteratorProtocolFastAndNonObservable())
-                iterator = cloneMapIteratorObject(globalObject, vm, iteratorObject, mapBucket, iteratedObject);
-        } else if (JSValue setBucket = iteratorObject->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName())) {
-            if (jsCast<JSSet*>(iteratedObject)->isIteratorProtocolFastAndNonObservable())
-                iterator = cloneSetIteratorObject(globalObject, vm, iteratorObject, setBucket, iteratedObject);
         }
     }
     RETURN_IF_EXCEPTION(scope, { });
index 6057128..7a642c0 100644 (file)
@@ -34,6 +34,7 @@
 #include "Interpreter.h"
 #include "JIT.h"
 #include "JSArrayInlines.h"
+#include "JSArrayIterator.h"
 #include "JSCBuiltins.h"
 #include "JSCInlines.h"
 #include "JSImmutableButterfly.h"
@@ -50,6 +51,8 @@ namespace JSC {
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(JSGlobalObject*, CallFrame*);
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(JSGlobalObject*, CallFrame*);
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncKeys(JSGlobalObject*, CallFrame*);
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncEntries(JSGlobalObject*, CallFrame*);
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(JSGlobalObject*, CallFrame*);
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(JSGlobalObject*, CallFrame*);
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(JSGlobalObject*, CallFrame*);
@@ -111,8 +114,8 @@ void ArrayPrototype::finishCreation(VM& vm, JSGlobalObject* globalObject)
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().reducePublicName(), arrayPrototypeReduceCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().reduceRightPublicName(), arrayPrototypeReduceRightCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().mapPublicName(), arrayPrototypeMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), arrayPrototypeEntriesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), arrayPrototypeKeysCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), arrayProtoFuncKeys, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, ArrayKeysIntrinsic);
+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), arrayProtoFuncEntries, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, ArrayEntriesIntrinsic);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().findPublicName(), arrayPrototypeFindCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().findIndexPublicName(), arrayPrototypeFindIndexCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().includesPublicName(), arrayPrototypeIncludesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -827,6 +830,35 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(JSGlobalObject* globalObject, Ca
     RELEASE_AND_RETURN(scope, JSValue::encode(fastJoin(globalObject, thisObject, viewWithString.view, length)));
 }
 
+inline EncodedJSValue createArrayIteratorObject(JSGlobalObject* globalObject, CallFrame* callFrame, IterationKind kind)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSObject* thisObject  = callFrame->thisValue().toObject(globalObject);
+    EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
+    UNUSED_PARAM(scope);
+    if (UNLIKELY(!thisObject))
+        return encodedJSValue();
+
+    return JSValue::encode(JSArrayIterator::create(vm, globalObject->arrayIteratorStructure(), thisObject, jsNumber(static_cast<unsigned>(kind))));
+}
+
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncValues(JSGlobalObject* globalObject, CallFrame* callFrame)
+{
+    return createArrayIteratorObject(globalObject, callFrame, IterationKind::Values);
+}
+
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncEntries(JSGlobalObject* globalObject, CallFrame* callFrame)
+{
+    return createArrayIteratorObject(globalObject, callFrame, IterationKind::Entries);
+}
+
+EncodedJSValue JSC_HOST_CALL arrayProtoFuncKeys(JSGlobalObject* globalObject, CallFrame* callFrame)
+{
+    return createArrayIteratorObject(globalObject, callFrame, IterationKind::Keys);
+}
+
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(JSGlobalObject* globalObject, CallFrame* callFrame)
 {
     VM& vm = globalObject->vm();
index 07cc7ac..470202f 100644 (file)
@@ -97,6 +97,7 @@
     macro(displayName) \
     macro(done) \
     macro(dotAll) \
+    macro(entries) \
     macro(enumerable) \
     macro(era) \
     macro(eval) \
     macro(isWatchpoint) \
     macro(jettisonReason) \
     macro(join) \
+    macro(keys) \
     macro(lastIndex) \
     macro(length) \
     macro(line) \
     macro(unicode) \
     macro(usage) \
     macro(value) \
+    macro(values) \
     macro(valueOf) \
     macro(weekday) \
     macro(writable) \
index 7f867f1..3535909 100644 (file)
@@ -79,6 +79,12 @@ const char* intrinsicName(Intrinsic intrinsic)
         return "ArrayPopIntrinsic";
     case ArraySliceIntrinsic:
         return "ArraySliceIntrinsic";
+    case ArrayValuesIntrinsic:
+        return "ArrayValuesIntrinsic";
+    case ArrayKeysIntrinsic:
+        return "ArrayKeysIntrinsic";
+    case ArrayEntriesIntrinsic:
+        return "ArrayEntriesIntrinsic";
     case CharCodeAtIntrinsic:
         return "CharCodeAtIntrinsic";
     case CharAtIntrinsic:
@@ -185,6 +191,12 @@ const char* intrinsicName(Intrinsic intrinsic)
         return "FRoundIntrinsic";
     case TruncIntrinsic:
         return "TruncIntrinsic";
+    case TypedArrayValuesIntrinsic:
+        return "TypedArrayValuesIntrinsic";
+    case TypedArrayKeysIntrinsic:
+        return "TypedArrayKeysIntrinsic";
+    case TypedArrayEntriesIntrinsic:
+        return "TypedArrayEntriesIntrinsic";
     case IsTypedArrayViewIntrinsic:
         return "IsTypedArrayViewIntrinsic";
     case BoundFunctionCallIntrinsic:
index bb2fee2..6bfff90 100644 (file)
@@ -25,6 +25,8 @@
 
 #pragma once
 
+#include "IterationKind.h"
+
 namespace JSC {
 
 enum Intrinsic : uint8_t {
@@ -52,6 +54,9 @@ enum Intrinsic : uint8_t {
     ArrayPopIntrinsic,
     ArraySliceIntrinsic,
     ArrayIndexOfIntrinsic,
+    ArrayValuesIntrinsic,
+    ArrayKeysIntrinsic,
+    ArrayEntriesIntrinsic,
     CharCodeAtIntrinsic,
     CharAtIntrinsic,
     DatePrototypeGetTimeIntrinsic,
@@ -105,6 +110,9 @@ enum Intrinsic : uint8_t {
     RandomIntrinsic,
     FRoundIntrinsic,
     TruncIntrinsic,
+    TypedArrayValuesIntrinsic,
+    TypedArrayKeysIntrinsic,
+    TypedArrayEntriesIntrinsic,
     IsTypedArrayViewIntrinsic,
     BoundFunctionCallIntrinsic,
     JSMapGetIntrinsic,
index 07f1fcf..cc29c21 100644 (file)
 
 namespace JSC {
     
-enum IterationKind : uint32_t {
-    IterateKey,
-    IterateValue,
-    IterateKeyValue,
+enum class IterationKind : uint32_t {
+    Keys,
+    Values,
+    Entries,
 };
 
-    
+
 } // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSArrayIterator.cpp b/Source/JavaScriptCore/runtime/JSArrayIterator.cpp
new file mode 100644 (file)
index 0000000..254e749
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSArrayIterator.h"
+
+#include "JSCInlines.h"
+#include "JSInternalFieldObjectImplInlines.h"
+
+namespace JSC {
+
+const ClassInfo JSArrayIterator::s_info = { "ArrayIterator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSArrayIterator) };
+
+JSArrayIterator* JSArrayIterator::create(VM& vm, Structure* structure, JSObject* iteratedObject, JSValue kind)
+{
+    ASSERT(kind.asUInt32() <= static_cast<uint32_t>(IterationKind::Entries));
+    JSArrayIterator* iterator = new (NotNull, allocateCell<JSArrayIterator>(vm.heap)) JSArrayIterator(vm, structure);
+    iterator->finishCreation(vm);
+    iterator->internalField(Field::IteratedObject).set(vm, iterator, iteratedObject);
+    iterator->internalField(Field::Kind).set(vm, iterator, kind);
+    return iterator;
+}
+
+JSArrayIterator* JSArrayIterator::createWithInitialValues(VM& vm, Structure* structure)
+{
+    JSArrayIterator* iterator = new (NotNull, allocateCell<JSArrayIterator>(vm.heap)) JSArrayIterator(vm, structure);
+    iterator->finishCreation(vm);
+    return iterator;
+}
+
+Structure* JSArrayIterator::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(JSArrayIteratorType, StructureFlags), info());
+}
+
+JSArrayIterator::JSArrayIterator(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{
+}
+
+void JSArrayIterator::finishCreation(VM& vm)
+{
+    auto values = initialValues();
+    for (unsigned index = 0; index < values.size(); ++index)
+        Base::internalField(index).set(vm, this, values[index]);
+    Base::finishCreation(vm);
+}
+
+void JSArrayIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    auto* thisObject = jsCast<JSArrayIterator*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSArrayIterator.h b/Source/JavaScriptCore/runtime/JSArrayIterator.h
new file mode 100644 (file)
index 0000000..b5ea8d8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSInternalFieldObjectImpl.h"
+
+namespace JSC {
+
+class JSArrayIterator final : public JSInternalFieldObjectImpl<4> {
+public:
+    using Base = JSInternalFieldObjectImpl<4>;
+
+    enum class Field : uint8_t { 
+        Index = 0,
+        IsDone,
+        IteratedObject,
+        Kind,
+    };
+
+    // JSArrayIterator has one inline storage slot, which is pointing internalField(0).
+    static size_t allocationSize(Checked<size_t> inlineCapacity)
+    {
+        ASSERT_UNUSED(inlineCapacity, inlineCapacity == 0U);
+        return sizeof(JSArrayIterator);
+    }
+    
+    template<typename CellType, SubspaceAccess mode>
+    static IsoSubspace* subspaceFor(VM& vm)
+    {
+        return vm.arrayIteratorSpace<mode>();
+    }
+
+    static std::array<JSValue, numberOfInternalFields> initialValues()
+    {
+        return { {
+            jsNumber(0),
+            jsBoolean(false),
+            jsNull(),
+            jsNumber(0),
+        } };
+    }
+
+    const WriteBarrier<Unknown>& internalField(Field field) const { return Base::internalField(static_cast<uint32_t>(field)); }
+    WriteBarrier<Unknown>& internalField(Field field) { return Base::internalField(static_cast<uint32_t>(field)); }
+
+    IterationKind kind() const { return static_cast<IterationKind>(internalField(Field::Kind).get().asUInt32()); }
+    JSObject* iteratedObject() const { return jsCast<JSObject*>(internalField(Field::IteratedObject).get()); }
+
+    static JSArrayIterator* create(VM&, Structure*, JSObject* iteratedObject, JSValue kind);
+    static JSArrayIterator* createWithInitialValues(VM&, Structure*);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    DECLARE_INFO;
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+private:
+    JSArrayIterator(VM&, Structure*);
+    void finishCreation(VM&);
+};
+
+} // namespace JSC
index 58c1aee..1bdc82f 100644 (file)
@@ -79,6 +79,7 @@
 #include "JSArrayBuffer.h"
 #include "JSArrayBufferConstructor.h"
 #include "JSArrayBufferPrototype.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncFunction.h"
 #include "JSAsyncGeneratorFunction.h"
 #include "JSBigInt.h"
@@ -558,7 +559,7 @@ void JSGlobalObject::init(VM& vm)
         });
     m_arrayProtoValuesFunction.initLater(
         [] (const Initializer<JSFunction>& init) {
-            init.set(JSFunction::create(init.vm, arrayPrototypeValuesCodeGenerator(init.vm), init.owner));
+            init.set(JSFunction::create(init.vm, init.owner, 0, init.vm.propertyNames->values.string(), arrayProtoFuncValues, ArrayValuesIntrinsic));
         });
 
     m_iteratorProtocolFunction.initLater(
@@ -755,6 +756,10 @@ void JSGlobalObject::init(VM& vm)
     m_generatorPrototype.set(vm, this, GeneratorPrototype::create(vm, this, GeneratorPrototype::createStructure(vm, this, m_iteratorPrototype.get())));
     m_asyncGeneratorPrototype.set(vm, this, AsyncGeneratorPrototype::create(vm, this, AsyncGeneratorPrototype::createStructure(vm, this, m_asyncIteratorPrototype.get())));
 
+    auto* arrayIteratorPrototype = ArrayIteratorPrototype::create(vm, this, ArrayIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
+    m_arrayIteratorPrototype.set(vm, this, arrayIteratorPrototype);
+    m_arrayIteratorStructure.set(vm, this, JSArrayIterator::createStructure(vm, this, arrayIteratorPrototype));
+
     JSFunction* defaultPromiseThen = JSFunction::create(vm, promisePrototypeThenCodeGenerator(vm), this);
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::defaultPromiseThen)].set(vm, this, defaultPromiseThen);
 
@@ -992,9 +997,6 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
 
     // FIXME: Initializing them lazily.
     // https://bugs.webkit.org/show_bug.cgi?id=203795
-    JSObject* arrayIteratorPrototype = ArrayIteratorPrototype::create(vm, this, ArrayIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
-    jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::ArrayIterator))->putDirect(vm, vm.propertyNames->prototype, arrayIteratorPrototype);
-
     JSObject* asyncFromSyncIteratorPrototype = AsyncFromSyncIteratorPrototype::create(vm, this, AsyncFromSyncIteratorPrototype::createStructure(vm, this, m_iteratorPrototype.get()));
     jsCast<JSObject*>(linkTimeConstant(LinkTimeConstant::AsyncFromSyncIterator))->putDirect(vm, vm.propertyNames->prototype, asyncFromSyncIteratorPrototype);
 
@@ -1216,6 +1218,7 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
 
 #undef CREATE_PROTOTYPE_FOR_LAZY_TYPE
 
+
     {
         ObjectPropertyCondition condition = setupAdaptiveWatchpoint(this, arrayIteratorPrototype, vm.propertyNames->next);
         m_arrayIteratorPrototypeNext = makeUnique<ObjectPropertyChangeAdaptiveWatchpoint<InlineWatchpointSet>>(this, condition, m_arrayIteratorProtocolWatchpointSet);
@@ -1762,6 +1765,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(thisObject->m_iteratorPrototype);
     visitor.append(thisObject->m_generatorFunctionPrototype);
     visitor.append(thisObject->m_generatorPrototype);
+    visitor.append(thisObject->m_arrayIteratorPrototype);
     visitor.append(thisObject->m_asyncFunctionPrototype);
     visitor.append(thisObject->m_asyncGeneratorPrototype);
     visitor.append(thisObject->m_asyncIteratorPrototype);
@@ -1812,6 +1816,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(thisObject->m_asyncGeneratorFunctionStructure);
     visitor.append(thisObject->m_generatorStructure);
     visitor.append(thisObject->m_asyncGeneratorStructure);
+    visitor.append(thisObject->m_arrayIteratorStructure);
     thisObject->m_iteratorResultObjectStructure.visit(visitor);
     visitor.append(thisObject->m_regExpMatchesArrayStructure);
     thisObject->m_moduleRecordStructure.visit(visitor);
index ce3df49..4a8fdc6 100644 (file)
@@ -62,6 +62,7 @@ class JSGlobalObjectInspectorController;
 namespace JSC {
 class ArrayConstructor;
 class ArrayPrototype;
+class ArrayIteratorPrototype;
 class AsyncIteratorPrototype;
 class AsyncFunctionPrototype;
 class AsyncGeneratorPrototype;
@@ -321,6 +322,7 @@ public:
     WriteBarrier<GeneratorFunctionPrototype> m_generatorFunctionPrototype;
     WriteBarrier<GeneratorPrototype> m_generatorPrototype;
     WriteBarrier<AsyncGeneratorPrototype> m_asyncGeneratorPrototype;
+    WriteBarrier<ArrayIteratorPrototype> m_arrayIteratorPrototype;
 
     LazyProperty<JSGlobalObject, Structure> m_debuggerScopeStructure;
     LazyProperty<JSGlobalObject, Structure> m_withScopeStructure;
@@ -375,6 +377,7 @@ public:
     WriteBarrier<Structure> m_generatorFunctionStructure;
     WriteBarrier<Structure> m_generatorStructure;
     WriteBarrier<Structure> m_asyncGeneratorStructure;
+    WriteBarrier<Structure> m_arrayIteratorStructure;
     LazyProperty<JSGlobalObject, Structure> m_iteratorResultObjectStructure;
     WriteBarrier<Structure> m_regExpMatchesArrayStructure;
     LazyProperty<JSGlobalObject, Structure> m_moduleRecordStructure;
@@ -652,6 +655,7 @@ public:
     GeneratorFunctionPrototype* generatorFunctionPrototype() const { return m_generatorFunctionPrototype.get(); }
     GeneratorPrototype* generatorPrototype() const { return m_generatorPrototype.get(); }
     AsyncFunctionPrototype* asyncFunctionPrototype() const { return m_asyncFunctionPrototype.get(); }
+    ArrayIteratorPrototype* arrayIteratorPrototype() const { return m_arrayIteratorPrototype.get(); }
     JSObject* mapPrototype() const { return m_mapStructure.prototype(this); }
     // Workaround for the name conflict between JSCell::setPrototype.
     JSObject* jsSetPrototype() const { return m_setStructure.prototype(this); }
@@ -759,6 +763,7 @@ public:
     Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); }
     Structure* asyncFunctionStructure() const { return m_asyncFunctionStructure.get(); }
     Structure* asyncGeneratorFunctionStructure() const { return m_asyncGeneratorFunctionStructure.get(); }
+    Structure* arrayIteratorStructure() const { return m_arrayIteratorStructure.get(); }    
     Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
     Structure* iteratorResultObjectStructure() const { return m_iteratorResultObjectStructure.get(this); }
     Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
index fef725d..760b19e 100644 (file)
@@ -79,9 +79,9 @@ public:
         if (!bucket)
             return false;
 
-        if (m_kind == IterateValue)
+        if (m_kind == IterationKind::Values)
             value = bucket->value();
-        else if (m_kind == IterateKey)
+        else if (m_kind == IterationKind::Keys)
             value = bucket->key();
         else
             value = createPair(globalObject, bucket->key(), bucket->value());
index 5d7d94d..0558673 100644 (file)
@@ -80,7 +80,7 @@ public:
         if (!bucket)
             return false;
 
-        if (m_kind == IterateValue || m_kind == IterateKey)
+        if (m_kind == IterationKind::Values || m_kind == IterationKind::Keys)
             value = bucket->key();
         else
             value = createPair(globalObject, bucket->key(), bucket->key());
index 251edc8..1038dc5 100644 (file)
@@ -99,6 +99,7 @@ void printInternal(PrintStream& out, JSC::JSType type)
     CASE(ProxyObjectType)
     CASE(JSGeneratorType)
     CASE(JSAsyncGeneratorType)
+    CASE(JSArrayIteratorType)
     CASE(JSPromiseType)
     CASE(JSMapType)
     CASE(JSSetType)
index addf769..d279f00 100644 (file)
@@ -110,6 +110,7 @@ enum JSType : uint8_t {
     ProxyObjectType,
     JSGeneratorType,
     JSAsyncGeneratorType,
+    JSArrayIteratorType,
     JSPromiseType,
     JSMapType,
     JSSetType,
index bf43c64..29a1167 100644 (file)
@@ -29,6 +29,7 @@
 #include "BuiltinNames.h"
 #include "CallFrame.h"
 #include "GetterSetter.h"
+#include "JSArrayIterator.h"
 #include "JSCInlines.h"
 #include "JSFunction.h"
 #include "JSGenericTypedArrayViewPrototypeFunctions.h"
@@ -95,6 +96,37 @@ EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncGetOriginalConstructor(JSG
     return JSValue::encode(globalObject->typedArrayConstructor(type));
 }
 
+inline EncodedJSValue createTypedArrayIteratorObject(JSGlobalObject* globalObject, CallFrame* callFrame, IterationKind kind)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (!callFrame->thisValue().isCell() || !isTypedArrayType(callFrame->thisValue().asCell()->type()))
+        return throwVMTypeError(globalObject, scope, "Receiver should be a typed array view"_s);
+
+    JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(callFrame->thisValue());
+
+    if (thisObject->isNeutered())
+        return throwVMTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s);
+
+    return JSValue::encode(JSArrayIterator::create(vm, globalObject->arrayIteratorStructure(), thisObject, jsNumber(static_cast<unsigned>(kind))));
+}
+
+static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncValues(JSGlobalObject* globalObject, CallFrame* callFrame)
+{
+    return createTypedArrayIteratorObject(globalObject, callFrame, IterationKind::Values);
+}
+
+static EncodedJSValue JSC_HOST_CALL typedArrayProtoViewFuncEntries(JSGlobalObject* globalObject, CallFrame* callFrame)
+{
+    return createTypedArrayIteratorObject(globalObject, callFrame, IterationKind::Entries);
+}
+
+static EncodedJSValue JSC_HOST_CALL typedArrayViewProtoFuncKeys(JSGlobalObject* globalObject, CallFrame* callFrame)
+{
+    return createTypedArrayIteratorObject(globalObject, callFrame, IterationKind::Keys);
+}
+
 EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncSort(JSGlobalObject* globalObject, CallFrame* callFrame)
 {
     VM& vm = globalObject->vm();
@@ -303,7 +335,7 @@ void JSTypedArrayViewPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("every", typedArrayPrototypeEveryCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("filter", typedArrayPrototypeFilterCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("sort", typedArrayPrototypeSortCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().entriesPublicName(), typedArrayPrototypeEntriesCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->entries, typedArrayProtoViewFuncEntries, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, TypedArrayEntriesIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("includes", typedArrayViewProtoFuncIncludes, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("fill", typedArrayPrototypeFillCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("find", typedArrayPrototypeFindCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -311,7 +343,7 @@ void JSTypedArrayViewPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->forEach, typedArrayPrototypeForEachCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("indexOf", typedArrayViewProtoFuncIndexOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->join, typedArrayViewProtoFuncJoin, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
-    JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().keysPublicName(), typedArrayPrototypeKeysCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->keys, typedArrayViewProtoFuncKeys, static_cast<unsigned>(PropertyAttribute::DontEnum), 0, TypedArrayKeysIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("lastIndexOf", typedArrayViewProtoFuncLastIndexOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
     JSC_NATIVE_INTRINSIC_GETTER_WITHOUT_TRANSITION(vm.propertyNames->length, typedArrayViewProtoGetterFuncLength, static_cast<unsigned>(PropertyAttribute::DontEnum) | PropertyAttribute::ReadOnly, TypedArrayLengthIntrinsic);
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("map", typedArrayPrototypeMapCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -328,7 +360,7 @@ void JSTypedArrayViewPrototype::finishCreation(VM& vm, JSGlobalObject* globalObj
     GetterSetter* toStringTagAccessor = GetterSetter::create(vm, globalObject, toStringTagFunction, nullptr);
     putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->toStringTagSymbol, toStringTagAccessor, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly | PropertyAttribute::Accessor);
 
-    JSFunction* valuesFunction = JSFunction::create(vm, typedArrayPrototypeValuesCodeGenerator(vm), globalObject);
+    JSFunction* valuesFunction = JSFunction::create(vm, globalObject, 0, vm.propertyNames->values.string(), typedArrayViewProtoFuncValues, TypedArrayValuesIntrinsic);
 
     putDirectWithoutTransition(vm, vm.propertyNames->builtinNames().valuesPublicName(), valuesFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->iteratorSymbol, valuesFunction, static_cast<unsigned>(PropertyAttribute::DontEnum));
index e38a416..ac234dd 100644 (file)
@@ -86,6 +86,7 @@
 #include "JSArray.h"
 #include "JSArrayBuffer.h"
 #include "JSArrayBufferConstructor.h"
+#include "JSArrayIterator.h"
 #include "JSAsyncFunction.h"
 #include "JSBigInt.h"
 #include "JSBoundFunction.h"
@@ -1456,6 +1457,7 @@ DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(float32ArraySpace, cellHeapCellType.get(
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(float64ArraySpace, cellHeapCellType.get(), JSFloat64Array)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(functionRareDataSpace, destructibleCellHeapCellType.get(), FunctionRareData)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(generatorSpace, cellHeapCellType.get(), JSGenerator)
+DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(arrayIteratorSpace, cellHeapCellType.get(), JSArrayIterator)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(globalObjectSpace, globalObjectHeapCellType.get(), JSGlobalObject)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(jsModuleRecordSpace, jsModuleRecordHeapCellType.get(), JSModuleRecord)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(int8ArraySpace, cellHeapCellType.get(), JSInt8Array)
index abec994..824769c 100644 (file)
@@ -509,6 +509,7 @@ public:
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(float64ArraySpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(functionRareDataSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(generatorSpace)
+    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(arrayIteratorSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(globalObjectSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(int8ArraySpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(int16ArraySpace)
index 39eb252..59e786d 100644 (file)
@@ -1,3 +1,32 @@
+2020-01-08  Keith Miller  <keith_miller@apple.com>
+
+        [JSC] Introduce JSArrayIterator
+        https://bugs.webkit.org/show_bug.cgi?id=204043
+
+        Reviewed by Yusuke Suzuki.
+
+        JSDOMIterator should just use the JSC IterationKind enum. Also,
+        update other files for the enum member name changes.
+
+        * bindings/js/JSDOMIterator.h:
+        (WebCore::IteratorTraits>::asJS):
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::serialize):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateIterableDefinition):
+        * bindings/scripts/test/JS/JSTestInterface.cpp:
+        (WebCore::jsTestInterfacePrototypeFunctionEntriesCaller):
+        (WebCore::jsTestInterfacePrototypeFunctionKeysCaller):
+        (WebCore::jsTestInterfacePrototypeFunctionValuesCaller):
+        * bindings/scripts/test/JS/JSTestIterable.cpp:
+        (WebCore::jsTestIterablePrototypeFunctionEntriesCaller):
+        (WebCore::jsTestIterablePrototypeFunctionKeysCaller):
+        (WebCore::jsTestIterablePrototypeFunctionValuesCaller):
+        * bindings/scripts/test/JS/JSTestNode.cpp:
+        (WebCore::jsTestNodePrototypeFunctionEntriesCaller):
+        (WebCore::jsTestNodePrototypeFunctionKeysCaller):
+        (WebCore::jsTestNodePrototypeFunctionValuesCaller):
+
 2020-01-08  Yusuke Suzuki  <ysuzuki@apple.com>
 
         Reduce binary size by purging C++ type information in Objective-C fields and parameters
index 9003599..0c03cd4 100644 (file)
@@ -74,7 +74,7 @@ private:
     void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
 };
 
-enum class IterationKind { Key, Value, KeyValue };
+using IterationKind = JSC::IterationKind;
 
 template<typename JSWrapper, typename IteratorTraits> class JSDOMIterator : public JSDOMObject {
 public:
@@ -155,11 +155,11 @@ template<typename IteratorValue, typename T> inline EnableIfMap<T, JSC::JSValue>
     ASSERT(value);
     
     switch (m_kind) {
-    case IterationKind::Key:
+    case IterationKind::Keys:
         return toJS<typename Traits::KeyType>(lexicalGlobalObject, *globalObject(), value->key);
-    case IterationKind::Value:
+    case IterationKind::Values:
         return toJS<typename Traits::ValueType>(lexicalGlobalObject, *globalObject(), value->value);
-    case IterationKind::KeyValue:
+    case IterationKind::Entries:
         return jsPair<typename Traits::KeyType, typename Traits::ValueType>(lexicalGlobalObject, *globalObject(), value->key, value->value);
     };
     
@@ -176,10 +176,10 @@ template<typename IteratorValue, typename T> inline EnableIfSet<T, JSC::JSValue>
     auto result = toJS<typename Traits::ValueType>(lexicalGlobalObject, *globalObject, value);
 
     switch (m_kind) {
-    case IterationKind::Key:
-    case IterationKind::Value:
+    case IterationKind::Keys:
+    case IterationKind::Values:
         return result;
-    case IterationKind::KeyValue:
+    case IterationKind::Entries:
         return jsPair(lexicalGlobalObject, *globalObject, result, result);
     };
 
index 1817515..64dff2d 100644 (file)
@@ -1652,7 +1652,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                 JSMap* inMap = jsCast<JSMap*>(inValue);
                 if (!startMap(inMap))
                     break;
-                JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure(), inMap, IterateKeyValue);
+                JSMapIterator* iterator = JSMapIterator::create(vm, vm.mapIteratorStructure(), inMap, IterationKind::Entries);
                 m_gcBuffer.appendWithCrashOnOverflow(inMap);
                 m_gcBuffer.appendWithCrashOnOverflow(iterator);
                 mapIteratorStack.append(iterator);
@@ -1696,7 +1696,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
                 JSSet* inSet = jsCast<JSSet*>(inValue);
                 if (!startSet(inSet))
                     break;
-                JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure(), inSet, IterateKey);
+                JSSetIterator* iterator = JSSetIterator::create(vm, vm.setIteratorStructure(), inSet, IterationKind::Keys);
                 m_gcBuffer.appendWithCrashOnOverflow(inSet);
                 m_gcBuffer.appendWithCrashOnOverflow(iterator);
                 setIteratorStack.append(iterator);
index 229b30d..1dec78f 100644 (file)
@@ -6467,10 +6467,10 @@ static inline EncodedJSValue ${functionName}Caller(JSGlobalObject* lexicalGlobal
 
 END
         } else {
-            my $iterationKind = "KeyValue";
-            $iterationKind = "Key" if $propertyName eq "keys";
-            $iterationKind = "Value" if $propertyName eq "values";
-            $iterationKind = "Value" if $propertyName eq "entries" and not $interface->iterable->isKeyValue;
+            my $iterationKind = "Entries";
+            $iterationKind = "Keys" if $propertyName eq "keys";
+            $iterationKind = "Values" if $propertyName eq "values";
+            $iterationKind = "Values" if $propertyName eq "entries" and not $interface->iterable->isKeyValue;
 
             push(@implContent,  <<END);
 static inline EncodedJSValue ${functionName}Caller(JSGlobalObject*, CallFrame*, JS$interfaceName* thisObject, JSC::ThrowScope&)
index 94fbae9..da05559 100644 (file)
@@ -1069,7 +1069,7 @@ const JSC::ClassInfo TestInterfaceIteratorPrototype::s_info = { "TestInterface I
 
 static inline EncodedJSValue jsTestInterfacePrototypeFunctionEntriesCaller(JSGlobalObject*, CallFrame*, JSTestInterface* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestInterfaceIterator>(*thisObject, IterationKind::KeyValue));
+    return JSValue::encode(iteratorCreate<TestInterfaceIterator>(*thisObject, IterationKind::Entries));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestInterfacePrototypeFunctionEntries(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
@@ -1079,7 +1079,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestInterfacePrototypeFunctionEntries(JSC::J
 
 static inline EncodedJSValue jsTestInterfacePrototypeFunctionKeysCaller(JSGlobalObject*, CallFrame*, JSTestInterface* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestInterfaceIterator>(*thisObject, IterationKind::Key));
+    return JSValue::encode(iteratorCreate<TestInterfaceIterator>(*thisObject, IterationKind::Keys));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestInterfacePrototypeFunctionKeys(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
@@ -1089,7 +1089,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestInterfacePrototypeFunctionKeys(JSC::JSGl
 
 static inline EncodedJSValue jsTestInterfacePrototypeFunctionValuesCaller(JSGlobalObject*, CallFrame*, JSTestInterface* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestInterfaceIterator>(*thisObject, IterationKind::Value));
+    return JSValue::encode(iteratorCreate<TestInterfaceIterator>(*thisObject, IterationKind::Values));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestInterfacePrototypeFunctionValues(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
index e879665..16b62a3 100644 (file)
@@ -201,7 +201,7 @@ const JSC::ClassInfo TestIterableIteratorPrototype::s_info = { "TestIterable Ite
 
 static inline EncodedJSValue jsTestIterablePrototypeFunctionEntriesCaller(JSGlobalObject*, CallFrame*, JSTestIterable* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestIterableIterator>(*thisObject, IterationKind::Value));
+    return JSValue::encode(iteratorCreate<TestIterableIterator>(*thisObject, IterationKind::Values));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestIterablePrototypeFunctionEntries(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
@@ -211,7 +211,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestIterablePrototypeFunctionEntries(JSC::JS
 
 static inline EncodedJSValue jsTestIterablePrototypeFunctionKeysCaller(JSGlobalObject*, CallFrame*, JSTestIterable* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestIterableIterator>(*thisObject, IterationKind::Key));
+    return JSValue::encode(iteratorCreate<TestIterableIterator>(*thisObject, IterationKind::Keys));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestIterablePrototypeFunctionKeys(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
@@ -221,7 +221,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestIterablePrototypeFunctionKeys(JSC::JSGlo
 
 static inline EncodedJSValue jsTestIterablePrototypeFunctionValuesCaller(JSGlobalObject*, CallFrame*, JSTestIterable* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestIterableIterator>(*thisObject, IterationKind::Value));
+    return JSValue::encode(iteratorCreate<TestIterableIterator>(*thisObject, IterationKind::Values));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestIterablePrototypeFunctionValues(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
index 97f3f9e..eb7acdc 100644 (file)
@@ -374,7 +374,7 @@ const JSC::ClassInfo TestNodeIteratorPrototype::s_info = { "TestNode Iterator",
 
 static inline EncodedJSValue jsTestNodePrototypeFunctionEntriesCaller(JSGlobalObject*, CallFrame*, JSTestNode* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestNodeIterator>(*thisObject, IterationKind::Value));
+    return JSValue::encode(iteratorCreate<TestNodeIterator>(*thisObject, IterationKind::Values));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestNodePrototypeFunctionEntries(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
@@ -384,7 +384,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestNodePrototypeFunctionEntries(JSC::JSGlob
 
 static inline EncodedJSValue jsTestNodePrototypeFunctionKeysCaller(JSGlobalObject*, CallFrame*, JSTestNode* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestNodeIterator>(*thisObject, IterationKind::Key));
+    return JSValue::encode(iteratorCreate<TestNodeIterator>(*thisObject, IterationKind::Keys));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestNodePrototypeFunctionKeys(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)
@@ -394,7 +394,7 @@ JSC::EncodedJSValue JSC_HOST_CALL jsTestNodePrototypeFunctionKeys(JSC::JSGlobalO
 
 static inline EncodedJSValue jsTestNodePrototypeFunctionValuesCaller(JSGlobalObject*, CallFrame*, JSTestNode* thisObject, JSC::ThrowScope&)
 {
-    return JSValue::encode(iteratorCreate<TestNodeIterator>(*thisObject, IterationKind::Value));
+    return JSValue::encode(iteratorCreate<TestNodeIterator>(*thisObject, IterationKind::Values));
 }
 
 JSC::EncodedJSValue JSC_HOST_CALL jsTestNodePrototypeFunctionValues(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame)