[JSC] AsyncGenerator should have internal fields
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Oct 2019 21:23:09 +0000 (21:23 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 2 Oct 2019 21:23:09 +0000 (21:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=201498

Reviewed by Saam Barati.

JSTests:

* stress/async-generator-construct-failure.js: Added.
(shouldThrow):
(async.gen):
(TypeError):
* stress/async-generator-prototype-change.js: Added.
(shouldBe):
(async.gen):
* stress/async-generator-prototype-closure.js: Added.
(shouldBe):
(test.async.gen):
(test):
* stress/create-async-generator.js: Added.
(shouldBe):
(test.async.generator):
(test):

Source/JavaScriptCore:

This patch introduces JSAsyncGenerator. We did this already for JSGenerator. This patch does the same thing for JSAsyncGenerator
This patch cleans up JSGenerator's code to share it with JSAsyncGenerator, e.g. JSGenerator::initialValues etc.
It improves JetStream2/async-fs by ~10%.

We also fixed the pre-existing bug. We are using OpcodeID for the key of hashmap. And using op_add code as a part of key.
By adding a new bytecode, it suddenly becomes 0. And 0 is not valid key in WTF::HashMap. This patch adds 1 to opcodeID when using
for HashMap's key to fix this issue.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* builtins/AsyncGeneratorPrototype.js:
(globalPrivate.asyncGeneratorQueueIsEmpty):
(globalPrivate.asyncGeneratorQueueEnqueue):
(globalPrivate.asyncGeneratorQueueDequeue):
(globalPrivate.isExecutionState):
(globalPrivate.isSuspendYieldState):
(globalPrivate.asyncGeneratorReject):
(globalPrivate.asyncGeneratorResolve):
(asyncGeneratorYieldAwaited):
(globalPrivate.asyncGeneratorYield):
(globalPrivate.doAsyncGeneratorBodyCall):
(globalPrivate.asyncGeneratorResumeNext):
(globalPrivate.asyncGeneratorEnqueue):
* builtins/BuiltinNames.h:
* bytecode/BytecodeIntrinsicRegistry.cpp:
(JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
* bytecode/BytecodeIntrinsicRegistry.h:
* bytecode/BytecodeList.rb:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finalizeLLIntInlineCaches):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):
(JSC::BytecodeGenerator::emitCreateAsyncGenerator):
(JSC::BytecodeGenerator::emitYieldPoint):
(JSC::BytecodeGenerator::emitYield):
(JSC::BytecodeGenerator::emitAwait):
(JSC::BytecodeGenerator::emitDelegateYield):
(JSC::BytecodeGenerator::emitGeneratorStateChange):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitIsAsyncGenerator):
* bytecompiler/NodesCodegen.cpp:
(JSC::asyncGeneratorInternalFieldIndex):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_getAsyncGeneratorInternalField):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_putAsyncGeneratorInternalField):
(JSC::BytecodeIntrinsicNode::emit_intrinsic_isAsyncGenerator):
(JSC::YieldExprNode::emitBytecode):
(JSC::AwaitExprNode::emitBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::handleCreateInternalFieldObject):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* 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/DFGNode.h:
(JSC::DFG::Node::convertToNewInternalFieldObject):
(JSC::DFG::Node::hasStructure):
(JSC::DFG::Node::convertToNewGenerator): Deleted.
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCreateInternalFieldObject):
(JSC::DFG::SpeculativeJIT::compileCreateGenerator):
(JSC::DFG::SpeculativeJIT::compileCreateAsyncGenerator):
(JSC::DFG::SpeculativeJIT::compileNewInternalFieldObject):
(JSC::DFG::SpeculativeJIT::compileNewGenerator):
(JSC::DFG::SpeculativeJIT::compileNewAsyncGenerator):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileNewInternalFieldObject):
(JSC::FTL::DFG::LowerDFGToB3::compileNewGenerator):
(JSC::FTL::DFG::LowerDFGToB3::compileNewAsyncGenerator):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateInternalFieldObject):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateGenerator):
(JSC::FTL::DFG::LowerDFGToB3::compileCreateAsyncGenerator):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JITInlines.h:
(JSC::JIT::copiedArithProfile):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LowLevelInterpreter.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::createInternalFieldObject):
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* runtime/JSAsyncGenerator.cpp: Copied from Source/JavaScriptCore/runtime/JSGenerator.cpp.
(JSC::JSAsyncGenerator::create):
(JSC::JSAsyncGenerator::createStructure):
(JSC::JSAsyncGenerator::JSAsyncGenerator):
(JSC::JSAsyncGenerator::finishCreation):
(JSC::JSAsyncGenerator::visitChildren):
* runtime/JSAsyncGenerator.h: Copied from Source/JavaScriptCore/runtime/JSGenerator.h.
* runtime/JSAsyncGeneratorFunction.h:
* runtime/JSGenerator.cpp:
(JSC::JSGenerator::finishCreation):
* runtime/JSGenerator.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::asyncGeneratorStructure const):
* runtime/JSType.cpp:
(WTF::printInternal):
* runtime/JSType.h:

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

55 files changed:
JSTests/ChangeLog
JSTests/stress/async-generator-construct-failure.js [new file with mode: 0644]
JSTests/stress/async-generator-prototype-change.js [new file with mode: 0644]
JSTests/stress/async-generator-prototype-closure.js [new file with mode: 0644]
JSTests/stress/create-async-generator.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/builtins/AsyncGeneratorPrototype.js
Source/JavaScriptCore/builtins/BuiltinNames.h
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.cpp
Source/JavaScriptCore/bytecode/BytecodeIntrinsicRegistry.h
Source/JavaScriptCore/bytecode/BytecodeList.rb
Source/JavaScriptCore/bytecode/BytecodeUseDef.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.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/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
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/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JITInlines.h
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITOperations.h
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/JSAsyncGenerator.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSAsyncGenerator.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSAsyncGeneratorFunction.h
Source/JavaScriptCore/runtime/JSGenerator.cpp
Source/JavaScriptCore/runtime/JSGenerator.h
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSType.cpp
Source/JavaScriptCore/runtime/JSType.h

index c085e5f..0740cb6 100644 (file)
@@ -1,3 +1,26 @@
+2019-10-02  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] AsyncGenerator should have internal fields
+        https://bugs.webkit.org/show_bug.cgi?id=201498
+
+        Reviewed by Saam Barati.
+
+        * stress/async-generator-construct-failure.js: Added.
+        (shouldThrow):
+        (async.gen):
+        (TypeError):
+        * stress/async-generator-prototype-change.js: Added.
+        (shouldBe):
+        (async.gen):
+        * stress/async-generator-prototype-closure.js: Added.
+        (shouldBe):
+        (test.async.gen):
+        (test):
+        * stress/create-async-generator.js: Added.
+        (shouldBe):
+        (test.async.generator):
+        (test):
+
 2019-10-01  Saam Barati  <sbarati@apple.com>
 
         ObjectAllocationSinkingPhase shouldn't insert hints for allocations which are no longer valid
diff --git a/JSTests/stress/async-generator-construct-failure.js b/JSTests/stress/async-generator-construct-failure.js
new file mode 100644 (file)
index 0000000..f353e6e
--- /dev/null
@@ -0,0 +1,24 @@
+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+async function* gen() { }
+
+shouldThrow(() => {
+    new gen()
+}, `TypeError: function is not a constructor (evaluating 'new gen()')`);
+
+shouldThrow(() => {
+    Reflect.construct(gen, [], {});
+}, `TypeError: Reflect.construct requires the first argument be a constructor`);
diff --git a/JSTests/stress/async-generator-prototype-change.js b/JSTests/stress/async-generator-prototype-change.js
new file mode 100644 (file)
index 0000000..45899e7
--- /dev/null
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+async function* gen()
+{
+}
+var originalPrototype = gen.prototype;
+
+for (var i = 0; i < 1e6; ++i) {
+    var g = gen();
+    shouldBe(g.__proto__, gen.prototype);
+}
+gen.prototype = {};
+var g = gen();
+shouldBe(g.__proto__, gen.prototype);
+shouldBe(g.__proto__ !== originalPrototype, true);
diff --git a/JSTests/stress/async-generator-prototype-closure.js b/JSTests/stress/async-generator-prototype-closure.js
new file mode 100644 (file)
index 0000000..dabd57d
--- /dev/null
@@ -0,0 +1,22 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test() {
+    async function* gen()
+    {
+    }
+    var originalPrototype = gen.prototype;
+
+    var g = gen();
+    shouldBe(g.__proto__, gen.prototype);
+    gen.prototype = {};
+    var g = gen();
+    shouldBe(g.__proto__, gen.prototype);
+    shouldBe(g.__proto__ !== originalPrototype, true);
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i)
+    test();
diff --git a/JSTests/stress/create-async-generator.js b/JSTests/stress/create-async-generator.js
new file mode 100644 (file)
index 0000000..488b26a
--- /dev/null
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test() {
+    async function* generator() {
+        return this;
+    }
+
+    var g = generator();
+    shouldBe(g.__proto__, generator.prototype);
+    return g;
+}
+
+for (var i = 0; i < 1e6; ++i) {
+    var g1 = test();
+    var g2 = test();
+    shouldBe(g1.__proto__ != g2.__proto__, true);
+}
index 4283a6a..87a4306 100644 (file)
@@ -1,3 +1,143 @@
+2019-10-02  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [JSC] AsyncGenerator should have internal fields
+        https://bugs.webkit.org/show_bug.cgi?id=201498
+
+        Reviewed by Saam Barati.
+
+        This patch introduces JSAsyncGenerator. We did this already for JSGenerator. This patch does the same thing for JSAsyncGenerator
+        This patch cleans up JSGenerator's code to share it with JSAsyncGenerator, e.g. JSGenerator::initialValues etc.
+        It improves JetStream2/async-fs by ~10%.
+
+        We also fixed the pre-existing bug. We are using OpcodeID for the key of hashmap. And using op_add code as a part of key.
+        By adding a new bytecode, it suddenly becomes 0. And 0 is not valid key in WTF::HashMap. This patch adds 1 to opcodeID when using
+        for HashMap's key to fix this issue.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * builtins/AsyncGeneratorPrototype.js:
+        (globalPrivate.asyncGeneratorQueueIsEmpty):
+        (globalPrivate.asyncGeneratorQueueEnqueue):
+        (globalPrivate.asyncGeneratorQueueDequeue):
+        (globalPrivate.isExecutionState):
+        (globalPrivate.isSuspendYieldState):
+        (globalPrivate.asyncGeneratorReject):
+        (globalPrivate.asyncGeneratorResolve):
+        (asyncGeneratorYieldAwaited):
+        (globalPrivate.asyncGeneratorYield):
+        (globalPrivate.doAsyncGeneratorBodyCall):
+        (globalPrivate.asyncGeneratorResumeNext):
+        (globalPrivate.asyncGeneratorEnqueue):
+        * builtins/BuiltinNames.h:
+        * bytecode/BytecodeIntrinsicRegistry.cpp:
+        (JSC::BytecodeIntrinsicRegistry::BytecodeIntrinsicRegistry):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecode/BytecodeList.rb:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finalizeLLIntInlineCaches):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitPutAsyncGeneratorFields):
+        (JSC::BytecodeGenerator::emitCreateAsyncGenerator):
+        (JSC::BytecodeGenerator::emitYieldPoint):
+        (JSC::BytecodeGenerator::emitYield):
+        (JSC::BytecodeGenerator::emitAwait):
+        (JSC::BytecodeGenerator::emitDelegateYield):
+        (JSC::BytecodeGenerator::emitGeneratorStateChange):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitIsAsyncGenerator):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::asyncGeneratorInternalFieldIndex):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_getAsyncGeneratorInternalField):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_putAsyncGeneratorInternalField):
+        (JSC::BytecodeIntrinsicNode::emit_intrinsic_isAsyncGenerator):
+        (JSC::YieldExprNode::emitBytecode):
+        (JSC::AwaitExprNode::emitBytecode):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::handleCreateInternalFieldObject):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * 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/DFGNode.h:
+        (JSC::DFG::Node::convertToNewInternalFieldObject):
+        (JSC::DFG::Node::hasStructure):
+        (JSC::DFG::Node::convertToNewGenerator): Deleted.
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCreateInternalFieldObject):
+        (JSC::DFG::SpeculativeJIT::compileCreateGenerator):
+        (JSC::DFG::SpeculativeJIT::compileCreateAsyncGenerator):
+        (JSC::DFG::SpeculativeJIT::compileNewInternalFieldObject):
+        (JSC::DFG::SpeculativeJIT::compileNewGenerator):
+        (JSC::DFG::SpeculativeJIT::compileNewAsyncGenerator):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStoreBarrierInsertionPhase.cpp:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewInternalFieldObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewGenerator):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewAsyncGenerator):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateInternalFieldObject):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateGenerator):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCreateAsyncGenerator):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JITInlines.h:
+        (JSC::JIT::copiedArithProfile):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * llint/LowLevelInterpreter.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::createInternalFieldObject):
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+        * runtime/JSAsyncGenerator.cpp: Copied from Source/JavaScriptCore/runtime/JSGenerator.cpp.
+        (JSC::JSAsyncGenerator::create):
+        (JSC::JSAsyncGenerator::createStructure):
+        (JSC::JSAsyncGenerator::JSAsyncGenerator):
+        (JSC::JSAsyncGenerator::finishCreation):
+        (JSC::JSAsyncGenerator::visitChildren):
+        * runtime/JSAsyncGenerator.h: Copied from Source/JavaScriptCore/runtime/JSGenerator.h.
+        * runtime/JSAsyncGeneratorFunction.h:
+        * runtime/JSGenerator.cpp:
+        (JSC::JSGenerator::finishCreation):
+        * runtime/JSGenerator.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildren):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::asyncGeneratorStructure const):
+        * runtime/JSType.cpp:
+        (WTF::printInternal):
+        * runtime/JSType.h:
+
 2019-10-02  Keith Miller  <keith_miller@apple.com>
 
         FTL OSR exit shouldn't bother updating get_by_id array profiles that have changed modes
