Impl rsp frame of generator

1. Resume rsp of SuspendGenerator
2. Remove duplicated stack frame switching of ChangeGenContext and
ResumeContext
Issue:https://gitee.com/openharmony/ark_js_runtime/issues/I57IXJ?from=project-issue

Signed-off-by: zhangyukun <zhangyukun8@huawei.com>
Change-Id: I3a86c645864ec73f5dd351882125b4ee721b5468
This commit is contained in:
zhangyukun 2022-05-16 09:18:47 +08:00
parent e565046c8c
commit 903a0cd046
9 changed files with 12 additions and 152 deletions

View File

@ -4575,6 +4575,9 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8)
}
Bind(&tryContinue);
#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK
GateRef currentSp = *varSp;
#endif
varSp = Load(VariableType::NATIVE_POINTER(), frame,
IntPtr(AsmInterpretedFrame::GetBaseOffset(env->IsArch32Bit())));
GateRef prevState = GetFrame(*varSp);
@ -4590,7 +4593,9 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8)
}
Bind(&pcNotEqualNullptr);
{
#if !ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK
SetCurrentSpFrame(glue, *varSp);
#endif
GateRef function = GetFunctionFromFrame(prevState);
varConstpool = GetConstpoolFromFunction(function);
varProfileTypeInfo = GetProfileTypeInfoFromFunction(function);
@ -4598,8 +4603,15 @@ DECLARE_ASM_HANDLER(HandleSuspendGeneratorPrefV8V8)
IntPtr(JSFunctionBase::METHOD_OFFSET));
varHotnessCounter = GetHotnessCounterFromMethod(method);
GateRef jumpSize = GetCallSizeFromFrame(prevState);
#if ECMASCRIPT_ENABLE_ASM_INTERPRETER_RSP_STACK
CallNGCRuntime(glue, RTSTUB_ID(ResumeRspAndDispatch),
{ glue, currentSp, *varPc, *varConstpool, *varProfileTypeInfo,
*varAcc, *varHotnessCounter, jumpSize });
Return();
#else
Dispatch(glue, *varSp, *varPc, *varConstpool, *varProfileTypeInfo, *varAcc,
*varHotnessCounter, jumpSize);
#endif
}
}

View File

@ -75,17 +75,4 @@ JSHandle<JSObject> GeneratorHelper::Throw(JSThread *thread, const JSHandle<Gener
RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSObject, thread);
return JSIterator::CreateIterResultObject(thread, throwValue, true);
}
// main->foo
void GeneratorHelper::ChangeGenContext(JSThread *thread, const JSHandle<GeneratorContext> &genContext)
{
JSThread *jsThread = thread;
EcmaInterpreter::ChangeGenContext(jsThread, genContext);
}
// foo->main
void GeneratorHelper::ResumeContext(JSThread *thread)
{
EcmaInterpreter::ResumeContext(thread);
}
} // namespace panda::ecmascript

View File

@ -31,8 +31,6 @@ public:
static JSHandle<JSObject> Throw(JSThread *thread, const JSHandle<GeneratorContext> &genContext,
JSTaggedValue value);
static void ChangeGenContext(JSThread *thread, const JSHandle<GeneratorContext> &genContext);
static void ResumeContext(JSThread *thread);
};
} // namespace panda::ecmascript

View File

