Add Call Stub

Change several structures for call stub.

Related issue: #I4XK12

Signed-off-by: lichenshuai <lichenshuai@huawei.com>
Change-Id: Ie7389ff96c619451304a3f0d352b271310c4b73e
This commit is contained in:
lichenshuai 2022-03-12 18:47:21 +08:00
parent aa42d76018
commit e6b8f48f69
16 changed files with 630 additions and 58 deletions

View File

@ -197,6 +197,11 @@ GateRef InterpreterStub::GetEnvFromFrame(GateRef frame)
GetIntPtrConstant(InterpretedFrame::GetEnvOffset(GetEnvironment()->IsArch32Bit())));
}
GateRef InterpreterStub::GetEnvFromFunction(GateRef function)
{
return Load(VariableType::JS_POINTER(), function, GetIntPtrConstant(JSFunction::LEXICAL_ENV_OFFSET));
}
GateRef InterpreterStub::GetProfileTypeInfoFromFunction(GateRef function)
{
return Load(VariableType::JS_POINTER(), function, GetIntPtrConstant(JSFunction::PROFILE_TYPE_INFO_OFFSET));

View File

@ -74,8 +74,8 @@ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef pc, GateRef sp,
#define DISPATCH_LAST() \
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, acc, hotnessCounter) \
#define DISPATCH_LAST() \
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, acc, hotnessCounter) \
#define DISPATCH_LAST_WITH_ACC() \
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter) \
#define UPDATE_HOTNESS(_sp) \
varHotnessCounter = Int32Add(offset, *varHotnessCounter); \
@ -83,7 +83,7 @@ void name##Stub::GenerateCircuitImpl(GateRef glue, GateRef pc, GateRef sp,
Bind(&slowPath); \
{ \
varProfileTypeInfo = CallRuntimeTrampoline(glue, \
GetInt64Constant(RUNTIME_CALL_ID(UpdateHotnessCounter)), {}); \
GetInt64Constant(RUNTIME_CALL_ID(UpdateHotnessCounter)), {}); \
varHotnessCounter = GetInt32Constant(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD); \
Jump(&dispatch); \
} \
@ -869,7 +869,7 @@ DECLARE_ASM_HANDLER(HandleGetPropIteratorPref)
Branch(TaggedIsException(res), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
varAcc = res;
@ -887,7 +887,7 @@ DECLARE_ASM_HANDLER(HandleAsyncFunctionEnterPref)
Branch(TaggedIsException(res), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
varAcc = res;
@ -941,7 +941,7 @@ DECLARE_ASM_HANDLER(HandleGetIteratorPref)
Branch(TaggedIsException(res), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
varAcc = res;
@ -2781,7 +2781,7 @@ DECLARE_ASM_HANDLER(HandleLdSuperByNamePrefId32V8)
Branch(TaggedIsException(result), &isException, &dispatch);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&dispatch);
varAcc = result;
@ -2953,7 +2953,7 @@ DECLARE_ASM_HANDLER(HandleStConstToGlobalRecordPrefId32)
Branch(TaggedIsException(result), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
DISPATCH_WITH_ACC(PREF_ID32);
@ -2974,7 +2974,7 @@ DECLARE_ASM_HANDLER(HandleStLetToGlobalRecordPrefId32)
Branch(TaggedIsException(result), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
DISPATCH_WITH_ACC(PREF_ID32);
@ -2995,7 +2995,7 @@ DECLARE_ASM_HANDLER(HandleStClassToGlobalRecordPrefId32)
Branch(TaggedIsException(result), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
DISPATCH_WITH_ACC(PREF_ID32);
@ -3052,7 +3052,7 @@ DECLARE_ASM_HANDLER(HandleNegDynPrefV8)
Branch(TaggedIsException(result), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
varAcc = result;
@ -3104,7 +3104,7 @@ DECLARE_ASM_HANDLER(HandleNotDynPrefV8)
Branch(TaggedIsException(result), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
varAcc = result;
@ -3193,7 +3193,7 @@ DECLARE_ASM_HANDLER(HandleAnd2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -3286,7 +3286,7 @@ DECLARE_ASM_HANDLER(HandleOr2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -3379,7 +3379,7 @@ DECLARE_ASM_HANDLER(HandleXOr2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -3472,7 +3472,7 @@ DECLARE_ASM_HANDLER(HandleAshr2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -3566,7 +3566,7 @@ DECLARE_ASM_HANDLER(HandleShr2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -3659,7 +3659,7 @@ DECLARE_ASM_HANDLER(HandleShl2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &IsException, &NotException);
Bind(&IsException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&NotException);
{
@ -3717,7 +3717,7 @@ DECLARE_ASM_HANDLER(HandleDefineClassWithBufferPrefId16Imm16Imm16V8V8)
Branch(TaggedIsException(*res), &isException, &isNotException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&isNotException);
GateRef newLexicalEnv = GetVregValue(sp, ZExtInt8ToPtr(v0)); // slow runtime may gc
@ -3807,7 +3807,7 @@ DECLARE_ASM_HANDLER(HandleLdObjByNamePrefId32V8)
Branch(TaggedIsException(result), &isException, &noException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&noException);
varAcc = result;
@ -4598,7 +4598,7 @@ DECLARE_ASM_HANDLER(HandleTryLdGlobalByNamePrefId32)
Branch(TaggedIsException(*icResult), &isException, &isNotException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&isNotException);
varAcc = *icResult;
@ -4630,7 +4630,7 @@ DECLARE_ASM_HANDLER(HandleTryLdGlobalByNamePrefId32)
Branch(TaggedIsException(slowResult), &isException, &isNotException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&isNotException);
varAcc = slowResult;
@ -4791,7 +4791,7 @@ DECLARE_ASM_HANDLER(HandleLdGlobalVarPrefId32)
Branch(TaggedIsException(*result), &isException, &dispatch);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
}
Bind(&dispatch);
@ -4973,7 +4973,7 @@ DECLARE_ASM_HANDLER(HandleToNumberPrefV8)
Branch(TaggedIsException(res), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -5078,7 +5078,7 @@ DECLARE_ASM_HANDLER(HandleAdd2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -5188,7 +5188,7 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8)
Branch(TaggedIsException(taggedNumber), &isException, &notException);
Bind(&isException);
{
DispatchLast(glue, pc, sp, constpool, profileTypeInfo, *varAcc, hotnessCounter);
DISPATCH_LAST_WITH_ACC();
}
Bind(&notException);
{
@ -5200,9 +5200,475 @@ DECLARE_ASM_HANDLER(HandleSub2DynPrefV8)
Bind(&accDispatch);
DISPATCH_WITH_ACC(PREF_V8);
}
#define CALL_INITIALIZE() \
SetPcToFrame(glue, GetFrame(sp), pc); \
GateRef func = GetVregValue(sp, ZExtInt8ToPtr(funcReg)); \
Label funcIsHeapObject(env); \
Label funcIsCallable(env); \
Label funcNotCallable(env); \
Branch(TaggedIsHeapObject(func), &funcIsHeapObject, &funcNotCallable); \
Bind(&funcIsHeapObject); \
Branch(IsCallable(func), &funcIsCallable, &funcNotCallable); \
Bind(&funcNotCallable); \
{ \
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetNotCallableException)), {}); \
DISPATCH_LAST(); \
} \
Bind(&funcIsCallable); \
DEFVARIABLE(methodOffset, VariableType::INT32(), GetInt32Constant(0)); \
/* method = func->GetCallTarget() */ \
/* ASSERT(JSTaggedValue(func).IsJSFunctionBase() || JSTaggedValue(func).IsJSProxy()) */ \
Label funcIsJSFunctionBase(env); \
Label funcIsJSProxy(env); \
Label getMethod(env); \
Branch(IsJSFunctionBase(func), &funcIsJSFunctionBase, &funcIsJSProxy); \
Bind(&funcIsJSFunctionBase); \
{ \
methodOffset = GetInt32Constant(JSFunctionBase::METHOD_OFFSET); \
Jump(&getMethod); \
} \
Bind(&funcIsJSProxy); \
{ \
methodOffset = GetInt32Constant(JSProxy::METHOD_OFFSET); \
Jump(&getMethod); \
} \
Bind(&getMethod); \
GateRef method = Load(VariableType::POINTER(), func, ChangeInt32ToIntPtr(*methodOffset)); \
GateRef callFieldOffset = GetIntPtrConstant(JSMethod::GetCallFieldOffset(env->IsArch32Bit())); \
GateRef callField = Load(VariableType::INT64(), method, callFieldOffset); \
DEFVARIABLE(newSp, VariableType::POINTER(), \
PointerSub(sp, GetIntPtrConstant(InterpretedFrame::GetSize(env->IsArch32Bit()))))
#define CALL_PUSH_UNDEFINED(n) \
i = GetInt32Constant(0); \
Label pushUndefined(env); \
Label pushUndefinedAgain(env); \
Label pushUndefinedEnd(env); \
Branch(Int32LessThan(*i, n), &pushUndefined, &pushUndefinedEnd); \
LoopBegin(&pushUndefined); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
i = Int32Add(*i, GetInt32Constant(1)); \
Branch(Int32LessThan(*i, n), &pushUndefinedAgain, &pushUndefinedEnd); \
Bind(&pushUndefinedAgain); \
LoopEnd(&pushUndefined); \
Bind(&pushUndefinedEnd)
#define CALL_PUSH_ARGS(format) \
DEFVARIABLE(i, VariableType::INT32(), GetInt32Constant(0)); \
GateRef isNativeMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::IsNativeBit::START_BIT); \
Label methodIsNative(env); \
Label methodNotNative(env); \
Branch(Int64NotEqual(Int64And(callField, isNativeMask), GetInt64Constant(0)), &methodIsNative, &methodNotNative); \
Bind(&methodIsNative); \
{ \
CALL_PUSH_ARGS_##format(); \
SET_VREGS_AND_FRAME_NATIVE(format); \
} \
Bind(&methodNotNative); \
GateRef numArgsOffset = GetInt64Constant(JSMethod::NumArgsBits::START_BIT); \
GateRef numArgsMask = GetInt64Constant((static_cast<uint64_t>(1) << JSMethod::NumArgsBits::SIZE) - 1); \
GateRef declaredNumArgs = ChangeInt64ToInt32(Int64And(UInt64LSR(callField, numArgsOffset), numArgsMask)); \
Label fastPath(env); \
Label slowPath(env); \
Label setVregsAndFrameNotNative(env); \
Branch(Int32Equal(actualNumArgs, declaredNumArgs), &fastPath, &slowPath); \
Bind(&fastPath); \
{ \
CALL_PUSH_ARGS_##format(); \
Jump(&setVregsAndFrameNotNative); \
} \
Bind(&slowPath); \
GateRef haveExtraMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::HaveExtraBit::START_BIT); \
Label methodNoExtra(env); \
Label methodHaveExtra(env); \
Branch(Int64NotEqual(Int64And(callField, haveExtraMask), GetInt64Constant(0)), &methodHaveExtra, &methodNoExtra); \
Bind(&methodNoExtra); \
{ \
GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \
CALL_PUSH_UNDEFINED(undefinedNumArgs); \
CALL_PUSH_ARGS_NO_EXTRA_##format(); \
Jump(&setVregsAndFrameNotNative); \
} \
Bind(&methodHaveExtra); \
{ \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), IntBuildTaggedTypeWithNoGC(actualNumArgs)); \
GateRef undefinedNumArgs = Int32Sub(declaredNumArgs, actualNumArgs); \
CALL_PUSH_UNDEFINED(undefinedNumArgs); \
CALL_PUSH_ARGS_##format(); \
Jump(&setVregsAndFrameNotNative); \
} \
Bind(&setVregsAndFrameNotNative); \
SET_VREGS_AND_FRAME_NOT_NATIVE(format)
#define SET_VREGS_AND_FRAME_NATIVE(format) \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Label pushThis(env); \
Label pushThisUndefined(env); \
Label pushNewTarget(env); \
Branch(callThis, &pushThis, &pushThisUndefined); \
Bind(&pushThis); \
{ \
GateRef thisValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), GetIntPtrConstant(1))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), thisValue); \
Jump(&pushNewTarget); \
} \
Bind(&pushThisUndefined); \
{ \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
Jump(&pushNewTarget); \
} \
Bind(&pushNewTarget); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), func); \
/* ASSERT(JSMethod::NumVregsBits::Decode(callField) == 0) */ \
/* thread->DoStackOverflowCheck(newSp) */ \
GateRef frameBaseOffset = GetIntPtrConstant(JSThread::GlueData::GetFrameBaseOffset(env->IsArch32Bit())); \
GateRef frameBase = Load(VariableType::POINTER(), glue, frameBaseOffset); \
Label stackOverflow(env); \
Label stackNotOverflow(env); \
Branch(UInt64LessThanOrEqual(*newSp, IntPtrAdd(frameBase, \
/* 2: double size in case */ \
GetIntPtrConstant(JSThread::RESERVE_STACK_SIZE * sizeof(JSTaggedType) * 2))), \
&stackOverflow, &stackNotOverflow); \
Bind(&stackOverflow); \
{ \
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetStackOverflowException)), {}); \
DISPATCH_LAST(); \
} \
Bind(&stackNotOverflow); \
GateRef state = GetFrame(*newSp); \
GateRef prevOffset = GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \
Store(VariableType::POINTER(), glue, state, prevOffset, sp); \
GateRef frameTypeOffset = IntPtrAdd(prevOffset, GetIntPtrSize()); \
Store(VariableType::INT64(), glue, state, frameTypeOffset, \
GetInt64Constant(static_cast<uint64_t>(FrameType::INTERPRETER_FRAME))); \
SetPcToFrame(glue, state, GetIntPtrConstant(0)); \
SetFunctionToFrame(glue, state, func); \
SetCurrentSpFrame(glue, *newSp); \
GateRef numArgs = Int32Add(GetInt32Constant(NUM_MANDATORY_JSFUNC_ARGS), actualNumArgs); \
GateRef retValue = CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(CallNative)), \
{IntBuildTaggedTypeWithNoGC(numArgs), *newSp, method}); \
SetCurrentSpFrame(glue, sp); \
DEFVARIABLE(varAcc, VariableType::JS_ANY(), retValue); \
DISPATCH_WITH_ACC(format)
#define SET_VREGS_AND_FRAME_NOT_NATIVE(format) \
Label funcIsClassConstructor(env); \
Label funcNotClassConstructor(env); \
Branch(IsClassConstructor(func), &funcIsClassConstructor, &funcNotClassConstructor); \
Bind(&funcIsClassConstructor); \
{ \
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetCallConstructorException)), {}); \
DISPATCH_LAST(); \
} \
Bind(&funcNotClassConstructor); \
Label notNormalCallType(env); \
Label isNormalCallType(env); \
Branch(Int64Equal(Int64And(callField, GetInt64Constant(CALL_TYPE_MASK)), GetInt64Constant(0)), \
&isNormalCallType, &notNormalCallType); \
Bind(&notNormalCallType); \
{ \
GateRef haveThisMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::HaveThisBit::START_BIT); \
Label methodHaveThis(env); \
Label methodNoThis(env); \
Branch(Int64NotEqual(Int64And(callField, haveThisMask), GetInt64Constant(0)), \
&methodHaveThis, &methodNoThis); \
Bind(&methodHaveThis); \
{ \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Label pushThis(env); \
Label pushThisUndefined(env); \
Branch(callThis, &pushThis, &pushThisUndefined); \
Bind(&pushThis); \
{ \
GateRef thisValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), GetIntPtrConstant(1))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), thisValue); \
Jump(&methodNoThis); \
} \
Bind(&pushThisUndefined); \
{ \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
Jump(&methodNoThis); \
} \
} \
Bind(&methodNoThis); \
GateRef haveNewTargetMask = GetInt64Constant(static_cast<uint64_t>(1) << \
JSMethod::HaveNewTargetBit::START_BIT); \
Label methodHaveNewTarget(env); \
Label methodNoNewTarget(env); \
Branch(Int64NotEqual(Int64And(callField, haveNewTargetMask), GetInt64Constant(0)), \
&methodHaveNewTarget, &methodNoNewTarget); \
Bind(&methodHaveNewTarget); \
{ \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), \
GetInt64Constant(JSTaggedValue::VALUE_UNDEFINED)); \
Jump(&methodNoNewTarget); \
} \
Bind(&methodNoNewTarget); \
GateRef haveFuncMask = GetInt64Constant(static_cast<uint64_t>(1) << JSMethod::HaveFuncBit::START_BIT); \
Label methodHaveFunc(env); \
Label methodNoFunc(env); \
Branch(Int64NotEqual(Int64And(callField, haveFuncMask), GetInt64Constant(0)), \
&methodHaveFunc, &methodNoFunc); \
Bind(&methodHaveFunc); \
{ \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), func); \
Jump(&methodNoFunc); \
} \
Bind(&methodNoFunc); \
Jump(&isNormalCallType); \
} \
Bind(&isNormalCallType); \
{ \
GateRef numVregsOffset = GetInt64Constant(JSMethod::NumVregsBits::START_BIT); \
GateRef numVregsMask = GetInt64Constant((static_cast<uint64_t>(1) << JSMethod::NumVregsBits::SIZE) - 1); \
GateRef numVregs = ChangeInt64ToInt32(Int64And(UInt64LSR(callField, numVregsOffset), numVregsMask)); \
CALL_PUSH_UNDEFINED(numVregs); \
/* thread->DoStackOverflowCheck(newSp) */ \
GateRef frameBaseOffset = GetIntPtrConstant(JSThread::GlueData::GetFrameBaseOffset(env->IsArch32Bit())); \
GateRef frameBase = Load(VariableType::POINTER(), glue, frameBaseOffset); \
Label stackOverflow(env); \
Label stackNotOverflow(env); \
Branch(UInt64LessThanOrEqual(*newSp, IntPtrAdd(frameBase, \
/* 2: double size in case */ \
GetIntPtrConstant(JSThread::RESERVE_STACK_SIZE * sizeof(JSTaggedType) * 2))), \
&stackOverflow, &stackNotOverflow); \
Bind(&stackOverflow); \
{ \
CallRuntimeTrampoline(glue, GetInt64Constant(RUNTIME_CALL_ID(SetStackOverflowException)), {}); \
DISPATCH_LAST(); \
} \
Bind(&stackNotOverflow); \
SetPcToFrame(glue, GetFrame(sp), \
IntPtrAdd(pc, GetIntPtrConstant(BytecodeInstruction::Size(BytecodeInstruction::Format::format)))); \
GateRef state = GetFrame(*newSp); \
GateRef prevOffset = GetIntPtrConstant(InterpretedFrame::GetBaseOffset(env->IsArch32Bit())); \
Store(VariableType::POINTER(), glue, state, prevOffset, sp); \
GateRef frameTypeOffset = IntPtrAdd(prevOffset, GetIntPtrConstant( \
env->IsArch32Bit() ? InterpretedFrameBase::TYPE_OFFSET_32 : InterpretedFrameBase::TYPE_OFFSET_64)); \
Store(VariableType::INT64(), glue, state, frameTypeOffset, \
GetInt64Constant(static_cast<uint64_t>(FrameType::INTERPRETER_FRAME))); \
GateRef bytecodeArrayOffset = GetIntPtrConstant(JSMethod::GetBytecodeArrayOffset(env->IsArch32Bit())); \
GateRef bytecodeArray = Load(VariableType::POINTER(), method, bytecodeArrayOffset); \
SetPcToFrame(glue, state, bytecodeArray); \
SetFunctionToFrame(glue, state, func); \
SetAccToFrame(glue, state, GetHoleConstant(VariableType::JS_ANY())); \
GateRef newEnv = GetEnvFromFunction(func); \
SetEnvToFrame(glue, state, newEnv); \
SetCurrentSpFrame(glue, *newSp); \
GateRef newConstpool = GetConstpoolFromFunction(func); \
GateRef newProfileTypeInfo = GetProfileTypeInfoFromFunction(func); \
GateRef newHotnessCounter = Load(VariableType::INT32(), method, \
GetIntPtrConstant(JSMethod::HOTNESS_COUNTER_OFFSET)); \
Dispatch(glue, bytecodeArray, *newSp, newConstpool, newProfileTypeInfo, \
GetHoleConstant(VariableType::JS_ANY()), newHotnessCounter, GetIntPtrConstant(0)); \
}
#define CALL_PUSH_ARGS_PREF_V8() \
static_cast<void>(0) // do nothing when 0 arg
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8() \
static_cast<void>(0) // do nothing when 0 arg
#define CALL_PUSH_ARGS_PREF_V8_V8() \
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a0Value)
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8() \
Label push0(env); \
Label skip0(env); \
Branch(Int32GreaterThanOrEqual(declaredNumArgs, \
GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG1)), &push0, &skip0); \
Bind(&push0); \
{ \
GateRef a0Value = GetVregValue(sp, ZExtInt8ToPtr(a0)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a0Value); \
Jump(&skip0); \
} \
Bind(&skip0)
#define CALL_PUSH_ARGS_PREF_V8_V8_V8() \
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a1Value); \
CALL_PUSH_ARGS_PREF_V8_V8()
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8() \
Label push1(env); \
Label skip1(env); \
Branch(Int32GreaterThanOrEqual(declaredNumArgs, \
GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS2)), &push1, &skip1); \
Bind(&push1); \
{ \
GateRef a1Value = GetVregValue(sp, ZExtInt8ToPtr(a1)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a1Value); \
Jump(&skip1); \
} \
Bind(&skip1); \
CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8()
#define CALL_PUSH_ARGS_PREF_V8_V8_V8_V8() \
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a2Value); \
CALL_PUSH_ARGS_PREF_V8_V8_V8()
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8_V8() \
Label push2(env); \
Label skip2(env); \
Branch(Int32GreaterThanOrEqual(declaredNumArgs, \
GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS3)), &push2, &skip2); \
Bind(&push2); \
{ \
GateRef a2Value = GetVregValue(sp, ZExtInt8ToPtr(a2)); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), a2Value); \
Jump(&skip2); \
} \
Bind(&skip2); \
CALL_PUSH_ARGS_NO_EXTRA_PREF_V8_V8_V8()
#define CALL_PUSH_ARGS_PREF_IMM16_V8() \
i = actualNumArgs; \
CALL_PUSH_ARGS_I()
#define CALL_PUSH_ARGS_NO_EXTRA_PREF_IMM16_V8() \
/* i = std::min(actualNumArgs, declaredNumArgs) */ \
i = actualNumArgs; \
Label declaredNumArgsSmaller(env); \
Label callPushArgsI(env); \
Branch(Int32LessThan(*i, declaredNumArgs), &callPushArgsI, &declaredNumArgsSmaller); \
Bind(&declaredNumArgsSmaller); \
i = declaredNumArgs; \
Jump(&callPushArgsI); \
Bind(&callPushArgsI); \
CALL_PUSH_ARGS_I()
#define CALL_PUSH_ARGS_I() \
Label pushWithThis(env); \
Label pushWithoutThis(env); \
Label pushArgsEnd(env); \
Branch(callThis, &pushWithThis, &pushWithoutThis); \
Bind(&pushWithThis); \
{ \
i = Int32Add(*i, GetInt32Constant(1)); /* 1: skip this */ \
Label pushArgs(env); \
Label pushArgsAgain(env); \
Branch(Int32GreaterThan(*i, GetInt32Constant(1)), &pushArgs, &pushArgsEnd); \
LoopBegin(&pushArgs); \
GateRef aValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), ChangeInt32ToIntPtr(*i))); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), aValue); \
i = Int32Sub(*i, GetInt32Constant(1)); \
Branch(Int32GreaterThan(*i, GetInt32Constant(1)), &pushArgsAgain, &pushArgsEnd); \
Bind(&pushArgsAgain); \
LoopEnd(&pushArgs); \
} \
Bind(&pushWithoutThis); \
{ \
Label pushArgs(env); \
Label pushArgsAgain(env); \
Branch(Int32GreaterThan(*i, GetInt32Constant(0)), &pushArgs, &pushArgsEnd); \
LoopBegin(&pushArgs); \
GateRef aValue = GetVregValue(sp, IntPtrAdd(ZExtInt8ToPtr(funcReg), ChangeInt32ToIntPtr(*i))); \
newSp = PointerSub(*newSp, GetIntPtrConstant(sizeof(JSTaggedType))); \
Store(VariableType::INT64(), glue, *newSp, GetIntPtrConstant(0), aValue); \
i = Int32Sub(*i, GetInt32Constant(1)); \
Branch(Int32GreaterThan(*i, GetInt32Constant(0)), &pushArgsAgain, &pushArgsEnd); \
Bind(&pushArgsAgain); \
LoopEnd(&pushArgs); \
} \
Bind(&pushArgsEnd)
DECLARE_ASM_HANDLER(HandleCallArg0DynPrefV8)
{
auto env = GetEnvironment();
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG0);
GateRef funcReg = ReadInst8_1(pc);
CALL_INITIALIZE();
GateRef callThis = FalseConstant();
CALL_PUSH_ARGS(PREF_V8);
}
DECLARE_ASM_HANDLER(HandleCallArg1DynPrefV8V8)
{
auto env = GetEnvironment();
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARG1);
GateRef funcReg = ReadInst8_1(pc);
GateRef a0 = ReadInst8_2(pc);
CALL_INITIALIZE();
GateRef callThis = FalseConstant();
CALL_PUSH_ARGS(PREF_V8_V8);
}
DECLARE_ASM_HANDLER(HandleCallArgs2DynPrefV8V8V8)
{
auto env = GetEnvironment();
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS2);
GateRef funcReg = ReadInst8_1(pc);
GateRef a0 = ReadInst8_2(pc);
GateRef a1 = ReadInst8_3(pc);
CALL_INITIALIZE();
GateRef callThis = FalseConstant();
CALL_PUSH_ARGS(PREF_V8_V8_V8);
}
DECLARE_ASM_HANDLER(HandleCallArgs3DynPrefV8V8V8V8)
{
auto env = GetEnvironment();
GateRef actualNumArgs = GetInt32Constant(EcmaInterpreter::ActualNumArgsOfCall::CALLARGS3);
GateRef funcReg = ReadInst8_1(pc);
GateRef a0 = ReadInst8_2(pc);
GateRef a1 = ReadInst8_3(pc);
GateRef a2 = ReadInst8_4(pc);
CALL_INITIALIZE();
GateRef callThis = FalseConstant();
CALL_PUSH_ARGS(PREF_V8_V8_V8_V8);
}
DECLARE_ASM_HANDLER(HandleCallIRangeDynPrefImm16V8)
{
auto env = GetEnvironment();
GateRef actualNumArgs = ZExtInt16ToInt32(ReadInst16_1(pc));
GateRef funcReg = ReadInst8_3(pc);
CALL_INITIALIZE();
GateRef callThis = FalseConstant();
CALL_PUSH_ARGS(PREF_IMM16_V8);
}
DECLARE_ASM_HANDLER(HandleCallIThisRangeDynPrefImm16V8)
{
auto env = GetEnvironment();
GateRef actualNumArgs = Int32Sub(ZExtInt16ToInt32(ReadInst16_1(pc)), GetInt32Constant(1)); // 1: exclude this
GateRef funcReg = ReadInst8_3(pc);
CALL_INITIALIZE();
GateRef callThis = TrueConstant();
CALL_PUSH_ARGS(PREF_IMM16_V8);
}
#endif
#undef DECLARE_ASM_HANDLER
#undef DISPATCH
#undef DISPATCH_WITH_ACC
#undef DISPATCH_LAST
#undef DISPATCH_LAST_WITH_ACC
} // namespace panda::ecmascript::kungfu