index afa7e32..3e9d4c9 100644 (file)
                E39D8B2E23021E2600265852 /* WasmOperations.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D8B2D23021E1E00265852 /* WasmOperations.h */; };
                E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E39EEAF322812450008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */; };
+               E39FEBE32339C5D900B40AB0 /* JSAsyncGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = E39FEBE22339C5D400B40AB0 /* JSAsyncGenerator.h */; };
                E3A0531A21342B680022EC14 /* WasmStreamingParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A0531621342B660022EC14 /* WasmStreamingParser.h */; };
                E3A0531C21342B680022EC14 /* WasmSectionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A0531821342B670022EC14 /* WasmSectionParser.h */; };
                E3A32BC71FC83147007D7E76 /* WeakMapImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A32BC61FC8312E007D7E76 /* WeakMapImpl.h */; };
                E39E030D22D9EA3E00408C18 /* WebAssembly.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = WebAssembly.js; sourceTree = "<group>"; };
                E39EEAF12281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectToStringAdaptiveStructureWatchpoint.cpp; sourceTree = "<group>"; };
                E39EEAF22281244C008474F4 /* ObjectToStringAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjectToStringAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; };
+               E39FEBE12339C5D400B40AB0 /* JSAsyncGenerator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSAsyncGenerator.cpp; sourceTree = "<group>"; };
+               E39FEBE22339C5D400B40AB0 /* JSAsyncGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSAsyncGenerator.h; sourceTree = "<group>"; };
                E3A0531621342B660022EC14 /* WasmStreamingParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmStreamingParser.h; sourceTree = "<group>"; };
                E3A0531721342B660022EC14 /* WasmSectionParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmSectionParser.cpp; sourceTree = "<group>"; };
                E3A0531821342B670022EC14 /* WasmSectionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmSectionParser.h; sourceTree = "<group>"; };
                                539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */,
                                5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */,
                                5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */,
+                               E39FEBE12339C5D400B40AB0 /* JSAsyncGenerator.cpp */,
+                               E39FEBE22339C5D400B40AB0 /* JSAsyncGenerator.h */,
                                8BC064871E1A583F00B2B8CA /* JSAsyncGeneratorFunction.cpp */,
                                8BC064881E1A584000B2B8CA /* JSAsyncGeneratorFunction.h */,
                                868921C31F9C2947001159F6 /* JSBigInt.cpp */,
                                0F2B66EA17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h in Headers */,
                                539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */,
                                5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */,
+                               E39FEBE32339C5D900B40AB0 /* JSAsyncGenerator.h in Headers */,
                                8BC064891E1ABA6400B2B8CA /* JSAsyncGeneratorFunction.h in Headers */,
                                BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */,
                                79872C48221BBAF3008C6969 /* JSBaseInternal.h in Headers */,
index ba86676..a2e88b1 100644 (file)
@@ -809,6 +809,7 @@ runtime/JSArrayBufferConstructor.cpp
 runtime/JSArrayBufferPrototype.cpp
 runtime/JSArrayBufferView.cpp
 runtime/JSAsyncFunction.cpp
+runtime/JSAsyncGenerator.cpp
 runtime/JSAsyncGeneratorFunction.cpp
 runtime/JSBigInt.cpp
 runtime/JSBoundFunction.cpp
index 90de920..b0ac403 100644 (file)
@@ -29,7 +29,7 @@ function asyncGeneratorQueueIsEmpty(generator)
 {
     "use strict";
 
-    return @getByIdDirectPrivate(generator, "asyncGeneratorQueueFirst") === null;
+    return @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueFirst) === null;
 }
 
 @globalPrivate
@@ -39,15 +39,15 @@ function asyncGeneratorQueueEnqueue(generator, item)
 
     @assert(@getByIdDirectPrivate(item, "asyncGeneratorQueueItemNext") === null);
 
-    if (@getByIdDirectPrivate(generator, "asyncGeneratorQueueFirst") === null) {
-        @assert(@getByIdDirectPrivate(generator, "asyncGeneratorQueueLast") === null);
+    if (@getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueFirst) === null) {
+        @assert(@getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueLast) === null);
 
-        @putByIdDirectPrivate(generator, "asyncGeneratorQueueFirst", item);
-        @putByIdDirectPrivate(generator, "asyncGeneratorQueueLast", item);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueFirst, item);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueLast, item);
     } else {
-        var last = @getByIdDirectPrivate(generator, "asyncGeneratorQueueLast");
+        var last = @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueLast);
         @putByIdDirectPrivate(last, "asyncGeneratorQueueItemNext", item);
-        @putByIdDirectPrivate(generator, "asyncGeneratorQueueLast", item);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueLast, item);
     }
 }
 
@@ -58,13 +58,13 @@ function asyncGeneratorQueueDequeue(generator)
 
     @assert(!@asyncGeneratorQueueIsEmpty(generator), "Async genetator's Queue is an empty List.");
 
-    var result = @getByIdDirectPrivate(generator, "asyncGeneratorQueueFirst");
+    var result = @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueFirst);
 
     var updatedFirst = @getByIdDirectPrivate(result, "asyncGeneratorQueueItemNext");
-    @putByIdDirectPrivate(generator, "asyncGeneratorQueueFirst", updatedFirst);
+    @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueFirst, updatedFirst);
 
     if (updatedFirst === null)
-        @putByIdDirectPrivate(generator, "asyncGeneratorQueueLast", null);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueLast, null);
 
     return result;
 }
@@ -74,8 +74,8 @@ function isExecutionState(generator)
 {
     "use strict";
 
-    var state = @getByIdDirectPrivate(generator, "generatorState");
-    var reason = @getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason");
+    var state = @getAsyncGeneratorInternalField(generator, @generatorFieldState);
+    var reason = @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason);
     return (state > 0 && reason === @AsyncGeneratorSuspendReasonNone)
         || state === @AsyncGeneratorStateExecuting
         || reason === @AsyncGeneratorSuspendReasonAwait;
@@ -86,8 +86,8 @@ function isSuspendYieldState(generator)
 {
     "use strict";
 
-    var state = @getByIdDirectPrivate(generator, "generatorState");
-    return (state > 0 && @getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") === @AsyncGeneratorSuspendReasonYield)
+    var state = @getAsyncGeneratorInternalField(generator, @generatorFieldState);
+    return (state > 0 && @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason) === @AsyncGeneratorSuspendReasonYield)
         || state === @AsyncGeneratorStateSuspendedYield;
 }
 
@@ -96,7 +96,7 @@ function asyncGeneratorReject(generator, exception)
 {
     "use strict";
 
-    @assert(typeof @getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") === "number", "Generator is not an AsyncGenerator instance.");
+    @assert(@isAsyncGenerator(generator), "Generator is not an AsyncGenerator instance.");
 
     var promise = @asyncGeneratorQueueDequeue(generator).promise;
     @assert(@isPromise(promise));
@@ -110,7 +110,7 @@ function asyncGeneratorResolve(generator, value, done)
 {
     "use strict";
 
-    @assert(typeof @getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") === "number", "Generator is not an AsyncGenerator instance.");
+    @assert(@isAsyncGenerator(generator), "Generator is not an AsyncGenerator instance.");
 
     var promise = @asyncGeneratorQueueDequeue(generator).promise;
     @assert(@isPromise(promise));
@@ -126,11 +126,11 @@ function asyncGeneratorYield(generator, value, resumeMode)
 
     function asyncGeneratorYieldAwaited(result)
     {
-        @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonYield);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason, @AsyncGeneratorSuspendReasonYield);
         @asyncGeneratorResolve(generator, result, false);
     }
 
-    @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonAwait);
+    @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason, @AsyncGeneratorSuspendReasonAwait);
 
     @awaitValue(generator, value, asyncGeneratorYieldAwaited);
 }
@@ -150,34 +150,39 @@ function doAsyncGeneratorBodyCall(generator, resumeValue, resumeMode)
     "use strict";
 
     var value = @undefined;
-    var state = @getByIdDirectPrivate(generator, "generatorState");
+    var state = @getAsyncGeneratorInternalField(generator, @generatorFieldState);
 
-    @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateExecuting);
-    @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonNone);
+    @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateExecuting);
+    @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason, @AsyncGeneratorSuspendReasonNone);
 
     try {
-        value = @getByIdDirectPrivate(generator, "generatorNext").@call(@getByIdDirectPrivate(generator, "generatorThis"), generator, state, resumeValue, resumeMode, @getByIdDirectPrivate(generator, "generatorFrame"));
-        if (@getByIdDirectPrivate(generator, "generatorState") === @AsyncGeneratorStateExecuting)
-            @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
+        value = @getAsyncGeneratorInternalField(generator, @generatorFieldNext).@call(@getAsyncGeneratorInternalField(generator, @generatorFieldThis), generator, state, resumeValue, resumeMode, @getAsyncGeneratorInternalField(generator, @generatorFieldFrame));
+        state = @getAsyncGeneratorInternalField(generator, @generatorFieldState);
+        if (state === @AsyncGeneratorStateExecuting) {
+            @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateCompleted);
+            state = @AsyncGeneratorStateCompleted;
+        }
     } catch (error) {
-        @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
-        @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonNone);
+        @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateCompleted);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason, @AsyncGeneratorSuspendReasonNone);
 
         return @asyncGeneratorReject(generator, error);
     }
 
