haikuwebkit/JSTests/stress/async-arrow-functions-lexic...

44 lines
1.0 KiB
JavaScript
Raw Permalink Normal View History

[JSC] implement runtime for async functions https://bugs.webkit.org/show_bug.cgi?id=163760 Reviewed by Yusuke Suzuki. JSTests: * stress/async-await-basic.js: Added. (shouldBe): (shouldBeAsync): (shouldThrow): (shouldThrowAsync): (shouldThrowSyntaxError): (let.AsyncFunction.async): (async.asyncFunctionForProto): (Object.getPrototypeOf.async): (Object.getPrototypeOf.async.method): (async): (async.method): (async.asyncNonConstructorDecl): (shouldThrow.new.async): (shouldThrow.new.async.nonConstructor): (async.asyncDecl): (async.f): (MyError): (async.asyncDeclThrower): (shouldThrowAsync.async): (resolveLater): (rejectLater): (async.resumeAfterNormal): (O.async.resumeAfterNormal): (resumeAfterNormalArrow.async): (async.resumeAfterThrow): (O.async.resumeAfterThrow): (resumeAfterThrowArrow.async): (catch): * stress/async-await-module-reserved-word.js: Added. (shouldThrow): (SyntaxError.Canstring_appeared_hereawait.checkModuleSyntaxError.String.raw.await): (checkModuleSyntaxError.String.raw.await): (checkModuleSyntaxError.String.raw.async.await): (SyntaxError.Cannot.declare.named): * stress/async-await-mozilla.js: Added. (shouldBe): (shouldBeAsync): (shouldThrow): (shouldThrowAsync): (assert): (shouldThrowSyntaxError): (mozSemantics.async.empty): (mozSemantics.async.simpleReturn): (mozSemantics.async.simpleAwait): (mozSemantics.async.simpleAwaitAsync): (mozSemantics.async.returnOtherAsync): (mozSemantics.async.simpleThrower): (mozSemantics.async.delegatedThrower): (mozSemantics.async.tryCatch): (mozSemantics.async.tryCatchThrow): (mozSemantics.async.wellFinally): (mozSemantics.async.finallyMayFail): (mozSemantics.async.embedded.async.inner): (mozSemantics.async.embedded): (mozSemantics.async.fib): (mozSemantics.async.isOdd.async.isEven): (mozSemantics.async.isOdd): (mozSemantics.hardcoreFib.async.fib2): (mozSemantics.namedAsyncExpr.async.simple): (mozSemantics.async.executionOrder.async.first): (mozSemantics.async.executionOrder.async.second): (mozSemantics.async.executionOrder.async.third): (mozSemantics.async.executionOrder): (mozSemantics.async.miscellaneous): (mozSemantics.thrower): (mozSemantics.async.defaultArgs): (mozSemantics.shouldThrow): (mozSemantics): (mozMethods.X): (mozMethods.X.prototype.async.getValue): (mozMethods.X.prototype.setValue): (mozMethods.X.prototype.async.increment): (mozMethods.X.prototype.async.getBaseClassName): (mozMethods.X.async.getStaticValue): (mozMethods.Y.prototype.async.getBaseClassName): (mozMethods.Y): (mozFunctionNameInferrence.async.test): (mozSyntaxErrors): * stress/async-await-reserved-word.js: Added. (assert): (shouldThrowSyntaxError): (AsyncFunction.async): * stress/async_arrow_functions_lexical_arguments_binding.js: Added. (shouldBe): (shouldBeAsync): (shouldThrowAsync): (noArgumentsArrow2.async): * stress/async_arrow_functions_lexical_new.target_binding.js: Added. (shouldBe): (shouldBeAsync): (shouldThrowAsync): (C1): (C2): (shouldThrowAsync.async): * stress/async_arrow_functions_lexical_super_binding.js: Added. (shouldBe): (shouldBeAsync): (BaseClass.prototype.baseClassValue): (BaseClass.prototype.get property): (BaseClass): (ChildClass.prototype.asyncSuperProp): (ChildClass.prototype.asyncSuperProp2): (ChildClass): (ChildClass2): * stress/async_arrow_functions_lexical_this_binding.js: Added. (shouldBe): (shouldBeAsync): (d.y): Source/JavaScriptCore: Async functions generate bytecode equivalent to the following, which is highly dependent on the Generator implementation: ``` // Before translation: async function asyncfn() {} // After translation: function asyncfn() { let generator = { @generatorNext: function(@generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrameState) { // Body of async function }, @generatorState: 0, @generatorThis: this, @generatorFrameState: <frame state>, }; return @asyncFunctionResume(generator, undefined, GeneratorResumeMode::NormalMode); } ``` Await Expressions are equivalent to non-delegating Yield expressions, and emit identical bytecode. There are some caveats to be addressed later: 1) the `op_to_this` is always performed, whether it's used or not, like normal generators. (https://bugs.webkit.org/show_bug.cgi?id=151586) 2) for async arrow functions, the home object is always stored on the "body" function, regardless of whether it's needed or not, for the same reason as #1 (and should also be fixed as part of https://bugs.webkit.org/show_bug.cgi?id=151586) * CMakeLists.txt: * DerivedSources.make: * JavaScriptCore.xcodeproj/project.pbxproj: * builtins/AsyncFunctionPrototype.js: Added. (asyncFunctionResume): * bytecode/BytecodeList.json: * bytecode/BytecodeUseDef.h: (JSC::computeUsesForBytecodeOffset): (JSC::computeDefsForBytecodeOffset): * bytecode/CodeBlock.cpp: (JSC::CodeBlock::dumpBytecode): * bytecode/UnlinkedCodeBlock.h: (JSC::UnlinkedCodeBlock::isArrowFunction): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::generate): (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::emitNewFunctionExpressionCommon): (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewFunction): * bytecompiler/NodesCodegen.cpp: (JSC::FunctionNode::emitBytecode): * jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): * jit/JIT.h: * jit/JITOpcodes.cpp: (JSC::JIT::emitNewFuncCommon): (JSC::JIT::emit_op_new_async_func): (JSC::JIT::emitNewFuncExprCommon): (JSC::JIT::emit_op_new_async_func_exp): * jit/JITOperations.cpp: * jit/JITOperations.h: * llint/LLIntSlowPaths.cpp: (JSC::LLInt::LLINT_SLOW_PATH_DECL): * llint/LLIntSlowPaths.h: * llint/LowLevelInterpreter.asm: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseInner): (JSC::Parser<LexerType>::parseAsyncFunctionSourceElements): (JSC::Parser<LexerType>::parseFunctionInfo): * parser/Parser.h: (JSC::Scope::setSourceParseMode): * parser/ParserModes.h: (JSC::isGeneratorOrAsyncFunctionBodyParseMode): (JSC::isGeneratorOrAsyncFunctionWrapperParseMode): * runtime/AsyncFunctionConstructor.cpp: Added. (JSC::AsyncFunctionConstructor::AsyncFunctionConstructor): (JSC::AsyncFunctionConstructor::finishCreation): (JSC::callAsyncFunctionConstructor): (JSC::constructAsyncFunctionConstructor): (JSC::AsyncFunctionConstructor::getCallData): (JSC::AsyncFunctionConstructor::getConstructData): * runtime/AsyncFunctionConstructor.h: Added. (JSC::AsyncFunctionConstructor::create): (JSC::AsyncFunctionConstructor::createStructure): * runtime/AsyncFunctionPrototype.cpp: Added. (JSC::AsyncFunctionPrototype::AsyncFunctionPrototype): (JSC::AsyncFunctionPrototype::finishCreation): * runtime/AsyncFunctionPrototype.h: Added. (JSC::AsyncFunctionPrototype::create): (JSC::AsyncFunctionPrototype::createStructure): * runtime/FunctionConstructor.cpp: (JSC::constructFunctionSkippingEvalEnabledCheck): * runtime/FunctionConstructor.h: * runtime/JSAsyncFunction.cpp: Added. (JSC::JSAsyncFunction::JSAsyncFunction): (JSC::JSAsyncFunction::createImpl): (JSC::JSAsyncFunction::create): (JSC::JSAsyncFunction::createWithInvalidatedReallocationWatchpoint): * runtime/JSAsyncFunction.h: Added. (JSC::JSAsyncFunction::allocationSize): (JSC::JSAsyncFunction::createStructure): * runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::init): * runtime/JSGlobalObject.h: (JSC::JSGlobalObject::lazyAsyncFunctionStructure): (JSC::JSGlobalObject::asyncFunctionPrototype): (JSC::JSGlobalObject::asyncFunctionPrototypeConcurrently): (JSC::JSGlobalObject::asyncFunctionStructure): (JSC::JSGlobalObject::asyncFunctionStructureConcurrently): Canonical link: https://commits.webkit.org/181838@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208052 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-28 16:37:38 +00:00
function shouldBe(expected, actual, msg) {
if (msg === void 0)
msg = "";
else
msg = " for " + msg;
if (actual !== expected)
throw new Error("bad value" + msg + ": " + actual + ". Expected " + expected);
}
function shouldBeAsync(expected, run, msg) {
let actual;
var hadError = false;
run().then(function(value) { actual = value; },
function(error) { hadError = true; actual = error; });
drainMicrotasks();
if (hadError)
throw actual;
shouldBe(expected, actual, msg);
}
function C1() {
return async () => await new.target;
}
function C2() {
return async () => { return await new.target };
}
function C2WithAwait() {
return async () => {
var self = new.target; await new.target;
return new.target;
}
}
[JSC] implement runtime for async functions https://bugs.webkit.org/show_bug.cgi?id=163760 Reviewed by Yusuke Suzuki. JSTests: * stress/async-await-basic.js: Added. (shouldBe): (shouldBeAsync): (shouldThrow): (shouldThrowAsync): (shouldThrowSyntaxError): (let.AsyncFunction.async): (async.asyncFunctionForProto): (Object.getPrototypeOf.async): (Object.getPrototypeOf.async.method): (async): (async.method): (async.asyncNonConstructorDecl): (shouldThrow.new.async): (shouldThrow.new.async.nonConstructor): (async.asyncDecl): (async.f): (MyError): (async.asyncDeclThrower): (shouldThrowAsync.async): (resolveLater): (rejectLater): (async.resumeAfterNormal): (O.async.resumeAfterNormal): (resumeAfterNormalArrow.async): (async.resumeAfterThrow): (O.async.resumeAfterThrow): (resumeAfterThrowArrow.async): (catch): * stress/async-await-module-reserved-word.js: Added. (shouldThrow): (SyntaxError.Canstring_appeared_hereawait.checkModuleSyntaxError.String.raw.await): (checkModuleSyntaxError.String.raw.await): (checkModuleSyntaxError.String.raw.async.await): (SyntaxError.Cannot.declare.named): * stress/async-await-mozilla.js: Added. (shouldBe): (shouldBeAsync): (shouldThrow): (shouldThrowAsync): (assert): (shouldThrowSyntaxError): (mozSemantics.async.empty): (mozSemantics.async.simpleReturn): (mozSemantics.async.simpleAwait): (mozSemantics.async.simpleAwaitAsync): (mozSemantics.async.returnOtherAsync): (mozSemantics.async.simpleThrower): (mozSemantics.async.delegatedThrower): (mozSemantics.async.tryCatch): (mozSemantics.async.tryCatchThrow): (mozSemantics.async.wellFinally): (mozSemantics.async.finallyMayFail): (mozSemantics.async.embedded.async.inner): (mozSemantics.async.embedded): (mozSemantics.async.fib): (mozSemantics.async.isOdd.async.isEven): (mozSemantics.async.isOdd): (mozSemantics.hardcoreFib.async.fib2): (mozSemantics.namedAsyncExpr.async.simple): (mozSemantics.async.executionOrder.async.first): (mozSemantics.async.executionOrder.async.second): (mozSemantics.async.executionOrder.async.third): (mozSemantics.async.executionOrder): (mozSemantics.async.miscellaneous): (mozSemantics.thrower): (mozSemantics.async.defaultArgs): (mozSemantics.shouldThrow): (mozSemantics): (mozMethods.X): (mozMethods.X.prototype.async.getValue): (mozMethods.X.prototype.setValue): (mozMethods.X.prototype.async.increment): (mozMethods.X.prototype.async.getBaseClassName): (mozMethods.X.async.getStaticValue): (mozMethods.Y.prototype.async.getBaseClassName): (mozMethods.Y): (mozFunctionNameInferrence.async.test): (mozSyntaxErrors): * stress/async-await-reserved-word.js: Added. (assert): (shouldThrowSyntaxError): (AsyncFunction.async): * stress/async_arrow_functions_lexical_arguments_binding.js: Added. (shouldBe): (shouldBeAsync): (shouldThrowAsync): (noArgumentsArrow2.async): * stress/async_arrow_functions_lexical_new.target_binding.js: Added. (shouldBe): (shouldBeAsync): (shouldThrowAsync): (C1): (C2): (shouldThrowAsync.async): * stress/async_arrow_functions_lexical_super_binding.js: Added. (shouldBe): (shouldBeAsync): (BaseClass.prototype.baseClassValue): (BaseClass.prototype.get property): (BaseClass): (ChildClass.prototype.asyncSuperProp): (ChildClass.prototype.asyncSuperProp2): (ChildClass): (ChildClass2): * stress/async_arrow_functions_lexical_this_binding.js: Added. (shouldBe): (shouldBeAsync): (d.y): Source/JavaScriptCore: Async functions generate bytecode equivalent to the following, which is highly dependent on the Generator implementation: ``` // Before translation: async function asyncfn() {} // After translation: function asyncfn() { let generator = { @generatorNext: function(@generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrameState) { // Body of async function }, @generatorState: 0, @generatorThis: this, @generatorFrameState: <frame state>, }; return @asyncFunctionResume(generator, undefined, GeneratorResumeMode::NormalMode); } ``` Await Expressions are equivalent to non-delegating Yield expressions, and emit identical bytecode. There are some caveats to be addressed later: 1) the `op_to_this` is always performed, whether it's used or not, like normal generators. (https://bugs.webkit.org/show_bug.cgi?id=151586) 2) for async arrow functions, the home object is always stored on the "body" function, regardless of whether it's needed or not, for the same reason as #1 (and should also be fixed as part of https://bugs.webkit.org/show_bug.cgi?id=151586) * CMakeLists.txt: * DerivedSources.make: * JavaScriptCore.xcodeproj/project.pbxproj: * builtins/AsyncFunctionPrototype.js: Added. (asyncFunctionResume): * bytecode/BytecodeList.json: * bytecode/BytecodeUseDef.h: (JSC::computeUsesForBytecodeOffset): (JSC::computeDefsForBytecodeOffset): * bytecode/CodeBlock.cpp: (JSC::CodeBlock::dumpBytecode): * bytecode/UnlinkedCodeBlock.h: (JSC::UnlinkedCodeBlock::isArrowFunction): * bytecode/UnlinkedFunctionExecutable.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::generate): (JSC::BytecodeGenerator::BytecodeGenerator): (JSC::BytecodeGenerator::emitNewFunctionExpressionCommon): (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): (JSC::BytecodeGenerator::emitNewFunction): * bytecompiler/NodesCodegen.cpp: (JSC::FunctionNode::emitBytecode): * jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): * jit/JIT.h: * jit/JITOpcodes.cpp: (JSC::JIT::emitNewFuncCommon): (JSC::JIT::emit_op_new_async_func): (JSC::JIT::emitNewFuncExprCommon): (JSC::JIT::emit_op_new_async_func_exp): * jit/JITOperations.cpp: * jit/JITOperations.h: * llint/LLIntSlowPaths.cpp: (JSC::LLInt::LLINT_SLOW_PATH_DECL): * llint/LLIntSlowPaths.h: * llint/LowLevelInterpreter.asm: * parser/Parser.cpp: (JSC::Parser<LexerType>::parseInner): (JSC::Parser<LexerType>::parseAsyncFunctionSourceElements): (JSC::Parser<LexerType>::parseFunctionInfo): * parser/Parser.h: (JSC::Scope::setSourceParseMode): * parser/ParserModes.h: (JSC::isGeneratorOrAsyncFunctionBodyParseMode): (JSC::isGeneratorOrAsyncFunctionWrapperParseMode): * runtime/AsyncFunctionConstructor.cpp: Added. (JSC::AsyncFunctionConstructor::AsyncFunctionConstructor): (JSC::AsyncFunctionConstructor::finishCreation): (JSC::callAsyncFunctionConstructor): (JSC::constructAsyncFunctionConstructor): (JSC::AsyncFunctionConstructor::getCallData): (JSC::AsyncFunctionConstructor::getConstructData): * runtime/AsyncFunctionConstructor.h: Added. (JSC::AsyncFunctionConstructor::create): (JSC::AsyncFunctionConstructor::createStructure): * runtime/AsyncFunctionPrototype.cpp: Added. (JSC::AsyncFunctionPrototype::AsyncFunctionPrototype): (JSC::AsyncFunctionPrototype::finishCreation): * runtime/AsyncFunctionPrototype.h: Added. (JSC::AsyncFunctionPrototype::create): (JSC::AsyncFunctionPrototype::createStructure): * runtime/FunctionConstructor.cpp: (JSC::constructFunctionSkippingEvalEnabledCheck): * runtime/FunctionConstructor.h: * runtime/JSAsyncFunction.cpp: Added. (JSC::JSAsyncFunction::JSAsyncFunction): (JSC::JSAsyncFunction::createImpl): (JSC::JSAsyncFunction::create): (JSC::JSAsyncFunction::createWithInvalidatedReallocationWatchpoint): * runtime/JSAsyncFunction.h: Added. (JSC::JSAsyncFunction::allocationSize): (JSC::JSAsyncFunction::createStructure): * runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::init): * runtime/JSGlobalObject.h: (JSC::JSGlobalObject::lazyAsyncFunctionStructure): (JSC::JSGlobalObject::asyncFunctionPrototype): (JSC::JSGlobalObject::asyncFunctionPrototypeConcurrently): (JSC::JSGlobalObject::asyncFunctionStructure): (JSC::JSGlobalObject::asyncFunctionStructureConcurrently): Canonical link: https://commits.webkit.org/181838@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208052 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-28 16:37:38 +00:00
shouldBeAsync(C1, new C1());
shouldBeAsync(undefined, C1());
shouldBeAsync(C2, new C2());
shouldBeAsync(undefined, C2());
shouldBeAsync(C2WithAwait, new C2WithAwait());
shouldBeAsync(undefined, C2WithAwait());