From 9dc2b3f8332729aac445e45c39b2d2623826f979 Mon Sep 17 00:00:00 2001 From: ctw-ian Date: Tue, 19 Jul 2022 22:01:18 +0800 Subject: [PATCH] Fix async and generator for es2abc Fix async and generator to meet with implementation of runtime Issue:I5IPC4 Signed-off-by: ctw-ian Change-Id: If4bba32935b92ce392979684a2f4683018ea9afb --- es2panda/compiler/base/iterators.cpp | 38 ++++++++++--- es2panda/compiler/core/pandagen.cpp | 57 +++++-------------- es2panda/compiler/core/pandagen.h | 13 ++--- .../function/asyncFunctionBuilder.cpp | 19 ++++++- .../compiler/function/asyncFunctionBuilder.h | 2 +- .../asyncGeneratorFunctionBuilder.cpp | 6 +- .../function/asyncGeneratorFunctionBuilder.h | 2 +- .../compiler/function/functionBuilder.cpp | 14 +++-- es2panda/compiler/function/functionBuilder.h | 2 +- .../function/generatorFunctionBuilder.cpp | 19 ++++--- .../function/generatorFunctionBuilder.h | 2 +- 11 files changed, 95 insertions(+), 79 deletions(-) diff --git a/es2panda/compiler/base/iterators.cpp b/es2panda/compiler/base/iterators.cpp index 8ba4d12a11..47d653b8ee 100644 --- a/es2panda/compiler/base/iterators.cpp +++ b/es2panda/compiler/base/iterators.cpp @@ -35,13 +35,11 @@ Iterator::Iterator(PandaGen *pg, const ir::AstNode *node, IteratorType type) pg_->StoreAccumulator(node, iterator_); pg_->LoadObjByName(node_, iterator_, "next"); pg_->StoreAccumulator(node_, method_); - - pg_->ThrowIfNotObject(node_); } void Iterator::GetMethod(util::StringView name) const { - pg_->GetMethod(node_, iterator_, name); + pg_->LoadObjByName(node_, iterator_, name); pg_->StoreAccumulator(node_, method_); } @@ -63,8 +61,8 @@ void Iterator::Next() const pg_->FuncBuilder()->Await(node_); } - pg_->ThrowIfNotObject(node_); pg_->StoreAccumulator(node_, nextResult_); + pg_->ThrowIfNotObject(node_, nextResult_); } void Iterator::Complete() const @@ -80,10 +78,34 @@ void Iterator::Value() const void Iterator::Close(bool abruptCompletion) const { if (type_ == IteratorType::SYNC) { - if (!abruptCompletion) { - pg_->LoadConst(node_, Constant::JS_HOLE); + RegScope rs(pg_); + VReg exception = pg_->AllocReg(); + VReg doneResult = pg_->AllocReg(); + VReg innerResult = pg_->AllocReg(); + Label *noReturn = pg_->AllocLabel(); + + if (abruptCompletion) { + pg_->StoreAccumulator(node_, exception); + } + + pg_->StoreConst(node_, doneResult, Constant::JS_TRUE); + Complete(); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, doneResult, noReturn); + + // close iterator + pg_->LoadObjByName(node_, iterator_, "return"); + pg_->StoreAccumulator(node_, method_); + pg_->LoadConst(node_, Constant::JS_UNDEFINED); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, method_, noReturn); + CallMethod(); + pg_->StoreAccumulator(node_, innerResult); + pg_->ThrowIfNotObject(node_, innerResult); + + pg_->SetLabel(node_, noReturn); + if (abruptCompletion) { + pg_->LoadAccumulator(node_, exception); + pg_->EmitThrow(node_); } - pg_->CloseIterator(node_, iterator_); return; } @@ -159,7 +181,7 @@ void Iterator::Close(bool abruptCompletion) const // 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. pg_->LoadAccumulator(node_, innerResult); - pg_->ThrowIfNotObject(node_); + pg_->ThrowIfNotObject(node_, innerResult); } DestructuringIterator::DestructuringIterator(PandaGen *pg, const ir::AstNode *node) diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 17375d9a93..21ca7cf585 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -983,7 +983,9 @@ void PandaGen::LoadHomeObject(const ir::AstNode *node) void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) { auto formalParamCnt = realNode->FormalParamsLength(); - if (realNode->IsAsync()) { + if (realNode->IsMethod()) { + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); + } else if (realNode->IsAsync()) { if (realNode->IsGenerator()) { // TODO(): async generator } else { @@ -994,8 +996,6 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction } else if (realNode->IsArrow()) { LoadHomeObject(node); ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); - } else if (realNode->IsMethod()) { - ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } else { ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } @@ -1040,15 +1040,6 @@ void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) ra_.Emit(node, arg); } -void PandaGen::GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name) -{ - /** - * TODO - * ra_.Emit(node, name, obj); - * strings_.insert(name); - */ -} - void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) { ra_.Emit(node, funcObj); @@ -1062,20 +1053,14 @@ void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj) */ } -void PandaGen::CreateIterResultObject(const ir::AstNode *node, bool done) +void PandaGen::CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done) { - /* - * TODO: create iter result - * ra_.Emit(node, static_cast(done)); - */ + ra_.Emit(node, value, done); } -void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj) +void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult) { - /* - * TODO: suspend generator - * ra_.Emit(node, genObj); - */ + ra_.Emit(node, genObj, iterResult); } void PandaGen::SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj) @@ -1117,28 +1102,19 @@ void PandaGen::AsyncFunctionEnter(const ir::AstNode *node) sa_.Emit(node); } -void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal) { - /* - * TODO: async function await - * ra_.Emit(node, asyncFuncObj); - */ + ra_.Emit(node, asyncFuncObj, retVal); } -void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) { - /* - * TODO: async function resolve - * ra_.Emit(node, asyncFuncObj); - */ + ra_.Emit(node, asyncFuncObj, value, canSuspend); } -void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) { - /* - * TODO: async function reject - * ra_.Emit(node, asyncFuncObj); - */ + ra_.Emit(node, asyncFuncObj, value, canSuspend); } void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj) @@ -1324,12 +1300,9 @@ void PandaGen::StoreArraySpread(const ir::AstNode *node, VReg array, VReg index) ra_.Emit(node, array, index); } -void PandaGen::ThrowIfNotObject(const ir::AstNode *node) +void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj) { - // TODO: implement this method correctly - RegScope rs(this); - VReg value = AllocReg(); - ra_.Emit(node, value); + ra_.Emit(node, obj); } void PandaGen::ThrowThrowNotExist(const ir::AstNode *node) diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index 67582f92e3..6086561b14 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -294,16 +294,15 @@ public: void GetResumeMode(const ir::AstNode *node, VReg genObj); void AsyncFunctionEnter(const ir::AstNode *node); - void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj); - void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj); - void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj); + void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal); + void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); + void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); - void GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name); void GeneratorYield(const ir::AstNode *node, VReg genObj); void GeneratorComplete(const ir::AstNode *node, VReg genObj); void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj); - void CreateIterResultObject(const ir::AstNode *node, bool done); - void SuspendGenerator(const ir::AstNode *node, VReg genObj); + void CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done); + void SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult); void SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj); void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj); @@ -326,7 +325,7 @@ public: void CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx); void StoreArraySpread(const ir::AstNode *node, VReg array, VReg index); - void ThrowIfNotObject(const ir::AstNode *node); + void ThrowIfNotObject(const ir::AstNode *node, VReg obj); void ThrowThrowNotExist(const ir::AstNode *node); void GetIterator(const ir::AstNode *node); void GetAsyncIterator(const ir::AstNode *node); diff --git a/es2panda/compiler/function/asyncFunctionBuilder.cpp b/es2panda/compiler/function/asyncFunctionBuilder.cpp index acbbc790ab..170db32073 100644 --- a/es2panda/compiler/function/asyncFunctionBuilder.cpp +++ b/es2panda/compiler/function/asyncFunctionBuilder.cpp @@ -23,7 +23,15 @@ namespace panda::es2panda::compiler { void AsyncFunctionBuilder::DirectReturn(const ir::AstNode *node) const { - pg_->AsyncFunctionResolve(node, funcObj_); + RegScope rs(pg_); + VReg retVal = pg_->AllocReg(); + VReg canSuspend = pg_->AllocReg(); + + pg_->StoreAccumulator(node, retVal); + pg_->LoadConst(node, Constant::JS_TRUE); + pg_->StoreAccumulator(node, canSuspend); + pg_->AsyncFunctionResolve(node, funcObj_, retVal, canSuspend); + pg_->LoadAccumulator(node, retVal); pg_->EmitReturn(node); } @@ -33,7 +41,7 @@ void AsyncFunctionBuilder::ImplicitReturn(const ir::AstNode *node) const DirectReturn(node); } -void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) { pg_->AsyncFunctionEnter(node); pg_->StoreAccumulator(node, funcObj_); @@ -42,11 +50,16 @@ void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) const void AsyncFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const { + RegScope rs(pg_); const auto &labelSet = catchTable_->LabelSet(); pg_->SetLabel(node, labelSet.TryEnd()); pg_->SetLabel(node, labelSet.CatchBegin()); - pg_->AsyncFunctionReject(node, funcObj_); + VReg exception = pg_->AllocReg(); + VReg canSuspend = pg_->AllocReg(); + pg_->StoreAccumulator(node, exception); + pg_->StoreConst(node, canSuspend, Constant::JS_TRUE); + pg_->AsyncFunctionReject(node, funcObj_, exception, canSuspend); pg_->EmitReturn(node); pg_->SetLabel(node, labelSet.CatchEnd()); } diff --git a/es2panda/compiler/function/asyncFunctionBuilder.h b/es2panda/compiler/function/asyncFunctionBuilder.h index bd7f38a814..68bdd99433 100644 --- a/es2panda/compiler/function/asyncFunctionBuilder.h +++ b/es2panda/compiler/function/asyncFunctionBuilder.h @@ -30,7 +30,7 @@ public: NO_COPY_SEMANTIC(AsyncFunctionBuilder); NO_MOVE_SEMANTIC(AsyncFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp index c4360cd87a..a74eea46df 100644 --- a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp +++ b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp @@ -20,13 +20,13 @@ #include namespace panda::es2panda::compiler { -void AsyncGeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void AsyncGeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) { VReg callee = FunctionReg(node); pg_->CreateAsyncGeneratorObj(node, callee); pg_->StoreAccumulator(node, funcObj_); - pg_->SuspendGenerator(node, funcObj_); + // pg_->SuspendGenerator(node, funcObj_); TODO implement this part correctly while implementing async generator pg_->SetLabel(node, catchTable_->LabelSet().TryBegin()); } @@ -72,7 +72,7 @@ void AsyncGeneratorFunctionBuilder::Yield(const ir::AstNode *node) pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, completionType, notReturnCompletion); // 27.6.3.8.8.b. Let awaited be Await(resumptionValue.[[Value]]). pg_->LoadAccumulator(node, completionValue); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->AsyncFunctionAwait(node, funcObj_, completionValue); SuspendResumeExecution(node, completionType, completionValue); // 27.6.3.8.8.c. If awaited.[[Type]] is throw, return Completion(awaited). diff --git a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h index f492da49d1..8ae591a79c 100644 --- a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h +++ b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h @@ -30,7 +30,7 @@ public: NO_COPY_SEMANTIC(AsyncGeneratorFunctionBuilder); NO_MOVE_SEMANTIC(AsyncGeneratorFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/compiler/function/functionBuilder.cpp b/es2panda/compiler/function/functionBuilder.cpp index eaba22a71a..47184ca1f5 100644 --- a/es2panda/compiler/function/functionBuilder.cpp +++ b/es2panda/compiler/function/functionBuilder.cpp @@ -68,7 +68,10 @@ void FunctionBuilder::SuspendResumeExecution(const ir::AstNode *node, VReg compl ASSERT(BuilderKind() == BuilderType::ASYNC || BuilderKind() == BuilderType::ASYNC_GENERATOR || BuilderKind() == BuilderType::GENERATOR); - pg_->SuspendGenerator(node, funcObj_); + RegScope rs(pg_); + VReg iterResult = pg_->AllocReg(); + pg_->StoreAccumulator(node, iterResult); + pg_->SuspendGenerator(node, funcObj_, iterResult); resumeGenerator(node, completionType, completionValue); } @@ -103,8 +106,10 @@ void FunctionBuilder::Await(const ir::AstNode *node) RegScope rs(pg_); VReg completionType = pg_->AllocReg(); VReg completionValue = pg_->AllocReg(); + VReg retVal = pg_->AllocReg(); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->StoreAccumulator(node, retVal); + pg_->AsyncFunctionAwait(node, funcObj_, retVal); SuspendResumeExecution(node, completionType, completionValue); HandleCompletion(node, completionType, completionValue); @@ -239,7 +244,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) // ii. If Type(innerResult) is not Object, throw a TypeError exception. // 4. If Type(innerResult) is not Object, throw a TypeError exception. // vi. If Type(innerReturnResult) is not Object, throw a TypeError exception. - pg_->ThrowIfNotObject(node); + pg_->ThrowIfNotObject(node, receivedValue); // iv. Let done be ? IteratorComplete(innerResult). // v. Let done be ? IteratorComplete(innerResult). @@ -264,8 +269,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, receivedType, loopStart); // b. Let awaited be Await(resumptionValue.[[Value]]). - pg_->LoadAccumulator(node, receivedValue); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->AsyncFunctionAwait(node, funcObj_, receivedValue); SuspendResumeExecution(node, receivedType, receivedValue); // c. If awaited.[[Type]] is throw, return Completion(awaited). diff --git a/es2panda/compiler/function/functionBuilder.h b/es2panda/compiler/function/functionBuilder.h index 4147c49577..63abf6f78e 100644 --- a/es2panda/compiler/function/functionBuilder.h +++ b/es2panda/compiler/function/functionBuilder.h @@ -49,7 +49,7 @@ public: NO_COPY_SEMANTIC(FunctionBuilder); NO_MOVE_SEMANTIC(FunctionBuilder); - virtual void Prepare([[maybe_unused]] const ir::ScriptFunction *node) const {}; + virtual void Prepare([[maybe_unused]] const ir::ScriptFunction *node) {}; virtual void CleanUp([[maybe_unused]] const ir::ScriptFunction *node) const {}; virtual void DirectReturn(const ir::AstNode *node) const; diff --git a/es2panda/compiler/function/generatorFunctionBuilder.cpp b/es2panda/compiler/function/generatorFunctionBuilder.cpp index a4d71b3fd2..e302dfe984 100644 --- a/es2panda/compiler/function/generatorFunctionBuilder.cpp +++ b/es2panda/compiler/function/generatorFunctionBuilder.cpp @@ -21,14 +21,17 @@ namespace panda::es2panda::compiler { -void GeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void GeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) { VReg callee = FunctionReg(node); + VReg completionType = pg_->AllocReg(); + VReg completionValue = pg_->AllocReg(); pg_->CreateGeneratorObj(node, callee); pg_->StoreAccumulator(node, funcObj_); - pg_->SuspendGenerator(node, funcObj_); - pg_->SetLabel(node, catchTable_->LabelSet().TryBegin()); + pg_->LoadConst(node, Constant::JS_UNDEFINED); + SuspendResumeExecution(node, completionType, completionValue); + HandleCompletion(node, completionType, completionValue); } void GeneratorFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const @@ -44,8 +47,6 @@ void GeneratorFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const void GeneratorFunctionBuilder::DirectReturn(const ir::AstNode *node) const { - pg_->GeneratorComplete(node, funcObj_); - pg_->CreateIterResultObject(node, true); pg_->EmitReturn(node); } @@ -58,11 +59,15 @@ void GeneratorFunctionBuilder::ImplicitReturn(const ir::AstNode *node) const void GeneratorFunctionBuilder::Yield(const ir::AstNode *node) { RegScope rs(pg_); + VReg value = pg_->AllocReg(); + VReg done = pg_->AllocReg(); VReg completionType = pg_->AllocReg(); VReg completionValue = pg_->AllocReg(); - pg_->CreateIterResultObject(node, false); - pg_->GeneratorYield(node, funcObj_); + pg_->StoreAccumulator(node, value); + pg_->LoadConst(node, Constant::JS_FALSE); + pg_->StoreAccumulator(node, done); + pg_->CreateIterResultObject(node, value, done); SuspendResumeExecution(node, completionType, completionValue); HandleCompletion(node, completionType, completionValue); diff --git a/es2panda/compiler/function/generatorFunctionBuilder.h b/es2panda/compiler/function/generatorFunctionBuilder.h index a1a1229565..6b3b96acb3 100644 --- a/es2panda/compiler/function/generatorFunctionBuilder.h +++ b/es2panda/compiler/function/generatorFunctionBuilder.h @@ -44,7 +44,7 @@ public: NO_COPY_SEMANTIC(GeneratorFunctionBuilder); NO_MOVE_SEMANTIC(GeneratorFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; -- Gitee