-    if (@getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") === @AsyncGeneratorSuspendReasonAwait) {
+    var reason = @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason);
+    if (reason === @AsyncGeneratorSuspendReasonAwait) {
         var onFulfilled = function(result) { @doAsyncGeneratorBodyCall(generator, result, @GeneratorResumeModeNormal); };
 
         @awaitValue(generator, value, onFulfilled);
         return;
     }
 
-    if (@getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") === @AsyncGeneratorSuspendReasonYield)
+    if (reason === @AsyncGeneratorSuspendReasonYield)
         return @asyncGeneratorYield(generator, value, resumeMode);
 
-    if (@getByIdDirectPrivate(generator, "generatorState") === @AsyncGeneratorStateCompleted) {
-        @putByIdDirectPrivate(generator, "asyncGeneratorSuspendReason", @AsyncGeneratorSuspendReasonNone);
+    if (state === @AsyncGeneratorStateCompleted) {
+        @assert(@getAsyncGeneratorInternalField(generator, @generatorFieldState) == @AsyncGeneratorStateCompleted);
+        @putAsyncGeneratorInternalField(generator, @asyncGeneratorFieldSuspendReason, @AsyncGeneratorSuspendReasonNone);
         return @asyncGeneratorResolve(generator, value, true);
     }
 }
@@ -187,9 +192,9 @@ function asyncGeneratorResumeNext(generator)
 {
     "use strict";
 
-    @assert(typeof @getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") === "number", "Generator is not an AsyncGenerator instance.");
+    @assert(@isAsyncGenerator(generator), "Generator is not an AsyncGenerator instance.");
 
-    var state = @getByIdDirectPrivate(generator, "generatorState");
+    var state = @getAsyncGeneratorInternalField(generator, @generatorFieldState);
 
     @assert(state !== @AsyncGeneratorStateExecuting, "Async generator should not be in executing state");
 
@@ -199,24 +204,24 @@ function asyncGeneratorResumeNext(generator)
     if (@asyncGeneratorQueueIsEmpty(generator))
         return;
 
-    var next = @getByIdDirectPrivate(generator, "asyncGeneratorQueueFirst");
+    var next = @getAsyncGeneratorInternalField(generator, @asyncGeneratorFieldQueueFirst);
 
     if (next.resumeMode !== @GeneratorResumeModeNormal) {
         if (state === @AsyncGeneratorStateSuspendedStart) {
-            @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
+            @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateCompleted);
             state = @AsyncGeneratorStateCompleted;
         }
 
         if (state === @AsyncGeneratorStateCompleted) {
             if (next.resumeMode === @GeneratorResumeModeReturn) {
-                @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateAwaitingReturn);
+                @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateAwaitingReturn);
                 @resolveWithoutPromise(next.value,
                     function (result) {
-                        @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
+                        @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateCompleted);
                         @asyncGeneratorResolve(generator, result, true);
                     },
                     function (error) {
-                        @putByIdDirectPrivate(generator, "generatorState", @AsyncGeneratorStateCompleted);
+                        @putAsyncGeneratorInternalField(generator, @generatorFieldState, @AsyncGeneratorStateCompleted);
                         @asyncGeneratorReject(generator, error);
                     });
                 return;
@@ -240,7 +245,7 @@ function asyncGeneratorEnqueue(generator, value, resumeMode)
     "use strict";
 
     var promise = @newPromise();
-    if (!@isObject(generator) || typeof @getByIdDirectPrivate(generator, "asyncGeneratorSuspendReason") !== 'number') {
+    if (!@isAsyncGenerator(generator)) {
         @rejectPromiseWithFirstResolvingFunctionCallCheck(promise, @makeTypeError('|this| should be an async generator'));
         return promise;
     }
index 35c1040..4880659 100644 (file)
@@ -108,15 +108,10 @@ namespace JSC {
     macro(generatorFrame) \
     macro(generatorValue) \
     macro(generatorThis) \
+    macro(generatorResumeMode) \
     macro(syncIterator) \
     macro(nextMethod) \
-    macro(asyncGeneratorState) \
-    macro(asyncGeneratorSuspendReason) \
-    macro(asyncGeneratorQueue) \
-    macro(asyncGeneratorQueueFirst) \
-    macro(asyncGeneratorQueueLast) \
     macro(asyncGeneratorQueueItemNext) \
-    macro(generatorResumeMode) \
     macro(dateTimeFormat) \
     macro(intlSubstituteValue) \
     macro(thisTimeValue) \
index 06fc581..d41633c 100644 (file)
@@ -31,7 +31,7 @@
 #include "BuiltinNames.h"
 #include "BytecodeGenerator.h"
 #include "IterationKind.h"
-#include "JSAsyncGeneratorFunction.h"
+#include "JSAsyncGenerator.h"
 #include "JSCInlines.h"
 #include "JSGenerator.h"
 #include "JSGlobalObject.h"
@@ -85,14 +85,17 @@ 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_AsyncGeneratorStateCompleted.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorState::Completed)));
-    m_AsyncGeneratorStateExecuting.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorState::Executing)));
-    m_AsyncGeneratorStateSuspendedStart.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorState::SuspendedStart)));
-    m_AsyncGeneratorStateSuspendedYield.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorState::SuspendedYield)));
-    m_AsyncGeneratorStateAwaitingReturn.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorState::AwaitingReturn)));
-    m_AsyncGeneratorSuspendReasonYield.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield)));
-    m_AsyncGeneratorSuspendReasonAwait.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await)));
-    m_AsyncGeneratorSuspendReasonNone.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::None)));
+    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)));
+    m_AsyncGeneratorStateCompleted.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorState::Completed)));
+    m_AsyncGeneratorStateExecuting.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorState::Executing)));
+    m_AsyncGeneratorStateSuspendedStart.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorState::SuspendedStart)));
+    m_AsyncGeneratorStateSuspendedYield.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorState::SuspendedYield)));
+    m_AsyncGeneratorStateAwaitingReturn.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorState::AwaitingReturn)));
+    m_AsyncGeneratorSuspendReasonYield.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield)));
+    m_AsyncGeneratorSuspendReasonAwait.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorSuspendReason::Await)));
+    m_AsyncGeneratorSuspendReasonNone.set(m_vm, jsNumber(static_cast<int32_t>(JSAsyncGenerator::AsyncGeneratorSuspendReason::None)));
 }
 
 BytecodeIntrinsicNode::EmitterType BytecodeIntrinsicRegistry::lookup(const Identifier& ident) const
index 280b7f9..faeb238 100644 (file)
@@ -43,12 +43,14 @@ class RegisterID;
     macro(getByIdDirectPrivate) \
     macro(getPromiseInternalField) \
     macro(getGeneratorInternalField) \
+    macro(getAsyncGeneratorInternalField) \
     macro(idWithProfile) \
     macro(isObject) \
     macro(isJSArray) \
     macro(isProxyObject) \
     macro(isDerivedArray) \
     macro(isGenerator) \
+    macro(isAsyncGenerator) \
     macro(isPromise) \
     macro(isRegExpObject) \
     macro(isMap) \
@@ -64,6 +66,7 @@ class RegisterID;
     macro(putByValDirect) \
     macro(putPromiseInternalField) \
     macro(putGeneratorInternalField) \
+    macro(putAsyncGeneratorInternalField) \
     macro(toNumber) \
     macro(toString) \
     macro(toObject) \
@@ -110,6 +113,9 @@ class RegisterID;
     macro(GeneratorResumeModeReturn) \
     macro(GeneratorStateCompleted) \
     macro(GeneratorStateExecuting) \
+    macro(asyncGeneratorFieldSuspendReason) \
+    macro(asyncGeneratorFieldQueueFirst) \
+    macro(asyncGeneratorFieldQueueLast) \
     macro(AsyncGeneratorStateCompleted) \
     macro(AsyncGeneratorStateExecuting) \
     macro(AsyncGeneratorStateAwaitingReturn) \
index 8bc0182..1e7e96a 100644 (file)
@@ -134,18 +134,22 @@ op :new_promise,
         isInternalPromise: bool,
     }
 
-op :create_generator,
+op :new_generator,
     args: {
         dst: VirtualRegister,
-        callee: VirtualRegister,
-    },
-    metadata: {
-        cachedCallee: WriteBarrier[JSCell]
     }
 
-op :new_generator,
+op_group :CreateInternalFieldObjectOp,
+    [
+        :create_generator,
+        :create_async_generator,
+    ],
     args: {
         dst: VirtualRegister,
+        callee: VirtualRegister,
+    },
+    metadata: {
+        cachedCallee: WriteBarrier[JSCell]
     }
 
 op :get_argument,
index 4079249..022f3bf 100644 (file)
@@ -196,6 +196,7 @@ void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, const Ins
     USES(OpCreateThis, callee)
     USES(OpCreatePromise, callee)
     USES(OpCreateGenerator, callee)
+    USES(OpCreateAsyncGenerator, callee)
     USES(OpDelById, base)
     USES(OpNewFunc, scope)
     USES(OpNewAsyncGeneratorFunc, scope)
@@ -388,6 +389,7 @@ void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, const Ins
     DEFS(OpCreateThis, dst)
     DEFS(OpCreatePromise, dst)
     DEFS(OpCreateGenerator, dst)
+    DEFS(OpCreateAsyncGenerator, dst)
     DEFS(OpNewArray, dst)
     DEFS(OpNewArrayWithSpread, dst)
     DEFS(OpSpread, dst)
index fad95e2..e78d318 100644 (file)
@@ -1279,6 +1279,9 @@ void CodeBlock::finalizeLLIntInlineCaches()
         m_metadata->forEach<OpCreateGenerator>([&] (auto& metadata) {
             handleCreateBytecode(metadata, "op_create_generator"_s);
         });
+        m_metadata->forEach<OpCreateAsyncGenerator>([&] (auto& metadata) {
+            handleCreateBytecode(metadata, "op_create_async_generator"_s);
+        });
 
         m_metadata->forEach<OpResolveScope>([&] (auto& metadata) {
             // Right now this isn't strictly necessary. Any symbol tables that this will refer to
index 32e4086..e7914aa 100644 (file)
@@ -41,7 +41,7 @@
 #include "CatchScope.h"
 #include "DefinePropertyAttributes.h"
 #include "Interpreter.h"
-#include "JSAsyncGeneratorFunction.h"
+#include "JSAsyncGenerator.h"
 #include "JSBigInt.h"
 #include "JSCInlines.h"
 #include "JSFixedArray.h"
@@ -702,8 +702,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
         // https://bugs.webkit.org/show_bug.cgi?id=151586
         emitToThis();
 
-        move(m_generatorRegister, &m_calleeRegister);
-        emitCreateThis(m_generatorRegister);
+        emitCreateAsyncGenerator(m_generatorRegister, &m_calleeRegister);
         break;
     }
 
@@ -876,10 +875,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke
             // Generatorification inserts lexical environment creation if necessary. Otherwise, we convert it to op_mov frame, `undefined`.
             OpCreateGeneratorFrameEnvironment::emit(this, generatorFrameRegister(), scopeRegister(), VirtualRegister { symbolTableConstantIndex }, addConstantValue(jsUndefined()));
         }
