Skip to content

Commit b83edb0

Browse files
committed
[MERGE #6187 @nhat-nguyen] Fix lowering code for ES2018 Async Iteration
Merge pull request #6187 from nhat-nguyen:async Also took this opportunity to do a bit refactor on how we initialize the `generator` pointer inside `ResumeYieldData`. I think it's cleaner if we do everything in the constructor instead of only setting it in `CallAsyncGenerator`. Related PR: #5834
2 parents bb7131b + e0a0b16 commit b83edb0

File tree

4 files changed

+38
-21
lines changed

4 files changed

+38
-21
lines changed

lib/Backend/IRBuilder.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,24 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
18791879
break;
18801880
}
18811881

1882+
case Js::OpCode::Await:
1883+
case Js::OpCode::AsyncYield:
1884+
case Js::OpCode::AsyncYieldStar:
1885+
{
1886+
// All of these opcodes rely on the ResumeYieldData passed as an argument to the jit'd frame,
1887+
// load it first before we do the actual operation.
1888+
// Also need to create the instruction differently because, unlike other Reg2 instructions,
1889+
// these opcodes actually use their destination operand as a source and have no destination.
1890+
1891+
IR::Instr* loadResumeYieldData = IR::Instr::New(Js::OpCode::GeneratorLoadResumeYieldData, dstOpnd /* dst */, m_func);
1892+
this->AddInstr(loadResumeYieldData, offset);
1893+
1894+
instr = IR::Instr::New(newOpcode, nullptr /* dst */, dstOpnd /* src1 */, src1Opnd /* src2 */, m_func);
1895+
this->AddInstr(instr, offset);
1896+
1897+
return;
1898+
}
1899+
18821900
case Js::OpCode::Yield:
18831901
instr = IR::Instr::New(newOpcode, dstOpnd, src1Opnd, m_func);
18841902
this->AddInstr(instr, offset);

lib/Backend/Lower.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,11 +2957,9 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
29572957
case Js::OpCode::NewAsyncFromSyncIterator:
29582958
{
29592959
IR::Opnd *src1Opnd = instr->UnlinkSrc1();
2960-
29612960
LoadScriptContext(instr);
29622961
m_lowererMD.LoadHelperArgument(instr, src1Opnd);
29632962
m_lowererMD.ChangeToHelperCall(instr, IR::HelperNewAsyncFromSyncIterator);
2964-
29652963
break;
29662964
}
29672965

lib/Runtime/Library/JavascriptGenerator.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,9 @@ namespace Js
325325

326326
AsyncGeneratorNextProcessor* resumeNextReturnProcessor = VarTo<AsyncGeneratorNextProcessor>(function);
327327

328-
ResumeYieldData yieldData(args[1], RecyclerNew(scriptContext->GetRecycler(), JavascriptExceptionObject, args[1], scriptContext, nullptr));
329-
resumeNextReturnProcessor->GetGenerator()->CallAsyncGenerator(&yieldData);
328+
Var data = args[1];
329+
JavascriptExceptionObject* exceptionObj = RecyclerNew(scriptContext->GetRecycler(), JavascriptExceptionObject, args[1], scriptContext, nullptr);
330+
resumeNextReturnProcessor->GetGenerator()->CallAsyncGenerator(data, exceptionObj);
330331
return scriptContext->GetLibrary()->GetUndefined();
331332
}
332333

@@ -340,22 +341,23 @@ namespace Js
340341

341342
AsyncGeneratorNextProcessor* resumeNextReturnProcessor = VarTo<AsyncGeneratorNextProcessor>(function);
342343

343-
ResumeYieldData yieldData(args.Values[1], nullptr);
344-
resumeNextReturnProcessor->GetGenerator()->CallAsyncGenerator(&yieldData);
344+
Var data = args.Values[1];
345+
JavascriptExceptionObject* exceptionObj = nullptr;
346+
resumeNextReturnProcessor->GetGenerator()->CallAsyncGenerator(data, exceptionObj);
345347
return scriptContext->GetLibrary()->GetUndefined();
346348
}
347349