@ -644,74 +644,6 @@ JSTaggedValue EcmaInterpreter::GeneratorReEnterInterpreter(JSThread *thread, JSH
return res;
}
void EcmaInterpreter::ChangeGenContext(JSThread *thread, JSHandle<GeneratorContext> context)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
if (thread->IsAsmInterpreter()) {
return InterpreterAssembly::ChangeGenContext(thread, context);
}
JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(JSHandle<JSTaggedValue>(thread, context->GetMethod()));
JSMethod *method = func->GetCallTarget();
JSTaggedType *currentSp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
// push break frame
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
JSTaggedType *breakSp = currentSp - INTERPRETER_FRAME_STATE_SIZE;
if (UNLIKELY(thread->DoStackOverflowCheck(breakSp))) {
return;
}
InterpretedFrame *breakState = GET_FRAME(breakSp);
breakState->pc = nullptr;
breakState->sp = nullptr;
breakState->function = JSTaggedValue::Hole();
breakState->base.prev = currentSp;
breakState->base.type = FrameType::INTERPRETER_FRAME;
// create new frame and resume sp and pc
uint32_t nregs = context->GetNRegs();
size_t newFrameSize = INTERPRETER_FRAME_STATE_SIZE + nregs;
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic
JSTaggedType *newSp = breakSp - newFrameSize;
if (UNLIKELY(thread->DoStackOverflowCheck(newSp))) {
return;
}
JSHandle<TaggedArray> regsArray(thread, context->GetRegsArray());
for (size_t i = 0; i < nregs; i++) {
newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
}
JSTaggedValue constpool = func->GetConstantPool();
uint32_t pcOffset = context->GetBCOffset();
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
const uint8_t *pc = method->GetBytecodeArray() + pcOffset;
InterpretedFrame *state = GET_FRAME(newSp);
state->pc = pc;
state->sp = newSp;
state->function = func.GetTaggedValue();
state->constpool = constpool;
state->profileTypeInfo = func->GetProfileTypeInfo();
state->acc = context->GetAcc();
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
state->base.prev = breakSp;
state->base.type = FrameType::INTERPRETER_FRAME;
state->env = context->GetLexicalEnv();
thread->SetCurrentSPFrame(newSp);
}
void EcmaInterpreter::ResumeContext(JSThread *thread)
{
if (thread->IsAsmInterpreter()) {
return InterpreterAssembly::ResumeContext(thread);
}
JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
InterpretedFrame *state = GET_FRAME(sp);
thread->SetCurrentSPFrame(state->base.prev);
}
void EcmaInterpreter::NotifyBytecodePcChanged(JSThread *thread)
{
FrameHandler frameHandler(thread);

View File

@ -49,8 +49,6 @@ public:
JSThread *thread, JSHandle<JSTaggedValue> func, JSHandle<JSTaggedValue> thisObj,
JSHandle<JSTaggedValue> newTarget, size_t numArgs);
static inline JSTaggedValue GeneratorReEnterInterpreter(JSThread *thread, JSHandle<GeneratorContext> context);
static inline void ChangeGenContext(JSThread *thread, JSHandle<GeneratorContext> context);
static inline void ResumeContext(JSThread *thread);
static inline void RunInternal(JSThread *thread, ConstantPool *constpool, const uint8_t *pc, JSTaggedType *sp);
static inline uint8_t ReadU8(const uint8_t *pc, uint32_t offset);
static inline void InitStackFrame(JSThread *thread);

View File

@ -703,61 +703,6 @@ JSTaggedValue InterpreterAssembly::GeneratorReEnterInterpreter(JSThread *thread,
return res;
}
void InterpreterAssembly::ChangeGenContext(JSThread *thread, JSHandle<GeneratorContext> context)
{
JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(JSHandle<JSTaggedValue>(thread, context->GetMethod()));
JSMethod *method = func->GetCallTarget();
JSTaggedType *currentSp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
// push break frame
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
JSTaggedType *breakSp = currentSp - AsmInterpretedFrame::NumOfMembers();
if (thread->DoStackOverflowCheck(breakSp) || thread->HasPendingException()) {
return;
}
AsmInterpretedFrame *breakState = GET_ASM_FRAME(breakSp);
breakState->pc = nullptr;
breakState->function = JSTaggedValue::Hole();
breakState->base.prev = currentSp;
breakState->base.type = FrameType::ASM_INTERPRETER_FRAME;
// create new frame and resume sp and pc
uint32_t nregs = context->GetNRegs();
size_t newFrameSize = AsmInterpretedFrame::NumOfMembers() + nregs;
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic
JSTaggedType *newSp = breakSp - newFrameSize;
if (thread->DoStackOverflowCheck(newSp) || thread->HasPendingException()) {
return;
}
JSHandle<TaggedArray> regsArray(thread, context->GetRegsArray());
for (size_t i = 0; i < nregs; i++) {
newSp[i] = regsArray->Get(i).GetRawData(); // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
}
uint32_t pcOffset = context->GetBCOffset();
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
const uint8_t *pc = method->GetBytecodeArray() + pcOffset;
AsmInterpretedFrame *state = GET_ASM_FRAME(newSp);
state->pc = pc;
state->function = func.GetTaggedValue();
state->acc = context->GetAcc();
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
state->base.prev = breakSp;
state->base.type = FrameType::ASM_INTERPRETER_FRAME;
state->env = context->GetLexicalEnv();
thread->SetCurrentSPFrame(newSp);
}
void InterpreterAssembly::ResumeContext(JSThread *thread)
{
JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame());
AsmInterpretedFrame *state = GET_ASM_FRAME(sp);
thread->SetCurrentSPFrame(state->base.prev);
}
void InterpreterAssembly::HandleMovV4V4(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int32_t hotnessCounter)