-        if (parseMode == SourceParseMode::AsyncGeneratorBodyMode)
-            emitPutById(generatorRegister(), propertyNames().builtinNames().generatorFramePrivateName(), generatorFrameRegister());
-        else
-            emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::Frame), generatorFrameRegister());
+        static_assert(static_cast<unsigned>(JSGenerator::Field::Frame) == static_cast<unsigned>(JSAsyncGenerator::Field::Frame));
+        emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::Frame), generatorFrameRegister());
     }
 
     bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
@@ -2723,18 +2720,8 @@ void BytecodeGenerator::emitPutAsyncGeneratorFields(RegisterID* nextFunction)
 {
     ASSERT(isAsyncGeneratorWrapperParseMode(parseMode()));
 
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().generatorNextPrivateName(), nextFunction, PropertyNode::KnownDirect);
-        
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().generatorThisPrivateName(), &m_thisRegister, PropertyNode::KnownDirect);
-        
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().generatorStatePrivateName(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorState::SuspendedStart))), PropertyNode::KnownDirect);
-        
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().generatorFramePrivateName(), emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
-
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorSuspendReasonPrivateName(), emitLoad(nullptr, jsNumber(static_cast<int32_t>(JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::None))), PropertyNode::KnownDirect);
-
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorQueueFirstPrivateName(), emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
-    emitDirectPutById(m_generatorRegister, propertyNames().builtinNames().asyncGeneratorQueueLastPrivateName(), emitLoad(nullptr, jsNull()), PropertyNode::KnownDirect);
+    emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSAsyncGenerator::Field::Next), nextFunction);
+    emitPutInternalField(m_generatorRegister, static_cast<unsigned>(JSAsyncGenerator::Field::This), &m_thisRegister);
 }
 
 RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, const Identifier& property)
@@ -2875,6 +2862,12 @@ RegisterID* BytecodeGenerator::emitNewGenerator(RegisterID* dst)
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitCreateAsyncGenerator(RegisterID* dst, RegisterID* newTarget)
+{
+    OpCreateAsyncGenerator::emit(this, dst, newTarget);
+    return dst;
+}
+
 void BytecodeGenerator::emitTDZCheck(RegisterID* target)
 {
     OpCheckTdz::emit(this, target);
@@ -4515,7 +4508,7 @@ void BytecodeGenerator::emitRequireObjectCoercible(RegisterID* value, const Stri
     emitLabel(target.get());
 }
 
-void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason result)
+void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason result)
 {
     Ref<Label> mergePoint = newLabel();
     unsigned yieldPointIndex = m_yieldPoints++;
@@ -4523,7 +4516,7 @@ void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGeneratorFun
 
     if (parseMode() == SourceParseMode::AsyncGeneratorBodyMode) {
         int suspendReason = static_cast<int32_t>(result);
-        emitPutById(generatorRegister(), propertyNames().builtinNames().asyncGeneratorSuspendReasonPrivateName(), emitLoad(nullptr, jsNumber(suspendReason)));
+        emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSAsyncGenerator::Field::SuspendReason), emitLoad(nullptr, jsNumber(suspendReason)));
     }
 
     // Split the try range here.
@@ -4555,7 +4548,7 @@ void BytecodeGenerator::emitYieldPoint(RegisterID* argument, JSAsyncGeneratorFun
     emitLabel(mergePoint.get());
 }
 
-RegisterID* BytecodeGenerator::emitYield(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason result)
+RegisterID* BytecodeGenerator::emitYield(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason result)
 {
     emitYieldPoint(argument, result);
 
@@ -4595,7 +4588,7 @@ RegisterID* BytecodeGenerator::emitCallIterator(RegisterID* iterator, RegisterID
 
 void BytecodeGenerator::emitAwait(RegisterID* value)
 {
-    emitYield(value, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await);
+    emitYield(value, JSAsyncGenerator::AsyncGeneratorSuspendReason::Await);
     move(value, generatorValueRegister());
 }
 
@@ -4667,7 +4660,7 @@ RegisterID* BytecodeGenerator::emitDelegateYield(RegisterID* argument, Throwable
 
             Ref<Label> branchOnResult = newLabel();
             {
-                emitYieldPoint(value.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield);
+                emitYieldPoint(value.get(), JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield);
 
                 Ref<Label> normalLabel = newLabel();
                 Ref<Label> returnLabel = newLabel();
@@ -4778,10 +4771,8 @@ RegisterID* BytecodeGenerator::emitDelegateYield(RegisterID* argument, Throwable
 void BytecodeGenerator::emitGeneratorStateChange(int32_t state)
 {
     RegisterID* completedState = emitLoad(nullptr, jsNumber(state));
-    if (m_codeBlock->parseMode() == SourceParseMode::AsyncGeneratorBodyMode)
-        emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState);
-    else
-        emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::State), completedState);
+    static_assert(static_cast<unsigned>(JSGenerator::Field::State) == static_cast<unsigned>(JSAsyncGenerator::Field::State));
+    emitPutInternalField(generatorRegister(), static_cast<unsigned>(JSGenerator::Field::State), completedState);
 }
 
 bool BytecodeGenerator::emitJumpViaFinallyIfNeeded(int targetLabelScopeDepth, Label& jumpTarget)
index 2694b22..4197abc 100644 (file)
@@ -33,7 +33,7 @@
 #include "CodeBlock.h"
 #include "Instruction.h"
 #include "Interpreter.h"
-#include "JSAsyncGeneratorFunction.h"
+#include "JSAsyncGenerator.h"
 #include "JSBigInt.h"
 #include "JSGenerator.h"
 #include "JSTemplateObjectDescriptor.h"
@@ -725,6 +725,7 @@ namespace JSC {
         RegisterID* emitCreateThis(RegisterID* dst);
         RegisterID* emitCreatePromise(RegisterID* dst, RegisterID* newTarget, bool isInternalPromise);
         RegisterID* emitCreateGenerator(RegisterID* dst, RegisterID* newTarget);
+        RegisterID* emitCreateAsyncGenerator(RegisterID* dst, RegisterID* newTarget);
         void emitTDZCheck(RegisterID* target);
         bool needsTDZCheck(const Variable&);
         void emitTDZCheckIfNecessary(const Variable&, RegisterID* target, RegisterID* scope);
@@ -869,6 +870,7 @@ namespace JSC {
 
         RegisterID* emitIsCellWithType(RegisterID* dst, RegisterID* src, JSType);
         RegisterID* emitIsGenerator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSGeneratorType); }
+        RegisterID* emitIsAsyncGenerator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSAsyncGeneratorType); }
         RegisterID* emitIsJSArray(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, ArrayType); }
         RegisterID* emitIsPromise(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSPromiseType); }
         RegisterID* emitIsProxyObject(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, ProxyObjectType); }