348-
void JavascriptGenerator::CallAsyncGenerator(ResumeYieldData* yieldData)
350+
void JavascriptGenerator::CallAsyncGenerator(Var data, JavascriptExceptionObject* exceptionObj)
349351
{
350352
AssertOrFailFastMsg(isAsync, "Should not call CallAsyncGenerator on a non-async generator");
351353
ScriptContext* scriptContext = this->GetScriptContext();
352354
Var result = nullptr;
353355
JavascriptExceptionObject *exception = nullptr;
354-
yieldData->generator = this;
355356

356357
SetState(GeneratorState::Executing);
357358

358-
Var thunkArgs[] = { this, yieldData };
359+
ResumeYieldData yieldData(data, exceptionObj, this);
360+
Var thunkArgs[] = { this, &yieldData };
359361
Arguments arguments(_countof(thunkArgs), thunkArgs);
360362
try
361363
{
@@ -557,8 +559,7 @@ namespace Js
557559
SetState(GeneratorState::Executing);
558560
// 17. Push genContext onto the execution context stack; genContext is now the running execution context.
559561
// 18. Resume the suspended evaluation of genContext using completion as the result of the operation that suspended it. Let result be the completion record returned by the resumed computation.
560-
ResumeYieldData data(next->data, next->exceptionObj);
561-
CallAsyncGenerator(&data);
562+
CallAsyncGenerator(next->data, next->exceptionObj);
562563
// 19. Assert: result is never an abrupt completion.
563564
// 20. Assert: When we return here, genContext has already been removed from the execution context stack and callerContext is the currently running execution context.
564565
// 21. Return undefined.

lib/Runtime/Library/JavascriptGenerator.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@ namespace Js
1111
// `data` stores the value that was passed in as parameter to .next()
1212
struct ResumeYieldData
1313
{
14-
Var data;
15-
JavascriptExceptionObject* exceptionObj;
16-
JavascriptGenerator* generator = nullptr;
14+
Var const data;
15+
JavascriptExceptionObject* const exceptionObj;
16+
JavascriptGenerator* const generator;
1717

18-
ResumeYieldData(Var data, JavascriptExceptionObject* exceptionObj) : data(data), exceptionObj(exceptionObj) { }
18+
ResumeYieldData(Var data, JavascriptExceptionObject* exceptionObj, JavascriptGenerator* generator = nullptr) :
19+
data(data), exceptionObj(exceptionObj), generator(generator) {}
1920
};
2021

2122
struct AsyncGeneratorRequest
2223
{
23-
Field(Var) data;
24-
Field(JavascriptExceptionObject*) exceptionObj;
25-
Field(JavascriptPromise*) promise;
24+
Field(Var) const data;
25+
Field(JavascriptExceptionObject*) const exceptionObj;
26+
Field(JavascriptPromise*) const promise;
2627

2728
AsyncGeneratorRequest(Var data, JavascriptExceptionObject* exceptionObj, JavascriptPromise* promise)
28-
: data(data), exceptionObj(exceptionObj), promise(promise) { }
29-
29+
: data(data), exceptionObj(exceptionObj), promise(promise) {}
3030
};
3131

3232
typedef JsUtil::List<AsyncGeneratorRequest*, Recycler> AsyncGeneratorQueue;
@@ -114,7 +114,7 @@ namespace Js
114114
void AsyncGeneratorResumeNext();
115115
void AsyncGeneratorReject(Var reason);
116116
void AsyncGeneratorResolve(Var value, bool done);
117-
void CallAsyncGenerator(ResumeYieldData* yieldData);
117+
void CallAsyncGenerator(Var data, JavascriptExceptionObject* exceptionObj);
118118
void InitialiseAsyncGenerator(ScriptContext* scriptContext);
119119

120120
void SetScriptFunction(ScriptFunction* sf)

0 commit comments

Comments
 (0)