mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 16:13:49 +00:00
!4612 Optimize aot stackoverflow
Merge pull request !4612 from wpy111/master
This commit is contained in:
commit
c2214d0e5f
@ -64,7 +64,7 @@ void SlowPathLowering::CallRuntimeLowering()
|
||||
LowerTypedFastCall(gate);
|
||||
break;
|
||||
case OpCode::CHECK_SAFEPOINT_AND_STACKOVER:
|
||||
LowerCheckSafePointAndStackOver(gate);
|
||||
LowerCheckSafePointAndStackOverflow(gate);
|
||||
break;
|
||||
case OpCode::GET_ENV:
|
||||
LowerGetEnv(gate);
|
||||
@ -3139,31 +3139,23 @@ void SlowPathLowering::LowerTypedFastCall(GateRef gate)
|
||||
ReplaceHirWithPendingException(gate, state, result, result);
|
||||
}
|
||||
|
||||
void SlowPathLowering::LowerCheckSafePointAndStackOver(GateRef gate)
|
||||
void SlowPathLowering::LowerCheckSafePointAndStackOverflow(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
Label slowPath(&builder_);
|
||||
Label dispatch(&builder_);
|
||||
Label checkStackOver(&builder_);
|
||||
Label checkStackOverflow(&builder_);
|
||||
Label stackOverflow(&builder_);
|
||||
GateRef stackLimit = builder_.Load(VariableType::INT64(), glue_,
|
||||
builder_.IntPtr(JSThread::GlueData::GetStackLimitOffset(builder_.GetCompilationConfig()->Is32Bit())));
|
||||
GateRef interruptsFlag = builder_.Load(VariableType::INT8(), glue_,
|
||||
builder_.IntPtr(JSThread::GlueData::GetInterruptVectorOffset(builder_.GetCompilationConfig()->Is32Bit())));
|
||||
GateRef stackLimitOffset =
|
||||
builder_.IntPtr(JSThread::GlueData::GetStackLimitOffset(builder_.GetCompilationConfig()->Is32Bit()));
|
||||
GateRef stackLimit = builder_.Load(VariableType::INT64(), glue_, stackLimitOffset);
|
||||
GateRef spValue = builder_.ReadSp();
|
||||
builder_.Branch(builder_.Int8Equal(interruptsFlag,
|
||||
builder_.Int8(VmThreadControl::VM_NEED_SUSPENSION)), &slowPath, &checkStackOver);
|
||||
builder_.Bind(&slowPath);
|
||||
builder_.Branch(builder_.Int64LessThanOrEqual(spValue, stackLimit), &checkStackOverflow, &dispatch);
|
||||
builder_.Bind(&checkStackOverflow);
|
||||
{
|
||||
LowerCallRuntime(glue_, RTSTUB_ID(CheckSafePoint), {}, true);
|
||||
builder_.Jump(&checkStackOver);
|
||||
}
|
||||
builder_.Bind(&checkStackOver);
|
||||
{
|
||||
builder_.Branch(builder_.Int64LessThanOrEqual(spValue, stackLimit), &stackOverflow, &dispatch);
|
||||
GateRef res = LowerCallRuntime(glue_, RTSTUB_ID(CheckSafePointAndStackOverflow), {}, true);
|
||||
builder_.Branch(builder_.TaggedIsUndefined(res), &dispatch, &stackOverflow);
|
||||
builder_.Bind(&stackOverflow);
|
||||
{
|
||||
GateRef res = LowerCallRuntime(glue_, RTSTUB_ID(ThrowStackOverflowException), {}, true);
|
||||
builder_.Return(res);
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ private:
|
||||
void LowerConstruct(GateRef gate);
|
||||
void LowerTypedCall(GateRef gate);
|
||||
void LowerTypedFastCall(GateRef gate);
|
||||
void LowerCheckSafePointAndStackOver(GateRef gate);
|
||||
void LowerCheckSafePointAndStackOverflow(GateRef gate);
|
||||
void LowerNotifyConcurrentResult(GateRef gate);
|
||||
void LowerGetEnv(GateRef gate);
|
||||
void DeleteLoopExit(GateRef gate);
|
||||
|
@ -138,7 +138,8 @@ void AsmInterpreterCall::JSCallCommonEntry(ExtendedAssembler *assembler, JSCallM
|
||||
// Reserve enough sp space to prevent stack parameters from being covered by cpu profiler.
|
||||
[[maybe_unused]] TempRegister1Scope scope(assembler);
|
||||
Register tempRegister = __ TempRegister1();
|
||||
__ Ldr(tempRegister, MemoryOperand(glueRegister, JSThread::GlueData::GetStackLimitOffset(false)));
|
||||
__ Ldr(tempRegister, MemoryOperand(glueRegister, JSThread::GlueData::GetCurrentContextOffset(false)));
|
||||
__ Ldr(tempRegister, MemoryOperand(tempRegister, 0));
|
||||
__ Mov(Register(SP), tempRegister);
|
||||
}
|
||||
|
||||
@ -483,7 +484,8 @@ void AsmInterpreterCall::CallNativeWithArgv(ExtendedAssembler *assembler, bool c
|
||||
|
||||
__ Mov(currentSlotRegister, spRegister);
|
||||
// Reserve enough sp space to prevent stack parameters from being covered by cpu profiler.
|
||||
__ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false)));
|
||||
__ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetCurrentContextOffset(false)));
|
||||
__ Ldr(temp, MemoryOperand(temp, 0));
|
||||
__ Mov(Register(SP), temp);
|
||||
|
||||
__ Mov(opArgc, argc);
|
||||
@ -997,7 +999,8 @@ void AsmInterpreterCall::GeneratorReEnterAsmInterpDispatch(ExtendedAssembler *as
|
||||
__ Mov(fpRegister, spRegister);
|
||||
__ Mov(currentSlotRegister, spRegister);
|
||||
// Reserve enough sp space to prevent stack parameters from being covered by cpu profiler.
|
||||
__ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetStackLimitOffset(false)));
|
||||
__ Ldr(temp, MemoryOperand(glue, JSThread::GlueData::GetCurrentContextOffset(false)));
|
||||
__ Ldr(temp, MemoryOperand(temp, 0));
|
||||
__ Mov(Register(SP), temp);
|
||||
// push context regs
|
||||
__ Ldr(nRegsRegister, MemoryOperand(contextRegister, GeneratorContext::GENERATOR_NREGS_OFFSET));
|
||||
|
@ -140,6 +140,9 @@ void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue,
|
||||
__ Sub(op, currentSlot, Operand(op, UXTX, 0));
|
||||
__ Cmp(op, Operand(numArgs, LSL, 3)); // 3: each args occupies 8 bytes
|
||||
__ B(Condition::GT, &skipThrow);
|
||||
__ Ldr(op, MemoryOperand(glue, JSThread::GlueData::GetInterruptVectorOffset(false)));
|
||||
__ Tbnz(op, JSThread::CheckSafePointBit::START_BIT, &skipThrow);
|
||||
// CheckSafePointBit is false, is actual stack over flow
|
||||
__ Ldr(op, MemoryOperand(glue, JSThread::GlueData::GetAllowCrossThreadExecutionOffset(false)));
|
||||
__ Cbz(op, stackOverflow);
|
||||
__ Bind(&skipThrow);
|
||||
|
@ -107,6 +107,7 @@ void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue,
|
||||
{
|
||||
Register temp1 = op1;
|
||||
Register temp2 = op2;
|
||||
Label skipThrow;
|
||||
if (op1 == op2) {
|
||||
// reuse glue as an op register for temporary
|
||||
__ Pushq(glue);
|
||||
@ -118,10 +119,17 @@ void CommonCall::StackOverflowCheck(ExtendedAssembler *assembler, Register glue,
|
||||
__ Movl(numArgs, temp1);
|
||||
__ Shlq(3, temp1); // 3: each arg occupies 8 bytes
|
||||
__ Cmpq(temp1, temp2);
|
||||
__ Jg(&skipThrow);
|
||||
if (op1 == op2) {
|
||||
__ Popq(glue);
|
||||
}
|
||||
__ Movq(Operand(glue, JSThread::GlueData::GetInterruptVectorOffset(false)), temp1);
|
||||
__ Btq(JSThread::CheckSafePointBit::START_BIT, temp1);
|
||||
__ Jnb(stackOverflow); // CheckSafePointBit is false, is actual stack over flow
|
||||
__ Bind(&skipThrow);
|
||||
if (op1 == op2) {
|
||||
__ Popq(glue);
|
||||
}
|
||||
__ Jle(stackOverflow);
|
||||
}
|
||||
#undef __
|
||||
} // namespace panda::ecmascript::x64
|
||||
|
@ -407,7 +407,8 @@ private:
|
||||
bool LoadAOTFiles(const std::string &aotFileName);
|
||||
NO_MOVE_SEMANTIC(EcmaContext);
|
||||
NO_COPY_SEMANTIC(EcmaContext);
|
||||
|
||||
uint64_t stackLimit_ {0};
|
||||
uint64_t stackStart_ {0};
|
||||
JSThread *thread_ {nullptr};
|
||||
EcmaVM *vm_ {nullptr};
|
||||
|
||||
@ -469,8 +470,6 @@ private:
|
||||
JSTaggedType *leaveFrame_ {nullptr};
|
||||
JSTaggedType *lastFp_ {nullptr};
|
||||
JSTaggedType *frameBase_ {nullptr};
|
||||
uint64_t stackStart_ {0};
|
||||
uint64_t stackLimit_ {0};
|
||||
PropertiesCache *propertiesCache_ {nullptr};
|
||||
GlobalEnvConstants globalConst_;
|
||||
// Join Stack
|
||||
|
@ -216,7 +216,7 @@ void JSThread::Iterate(const RootVisitor &visitor, const RootRangeVisitor &range
|
||||
visitor(Root::ROOT_VM, ObjectSlot(ToUintPtr(&glueData_.exception_)));
|
||||
}
|
||||
|
||||
EcmaContext *tempContext = currentContext_;
|
||||
EcmaContext *tempContext = glueData_.currentContext_;
|
||||
for (EcmaContext *context : contexts_) {
|
||||
// visit stack roots
|
||||
SwitchCurrentContext(context, true);
|
||||
@ -570,9 +570,9 @@ void JSThread::PushContext(EcmaContext *context)
|
||||
const_cast<Heap *>(vm_->GetHeap())->WaitAllTasksFinished();
|
||||
contexts_.emplace_back(context);
|
||||
|
||||
if (!currentContext_) {
|
||||
if (!glueData_.currentContext_) {
|
||||
// The first context in ecma vm.
|
||||
currentContext_ = context;
|
||||
SetCurrentEcmaContext(context);
|
||||
context->SetFramePointers(const_cast<JSTaggedType *>(GetCurrentSPFrame()),
|
||||
const_cast<JSTaggedType *>(GetLastLeaveFrame()),
|
||||
const_cast<JSTaggedType *>(GetLastFp()));
|
||||
@ -596,27 +596,33 @@ void JSThread::PushContext(EcmaContext *context)
|
||||
void JSThread::PopContext()
|
||||
{
|
||||
contexts_.pop_back();
|
||||
currentContext_ = contexts_.back();
|
||||
SwitchCurrentContext(contexts_.back());
|
||||
}
|
||||
|
||||
void JSThread::SwitchCurrentContext(EcmaContext *currentContext, bool isInIterate)
|
||||
{
|
||||
ASSERT(std::count(contexts_.begin(), contexts_.end(), currentContext));
|
||||
|
||||
currentContext_->SetFramePointers(const_cast<JSTaggedType *>(GetCurrentSPFrame()),
|
||||
// If glueData_.currentContext_ == currentContext, don't need switch context
|
||||
if (glueData_.currentContext_ == currentContext) {
|
||||
return;
|
||||
}
|
||||
glueData_.currentContext_->SetFramePointers(const_cast<JSTaggedType *>(GetCurrentSPFrame()),
|
||||
const_cast<JSTaggedType *>(GetLastLeaveFrame()),
|
||||
const_cast<JSTaggedType *>(GetLastFp()));
|
||||
currentContext_->SetFrameBase(glueData_.frameBase_);
|
||||
currentContext_->SetStackLimit(GetStackLimit());
|
||||
currentContext_->SetStackStart(GetStackStart());
|
||||
currentContext_->SetGlobalEnv(GetGlueGlobalEnv());
|
||||
currentContext_->GetGlobalEnv()->SetJSGlobalObject(this, glueData_.globalObject_);
|
||||
glueData_.currentContext_->SetFrameBase(glueData_.frameBase_);
|
||||
glueData_.currentContext_->SetGlobalEnv(GetGlueGlobalEnv());
|
||||
glueData_.currentContext_->GetGlobalEnv()->SetJSGlobalObject(this, glueData_.globalObject_);
|
||||
|
||||
SetCurrentSPFrame(currentContext->GetCurrentFrame());
|
||||
SetLastLeaveFrame(currentContext->GetLeaveFrame());
|
||||
SetLastFp(currentContext->GetLastFp());
|
||||
glueData_.frameBase_ = currentContext->GetFrameBase();
|
||||
glueData_.stackLimit_ = currentContext->GetStackLimit();
|
||||
if (HasCheckSafePoint()) {
|
||||
// If CheckSafePointBit is true, stackLimit_ need to be stackStart_ like SetCheckSafePointStatus
|
||||
glueData_.stackLimit_ = currentContext->GetStackStart();
|
||||
} else {
|
||||
glueData_.stackLimit_ = currentContext->GetStackLimit();
|
||||
}
|
||||
glueData_.stackStart_ = currentContext->GetStackStart();
|
||||
if (!currentContext->GlobalEnvIsHole()) {
|
||||
SetGlueGlobalEnv(*(currentContext->GetGlobalEnv()));
|
||||
@ -627,7 +633,7 @@ void JSThread::SwitchCurrentContext(EcmaContext *currentContext, bool isInIterat
|
||||
glueData_.globalConst_ = const_cast<GlobalEnvConstants *>(currentContext->GlobalConstants());
|
||||
}
|
||||
|
||||
currentContext_ = currentContext;
|
||||
SetCurrentEcmaContext(currentContext);
|
||||
}
|
||||
|
||||
bool JSThread::EraseContext(EcmaContext *context)
|
||||
@ -636,7 +642,7 @@ bool JSThread::EraseContext(EcmaContext *context)
|
||||
bool isCurrentContext = false;
|
||||
auto iter = std::find(contexts_.begin(), contexts_.end(), context);
|
||||
if (*iter == context) {
|
||||
if (currentContext_ == context) {
|
||||
if (glueData_.currentContext_ == context) {
|
||||
isCurrentContext = true;
|
||||
}
|
||||
contexts_.erase(iter);
|
||||
@ -650,7 +656,7 @@ bool JSThread::EraseContext(EcmaContext *context)
|
||||
|
||||
PropertiesCache *JSThread::GetPropertiesCache() const
|
||||
{
|
||||
return currentContext_->GetPropertiesCache();
|
||||
return glueData_.currentContext_->GetPropertiesCache();
|
||||
}
|
||||
|
||||
const GlobalEnvConstants *JSThread::GetFirstGlobalConst() const
|
||||
@ -667,4 +673,19 @@ bool JSThread::IsAllContextsInitialized() const
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void JSThread::ResetCheckSafePointStatus()
|
||||
{
|
||||
ASSERT(static_cast<uint8_t>(glueData_.interruptVector_ & CHECKSAFEPOINT_FLAG) <= 1);
|
||||
CheckSafePointBit::Set(false, &glueData_.interruptVector_);
|
||||
ASSERT(glueData_.currentContext_ != nullptr);
|
||||
SetStackLimit(glueData_.currentContext_->GetStackLimit());
|
||||
}
|
||||
|
||||
void JSThread::SetCheckSafePointStatus()
|
||||
{
|
||||
ASSERT(static_cast<uint8_t>(glueData_.interruptVector_ & CHECKSAFEPOINT_FLAG) <= 1);
|
||||
CheckSafePointBit::Set(true, &glueData_.interruptVector_);
|
||||
SetStackLimit(GetStackStart());
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -190,6 +190,7 @@ public:
|
||||
static constexpr int PGO_PROFILER_BITFIELD_START = 16;
|
||||
static constexpr int BOOL_BITFIELD_NUM = 1;
|
||||
static constexpr uint32_t RESERVE_STACK_SIZE = 128;
|
||||
static constexpr uint64_t CHECKSAFEPOINT_FLAG = 0xFF;
|
||||
using MarkStatusBits = BitField<MarkStatus, 0, CONCURRENT_MARKING_BITFIELD_NUM>;
|
||||
using CheckSafePointBit = BitField<bool, 0, BOOL_BITFIELD_NUM>;
|
||||
using VMNeedSuspensionBit = BitField<bool, CHECK_SAFEPOINT_BITFIELD_NUM, BOOL_BITFIELD_NUM>;
|
||||
@ -542,16 +543,9 @@ public:
|
||||
return reinterpret_cast<JSThread *>(glue - GetGlueDataOffset());
|
||||
}
|
||||
|
||||
void SetCheckSafePointStatus()
|
||||
bool HasCheckSafePoint() const
|
||||
{
|
||||
ASSERT(static_cast<uint8_t>(glueData_.interruptVector_ & 0xFF) <= 1);
|
||||
CheckSafePointBit::Set(true, &glueData_.interruptVector_);
|
||||
}
|
||||
|
||||
void ResetCheckSafePointStatus()
|
||||
{
|
||||
ASSERT(static_cast<uint8_t>(glueData_.interruptVector_ & 0xFF) <= 1);
|
||||
CheckSafePointBit::Set(false, &glueData_.interruptVector_);
|
||||
return CheckSafePointBit::Decode(glueData_.interruptVector_);
|
||||
}
|
||||
|
||||
void SetVMNeedSuspension(bool flag)
|
||||
@ -605,6 +599,11 @@ public:
|
||||
return glueData_.stackLimit_;
|
||||
}
|
||||
|
||||
void SetStackLimit(uint64_t stackLimit)
|
||||
{
|
||||
glueData_.stackLimit_ = stackLimit;
|
||||
}
|
||||
|
||||
GlobalEnv *GetGlueGlobalEnv()
|
||||
{
|
||||
return glueData_.glueGlobalEnv_;
|
||||
@ -743,7 +742,8 @@ public:
|
||||
JSTaggedValue,
|
||||
base::AlignedBool,
|
||||
base::AlignedBool,
|
||||
JSTaggedValue> {
|
||||
JSTaggedValue,
|
||||
base::AlignedPointer> {
|
||||
enum class Index : size_t {
|
||||
BCStubEntriesIndex = 0,
|
||||
ExceptionIndex,
|
||||
@ -770,6 +770,7 @@ public:
|
||||
IsDebugModeIndex,
|
||||
IsFrameDroppedIndex,
|
||||
EntryFrameDroppedStateIndex,
|
||||
CurrentContextIndex,
|
||||
NumOfMembers
|
||||
};
|
||||
static_assert(static_cast<size_t>(Index::NumOfMembers) == NumOfTypes);
|
||||
@ -894,6 +895,11 @@ public:
|
||||
return GetOffset<static_cast<size_t>(Index::EntryFrameDroppedStateIndex)>(isArch32);
|
||||
}
|
||||
|
||||
static size_t GetCurrentContextOffset(bool isArch32)
|
||||
{
|
||||
return GetOffset<static_cast<size_t>(Index::CurrentContextIndex)>(isArch32);
|
||||
}
|
||||
|
||||
alignas(EAS) BCStubEntries bcStubEntries_;
|
||||
alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()};
|
||||
alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()};
|
||||
@ -919,6 +925,7 @@ public:
|
||||
alignas(EAS) bool isDebugMode_ {false};
|
||||
alignas(EAS) bool isFrameDropped_ {false};
|
||||
alignas(EAS) uint64_t entryFrameDroppedState_ {FrameDroppedState::StateFalse};
|
||||
alignas(EAS) EcmaContext *currentContext_ {nullptr};
|
||||
};
|
||||
STATIC_ASSERT_EQ_ARCH(sizeof(GlueData), GlueData::SizeArch32, GlueData::SizeArch64);
|
||||
|
||||
@ -927,7 +934,7 @@ public:
|
||||
|
||||
EcmaContext *GetCurrentEcmaContext() const
|
||||
{
|
||||
return currentContext_;
|
||||
return glueData_.currentContext_;
|
||||
}
|
||||
void SwitchCurrentContext(EcmaContext *currentContext, bool isInIterate = false);
|
||||
|
||||
@ -940,6 +947,8 @@ public:
|
||||
|
||||
const GlobalEnvConstants *GetFirstGlobalConst() const;
|
||||
bool IsAllContextsInitialized() const;
|
||||
void ResetCheckSafePointStatus();
|
||||
void SetCheckSafePointStatus();
|
||||
private:
|
||||
NO_COPY_SEMANTIC(JSThread);
|
||||
NO_MOVE_SEMANTIC(JSThread);
|
||||
@ -949,7 +958,7 @@ private:
|
||||
}
|
||||
void SetCurrentEcmaContext(EcmaContext *context)
|
||||
{
|
||||
currentContext_ = context;
|
||||
glueData_.currentContext_ = context;
|
||||
}
|
||||
|
||||
void SetArrayHClassIndexMap(const CMap<ElementsKind, ConstantIndex> &map)
|
||||
@ -1004,7 +1013,6 @@ private:
|
||||
CMap<ElementsKind, ConstantIndex> arrayHClassIndexMap_;
|
||||
|
||||
CVector<EcmaContext *> contexts_;
|
||||
EcmaContext *currentContext_ {nullptr};
|
||||
friend class GlobalHandleCollection;
|
||||
friend class EcmaVM;
|
||||
friend class EcmaContext;
|
||||
|
@ -2636,5 +2636,19 @@ JSTaggedValue RuntimeStubs::RuntimeNotifyDebuggerStatement(JSThread *thread)
|
||||
}
|
||||
return JSTaggedValue::Hole();
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::RuntimeThrowStackOverflowException(JSThread *thread)
|
||||
{
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
// Multi-thread could cause stack-overflow-check failed too,
|
||||
// so check thread here to distinguish it with the actual stack overflow.
|
||||
ecmaVm->CheckThread();
|
||||
if (LIKELY(!thread->HasPendingException())) {
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(ErrorType::RANGE_ERROR, "Stack overflow!", false);
|
||||
thread->SetException(error.GetTaggedValue());
|
||||
}
|
||||
return JSTaggedValue::Exception();
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_STUBS_RUNTIME_STUBS_INL_H
|
||||
|
@ -1027,11 +1027,14 @@ DEF_RUNTIME_STUBS(UpdateHotnessCounterWithProf)
|
||||
return profileTypeInfo.GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(CheckSafePoint)
|
||||
DEF_RUNTIME_STUBS(CheckSafePointAndStackOverflow)
|
||||
{
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
thread->CheckSafepoint();
|
||||
return JSTaggedValue::Undefined().GetRawData();
|
||||
if (thread->HasCheckSafePoint()) {
|
||||
thread->CheckSafepoint();
|
||||
return JSTaggedValue::Undefined().GetRawData();
|
||||
}
|
||||
return RuntimeThrowStackOverflowException(thread).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(LoadICByName)
|
||||
@ -1841,16 +1844,7 @@ DEF_RUNTIME_STUBS(ThrowNonConstructorException)
|
||||
DEF_RUNTIME_STUBS(ThrowStackOverflowException)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(ThrowStackOverflowException);
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
// Multi-thread could cause stack-overflow-check failed too,
|
||||
// so check thread here to distinguish it with the actual stack overflow.
|
||||
ecmaVm->CheckThread();
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSObject> error = factory->GetJSError(ErrorType::RANGE_ERROR, "Stack overflow!", false);
|
||||
if (LIKELY(!thread->HasPendingException())) {
|
||||
thread->SetException(error.GetTaggedValue());
|
||||
}
|
||||
return JSTaggedValue::Exception().GetRawData();
|
||||
return RuntimeThrowStackOverflowException(thread).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(ThrowDerivedMustReturnException)
|
||||
|
@ -203,7 +203,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(LoadICByName) \
|
||||
V(StoreICByName) \
|
||||
V(UpdateHotnessCounter) \
|
||||
V(CheckSafePoint) \
|
||||
V(CheckSafePointAndStackOverflow) \
|
||||
V(UpdateHotnessCounterWithProf) \
|
||||
V(GetModuleNamespaceByIndex) \
|
||||
V(GetModuleNamespaceByIndexOnJSFunc) \
|
||||
@ -685,6 +685,7 @@ private:
|
||||
static inline JSTaggedValue RuntimeNotifyConcurrentResult(JSThread *thread, JSTaggedValue result,
|
||||
JSTaggedValue hint);
|
||||
static inline JSTaggedValue RuntimeNotifyDebuggerStatement(JSThread *thread);
|
||||
static inline JSTaggedValue RuntimeThrowStackOverflowException(JSThread *thread);
|
||||
friend class SlowRuntimeStub;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
Loading…
Reference in New Issue
Block a user