@@ -985,11 +987,11 @@ namespace JSC {
         void beginSwitch(RegisterID*, SwitchInfo::SwitchType);
         void endSwitch(uint32_t clauseCount, const Vector<Ref<Label>, 8>&, ExpressionNode**, Label& defaultLabel, int32_t min, int32_t range);
 
-        void emitYieldPoint(RegisterID*, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason);
+        void emitYieldPoint(RegisterID*, JSAsyncGenerator::AsyncGeneratorSuspendReason);
 
         void emitGeneratorStateLabel();
         void emitGeneratorStateChange(int32_t state);
-        RegisterID* emitYield(RegisterID* argument, JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason = JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield);
+        RegisterID* emitYield(RegisterID* argument, JSAsyncGenerator::AsyncGeneratorSuspendReason = JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield);
         RegisterID* emitDelegateYield(RegisterID* argument, ThrowableExpressionData*);
         RegisterID* generatorStateRegister() { return &m_parameters[static_cast<int32_t>(JSGenerator::GeneratorArgument::State)]; }
         RegisterID* generatorValueRegister() { return &m_parameters[static_cast<int32_t>(JSGenerator::GeneratorArgument::Value)]; }
index 652766a..65937f3 100644 (file)
@@ -32,6 +32,7 @@
 #include "BytecodeGenerator.h"
 #include "CallFrame.h"
 #include "JIT.h"
+#include "JSAsyncGenerator.h"
 #include "JSCInlines.h"
 #include "JSFunction.h"
 #include "JSGenerator.h"
@@ -1034,6 +1035,26 @@ static JSGenerator::Field generatorInternalFieldIndex(BytecodeIntrinsicNode* nod
     return JSGenerator::Field::State;
 }
 
+static JSAsyncGenerator::Field asyncGeneratorInternalFieldIndex(BytecodeIntrinsicNode* node)
+{
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldState)
+        return JSAsyncGenerator::Field::State;
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldNext)
+        return JSAsyncGenerator::Field::Next;
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldThis)
+        return JSAsyncGenerator::Field::This;
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_generatorFieldFrame)
+        return JSAsyncGenerator::Field::Frame;
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldSuspendReason)
+        return JSAsyncGenerator::Field::SuspendReason;
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldQueueFirst)
+        return JSAsyncGenerator::Field::QueueFirst;
+    if (node->emitter() == &BytecodeIntrinsicNode::emit_intrinsic_asyncGeneratorFieldQueueLast)
+        return JSAsyncGenerator::Field::QueueLast;
+    RELEASE_ASSERT_NOT_REACHED();
+    return JSAsyncGenerator::Field::State;
+}
+
 RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getPromiseInternalField(BytecodeGenerator& generator, RegisterID* dst)
 {
     ArgumentListNode* node = m_args->m_listNode;
@@ -1060,6 +1081,19 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getGeneratorInternalField(Byte
     return generator.emitGetInternalField(generator.finalDestination(dst), base.get(), index);
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_getAsyncGeneratorInternalField(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>(asyncGeneratorInternalFieldIndex(static_cast<BytecodeIntrinsicNode*>(node->m_expr)));
+    ASSERT(index < JSAsyncGenerator::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;
@@ -1161,6 +1195,22 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putGeneratorInternalField(Byte
     return generator.move(dst, generator.emitPutInternalField(base.get(), index, value.get()));
 }
 
+RegisterID* BytecodeIntrinsicNode::emit_intrinsic_putAsyncGeneratorInternalField(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>(asyncGeneratorInternalFieldIndex(static_cast<BytecodeIntrinsicNode*>(node->m_expr)));
+    ASSERT(index < JSAsyncGenerator::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;
@@ -1283,7 +1333,16 @@ RegisterID* BytecodeIntrinsicNode::emit_intrinsic_isGenerator(JSC::BytecodeGener
 
     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;
@@ -4158,7 +4217,7 @@ RegisterID* YieldExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID
             generator.emitNode(arg.get(), argument());
         } else
             arg = generator.emitLoad(nullptr, jsUndefined());
-        RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Yield);
+        RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGenerator::AsyncGeneratorSuspendReason::Yield);
         if (dst == generator.ignoredResult())
             return nullptr;
         return generator.move(generator.finalDestination(dst), value.get());
@@ -4177,7 +4236,7 @@ RegisterID* AwaitExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID
 {
     RefPtr<RegisterID> arg = generator.newTemporary();
     generator.emitNode(arg.get(), argument());
-    RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGeneratorFunction::AsyncGeneratorSuspendReason::Await);
+    RefPtr<RegisterID> value = generator.emitYield(arg.get(), JSAsyncGenerator::AsyncGeneratorSuspendReason::Await);
     if (dst == generator.ignoredResult())
         return nullptr;
     return generator.move(generator.finalDestination(dst), value.get());
index 1e64abc..5a63b42 100644 (file)
@@ -37,6 +37,7 @@
 #include "GetterSetter.h"
 #include "HashMapImpl.h"
 #include "JITOperations.h"
+#include "JSAsyncGenerator.h"
 #include "JSGenerator.h"
 #include "JSImmutableButterfly.h"
 #include "JSInternalPromise.h"
@@ -2688,28 +2689,47 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
     }
 
-    case CreateGenerator: {
-        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-        if (JSValue base = forNode(node->child1()).m_value) {
-            if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
-                if (FunctionRareData* rareData = function->rareData()) {
-                    if (rareData->allocationProfileWatchpointSet().isStillValid()) {
-                        Structure* structure = rareData->internalFunctionAllocationStructure();
-                        if (structure
-                            && structure->classInfo() == JSGenerator::info()
-                            && structure->globalObject() == globalObject
-                            && rareData->allocationProfileWatchpointSet().isStillValid()) {
-                            m_graph.freeze(rareData);
-                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
-                            m_state.setFoundConstants(true);
-                            didFoldClobberWorld();
-                            setForNode(node, structure);
-                            break;
+    case CreateGenerator:
+    case CreateAsyncGenerator: {
+        auto tryToFold = [&] (const ClassInfo* classInfo) -> bool {
+            JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+            if (JSValue base = forNode(node->child1()).m_value) {
+                if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
+                    if (FunctionRareData* rareData = function->rareData()) {
+                        if (rareData->allocationProfileWatchpointSet().isStillValid()) {
+                            Structure* structure = rareData->internalFunctionAllocationStructure();
+                            if (structure
+                                && structure->classInfo() == classInfo
+                                && structure->globalObject() == globalObject
+                                && rareData->allocationProfileWatchpointSet().isStillValid()) {
+                                m_graph.freeze(rareData);
+                                m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+                                m_state.setFoundConstants(true);
+                                didFoldClobberWorld();
+                                setForNode(node, structure);
+                                return true;
+                            }
                         }
                     }
                 }
             }
+            return false;
+        };
+
+        bool found = false;
+        switch (node->op()) {
+        case CreateGenerator:
+            found = tryToFold(JSGenerator::info());
+            break;
+        case CreateAsyncGenerator:
+            found = tryToFold(JSAsyncGenerator::info());
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            break;
         }
+        if (found)
+            break;
         clobberWorld();
         setTypeForNode(node, SpecObjectOther);
         break;
@@ -2721,6 +2741,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
 
     case NewGenerator:
+    case NewAsyncGenerator:
         ASSERT(!!node->structure().get());
         setForNode(node, node->structure());
         break;
index 61c7973..73c812c 100644 (file)
@@ -203,6 +203,8 @@ private:
     void handleNewFunc(NodeType, Bytecode);
     template <typename Bytecode>
     void handleNewFuncExp(NodeType, Bytecode);
+    template <typename Bytecode>
+    void handleCreateInternalFieldObject(const ClassInfo*, NodeType createOp, NodeType newOp, Bytecode);
 
     // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
     // check the validity of the condition, but it may return a null one if it encounters a contradiction.
@@ -4954,51 +4956,15 @@ void ByteCodeParser::parseBlock(unsigned limit)
         }
 
         case op_create_generator: {
-            JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
-            auto bytecode = currentInstruction->as<OpCreateGenerator>();
-            Node* callee = get(VirtualRegister(bytecode.m_callee));
-
-            bool alreadyEmitted = false;
-
-            JSFunction* function = callee->dynamicCastConstant<JSFunction*>(*m_vm);
-            if (!function) {
-                JSCell* cachedFunction = bytecode.metadata(codeBlock).m_cachedCallee.unvalidatedGet();
-                if (cachedFunction
-                    && cachedFunction != JSCell::seenMultipleCalleeObjects()
-                    && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
-                    ASSERT(cachedFunction->inherits<JSFunction>(*m_vm));
-
-                    FrozenValue* frozen = m_graph.freeze(cachedFunction);
-                    addToGraph(CheckCell, OpInfo(frozen), callee);
-
-                    function = static_cast<JSFunction*>(cachedFunction);
-                }
-            }
-
-            if (function) {
-                if (FunctionRareData* rareData = function->rareData()) {
-                    if (rareData->allocationProfileWatchpointSet().isStillValid()) {
-                        Structure* structure = rareData->internalFunctionAllocationStructure();
-                        if (structure
-                            && structure->classInfo() == JSGenerator::info()
-                            && structure->globalObject() == globalObject
-                            && rareData->allocationProfileWatchpointSet().isStillValid()) {
-                            m_graph.freeze(rareData);
-                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
-
-                            set(VirtualRegister(bytecode.m_dst), addToGraph(NewGenerator, OpInfo(m_graph.registerStructure(structure))));
-                            // The callee is still live up to this point.
-                            addToGraph(Phantom, callee);
-                            alreadyEmitted = true;
-                        }
-                    }
-                }
-            }
-            if (!alreadyEmitted)
-                set(VirtualRegister(bytecode.m_dst), addToGraph(CreateGenerator, callee));
+            handleCreateInternalFieldObject(JSGenerator::info(), CreateGenerator, NewGenerator, currentInstruction->as<OpCreateGenerator>());
             NEXT_OPCODE(op_create_generator);
         }
 
+        case op_create_async_generator: {
+            handleCreateInternalFieldObject(JSAsyncGenerator::info(), CreateAsyncGenerator, NewAsyncGenerator, currentInstruction->as<OpCreateAsyncGenerator>());
+            NEXT_OPCODE(op_create_async_generator);
+        }
+
         case op_new_object: {
             auto bytecode = currentInstruction->as<OpNewObject>();
             set(bytecode.m_dst,
@@ -7510,6 +7476,51 @@ void ByteCodeParser::handleNewFuncExp(NodeType op, Bytecode bytecode)
     addToGraph(Phantom, scope);
 }
 
+template <typename Bytecode>
+void ByteCodeParser::handleCreateInternalFieldObject(const ClassInfo* classInfo, NodeType createOp, NodeType newOp, Bytecode bytecode)
+{
+    CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
+    JSGlobalObject* globalObject = m_graph.globalObjectFor(currentNodeOrigin().semantic);
+    Node* callee = get(VirtualRegister(bytecode.m_callee));
+
+    JSFunction* function = callee->dynamicCastConstant<JSFunction*>(*m_vm);
+    if (!function) {
+        JSCell* cachedFunction = bytecode.metadata(codeBlock).m_cachedCallee.unvalidatedGet();
+        if (cachedFunction
+            && cachedFunction != JSCell::seenMultipleCalleeObjects()
+            && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
+            ASSERT(cachedFunction->inherits<JSFunction>(*m_vm));
+
+            FrozenValue* frozen = m_graph.freeze(cachedFunction);
+            addToGraph(CheckCell, OpInfo(frozen), callee);
+
+            function = static_cast<JSFunction*>(cachedFunction);
+        }
+    }
+
+    if (function) {
+        if (FunctionRareData* rareData = function->rareData()) {
+            if (rareData->allocationProfileWatchpointSet().isStillValid()) {
+                Structure* structure = rareData->internalFunctionAllocationStructure();
+                if (structure
+                    && structure->classInfo() == classInfo
+                    && structure->globalObject() == globalObject
+                    && rareData->allocationProfileWatchpointSet().isStillValid()) {
+                    m_graph.freeze(rareData);
+                    m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+
+                    set(VirtualRegister(bytecode.m_dst), addToGraph(newOp, OpInfo(m_graph.registerStructure(structure))));
+                    // The callee is still live up to this point.
+                    addToGraph(Phantom, callee);
+                    return;
+                }
+            }
+        }
+    }
+
+    set(VirtualRegister(bytecode.m_dst), addToGraph(createOp, callee));
+}
+
 void ByteCodeParser::parse()
 {
     // Set during construction.
index 71ec7f1..d3376bd 100644 (file)
@@ -118,6 +118,7 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, const I
     case op_create_this:
     case op_create_promise:
     case op_create_generator:
+    case op_create_async_generator:
     case op_bitnot:
     case op_bitand:
     case op_bitor:
index 0828fd8..0c23552 100644 (file)
@@ -669,6 +669,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case CreateThis:
     case CreatePromise:
     case CreateGenerator:
+    case CreateAsyncGenerator:
     case InstanceOf:
     case StringValueOf:
     case ObjectKeys:
@@ -1569,6 +1570,7 @@ void clobberize(Graph& graph, Node* node, const ReadFunctor& read, const WriteFu
     case NewObject:
     case NewPromise:
     case NewGenerator:
+    case NewAsyncGenerator:
     case NewRegexp:
     case NewSymbol:
     case NewStringObject:
index d2f7ba4..ef68fd5 100644 (file)
@@ -59,6 +59,7 @@ bool clobbersExitState(Graph& graph, Node* node)
     case NewObject:
     case NewPromise:
     case NewGenerator:
+    case NewAsyncGenerator:
     case NewRegexp:
     case NewSymbol:
     case NewStringObject:
index f3f5cb6..59ccc81 100644 (file)
@@ -778,26 +778,41 @@ private:
                 break;
             }
 
-            case CreateGenerator: {
-                JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-                if (JSValue base = m_state.forNode(node->child1()).m_value) {
-                    if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
-                        if (FunctionRareData* rareData = function->rareData()) {
-                            if (rareData->allocationProfileWatchpointSet().isStillValid()) {
-                                Structure* structure = rareData->internalFunctionAllocationStructure();
-                                if (structure
-                                    && structure->classInfo() == JSGenerator::info()
-                                    && structure->globalObject() == globalObject
-                                    && rareData->allocationProfileWatchpointSet().isStillValid()) {
-                                    m_graph.freeze(rareData);
-                                    m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
-                                    node->convertToNewGenerator(m_graph.registerStructure(structure));
-                                    changed = true;
-                                    break;
+            case CreateGenerator:
+            case CreateAsyncGenerator: {
+                auto foldConstant = [&] (NodeType newOp, const ClassInfo* classInfo) {
+                    JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+                    if (JSValue base = m_state.forNode(node->child1()).m_value) {
+                        if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
+                            if (FunctionRareData* rareData = function->rareData()) {
+                                if (rareData->allocationProfileWatchpointSet().isStillValid()) {
+                                    Structure* structure = rareData->internalFunctionAllocationStructure();
+                                    if (structure
+                                        && structure->classInfo() == classInfo
+                                        && structure->globalObject() == globalObject
+                                        && rareData->allocationProfileWatchpointSet().isStillValid()) {
+                                        m_graph.freeze(rareData);
+                                        m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+                                        node->convertToNewInternalFieldObject(newOp, m_graph.registerStructure(structure));
+                                        changed = true;
+                                        return;
+                                    }
                                 }
                             }
                         }
                     }
+                };
+
+                switch (node->op()) {
+                case CreateGenerator:
+                    foldConstant(NewGenerator, JSGenerator::info());
+                    break;
+                case CreateAsyncGenerator:
+                    foldConstant(NewAsyncGenerator, JSAsyncGenerator::info());
+                    break;
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                    break;
                 }
                 break;
             }
index a98f795..5d2b05d 100644 (file)
@@ -334,6 +334,7 @@ bool doesGC(Graph& graph, Node* node)
     case CreateThis:
     case CreatePromise:
     case CreateGenerator:
+    case CreateAsyncGenerator:
     case ObjectCreate:
     case ObjectKeys:
     case AllocatePropertyStorage:
@@ -343,6 +344,7 @@ bool doesGC(Graph& graph, Node* node)
     case NewObject:
     case NewPromise:
     case NewGenerator:
+    case NewAsyncGenerator:
     case NewArray:
     case NewArrayWithSpread:
     case Spread:
index c7d7418..3f1c891 100644 (file)
@@ -1652,6 +1652,7 @@ private:
         case CreateThis:
         case CreatePromise:
         case CreateGenerator:
+        case CreateAsyncGenerator:
         case GetButterfly: {
             fixEdge<CellUse>(node->child1());
             break;
@@ -2410,6 +2411,7 @@ private:
         case NewObject:
         case NewPromise:
         case NewGenerator:
+        case NewAsyncGenerator:
         case NewRegexp:
         case DeleteById:
         case DeleteByVal:
index d68ba6e..11d8b40 100644 (file)
@@ -767,10 +767,10 @@ public:
         m_opInfo2 = internal;
     }
 
-    void convertToNewGenerator(RegisteredStructure structure)
+    void convertToNewInternalFieldObject(NodeType newOp, RegisteredStructure structure)
     {
-        ASSERT(m_op == CreateGenerator);
-        setOpAndDefaultFlags(NewGenerator);
+        ASSERT(m_op == CreateAsyncGenerator || m_op == CreateGenerator);
+        setOpAndDefaultFlags(newOp);
         children.reset();
         m_opInfo = structure;
         m_opInfo2 = OpInfoWrapper();
@@ -1923,6 +1923,7 @@ public:
         case NewObject:
         case NewPromise:
         case NewGenerator:
+        case NewAsyncGenerator:
         case NewStringObject:
             return true;
         default:
index 4101f5c..8ca3b79 100644 (file)
@@ -55,6 +55,7 @@ namespace JSC { namespace DFG {
     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
     macro(CreatePromise, NodeResultJS | NodeMustGenerate) \
     macro(CreateGenerator, NodeResultJS | NodeMustGenerate) \
+    macro(CreateAsyncGenerator, NodeResultJS | NodeMustGenerate) \
     macro(GetCallee, NodeResultJS) \
     macro(SetCallee, NodeMustGenerate) \
     macro(GetArgumentCountIncludingThis, NodeResultInt32) \
@@ -344,6 +345,7 @@ namespace JSC { namespace DFG {
     macro(NewObject, NodeResultJS) \
     macro(NewPromise, NodeResultJS) \
     macro(NewGenerator, NodeResultJS) \
+    macro(NewAsyncGenerator, NodeResultJS) \
     macro(NewArray, NodeResultJS | NodeHasVarArgs) \
     macro(NewArrayWithSpread, NodeResultJS | NodeHasVarArgs) \
     macro(NewArrayWithSize, NodeResultJS | NodeMustGenerate) \
index 082c8db..a1f6576 100644 (file)
@@ -408,6 +408,16 @@ JSCell* JIT_OPERATION operationCreateGenerator(ExecState* exec, JSObject* constr
     RELEASE_AND_RETURN(scope, JSGenerator::create(vm, structure));
 }
 
+JSCell* JIT_OPERATION operationCreateAsyncGenerator(ExecState* exec, JSObject* constructor, JSGlobalObject* globalObject)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    Structure* structure = InternalFunction::createSubclassStructure(exec, nullptr, constructor, globalObject->asyncGeneratorStructure());
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    RELEASE_AND_RETURN(scope, JSAsyncGenerator::create(vm, structure));
+}
+
 JSCell* JIT_OPERATION operationCallObjectConstructor(ExecState* exec, JSGlobalObject* globalObject, EncodedJSValue encodedTarget)
 {
     VM& vm = exec->vm();
index 294392e..add0cae 100644 (file)
@@ -51,6 +51,7 @@ JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, uin
 JSCell* JIT_OPERATION operationCreatePromise(ExecState*, JSObject* constructor, JSGlobalObject*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationCreateInternalPromise(ExecState*, JSObject* constructor, JSGlobalObject*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationCreateGenerator(ExecState*, JSObject* constructor, JSGlobalObject*) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationCreateAsyncGenerator(ExecState*, JSObject* constructor, JSGlobalObject*) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
 EncodedJSValue JIT_OPERATION operationValueMod(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
index 41f6c37..e72aa5d 100644 (file)
@@ -1019,6 +1019,8 @@ private:
 
         case CreateGenerator:
         case NewGenerator:
+        case CreateAsyncGenerator:
+        case NewAsyncGenerator:
             setPrediction(SpecObjectOther);
             break;
             
index 588b98d..46061c8 100644 (file)
@@ -180,6 +180,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case CreateThis:
     case CreatePromise:
     case CreateGenerator:
+    case CreateAsyncGenerator:
     case ObjectCreate:
     case ObjectKeys:
     case GetCallee:
@@ -324,6 +325,7 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node, bool igno
     case NewObject:
     case NewPromise:
     case NewGenerator:
+    case NewAsyncGenerator:
     case NewArray:
     case NewArrayWithSize:
     case NewArrayBuffer:
index cede902..5f05ee1 100644 (file)
@@ -12766,7 +12766,9 @@ void SpeculativeJIT::compileCreatePromise(Node* node)
     cellResult(resultGPR, node);
 }
 
-void SpeculativeJIT::compileCreateGenerator(Node* node)
+
+template<typename JSClass, typename Operation>
+void SpeculativeJIT::compileCreateInternalFieldObject(Node* node, Operation operation)
 {
     JSGlobalObject* globalObject = m_jit.globalObjectFor(node->origin.semantic);
 
@@ -12792,25 +12794,34 @@ void SpeculativeJIT::compileCreateGenerator(Node* node)
     slowCases.append(m_jit.branchTestPtr(MacroAssembler::Zero, rareDataGPR));
     m_jit.loadPtr(JITCompiler::Address(rareDataGPR, FunctionRareData::offsetOfInternalFunctionAllocationProfile() + InternalFunctionAllocationProfile::offsetOfStructure()), structureGPR);
     slowCases.append(m_jit.branchTestPtr(CCallHelpers::Zero, structureGPR));
-    m_jit.move(TrustedImmPtr(JSGenerator::info()), scratch1GPR);
+    m_jit.move(TrustedImmPtr(JSClass::info()), scratch1GPR);
     slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::classInfoOffset())));
     m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), globalObject), scratch1GPR);
     slowCases.append(m_jit.branchPtr(CCallHelpers::NotEqual, scratch1GPR, CCallHelpers::Address(structureGPR, Structure::globalObjectOffset())));
 
     auto butterfly = TrustedImmPtr(nullptr);
-    emitAllocateJSObjectWithKnownSize<JSGenerator>(resultGPR, structureGPR, butterfly, scratch1GPR, scratch2GPR, slowCases, sizeof(JSGenerator));
-    m_jit.storeTrustedValue(jsNull(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::PolyProto))));
-    m_jit.storeTrustedValue(jsNumber(static_cast<int32_t>(JSGenerator::GeneratorState::Init)), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::State))));
-    m_jit.storeTrustedValue(jsUndefined(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::Next))));
-    m_jit.storeTrustedValue(jsUndefined(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::This))));
-    m_jit.storeTrustedValue(jsUndefined(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::Frame))));
+    emitAllocateJSObjectWithKnownSize<JSClass>(resultGPR, structureGPR, butterfly, scratch1GPR, scratch2GPR, slowCases, sizeof(JSClass));
+    auto initialValues = JSClass::initialValues();
+    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());
 
-    addSlowPathGenerator(slowPathCall(slowCases, this, operationCreateGenerator, resultGPR, calleeGPR, TrustedImmPtr::weakPointer(m_jit.graph(), globalObject)));
+    addSlowPathGenerator(slowPathCall(slowCases, this, operation, resultGPR, calleeGPR, TrustedImmPtr::weakPointer(m_jit.graph(), globalObject)));
 
     cellResult(resultGPR, node);
 }
 
+void SpeculativeJIT::compileCreateGenerator(Node* node)
+{
+    compileCreateInternalFieldObject<JSGenerator>(node, operationCreateGenerator);
+}
+
+void SpeculativeJIT::compileCreateAsyncGenerator(Node* node)
+{
+    compileCreateInternalFieldObject<JSAsyncGenerator>(node, operationCreateAsyncGenerator);
+}
+
 void SpeculativeJIT::compileNewObject(Node* node)
 {
     GPRTemporary result(this);
@@ -12867,7 +12878,8 @@ void SpeculativeJIT::compileNewPromise(Node* node)
     cellResult(resultGPR, node);
 }
 
-void SpeculativeJIT::compileNewGenerator(Node* node)
+template<typename JSClass, typename Operation>
+void SpeculativeJIT::compileNewInternalFieldObject(Node* node, Operation operation)
 {
     GPRTemporary result(this);
     GPRTemporary scratch1(this);
@@ -12881,19 +12893,28 @@ void SpeculativeJIT::compileNewGenerator(Node* node)
 
     FrozenValue* structure = m_graph.freezeStrong(node->structure().get());
     auto butterfly = TrustedImmPtr(nullptr);
-    emitAllocateJSObjectWithKnownSize<JSGenerator>(resultGPR, TrustedImmPtr(structure), butterfly, scratch1GPR, scratch2GPR, slowCases, sizeof(JSGenerator));
-    m_jit.storeTrustedValue(jsNull(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::PolyProto))));
-    m_jit.storeTrustedValue(jsNumber(static_cast<int32_t>(JSGenerator::GeneratorState::Init)), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::State))));
-    m_jit.storeTrustedValue(jsUndefined(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::Next))));
-    m_jit.storeTrustedValue(jsUndefined(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::This))));
-    m_jit.storeTrustedValue(jsUndefined(), CCallHelpers::Address(resultGPR, JSInternalFieldObjectImpl<>::offsetOfInternalField(static_cast<unsigned>(JSGenerator::Field::Frame))));
+    emitAllocateJSObjectWithKnownSize<JSClass>(resultGPR, TrustedImmPtr(structure), butterfly, scratch1GPR, scratch2GPR, slowCases, sizeof(JSClass));
+    auto initialValues = JSClass::initialValues();
+    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());
 