View File

@ -64,6 +64,7 @@ public:
inline GateRef GetFunctionFromFrame(GateRef frame);
inline GateRef GetAccFromFrame(GateRef frame);
inline GateRef GetEnvFromFrame(GateRef frame);
inline GateRef GetEnvFromFunction(GateRef frame);
inline GateRef GetConstpoolFromFunction(GateRef function);
inline GateRef GetProfileTypeInfoFromFunction(GateRef function);

View File

@ -24,12 +24,15 @@ namespace panda::ecmascript::kungfu {
#define IGNORE_STUB(...)
#define INTERPRETER_STUB_LIST(V) \
ASM_INTERPRETER_STUB_LIST(IGNORE_STUB, V)
ASM_INTERPRETER_STUB_LIST(IGNORE_STUB, V, V)
#define INTERPRETER_IGNORE_STUB_LIST(V) \
ASM_INTERPRETER_STUB_LIST(IGNORE_STUB, IGNORE_STUB, V)
#define ASM_INTERPRETER_ID_LIST(V) \
ASM_INTERPRETER_STUB_LIST(V, V)
ASM_INTERPRETER_STUB_LIST(V, V, V)
#define ASM_INTERPRETER_STUB_LIST(V, T) \
#define ASM_INTERPRETER_STUB_LIST(V, T, I) \
T(HandleLdNanPref, 7) \
T(HandleLdInfinityPref, 7) \
T(HandleLdGlobalThisPref, 7) \
@ -89,7 +92,7 @@ namespace panda::ecmascript::kungfu {
T(HandleThrowConstAssignmentPrefV8, 7) \
T(HandleGetTemplateObjectPrefV8, 7) \
T(HandleGetNextPropNamePrefV8, 7) \
V(HandleCallArg0DynPrefV8, 7) \
I(HandleCallArg0DynPrefV8, 7) \
T(HandleThrowIfNotObjectPrefV8, 7) \
T(HandleIterNextPrefV8, 7) \
T(HandleCloseIteratorPrefV8, 7) \
@ -101,7 +104,7 @@ namespace panda::ecmascript::kungfu {
T(HandleSuspendGeneratorPrefV8V8, 7) \
T(HandleAsyncFunctionAwaitUncaughtPrefV8V8, 7) \
T(HandleThrowUndefinedIfHolePrefV8V8, 7) \
V(HandleCallArg1DynPrefV8V8, 7) \
I(HandleCallArg1DynPrefV8V8, 7) \
T(HandleCopyDataPropertiesPrefV8V8, 7) \
T(HandleStArraySpreadPrefV8V8, 7) \
T(HandleGetIteratorNextPrefV8V8, 7) \
@ -117,12 +120,12 @@ namespace panda::ecmascript::kungfu {
T(HandleCallSpreadDynPrefV8V8V8, 7) \
T(HandleAsyncFunctionResolvePrefV8V8V8, 7) \
T(HandleAsyncFunctionRejectPrefV8V8V8, 7) \
V(HandleCallArgs2DynPrefV8V8V8, 7) \
V(HandleCallArgs3DynPrefV8V8V8V8, 7) \
I(HandleCallArgs2DynPrefV8V8V8, 7) \
I(HandleCallArgs3DynPrefV8V8V8V8, 7) \
T(HandleDefineGetterSetterByValuePrefV8V8V8V8, 7) \
T(HandleNewObjDynRangePrefImm16V8, 7) \
V(HandleCallIRangeDynPrefImm16V8, 7) \
V(HandleCallIThisRangeDynPrefImm16V8, 7) \
I(HandleCallIRangeDynPrefImm16V8, 7) \
I(HandleCallIThisRangeDynPrefImm16V8, 7) \
T(HandleSuperCallPrefImm16V8, 7) \
T(HandleCreateObjectWithExcludedKeysPrefImm16V8V8, 7) \
T(HandleDefineFuncDynPrefId16Imm16V8, 7) \

View File

@ -126,8 +126,11 @@ void LLVMIRBuilder::AssignHandleMap()
{OpCode::SLT, &LLVMIRBuilder::HandleCmp},
{OpCode::ULT, &LLVMIRBuilder::HandleCmp},
{OpCode::SLE, &LLVMIRBuilder::HandleCmp},
{OpCode::ULE, &LLVMIRBuilder::HandleCmp},
{OpCode::SGT, &LLVMIRBuilder::HandleCmp},
{OpCode::UGT, &LLVMIRBuilder::HandleCmp},
{OpCode::SGE, &LLVMIRBuilder::HandleCmp},
{OpCode::UGE, &LLVMIRBuilder::HandleCmp},
{OpCode::NE, &LLVMIRBuilder::HandleCmp},
{OpCode::EQ, &LLVMIRBuilder::HandleCmp},
{OpCode::LOAD, &LLVMIRBuilder::HandleLoad},
@ -1264,7 +1267,8 @@ void LLVMIRBuilder::VisitSub(GateRef gate, GateRef e1, GateRef e2)
COMPILER_LOG(DEBUG) << "operand 1: " << LLVMValueToString(e2Value);
LLVMValueRef result = nullptr;
auto machineType = circuit_->LoadGatePtrConst(gate)->GetMachineType();
if (machineType == MachineType::I16 || machineType == MachineType::I32 || machineType == MachineType::I64) {
if (machineType == MachineType::I16 || machineType == MachineType::I32 ||
machineType == MachineType::I64 || machineType == MachineType::ARCH) {
result = LLVMBuildSub(builder_, e1Value, e2Value, "");
} else if (machineType == MachineType::F64) {
result = LLVMBuildFSub(builder_, e1Value, e2Value, "");
@ -1384,16 +1388,31 @@ void LLVMIRBuilder::VisitCmp(GateRef gate, GateRef e1, GateRef e2)
realOpcode = LLVMRealOLE;
break;
}
case OpCode::ULE: {
intOpcode = LLVMIntULE;
realOpcode = LLVMRealOLE;
break;
}
case OpCode::SGT: {
intOpcode = LLVMIntSGT;
realOpcode = LLVMRealOGT;
break;
}
case OpCode::UGT: {
intOpcode = LLVMIntUGT;
realOpcode = LLVMRealOGT;
break;
}
case OpCode::SGE: {
intOpcode = LLVMIntSGE;
realOpcode = LLVMRealOGE;
break;
}
case OpCode::UGE: {
intOpcode = LLVMIntUGE;
realOpcode = LLVMRealOGE;
break;
}
case OpCode::NE: {
intOpcode = LLVMIntNE;
realOpcode = LLVMRealONE;

View File

@ -477,6 +477,11 @@ GateRef Stub::IntPtrSub(GateRef x, GateRef y)
return Int64Sub(x, y);
}
GateRef Stub::PointerSub(GateRef x, GateRef y)
{
return env_.GetCircuitBuilder().NewArithmeticGate(OpCode(OpCode::SUB), MachineType::ARCH, x, y);
}
GateRef Stub::Int16Sub(GateRef x, GateRef y)
{
return env_.GetCircuitBuilder().NewArithmeticGate(OpCode(OpCode::SUB), MachineType::I16, x, y);

View File

@ -452,6 +452,7 @@ public:
inline GateRef DoubleAdd(GateRef x, GateRef y);
inline GateRef IntPtrAdd(GateRef x, GateRef y);
inline GateRef IntPtrSub(GateRef x, GateRef y);
inline GateRef PointerSub(GateRef x, GateRef y);
inline GateRef IntPtrEqual(GateRef x, GateRef y);
inline GateRef Int16Sub(GateRef x, GateRef y);
inline GateRef Int32Sub(GateRef x, GateRef y);

View File

@ -312,8 +312,10 @@ public:
~InterpretedFrameBase() = default;
JSTaggedType *prev; // for llvm :c-fp ; for interrupt: thread-fp for gc
FrameType type;
static constexpr size_t SizeArch32 = sizeof(JSTaggedType *) + sizeof(FrameType);
static constexpr size_t SizeArch64 = sizeof(JSTaggedType *) + sizeof(FrameType);
static constexpr size_t TYPE_OFFSET_32 = sizeof(uint32_t);
static constexpr size_t TYPE_OFFSET_64 = sizeof(uint64_t);
static constexpr size_t SizeArch32 = TYPE_OFFSET_32 + sizeof(FrameType);
static constexpr size_t SizeArch64 = TYPE_OFFSET_64 + sizeof(FrameType);
};
STATIC_ASSERT_EQ_ARCH(sizeof(InterpretedFrameBase), InterpretedFrameBase::SizeArch32, InterpretedFrameBase::SizeArch64);

View File

@ -3792,7 +3792,7 @@ uint32_t EcmaInterpreter::GetNumArgs(JSTaggedType *sp, uint32_t restIdx, uint32_
uint32_t numArgs = method->GetNumArgsWithCallField();
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
JSTaggedType *lastFrame = state->base.prev - FRAME_STATE_SIZE;
if (lastFrame - sp > numVregs + copyArgs + numArgs) {
if (static_cast<uint32_t>(lastFrame - sp) > numVregs + copyArgs + numArgs) {
// In this case, actualNumArgs is in the end
// If not, then actualNumArgs == declaredNumArgs, therefore do nothing
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)

View File

@ -35,10 +35,10 @@ static constexpr size_t STORAGE_PTR_NUM = 3;
V(CODEID, FILEID, sizeof(uint32_t), sizeof(uint32_t)) \
V(SHORTY, CODEID, sizeof(uint32_t), sizeof(uint32_t)) \
V(PROFILINGDATA, SHORTY, sizeof(uint32_t), sizeof(uint64_t)) \
V(BYTECODEARRAY, PROFILINGDATA, sizeof(uint32_t), sizeof(uint64_t)) \
V(CALLFIELD, PROFILINGDATA, sizeof(uint32_t), sizeof(uint64_t)) \
V(BYTECODEARRAY, CALLFIELD, sizeof(uint64_t), sizeof(uint64_t)) \
V(BYTECODEARRAYSIZE, BYTECODEARRAY, sizeof(uint32_t), sizeof(uint64_t)) \
V(SLOTSIZE, BYTECODEARRAYSIZE, sizeof(uint32_t), sizeof(uint32_t)) \
V(CALLFIELD, SLOTSIZE, sizeof(uint8_t), sizeof(uint8_t)) \
static constexpr uint32_t JS_METHOD_STOR32_OFFSET_32 = 0U;
static constexpr uint32_t JS_METHOD_STOR32_OFFSET_64 = 0U;
@ -131,6 +131,14 @@ public:
return callField_;
}
static constexpr uint32_t GetCallFieldOffset(bool isArm32)
{
if (isArm32) {
return JS_METHOD_CALLFIELD_OFFSET_32;
}
return JS_METHOD_CALLFIELD_OFFSET_64;
}
void SetNativeBit(bool isNative)
{
callField_ = IsNativeBit::Update(callField_, isNative);
@ -180,10 +188,10 @@ public:
}
private:
uint64_t callField_ {0};
const uint8_t *bytecodeArray_ {nullptr};
uint32_t bytecodeArraySize_ {0};
uint8_t slotSize_ {0};
uint64_t callField_ {0};
};
} // namespace panda::ecmascript

View File

@ -31,9 +31,9 @@ JSThread *JSThread::Create(Runtime *runtime, PandaVM *vm)
jsThread->nativeAreaAllocator_ = EcmaVM::Cast(vm)->GetNativeAreaAllocator();
jsThread->heapRegionAllocator_ = EcmaVM::Cast(vm)->GetHeapRegionAllocator();
// algin with 16
jsThread->frameBase_ = static_cast<JSTaggedType *>(
jsThread->glueData_.frameBase_ = static_cast<JSTaggedType *>(
EcmaVM::Cast(vm)->GetNativeAreaAllocator()->Allocate(sizeof(JSTaggedType) * MAX_STACK_SIZE));
jsThread->glueData_.currentFrame_ = jsThread->frameBase_ + MAX_STACK_SIZE;
jsThread->glueData_.currentFrame_ = jsThread->glueData_.frameBase_ + MAX_STACK_SIZE;
JSThread::SetCurrent(jsThread);
EcmaInterpreter::InitStackFrame(jsThread);
return jsThread;
@ -62,8 +62,8 @@ JSThread::~JSThread()
handleScopeStorageNext_ = handleScopeStorageEnd_ = nullptr;
EcmaVM::Cast(GetVM())->GetChunk()->Delete(globalStorage_);
GetNativeAreaAllocator()->Free(frameBase_, sizeof(JSTaggedType) * MAX_STACK_SIZE);
frameBase_ = nullptr;
GetNativeAreaAllocator()->Free(glueData_.frameBase_, sizeof(JSTaggedType) * MAX_STACK_SIZE);
glueData_.frameBase_ = nullptr;
nativeAreaAllocator_ = nullptr;
heapRegionAllocator_ = nullptr;
if (internalCallParams_ != nullptr) {
@ -158,7 +158,7 @@ void JSThread::IterateWeakEcmaGlobalStorage(const WeakRootVisitor &visitor)
bool JSThread::DoStackOverflowCheck(const JSTaggedType *sp)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
if (UNLIKELY(sp <= frameBase_ + RESERVE_STACK_SIZE)) {
if (UNLIKELY(sp <= glueData_.frameBase_ + RESERVE_STACK_SIZE)) {
ObjectFactory *factory = GetEcmaVM()->GetFactory();
JSHandle<JSObject> error = factory->GetJSError(base::ErrorType::RANGE_ERROR, "Stack overflow!");
if (LIKELY(!HasPendingException())) {
@ -247,7 +247,12 @@ void JSThread::LoadStubModule(const char *moduleFile)
glueData_.bcHandlers_.Set(kungfu::InterpreterStubId::name##Id, \
stubModule.GetStubEntry(kungfu::StubId::STUB_##name));
INTERPRETER_STUB_LIST(DEF_STUB)
#define UNDEF_STUB(name, counter) \
glueData_.bcHandlers_.Set(kungfu::InterpreterStubId::name##Id, \
stubModule.GetStubEntry(kungfu::StubId::STUB_SingleStepDebugging));
INTERPRETER_IGNORE_STUB_LIST(UNDEF_STUB)
#undef DEF_STUB
#undef UNDEF_STUB
#endif
#ifdef NDEBUG

View File

@ -96,6 +96,7 @@ STATIC_ASSERT_EQ_ARCH(sizeof(StubEntries), StubEntries::SizeArch32, StubEntries:
class JSThread : public ManagedThread {
public:
static constexpr int CONCURRENT_MARKING_BITFIELD_NUM = 2;
static constexpr uint32_t RESERVE_STACK_SIZE = 128;
using MarkStatusBits = BitField<MarkStatus, 0, CONCURRENT_MARKING_BITFIELD_NUM>;
static JSThread *Cast(ManagedThread *thread)
@ -356,6 +357,7 @@ public:
RTInterfaces,
StubEntries,
base::AlignedUint64,
base::AlignedPointer,
GlobalEnvConstants> {
enum class Index : size_t {
ExceptionIndex = 0,
@ -366,6 +368,7 @@ public:
RTInterfacesIndex,
StubEntriesIndex,
StateBitFieldIndex,
FrameBaseIndex,
GlobalConstIndex,
NumOfMembers
};
@ -416,6 +419,11 @@ public:
return GetOffset<static_cast<size_t>(Index::StubEntriesIndex)>(isArch32);
}
static size_t GetFrameBaseOffset(bool isArch32)
{
return GetOffset<static_cast<size_t>(Index::FrameBaseIndex)>(isArch32);
}
alignas(EAS) JSTaggedValue exception_ {JSTaggedValue::Hole()};
alignas(EAS) JSTaggedValue globalObject_ {JSTaggedValue::Hole()};
alignas(EAS) JSTaggedType *currentFrame_ {nullptr};
@ -424,6 +432,7 @@ public:
alignas(EAS) RTInterfaces rtInterfaces_;
alignas(EAS) StubEntries stubEntries_;
alignas(EAS) volatile uint64_t threadStateBitField_ {0ULL};
alignas(EAS) JSTaggedType *frameBase_ {nullptr};
alignas(EAS) GlobalEnvConstants globalConst_;
};
static_assert(MEMBER_OFFSET(GlueData, rtInterfaces_) == ASM_GLUE_RUNTIME_FUNCTIONS_OFFSET);
@ -438,7 +447,6 @@ private:
void DumpStack() DUMP_API_ATTR;
static constexpr uint32_t MAX_STACK_SIZE = 128 * 1024;
static constexpr uint32_t RESERVE_STACK_SIZE = 128;
static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10;
static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2;
static constexpr int32_t MIN_HANDLE_STORAGE_SIZE = 2;
@ -462,7 +470,6 @@ private:
bool gcState_ {false};
VmThreadControl *vmThreadControl_ {nullptr};
JSTaggedType *frameBase_ {nullptr};
bool stableArrayElementsGuardians_ {true};
InternalCallParams *internalCallParams_ {nullptr};
GlueData glueData_;

View File

@ -26,7 +26,8 @@ static std::array<std::string, MessageString::MAX_MESSAGE_COUNT> g_messageString
#undef DEF_COMMON_MESSAGE
#define DEF_ASM_INTERPRETER_STUB_MESSAGE(name, count) #name,
INTERPRETER_STUB_HELPER_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE)
ASM_INTERPRETER_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE, DEF_ASM_INTERPRETER_STUB_MESSAGE)
ASM_INTERPRETER_STUB_LIST(DEF_ASM_INTERPRETER_STUB_MESSAGE, DEF_ASM_INTERPRETER_STUB_MESSAGE,
DEF_ASM_INTERPRETER_STUB_MESSAGE)
#undef DEF_ASM_INTERPRETER_STUB_MESSAGE
};

View File

@ -38,7 +38,7 @@ public:
#define DEF_MESSAGE_ID(name, string) Message_##name,
COMMON_MESSAGE_STRING_LIST(DEF_MESSAGE_ID)
INTERPRETER_STUB_HELPER_LIST(DEF_MESSAGE_ID)
ASM_INTERPRETER_STUB_LIST(DEF_MESSAGE_ID, DEF_MESSAGE_ID)
ASM_INTERPRETER_STUB_LIST(DEF_MESSAGE_ID, DEF_MESSAGE_ID, DEF_MESSAGE_ID)
#undef DEF_MESSAGE_ID
MAX_MESSAGE_COUNT
};

View File

@ -157,6 +157,10 @@ namespace panda::ecmascript {
V(DefineGeneratorFunc, 2) \
V(DefineAsyncFunc, 2) \
V(DefineMethod, 3) \
V(SetNotCallableException, 0) \
V(SetCallConstructorException, 0) \
V(SetStackOverflowException, 0) \
V(CallNative, 3) \
V(CallSpreadDyn, 4) \
V(DefineGetterSetterByValue, 6) \
V(SuperCall, 5)

View File

@ -884,14 +884,13 @@ DEF_RUNTIME_TRAMPOLINES(UpdateHotnessCounter)
RUNTIME_TRAMPOLINES_HEADER(UpdateHotnessCounter);
InterpretedFrame *state = GET_FRAME(const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()));
thread->CheckSafepoint();
if (state->profileTypeInfo == JSTaggedValue::Undefined()) {
auto thisFunc = state->function;
auto method = ECMAObject::Cast(thisFunc.GetTaggedObject())->GetCallTarget();
auto res = SlowRuntimeStub::NotifyInlineCache(
thread, JSFunction::Cast(thisFunc.GetHeapObject()), method);
state->profileTypeInfo = res;
auto thisFunc = JSFunction::Cast(state->function.GetTaggedObject());
if (thisFunc->GetProfileTypeInfo() == JSTaggedValue::Undefined()) {
auto method = thisFunc->GetCallTarget();
auto res = SlowRuntimeStub::NotifyInlineCache(thread, thisFunc, method);
return res.GetRawData();
}
return state->profileTypeInfo.GetRawData();
return thisFunc->GetProfileTypeInfo().GetRawData();
}
DEF_RUNTIME_TRAMPOLINES(LoadICByName)
@ -1523,6 +1522,52 @@ DEF_RUNTIME_TRAMPOLINES(SuperCall)
static_cast<uint16_t>(length.GetInt())).GetRawData();
}
DEF_RUNTIME_TRAMPOLINES(SetNotCallableException)
{
RUNTIME_TRAMPOLINES_HEADER(SetNotCallableException);
EcmaVM *ecmaVm = thread->GetEcmaVM();
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR, "is not callable");
thread->SetException(error.GetTaggedValue());
return JSTaggedValue::Hole().GetRawData();
}
DEF_RUNTIME_TRAMPOLINES(SetCallConstructorException)
{
RUNTIME_TRAMPOLINES_HEADER(SetCallConstructorException);
EcmaVM *ecmaVm = thread->GetEcmaVM();
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
"class constructor cannot called without 'new'");
thread->SetException(error.GetTaggedValue());
return JSTaggedValue::Hole().GetRawData();
}
DEF_RUNTIME_TRAMPOLINES(SetStackOverflowException)
{
RUNTIME_TRAMPOLINES_HEADER(SetStackOverflowException);
EcmaVM *ecmaVm = thread->GetEcmaVM();
ObjectFactory *factory = ecmaVm->GetFactory();
JSHandle<JSObject> error = factory->GetJSError(base::ErrorType::RANGE_ERROR, "Stack overflow!");
if (LIKELY(!thread->HasPendingException())) {
thread->SetException(error.GetTaggedValue());
}
return JSTaggedValue::Hole().GetRawData();
}
DEF_RUNTIME_TRAMPOLINES(CallNative)
{
RUNTIME_TRAMPOLINES_HEADER(CallNative);
CONVERT_ARG_TAGGED_CHECKED(numArgs, 0);
CONVERT_ARG_PTR_CHECKED(JSTaggedValue *, sp, 1);
CONVERT_ARG_PTR_CHECKED(JSMethod *, method, 2);
EcmaRuntimeCallInfo ecmaRuntimeCallInfo(thread, numArgs.GetInt(), sp);
JSTaggedValue retValue = reinterpret_cast<EcmaEntrypoint>(
const_cast<void *>(method->GetNativePointer()))(&ecmaRuntimeCallInfo);
return retValue.GetRawData();
}
int32_t RuntimeTrampolines::DoubleToInt(double x)
{
return base::NumberHelper::DoubleToInt(x, base::INT32_BITS);