Ignore:
Timestamp:
Oct 28, 2016, 9:37:38 AM (9 years ago)
Author:
[email protected]
Message:

[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):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/parser/ParserModes.h

    r206525 r208052  
    149149}
    150150
     151ALWAYS_INLINE bool isGeneratorOrAsyncFunctionBodyParseMode(SourceParseMode parseMode)
     152{
     153    return SourceParseModeSet(
     154        SourceParseMode::GeneratorBodyMode,
     155        SourceParseMode::AsyncFunctionBodyMode,
     156        SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
     157}
     158
     159ALWAYS_INLINE bool isGeneratorOrAsyncFunctionWrapperParseMode(SourceParseMode parseMode)
     160{
     161    return SourceParseModeSet(
     162        SourceParseMode::GeneratorWrapperFunctionMode,
     163        SourceParseMode::AsyncFunctionMode,
     164        SourceParseMode::AsyncArrowFunctionMode,
     165        SourceParseMode::AsyncMethodMode).contains(parseMode);
     166}
     167
     168ALWAYS_INLINE bool isArrowFunctionParseMode(SourceParseMode parseMode)
     169{
     170    return SourceParseModeSet(
     171        SourceParseMode::ArrowFunctionMode,
     172        SourceParseMode::AsyncArrowFunctionMode,
     173        SourceParseMode::AsyncArrowFunctionBodyMode).contains(parseMode);
     174}
     175
     176
    151177ALWAYS_INLINE bool isModuleParseMode(SourceParseMode parseMode)
    152178{
Note: See TracChangeset for help on using the changeset viewer.