-    addSlowPathGenerator(slowPathCall(slowCases, this, operationNewGenerator, resultGPR, TrustedImmPtr(structure)));
+    addSlowPathGenerator(slowPathCall(slowCases, this, operation, resultGPR, TrustedImmPtr(structure)));
 
     cellResult(resultGPR, node);
 }
 
+void SpeculativeJIT::compileNewGenerator(Node* node)
+{
+    compileNewInternalFieldObject<JSGenerator>(node, operationNewGenerator);
+}
+
+void SpeculativeJIT::compileNewAsyncGenerator(Node* node)
+{
+    compileNewInternalFieldObject<JSAsyncGenerator>(node, operationNewAsyncGenerator);
+}
+
 void SpeculativeJIT::compileToPrimitive(Node* node)
 {
     DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse, node->child1().useKind());
index e372e91..ad5dbfe 100644 (file)
@@ -1476,9 +1476,11 @@ public:
     void compileCreateThis(Node*);
     void compileCreatePromise(Node*);
     void compileCreateGenerator(Node*);
+    void compileCreateAsyncGenerator(Node*);
     void compileNewObject(Node*);
     void compileNewPromise(Node*);
     void compileNewGenerator(Node*);
+    void compileNewAsyncGenerator(Node*);
     void compileToPrimitive(Node*);
     void compileLogShadowChickenPrologue(Node*);
     void compileLogShadowChickenTail(Node*);
@@ -1488,6 +1490,11 @@ public:
     void compileProfileType(Node*);
     void compileStringCodePointAt(Node*);
 
+    template<typename JSClass, typename Operation>
+    void compileCreateInternalFieldObject(Node*, Operation);
+    template<typename JSClass, typename Operation>
+    void compileNewInternalFieldObject(Node*, Operation);
+
     void moveTrueTo(GPRReg);
     void moveFalseTo(GPRReg);
     void blessBoolean(GPRReg);