View File

@ -41,8 +41,6 @@ public:
static JSTaggedValue Execute(EcmaRuntimeCallInfo *info);
static JSTaggedValue ExecuteNative(EcmaRuntimeCallInfo *info);
static JSTaggedValue GeneratorReEnterInterpreter(JSThread *thread, JSHandle<GeneratorContext> context);
static void ChangeGenContext(JSThread *thread, JSHandle<GeneratorContext> context);
static void ResumeContext(JSThread *thread);
static uint32_t FindCatchBlock(JSMethod *caller, uint32_t pc);
static inline size_t GetJumpSizeAfterCall(const uint8_t *prevPc);

View File

@ -92,13 +92,11 @@ JSHandle<JSTaggedValue> JSAsyncAwaitStatusFunction::AsyncFunctionAwaitFulfilled(
JSHandle<GeneratorContext> asyncCtxt(thread, func->GetAsyncContext());
// 2.Let prevContext be the running execution context.
GeneratorHelper::ChangeGenContext(thread, asyncCtxt);
// 3.Suspend prevContext.
// 4.Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
// 5.Resume the suspended evaluation of asyncContext using NormalCompletion(value) as the result of the
// operation that suspended it. Let result be the value returned by the resumed computation.
JSHandle<JSObject> result = GeneratorHelper::Next(thread, asyncCtxt, value.GetTaggedValue());
GeneratorHelper::ResumeContext(thread);
// 6.Assert: When we reach this step, asyncContext has already been removed from the execution context stack
// and prevContext is the currently running execution context.
@ -113,14 +111,12 @@ JSHandle<JSTaggedValue> JSAsyncAwaitStatusFunction::AsyncFunctionAwaitRejected(
JSHandle<GeneratorContext> asyncCtxt(thread, func->GetAsyncContext());
// 2.Let prevContext be the running execution context.
GeneratorHelper::ChangeGenContext(thread, asyncCtxt);
// 3.Suspend prevContext.
// 4.Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
// 5.Resume the suspended evaluation of asyncContext using Completion{[[Type]]: throw,
// [[Value]]: reason, [[Target]]: empty} as the result of the operation that suspended it.
// Let result be the value returned by the resumed computation.
JSHandle<JSObject> result = GeneratorHelper::Throw(thread, asyncCtxt, reason.GetTaggedValue());
GeneratorHelper::ResumeContext(thread);
// 6.Assert: When we reach this step, asyncContext has already been removed from the execution context stack
// and prevContext is the currently running execution context.

View File

@ -71,15 +71,12 @@ JSHandle<JSObject> JSGeneratorObject::GeneratorResume(JSThread *thread, const JS
generator->SetGeneratorState(JSGeneratorState::EXECUTING);
// 8.Push genContext onto the execution context stack; genContext is now the running execution context.
GeneratorHelper::ChangeGenContext(thread, genContext);
// 9.Resume the suspended evaluation of genContext using NormalCompletion(value) as the result of the operation
// that suspended it. Let result be the value returned by the resumed computation.
// 10.Assert: When we return here, genContext has already been removed from the execution context stack and
// methodContext is the currently running execution context.
// 11.Return Completion(result).
JSHandle<JSObject> result = GeneratorHelper::Next(thread, genContext, value);
GeneratorHelper::ResumeContext(thread);
return result;
}
@ -128,8 +125,6 @@ JSHandle<JSObject> JSGeneratorObject::GeneratorResumeAbrupt(JSThread *thread,
generator->SetGeneratorState(JSGeneratorState::EXECUTING);
// 9.Push genContext onto the execution context stack; genContext is now the running execution context.
GeneratorHelper::ChangeGenContext(thread, genContext);
// 10.Resume the suspended evaluation of genContext using abruptCompletion as the result of the operation that
// suspended it. Let result be the completion record returned by the resumed computation.
// 11.Assert: When we return here, genContext has already been removed from the execution context stack and
@ -141,7 +136,6 @@ JSHandle<JSObject> JSGeneratorObject::GeneratorResumeAbrupt(JSThread *thread,
} else {
result = GeneratorHelper::Throw(thread, genContext, abruptCompletion->GetValue());
}
GeneratorHelper::ResumeContext(thread);
return result;
}
} // namespace panda::ecmascript