index 41c4467..02847b9 100644 (file)
@@ -3166,6 +3166,11 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case CreateAsyncGenerator: {
+        compileCreateAsyncGenerator(node);
+        break;
+    }
+
     case NewObject: {
         compileNewObject(node);
         break;
@@ -3181,6 +3186,11 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case NewAsyncGenerator: {
+        compileNewAsyncGenerator(node);
+        break;
+    }
+
     case GetCallee: {
         compileGetCallee(node);
         break;
index a35b4ed..47c182a 100644 (file)
@@ -3492,6 +3492,11 @@ void SpeculativeJIT::compile(Node* node)
         compileCreateGenerator(node);
         break;
     }
+
+    case CreateAsyncGenerator: {
+        compileCreateAsyncGenerator(node);
+        break;
+    }
         
     case NewObject: {
         compileNewObject(node);
@@ -3508,6 +3513,11 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    case NewAsyncGenerator: {
+        compileNewAsyncGenerator(node);
+        break;
+    }
+
     case GetCallee: {
         compileGetCallee(node);
         break;
index 54917db..75867bf 100644 (file)
@@ -323,6 +323,7 @@ private:
             case NewObject:
             case NewPromise:
             case NewGenerator:
+            case NewAsyncGenerator:
             case NewArray:
             case NewArrayWithSize:
             case NewArrayBuffer:
index d5b5528..c61f9e6 100644 (file)
@@ -76,6 +76,7 @@ inline CapabilityLevel canCompile(Node* node)
     case NewObject:
     case NewPromise:
     case NewGenerator:
+    case NewAsyncGenerator:
     case NewStringObject:
     case NewSymbol:
     case NewArray:
@@ -383,6 +384,7 @@ inline CapabilityLevel canCompile(Node* node)
     case CreateThis:
     case CreatePromise:
     case CreateGenerator:
+    case CreateAsyncGenerator:
     case DataViewGetInt:
     case DataViewGetFloat:
     case DataViewSet:
index 867bd77..4a5c545 100644 (file)
@@ -76,6 +76,7 @@
 #include "JITRightShiftGenerator.h"
 #include "JITSubGenerator.h"
 #include "JSAsyncFunction.h"
+#include "JSAsyncGenerator.h"
 #include "JSAsyncGeneratorFunction.h"
 #include "JSCInlines.h"
 #include "JSGenerator.h"
@@ -1055,6 +1056,9 @@ private:
         case NewGenerator:
             compileNewGenerator();
             break;
+        case NewAsyncGenerator:
+            compileNewAsyncGenerator();
+            break;
         case NewStringObject:
             compileNewStringObject();
             break;
@@ -1076,6 +1080,9 @@ private:
         case CreateGenerator:
             compileCreateGenerator();
             break;
+        case CreateAsyncGenerator:
+            compileCreateAsyncGenerator();
+            break;
         case Spread:
             compileSpread();
             break;
@@ -5932,31 +5939,41 @@ private:
         setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
     }
 
-    void compileNewGenerator()
+    template<typename JSClass, typename Operation>
+    void compileNewInternalFieldObject(Operation operation)
     {
         LBasicBlock slowCase = m_out.newBlock();
         LBasicBlock continuation = m_out.newBlock();
 
         LBasicBlock lastNext = m_out.insertNewBlocksBefore(slowCase);
 
-        LValue generator = allocateObject<JSGenerator>(m_node->structure(), m_out.intPtrZero, slowCase);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsNull())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::PolyProto)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsNumber(static_cast<int32_t>(JSGenerator::GeneratorState::Init)))), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::State)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsUndefined())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::Next)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsUndefined())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::This)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsUndefined())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::Frame)]);
+        LValue object = allocateObject<JSClass>(m_node->structure(), m_out.intPtrZero, slowCase);
+        auto initialValues = JSClass::initialValues();
+        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();
-        ValueFromBlock fastResult = m_out.anchor(generator);
+        ValueFromBlock fastResult = m_out.anchor(object);
         m_out.jump(continuation);
 
         m_out.appendTo(slowCase, continuation);
-        ValueFromBlock slowResult = m_out.anchor(vmCall(pointerType(), m_out.operation(operationNewGenerator), m_callFrame, frozenPointer(m_graph.freezeStrong(m_node->structure().get()))));
+        ValueFromBlock slowResult = m_out.anchor(vmCall(pointerType(), m_out.operation(operation), m_callFrame, frozenPointer(m_graph.freezeStrong(m_node->structure().get()))));
         m_out.jump(continuation);
 
         m_out.appendTo(continuation, lastNext);
         setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
     }
 
+    void compileNewGenerator()
+    {
+        compileNewInternalFieldObject<JSGenerator>(operationNewGenerator);
+    }
+
+    void compileNewAsyncGenerator()
+    {
+        compileNewInternalFieldObject<JSAsyncGenerator>(operationNewAsyncGenerator);
+    }
+
     void compileNewStringObject()
     {
         RegisteredStructure structure = m_node->structure();
@@ -6373,7 +6390,8 @@ private:
         setJSValue(result);
     }
 
-    void compileCreateGenerator()
+    template<typename JSClass, typename Operation>
+    void compileCreateInternalFieldObject(Operation operation)
     {
         JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
 
@@ -6398,24 +6416,23 @@ private:
         m_out.branch(m_out.isZero64(structure), rarely(slowCase), usually(hasStructure));
 
         m_out.appendTo(hasStructure, checkGlobalObjectCase);
-        m_out.branch(m_out.equal(m_out.loadPtr(structure, m_heaps.Structure_classInfo), m_out.constIntPtr(JSGenerator::info())), usually(checkGlobalObjectCase), rarely(slowCase));
+        m_out.branch(m_out.equal(m_out.loadPtr(structure, m_heaps.Structure_classInfo), m_out.constIntPtr(JSClass::info())), usually(checkGlobalObjectCase), rarely(slowCase));
 
         m_out.appendTo(checkGlobalObjectCase, fastAllocationCase);
         m_out.branch(m_out.equal(m_out.loadPtr(structure, m_heaps.Structure_globalObject), weakPointer(globalObject)), usually(fastAllocationCase), rarely(slowCase));
 
         m_out.appendTo(fastAllocationCase, slowCase);
-        LValue generator = allocateObject<JSGenerator>(structure, m_out.intPtrZero, slowCase);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsNull())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::PolyProto)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsNumber(static_cast<int32_t>(JSGenerator::GeneratorState::Init)))), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::State)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsUndefined())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::Next)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsUndefined())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::This)]);
-        m_out.store64(m_out.constInt64(JSValue::encode(jsUndefined())), generator, m_heaps.JSInternalFieldObjectImpl_internalFields[static_cast<unsigned>(JSGenerator::Field::Frame)]);
+        LValue object = allocateObject<JSClass>(structure, m_out.intPtrZero, slowCase);
+        auto initialValues = JSClass::initialValues();
+        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();
-        ValueFromBlock fastResult = m_out.anchor(generator);
+        ValueFromBlock fastResult = m_out.anchor(object);
         m_out.jump(continuation);
 
         m_out.appendTo(slowCase, continuation);
-        ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationCreateGenerator), m_callFrame, callee, weakPointer(globalObject)));
+        ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operation), m_callFrame, callee, weakPointer(globalObject)));
         m_out.jump(continuation);
 
         m_out.appendTo(continuation, lastNext);
@@ -6424,6 +6441,16 @@ private:
         setJSValue(result);
     }
 
+    void compileCreateGenerator()
+    {
+        compileCreateInternalFieldObject<JSGenerator>(operationCreateGenerator);
+    }
+
+    void compileCreateAsyncGenerator()
+    {
+        compileCreateInternalFieldObject<JSAsyncGenerator>(operationCreateAsyncGenerator);
+    }
+
     void compileSpread()
     {
         if (m_node->child1()->op() == PhantomNewArrayBuffer) {
index bbfcfe3..efad55c 100644 (file)
@@ -313,6 +313,7 @@ void JIT::privateCompileMainPass()
         DEFINE_SLOW_OP(create_promise)
         DEFINE_SLOW_OP(new_promise)
         DEFINE_SLOW_OP(create_generator)
+        DEFINE_SLOW_OP(create_async_generator)
         DEFINE_SLOW_OP(new_generator)
         DEFINE_SLOW_OP(pow)
 
@@ -583,6 +584,7 @@ void JIT::privateCompileSlowCases()
         DEFINE_SLOWCASE_SLOW_OP(create_this)
         DEFINE_SLOWCASE_SLOW_OP(create_promise)
         DEFINE_SLOWCASE_SLOW_OP(create_generator)
+        DEFINE_SLOWCASE_SLOW_OP(create_async_generator)
         DEFINE_SLOWCASE_SLOW_OP(to_this)
         DEFINE_SLOWCASE_SLOW_OP(to_primitive)
         DEFINE_SLOWCASE_SLOW_OP(to_number)
index d483f94..3959b8d 100644 (file)
@@ -719,7 +719,7 @@ ALWAYS_INLINE GetPutInfo JIT::copiedGetPutInfo(OpPutToScope bytecode)
 template<typename BinaryOp>
 ALWAYS_INLINE ArithProfile JIT::copiedArithProfile(BinaryOp bytecode)
 {
-    uint64_t key = static_cast<uint64_t>(BinaryOp::opcodeID) << 32 | static_cast<uint64_t>(bytecode.m_metadataID);
+    uint64_t key = (static_cast<uint64_t>(BinaryOp::opcodeID) + 1) << 32 | static_cast<uint64_t>(bytecode.m_metadataID);
     auto iterator = m_copiedArithProfiles.find(key);
     if (iterator != m_copiedArithProfiles.end())
         return iterator->value;
index 3c3e362..656e7dd 100644 (file)
@@ -1402,6 +1402,14 @@ JSCell* JIT_OPERATION operationNewGenerator(ExecState* exec, Structure* structur
     return JSGenerator::create(vm, structure);
 }
 
+JSCell* JIT_OPERATION operationNewAsyncGenerator(ExecState* exec, Structure* structure)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(vm, exec);
+
+    return JSAsyncGenerator::create(vm, structure);
+}
+
 JSCell* JIT_OPERATION operationNewRegexp(ExecState* exec, JSCell* regexpPtr)
 {
     SuperSamplerScope superSamplerScope(false);
index 1b749b2..d253231 100644 (file)
@@ -422,6 +422,7 @@ JSCell* JIT_OPERATION operationNewObject(ExecState*, Structure*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationNewPromise(ExecState*, Structure*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationNewInternalPromise(ExecState*, Structure*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationNewGenerator(ExecState*, Structure*) WTF_INTERNAL;
+JSCell* JIT_OPERATION operationNewAsyncGenerator(ExecState*, Structure*) WTF_INTERNAL;
 JSCell* JIT_OPERATION operationNewRegexp(ExecState*, JSCell*) WTF_INTERNAL;
 UnusedPtr JIT_OPERATION operationHandleTraps(ExecState*) WTF_INTERNAL;
 void JIT_OPERATION operationThrow(ExecState*, EncodedJSValue) WTF_INTERNAL;
index 0fea096..2d9a172 100644 (file)
@@ -1496,6 +1496,7 @@ slowPathOp(create_scoped_arguments)
 slowPathOp(create_this)
 slowPathOp(create_promise)
 slowPathOp(create_generator)
+slowPathOp(create_async_generator)
 slowPathOp(define_accessor_property)
 slowPathOp(define_data_property)
 slowPathOp(enumerator_generic_pname)
index a908e03..924f7e5 100644 (file)
@@ -309,16 +309,16 @@ SLOW_PATH_DECL(slow_path_new_promise)
     RETURN(result);
 }
 
-SLOW_PATH_DECL(slow_path_create_generator)
+template<typename JSClass, typename Bytecode>
+static JSClass* createInternalFieldObject(ExecState* exec, VM& vm, const Bytecode& bytecode, Structure* baseStructure)
 {
-    BEGIN();
-    auto bytecode = pc->as<OpCreateGenerator>();
-    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     JSObject* constructorAsObject = asObject(GET(bytecode.m_callee).jsValue());
 
-    Structure* structure = InternalFunction::createSubclassStructure(exec, nullptr, constructorAsObject, globalObject->generatorStructure());
-    CHECK_EXCEPTION();
-    JSGenerator* result = JSGenerator::create(vm, structure);
+    Structure* structure = InternalFunction::createSubclassStructure(exec, nullptr, constructorAsObject, baseStructure);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    JSClass* result = JSClass::create(vm, structure);
 
     JSFunction* constructor = jsDynamicCast<JSFunction*>(vm, constructorAsObject);
     if (constructor && constructor->canUseAllocationProfile()) {
@@ -328,7 +328,21 @@ SLOW_PATH_DECL(slow_path_create_generator)
         else if (cachedCallee.unvalidatedGet() != JSCell::seenMultipleCalleeObjects() && cachedCallee.get() != constructor)
             cachedCallee.setWithoutWriteBarrier(JSCell::seenMultipleCalleeObjects());
     }
-    RETURN(result);
+    RELEASE_AND_RETURN(scope, result);
+}
+
+SLOW_PATH_DECL(slow_path_create_generator)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpCreateGenerator>();
+    RETURN(createInternalFieldObject<JSGenerator>(exec, vm, bytecode, exec->lexicalGlobalObject()->generatorStructure()));
+}
+
+SLOW_PATH_DECL(slow_path_create_async_generator)
+{
+    BEGIN();
+    auto bytecode = pc->as<OpCreateAsyncGenerator>();
+    RETURN(createInternalFieldObject<JSAsyncGenerator>(exec, vm, bytecode, exec->lexicalGlobalObject()->asyncGeneratorStructure()));
 }
 
 SLOW_PATH_DECL(slow_path_new_generator)
index 7f90b14..d5d6f7e 100644 (file)
@@ -385,6 +385,7 @@ SLOW_PATH_HIDDEN_DECL(slow_path_is_var_scope);
 SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope_for_hoisting_func_decl_in_eval);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_promise);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_generator);
+SLOW_PATH_HIDDEN_DECL(slow_path_create_async_generator);
 SLOW_PATH_HIDDEN_DECL(slow_path_create_rest);
 SLOW_PATH_HIDDEN_DECL(slow_path_get_by_id_with_this);
 SLOW_PATH_HIDDEN_DECL(slow_path_get_by_val_with_this);
diff --git a/Source/JavaScriptCore/runtime/JSAsyncGenerator.cpp b/Source/JavaScriptCore/runtime/JSAsyncGenerator.cpp
new file mode 100644 (file)
index 0000000..5ab6810
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 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 "JSAsyncGenerator.h"
+
+#include "JSCInlines.h"
+#include "JSInternalFieldObjectImplInlines.h"
+
+namespace JSC {
+
+const ClassInfo JSAsyncGenerator::s_info = { "AsyncGenerator", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAsyncGenerator) };
+
+JSAsyncGenerator* JSAsyncGenerator::create(VM& vm, Structure* structure)
+{
+    JSAsyncGenerator* generator = new (NotNull, allocateCell<JSAsyncGenerator>(vm.heap)) JSAsyncGenerator(vm, structure);
+    generator->finishCreation(vm);
+    return generator;
+}
+
+Structure* JSAsyncGenerator::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(JSAsyncGeneratorType, StructureFlags), info());
+}
+
+JSAsyncGenerator::JSAsyncGenerator(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{
+}
+
+void JSAsyncGenerator::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    auto values = initialValues();
+    ASSERT(values.size() == numberOfInternalFields);
+    for (unsigned index = 0; index < values.size(); ++index)
+        internalField(index).set(vm, this, values[index]);
+}
+
+void JSAsyncGenerator::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    auto* thisObject = jsCast<JSAsyncGenerator*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+}
+
+} // namespace JSC
diff --git a/Source/JavaScriptCore/runtime/JSAsyncGenerator.h b/Source/JavaScriptCore/runtime/JSAsyncGenerator.h
new file mode 100644 (file)
index 0000000..ce5804a
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 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 "JSGenerator.h"
+#include "JSInternalFieldObjectImpl.h"
+
+namespace JSC {
+
+class JSAsyncGenerator final : public JSInternalFieldObjectImpl<8> {
+public:
+    using Base = JSInternalFieldObjectImpl<8>;
+
+    // JSAsyncGenerator 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(JSAsyncGenerator);
+    }
+
+    enum class AsyncGeneratorState : int32_t {
+        Completed = -1,
+        Executing = -2,
+        SuspendedStart = -3,
+        SuspendedYield = -4,
+        AwaitingReturn = -5,
+    };
+    static_assert(static_cast<int32_t>(AsyncGeneratorState::Completed) == static_cast<int32_t>(JSGenerator::GeneratorState::Completed));
+    static_assert(static_cast<int32_t>(AsyncGeneratorState::Executing) == static_cast<int32_t>(JSGenerator::GeneratorState::Executing));
+
+    enum class AsyncGeneratorSuspendReason : int32_t {
+        None = 0,
+        Yield = -1,
+        Await = -2
+    };
+
+    enum class Field : uint32_t {
+        // FIXME: JSAsyncGenerator should support PolyProto, since generator tends to be created with poly proto mode.
+        // We reserve the first internal field for PolyProto property. This offset is identical to JSFinalObject's first inline storage slot which will be used for PolyProto.
+        PolyProto = 0,
+        State,
+        Next,
+        This,
+        Frame,
+        SuspendReason,
+        QueueFirst,
+        QueueLast,
+    };
+    static_assert(numberOfInternalFields == 8);
+    static std::array<JSValue, numberOfInternalFields> initialValues()
+    {
+        return { {
+            jsNull(),
+            jsNumber(static_cast<int32_t>(AsyncGeneratorState::SuspendedStart)),
+            jsUndefined(),
+            jsUndefined(),
+            jsUndefined(),
+            jsNumber(static_cast<int32_t>(AsyncGeneratorSuspendReason::None)),
+            jsNull(),
+            jsNull(),
+        } };
+    }
+
+    static JSAsyncGenerator* create(VM&, Structure*);
+    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
+
+    DECLARE_EXPORT_INFO;
+
+    static void visitChildren(JSCell*, SlotVisitor&);
+
+protected:
+    JSAsyncGenerator(VM&, Structure*);
+    void finishCreation(VM&);
+};
+
+} // namespace JSC
index 86ba371..0ebf076 100644 (file)
@@ -56,19 +56,6 @@ public:
         return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
     }
 
-    enum class AsyncGeneratorState : int32_t {
-        Completed = -1,
-        Executing = -2,
-        SuspendedStart = -3,
-        SuspendedYield = -4,
-        AwaitingReturn = -5
-    };
-    
-    enum class AsyncGeneratorSuspendReason : int32_t {
-        None = 0,
-        Yield = -1,
-        Await = -2
-    };
 private:
     JSAsyncGeneratorFunction(VM&, FunctionExecutable*, JSScope*, Structure*);
 
index 758b707..18204a4 100644 (file)
@@ -53,11 +53,10 @@ JSGenerator::JSGenerator(VM& vm, Structure* structure)
 void JSGenerator::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
-    internalField(static_cast<unsigned>(Field::PolyProto)).set(vm, this, jsNull());
-    internalField(static_cast<unsigned>(Field::State)).set(vm, this, jsNumber(static_cast<int32_t>(GeneratorState::Init)));
-    internalField(static_cast<unsigned>(Field::Next)).set(vm, this, jsUndefined());
-    internalField(static_cast<unsigned>(Field::This)).set(vm, this, jsUndefined());
-    internalField(static_cast<unsigned>(Field::Frame)).set(vm, this, jsUndefined());
+    auto values = initialValues();
+    ASSERT(values.size() == numberOfInternalFields);
+    for (unsigned index = 0; index < values.size(); ++index)
+        internalField(index).set(vm, this, values[index]);
 }
 
 void JSGenerator::visitChildren(JSCell* cell, SlotVisitor& visitor)
index 7b44e77..9081c3c 100644 (file)
@@ -72,6 +72,16 @@ public:
         Frame,
     };
     static_assert(numberOfInternalFields == 5);
+    static std::array<JSValue, numberOfInternalFields> initialValues()
+    {
+        return { {
+            jsNull(),
+            jsNumber(static_cast<int32_t>(GeneratorState::Init)),
+            jsUndefined(),
+            jsUndefined(),
+            jsUndefined(),
+        } };
+    }
 
     static JSGenerator* create(VM&, Structure*);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
index 0d59894..a20b163 100644 (file)
@@ -833,6 +833,7 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
 
     m_asyncGeneratorPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, m_asyncGeneratorFunctionPrototype.get(), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
     m_asyncGeneratorFunctionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->prototype, m_asyncGeneratorPrototype.get(), PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly);
+    m_asyncGeneratorStructure.set(vm, this, JSAsyncGenerator::createStructure(vm, this, m_asyncGeneratorPrototype.get()));
     
     m_objectPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, objectConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     m_functionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, functionConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -1769,6 +1770,7 @@ void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(thisObject->m_asyncFunctionStructure);
     visitor.append(thisObject->m_asyncGeneratorFunctionStructure);
     visitor.append(thisObject->m_generatorStructure);
+    visitor.append(thisObject->m_asyncGeneratorStructure);
     thisObject->m_iteratorResultObjectStructure.visit(visitor);
     visitor.append(thisObject->m_regExpMatchesArrayStructure);
     visitor.append(thisObject->m_regExpMatchesArrayWithGroupsStructure);
index 1d2bc2d..be1bd25 100644 (file)
@@ -375,6 +375,7 @@ public:
     WriteBarrier<Structure> m_asyncGeneratorFunctionStructure;
     WriteBarrier<Structure> m_generatorFunctionStructure;
     WriteBarrier<Structure> m_generatorStructure;
+    WriteBarrier<Structure> m_asyncGeneratorStructure;
     LazyProperty<JSGlobalObject, Structure> m_iteratorResultObjectStructure;
     WriteBarrier<Structure> m_regExpMatchesArrayStructure;
     WriteBarrier<Structure> m_regExpMatchesArrayWithGroupsStructure;
@@ -754,6 +755,7 @@ public:
     Structure* mapStructure() const { return m_mapStructure.get(); }
     Structure* regExpStructure() const { return m_regExpStructure.get(); }
     Structure* generatorStructure() const { return m_generatorStructure.get(); }
+    Structure* asyncGeneratorStructure() const { return m_asyncGeneratorStructure.get(); }
     Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); }
     Structure* asyncFunctionStructure() const { return m_asyncFunctionStructure.get(); }
     Structure* asyncGeneratorFunctionStructure() const { return m_asyncGeneratorFunctionStructure.get(); }
index 502b46e..d1c673e 100644 (file)
@@ -98,6 +98,7 @@ void printInternal(PrintStream& out, JSC::JSType type)
     CASE(RegExpObjectType)
     CASE(ProxyObjectType)
     CASE(JSGeneratorType)
+    CASE(JSAsyncGeneratorType)
     CASE(JSPromiseType)
     CASE(JSMapType)
     CASE(JSSetType)
index 8151eee..e930fd3 100644 (file)
@@ -110,6 +110,7 @@ enum JSType : uint8_t {
     RegExpObjectType,
     ProxyObjectType,
     JSGeneratorType,
+    JSAsyncGeneratorType,
     JSPromiseType,
     JSMapType,
     JSSetType,