AOT support js stacktrace

1. add pcOffset into stackmap before call In AOT
2. parse stackmap to find pcOffset before any OptimziedJSFunctionFrame
3. remove use code of stubs in AOT
4. add testcase for js stacktrace of AOT

Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6GXRR?from=project-issue

Signed-off-by: zhangyukun8 <zhangyukun8@huawei.com>
Change-Id: Ib21646b7319628fb425ac8ce489dc2370a347b81
This commit is contained in:
zhangyukun8 2023-03-02 20:09:04 +08:00
parent 9cd0d162b6
commit 62a3e35295
80 changed files with 1377 additions and 741 deletions

View File

@ -494,16 +494,6 @@ JSTaggedValue BuiltinsGlobal::PrintEntrypoint(EcmaRuntimeCallInfo *msg)
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
PrintString(thread, *stringContent);
// print bc offset for ts aot
if (GetCallArg(msg, i)->IsJSError() && thread->IsPrintBCOffset()) {
auto list = thread->GetEcmaVM()->GetBCOffsetInfoList();
if (!list.empty()) {
for (auto info : list) {
std::cout << "\nException at function " << info.first << ": " << info.second;
}
}
}
if (i != numArgs - 1) {
std::cout << " ";
}

View File

@ -92,7 +92,7 @@ GateRef BuiltinLowering::TypedTrigonometric(GateRef gate, BuiltinsStubCSigns::ID
LOG_ECMA(FATAL) << "this branch is unreachable";
UNREACHABLE();
}
result = builder_.CallNGCRuntime(glue, index, Gate::InvalidGateRef, {value});
result = builder_.CallNGCRuntime(glue, index, Gate::InvalidGateRef, {value}, gate);
builder_.Jump(&exit);
}
builder_.Bind(&IsNan);
@ -191,7 +191,7 @@ GateRef BuiltinLowering::TypedSqrt(GateRef gate)
{
GateRef glue = acc_.GetGlueFromArgList();
result = builder_.CallNGCRuntime(
glue, RTSTUB_ID(FloatSqrt), Gate::InvalidGateRef, {*value});
glue, RTSTUB_ID(FloatSqrt), Gate::InvalidGateRef, {*value}, gate);
builder_.Jump(&exit);
}
// If value is NaN, the result is NaN

View File

@ -821,8 +821,9 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
GateRef gate = 0;
bool writable = !bytecodeInfo.NoSideEffects();
size_t pcOffset = GetPcOffset(iterator.Index());
auto meta = circuit_->JSBytecode(numValueInputs,
bytecodeInfo.GetOpcode(), iterator.Index(), writable);
bytecodeInfo.GetOpcode(), pcOffset, writable);
std::vector<GateRef> inList = CreateGateInList(bytecodeInfo, meta);
if (bytecodeInfo.IsDef()) {
gate = circuit_->NewGate(meta, MachineType::I64, inList.size(),
@ -906,8 +907,8 @@ void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, GateRef &state, GateRef
auto offset = GetJumpOffset(iterator.Index());
if (bytecodeInfo.IsCondJump()) {
ASSERT(!bytecodeInfo.Deopt());
auto meta = circuit_->JSBytecode(numValueInputs,
bytecodeInfo.GetOpcode(), iterator.Index(), false);
size_t pcOffset = GetPcOffset(iterator.Index());
auto meta = circuit_->JSBytecode(numValueInputs, bytecodeInfo.GetOpcode(), pcOffset, false);
auto numValues = meta->GetNumIns();
GateRef gate = circuit_->NewGate(meta, std::vector<GateRef>(numValues, Circuit::NullGate()));
gateAcc_.NewIn(gate, 0, state);

View File

@ -84,6 +84,16 @@ DEF_CALL_SIGNATURE(NotEqual)
BINARY_CALL_SIGNATURE(NotEqual)
}
DEF_CALL_SIGNATURE(StrictEqual)
{
BINARY_CALL_SIGNATURE(StrictEqual)
}
DEF_CALL_SIGNATURE(StrictNotEqual)
{
BINARY_CALL_SIGNATURE(StrictNotEqual)
}
DEF_CALL_SIGNATURE(Less)
{
BINARY_CALL_SIGNATURE(Less)
@ -632,6 +642,51 @@ DEF_CALL_SIGNATURE(ConstructorCheck)
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(CreateEmptyArray)
{
// 1 : 1 input parameters
CallSignature signature("CreateEmptyArray", 0, 1,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = signature;
// 1 : 1 input parameters
std::array<VariableType, 1> params = {
VariableType::NATIVE_POINTER(), // glue
};
callSign->SetParameters(params.data());
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(CreateArrayWithBuffer)
{
// 3 : 3 input parameters
CallSignature signature("CreateArrayWithBuffer", 0, 3,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = signature;
// 3 : 3 input parameters
std::array<VariableType, 3> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::INT32(), // index
VariableType::JS_ANY(), // jsFunc
};
callSign->SetParameters(params.data());
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(NewJSObject)
{
// 2 : 2 input parameters
CallSignature signature("NewJSObject", 0, 2,
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
*callSign = signature;
// 2 : 2 input parameters
std::array<VariableType, 2> params = {
VariableType::NATIVE_POINTER(), // glue
VariableType::JS_ANY(), // hclass
};
callSign->SetParameters(params.data());
callSign->SetCallConv(CallSignature::CallConv::CCallConv);
}
DEF_CALL_SIGNATURE(NewLexicalEnv)
{
// 3 : 3 input parameters

View File

@ -314,6 +314,8 @@ private:
V(TypeOf) \
V(Equal) \
V(NotEqual) \
V(StrictEqual) \
V(StrictNotEqual) \
V(Less) \
V(LessEq) \
V(Greater) \
@ -356,6 +358,9 @@ private:
V(GetUnmapedArgs) \
V(NewThisObjectChecked) \
V(ConstructorCheck) \
V(CreateEmptyArray) \
V(CreateArrayWithBuffer) \
V(NewJSObject) \
V(GetTaggedArrayPtrTest) \
V(BytecodeHandler) \
V(Builtins) \

View File

@ -121,10 +121,10 @@ public:
}
const GateMetaData* JSBytecode(size_t valuesIn, EcmaOpcode opcode,
uint32_t bcIndex, bool writable)
uint32_t pcOffset, bool writable)
{
GateFlags flags = writable ? GateFlags::NONE_FLAG : GateFlags::NO_WRITE;
return metaBuilder_.JSBytecode(valuesIn, opcode, bcIndex, flags);
return metaBuilder_.JSBytecode(valuesIn, opcode, pcOffset, flags);
}
const GateMetaData* TypedBinaryOp(uint64_t value, TypedBinOp binOp)
@ -151,6 +151,11 @@ public:
return static_cast<size_t>(gateCount_ - 1);
}
bool IsOptimizedJSFunctionFrame() const
{
return frameType_ == panda::ecmascript::FrameType::OPTIMIZED_JS_FUNCTION_FRAME;
}
private:
static const size_t CIRCUIT_SPACE = 1U << 30U; // 1GB

View File

@ -403,45 +403,50 @@ GateRef CircuitBuilder::BinaryCmp(const GateMetaData* meta, GateRef left, GateRe
GateRef CircuitBuilder::CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
const CallSignature *cs = BytecodeStubCSigns::BCHandler();
ASSERT(cs->IsBCStub());
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate());
return result;
}
GateRef CircuitBuilder::CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
const CallSignature *cs = BuiltinsStubCSigns::BuiltinsCSign();
ASSERT(cs->IsBuiltinsStub());
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate());
return result;
}
GateRef CircuitBuilder::CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
const CallSignature *cs = BuiltinsStubCSigns::BuiltinsWithArgvCSign();
ASSERT(cs->IsBuiltinsWithArgvStub());
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate());
return result;
}
GateRef CircuitBuilder::CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
const CallSignature *cs = BytecodeStubCSigns::BCDebuggerHandler();
ASSERT(cs->IsBCDebuggerStub());
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate());
return result;
}
GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args)
GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
GateRef hirGate)
{
GateRef target = IntPtr(index);
const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
@ -450,23 +455,29 @@ GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, con
if (depend == Gate::InvalidGateRef) {
depend = label->GetDepend();
}
GateRef result = Call(cs, glue, target, depend, args);
GateRef filteredHirGate = Circuit::NullGate();
if (GetCircuit()->IsOptimizedJSFunctionFrame()) {
ASSERT(hirGate != Circuit::NullGate());
filteredHirGate = hirGate;
}
GateRef result = Call(cs, glue, target, depend, args, filteredHirGate);
return result;
}
GateRef CircuitBuilder::CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntimeWithArgv));
GateRef target = IntPtr(index);
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
ASSERT(cs->IsRuntimeVAStub());
GateRef result = Call(cs, glue, target, depend, {argc, argv});
GateRef result = Call(cs, glue, target, depend, {argc, argv}, Circuit::NullGate());
return result;
}
// call operation
GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args)
GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
GateRef hirGate)
{
const CallSignature *cs = RuntimeStubCSigns::Get(index);
ASSERT(cs->IsRuntimeNGCStub());
@ -475,23 +486,35 @@ GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend,
if (depend == Gate::InvalidGateRef) {
depend = label->GetDepend();
}
GateRef result = Call(cs, glue, target, depend, args);
GateRef filteredHirGate = Circuit::NullGate();
if (GetCircuit()->IsOptimizedJSFunctionFrame() && RuntimeStubCSigns::IsAsmStub(index)) {
ASSERT(hirGate != Circuit::NullGate());
filteredHirGate = hirGate;
}
GateRef result = Call(cs, glue, target, depend, args, filteredHirGate);
return result;
}
GateRef CircuitBuilder::CallStub(GateRef glue, int index, const std::vector<GateRef> &args)
GateRef CircuitBuilder::CallStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args)
{
const CallSignature *cs = CommonStubCSigns::Get(index);
ASSERT(cs->IsCommonStub());
GateRef target = IntPtr(index);
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
GateRef result;
if (GetCircuit()->IsOptimizedJSFunctionFrame()) {
ASSERT(hirGate != Circuit::NullGate());
result = Call(cs, glue, target, depend, args, hirGate);
} else {
result = Call(cs, glue, target, depend, args, Circuit::NullGate());
}
return result;
}
GateRef CircuitBuilder::CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, bool isNew)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
int index = 0;
if (!isNew) {
index = static_cast<int>(RTSTUB_ID(PushCallArgsAndDispatchNative));
@ -505,16 +528,23 @@ GateRef CircuitBuilder::CallBuiltinRuntime(GateRef glue, GateRef depend, const s
if (depend == Gate::InvalidGateRef) {
depend = label->GetDepend();
}
GateRef result = Call(cs, glue, target, depend, args);
GateRef result = Call(cs, glue, target, depend, args, Circuit::NullGate());
return result;
}
GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
const std::vector<GateRef> &args)
const std::vector<GateRef> &args, GateRef hirGate)
{
std::vector<GateRef> inputs { depend, target, glue };
inputs.insert(inputs.end(), args.begin(), args.end());
auto numValuesIn = args.size() + 2; // 2: target & glue
if (GetCircuit()->IsOptimizedJSFunctionFrame() && hirGate != Circuit::NullGate()) {
GateRef pcOffset = (acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE) ?
Int64(acc_.GetPcOffset(hirGate)) : Int64(0);
inputs.emplace_back(pcOffset);
numValuesIn += 1;
}
const GateMetaData* meta = nullptr;
if (cs->IsCommonStub()) {
meta = circuit_->Call(numValuesIn);
@ -554,7 +584,7 @@ void CircuitBuilder::Store(VariableType type, GateRef glue, GateRef base, GateRe
MachineType::NOVALUE, { depend, value, ptr }, type.GetGateType());
label->SetDepend(result);
if (type == VariableType::JS_POINTER() || type == VariableType::JS_ANY()) {
CallStub(glue, CommonStubCSigns::SetValueWithBarrier, { glue, base, offset, value });
CallStub(glue, base, CommonStubCSigns::SetValueWithBarrier, { glue, base, offset, value });
}
}
@ -736,15 +766,16 @@ GateRef CircuitBuilder::GetConstPool(GateRef jsFunc)
return Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
}
GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef jsFunc, GateRef index, ConstPoolType type)
GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef jsFunc, GateRef index,
ConstPoolType type)
{
GateRef constPool = GetConstPool(jsFunc);
GateRef module = GetModuleFromFunction(jsFunc);
return GetObjectFromConstPool(glue, constPool, module, index, type);
return GetObjectFromConstPool(glue, hirGate, constPool, module, index, type);
}
GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool, GateRef module, GateRef index,
ConstPoolType type)
GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module,
GateRef index, ConstPoolType type)
{
Label entry(env_);
SubCfgEntry(&entry);
@ -759,16 +790,16 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool,
{
if (type == ConstPoolType::STRING) {
result = CallRuntime(glue, RTSTUB_ID(GetStringFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index) });
{ constPool, Int32ToTaggedInt(index) }, hirGate);
} else if (type == ConstPoolType::ARRAY_LITERAL) {
result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index), module });
{ constPool, Int32ToTaggedInt(index), module }, hirGate);
} else if (type == ConstPoolType::OBJECT_LITERAL) {
result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index), module });
{ constPool, Int32ToTaggedInt(index), module }, hirGate);
} else {
result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index) });
{ constPool, Int32ToTaggedInt(index) }, hirGate);
}
Jump(&exit);
}
@ -780,7 +811,7 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool,
Bind(&isInt);
{
result = CallRuntime(glue, RTSTUB_ID(GetMethodFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index) });
{ constPool, Int32ToTaggedInt(index) }, hirGate);
Jump(&exit);
}
} else if (type == ConstPoolType::ARRAY_LITERAL) {
@ -789,7 +820,7 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool,
Bind(&isAOTLiteralInfo);
{
result = CallRuntime(glue, RTSTUB_ID(GetArrayLiteralFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index), module });
{ constPool, Int32ToTaggedInt(index), module }, hirGate);
Jump(&exit);
}
} else if (type == ConstPoolType::OBJECT_LITERAL) {
@ -798,7 +829,7 @@ GateRef CircuitBuilder::GetObjectFromConstPool(GateRef glue, GateRef constPool,
Bind(&isAOTLiteralInfo);
{
result = CallRuntime(glue, RTSTUB_ID(GetObjectLiteralFromCache), Gate::InvalidGateRef,
{ constPool, Int32ToTaggedInt(index), module });
{ constPool, Int32ToTaggedInt(index), module }, hirGate);
Jump(&exit);
}
} else {
@ -838,6 +869,7 @@ GateRef CircuitBuilder::TryGetHashcodeFromString(GateRef string)
GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
{
ASSERT(!GetCircuit()->IsOptimizedJSFunctionFrame());
Label subentry(env_);
SubCfgEntry(&subentry);
Label noRawHashcode(env_);
@ -847,7 +879,8 @@ GateRef CircuitBuilder::GetHashcodeFromString(GateRef glue, GateRef value)
Branch(Int32Equal(*hashcode, Int32(0)), &noRawHashcode, &exit);
Bind(&noRawHashcode);
{
hashcode = GetInt32OfTInt(CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }));
hashcode = GetInt32OfTInt(
CallRuntime(glue, RTSTUB_ID(ComputeHashcode), Gate::InvalidGateRef, { value }, Circuit::NullGate()));
Store(VariableType::INT32(), glue, value, IntPtr(EcmaString::HASHCODE_OFFSET), *hashcode);
Jump(&exit);
}

View File

@ -293,12 +293,12 @@ public:
GateRef CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args);
GateRef CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args);
GateRef CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv);
GateRef CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args);
GateRef CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args);
GateRef CallStub(GateRef glue, int index, const std::vector<GateRef> &args);
GateRef CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args, GateRef hirGate);
GateRef CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args, GateRef hirGate);
GateRef CallStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args);
GateRef CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, bool isNew = false);
GateRef Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
const std::vector<GateRef> &args);
const std::vector<GateRef> &args, GateRef hirGate);
// memory
inline GateRef Load(VariableType type, GateRef base, GateRef offset);
@ -469,8 +469,8 @@ public:
GateRef value, GateRef attrOffset, VariableType type);
void SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value);
GateRef GetConstPool(GateRef jsFunc);
GateRef GetObjectFromConstPool(GateRef glue, GateRef jsFunc, GateRef index, ConstPoolType type);
GateRef GetObjectFromConstPool(GateRef glue, GateRef constPool, GateRef module, GateRef index,
GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef jsFunc, GateRef index, ConstPoolType type);
GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module, GateRef index,
ConstPoolType type);
void SetEnvironment(Environment *env)
{

View File

@ -100,6 +100,24 @@ void NotEqualStubBuilder::GenerateCircuit()
Return(operationBuilder.NotEqual(glue, x, y));
}
void StrictEqualStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2); // 2: 3rd argument
OperationsStubBuilder operationBuilder(this);
Return(operationBuilder.StrictEqual(glue, x, y));
}
void StrictNotEqualStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
GateRef x = TaggedArgument(1);
GateRef y = TaggedArgument(2); // 2: 3rd argument
OperationsStubBuilder operationBuilder(this);
Return(operationBuilder.StrictNotEqual(glue, x, y));
}
void LessStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
@ -642,6 +660,30 @@ void ConstructorCheckStubBuilder::GenerateCircuit()
Return(ConstructorCheck(glue, ctor, value, thisObj));
}
void CreateEmptyArrayStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
NewObjectStubBuilder newBuilder(this);
Return(newBuilder.CreateEmptyArray(glue));
}
void CreateArrayWithBufferStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
GateRef index = Int32Argument(1);
GateRef jsFunc = TaggedArgument(2); // 2 : 3rd para
NewObjectStubBuilder newBuilder(this);
Return(newBuilder.CreateArrayWithBuffer(glue, index, jsFunc));
}
void NewJSObjectStubBuilder::GenerateCircuit()
{
GateRef glue = PtrArgument(0);
GateRef hclass = TaggedArgument(1);
NewObjectStubBuilder newBuilder(this);
Return(newBuilder.NewJSObject(glue, hclass));
}
void JsProxyCallInternalStubBuilder::GenerateCircuit()
{
auto env = GetEnvironment();

View File

@ -28,6 +28,8 @@ namespace panda::ecmascript::kungfu {
V(Mod) \
V(Equal) \
V(NotEqual) \
V(StrictEqual) \
V(StrictNotEqual) \
V(Less) \
V(LessEq) \
V(Greater) \
@ -71,6 +73,9 @@ namespace panda::ecmascript::kungfu {
V(GetUnmapedArgs) \
V(NewThisObjectChecked) \
V(ConstructorCheck) \
V(CreateEmptyArray) \
V(CreateArrayWithBuffer) \
V(NewJSObject) \
V(JsProxyCallInternal)
#define COMMON_STUB_ID_LIST(V) \

View File

@ -175,11 +175,11 @@ const ChunkVector<char>& GateAccessor::GetConstantString(GateRef gate) const
return gatePtr->GetStringMetaData()->GetString();
}
uint32_t GateAccessor::GetBytecodeIndex(GateRef gate) const
uint32_t GateAccessor::GetPcOffset(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::JS_BYTECODE);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetJSBytecodeMetaData()->GetBytecodeIndex();
return gatePtr->GetJSBytecodeMetaData()->GetPcOffset();
}
EcmaOpcode GateAccessor::GetByteCodeOpcode(GateRef gate) const

View File

@ -380,7 +380,7 @@ public:
TypedUnaryAccessor GetTypedUnOp(GateRef gate) const;
uint64_t GetConstantValue(GateRef gate) const;
const ChunkVector<char>& GetConstantString(GateRef gate) const;
uint32_t GetBytecodeIndex(GateRef gate) const;
uint32_t GetPcOffset(GateRef gate) const;
EcmaOpcode GetByteCodeOpcode(GateRef gate) const;
void Print(GateRef gate) const;
void ShortPrint(GateRef gate) const;

View File

@ -461,9 +461,9 @@ inline std::ostream& operator<<(std::ostream& os, OpCode opcode)
class JSBytecodeMetaData : public GateMetaData {
public:
explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t bcIndex, GateFlags flags)
explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags)
: GateMetaData(OpCode::JS_BYTECODE, flags, 1, 1, valuesIn),
opcode_(opcode), bcIndex_(bcIndex)
opcode_(opcode), pcOffset_(pcOffset)
{
SetKind(GateMetaData::Kind::JSBYTECODE);
}
@ -474,9 +474,9 @@ public:
return static_cast<const JSBytecodeMetaData*>(meta);
}
uint32_t GetBytecodeIndex() const
uint32_t GetPcOffset() const
{
return bcIndex_;
return pcOffset_;
}
EcmaOpcode GetByteCodeOpcode() const
@ -485,7 +485,7 @@ public:
}
private:
EcmaOpcode opcode_;
uint32_t bcIndex_;
uint32_t pcOffset_;
};
class OneParameterMetaData : public GateMetaData {

View File

@ -108,9 +108,9 @@ public:
#undef DECLARE_GATE_META
explicit GateMetaBuilder(Chunk* chunk);
const GateMetaData* JSBytecode(size_t valuesIn, EcmaOpcode opcode, uint32_t bcIndex, GateFlags flags)
const GateMetaData* JSBytecode(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags)
{
return new (chunk_) JSBytecodeMetaData(valuesIn, opcode, bcIndex, flags);
return new (chunk_) JSBytecodeMetaData(valuesIn, opcode, pcOffset, flags);
}
const GateMetaData* TypedBinaryOp(uint64_t value, TypedBinOp binOp)

View File

@ -399,16 +399,16 @@ DECLARE_ASM_HANDLER(HandleCreateemptyobject)
DECLARE_ASM_HANDLER(HandleCreateemptyarrayImm8)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateEmptyArray), {});
varAcc = res;
NewObjectStubBuilder newBuilder(this);
varAcc = newBuilder.CreateEmptyArray(glue);
DISPATCH_WITH_ACC(CREATEEMPTYARRAY_IMM8);
}
DECLARE_ASM_HANDLER(HandleCreateemptyarrayImm16)
{
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateEmptyArray), {});
varAcc = res;
NewObjectStubBuilder newBuilder(this);
varAcc = newBuilder.CreateEmptyArray(glue);
DISPATCH_WITH_ACC(CREATEEMPTYARRAY_IMM16);
}
@ -892,55 +892,25 @@ DECLARE_ASM_HANDLER(HandleInstanceofImm8V8)
DECLARE_ASM_HANDLER(HandleStrictnoteqImm8V8)
{
auto env = GetEnvironment();
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
GateRef v0 = ReadInst8_1(pc);
GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0));
Label strictEqual(env);
Label notStrictEqual(env);
Label dispatch(env);
Branch(FastStrictEqual(glue, left, acc), &strictEqual, &notStrictEqual);
Bind(&strictEqual);
{
varAcc = TaggedFalse();
Jump(&dispatch);
}
Bind(&notStrictEqual);
{
varAcc = TaggedTrue();
Jump(&dispatch);
}
Bind(&dispatch);
OperationsStubBuilder builder(this);
varAcc = builder.StrictNotEqual(glue, left, acc);
DISPATCH_WITH_ACC(STRICTNOTEQ_IMM8_V8);
}
DECLARE_ASM_HANDLER(HandleStricteqImm8V8)
{
auto env = GetEnvironment();
DEFVARIABLE(varAcc, VariableType::JS_ANY(), acc);
GateRef v0 = ReadInst8_1(pc);
GateRef left = GetVregValue(sp, ZExtInt8ToPtr(v0));
Label strictEqual(env);
Label notStrictEqual(env);
Label dispatch(env);
Branch(FastStrictEqual(glue, left, acc), &strictEqual, &notStrictEqual);
Bind(&strictEqual);
{
varAcc = TaggedTrue();
Jump(&dispatch);
}
Bind(&notStrictEqual);
{
varAcc = TaggedFalse();
Jump(&dispatch);
}
Bind(&dispatch);
OperationsStubBuilder builder(this);
varAcc = builder.StrictEqual(glue, left, acc);
DISPATCH_WITH_ACC(STRICTEQ_IMM8_V8);
}
@ -3780,9 +3750,9 @@ DECLARE_ASM_HANDLER(HandleCreatearraywithbufferImm8Id16)
{
GateRef imm = ZExtInt16ToInt32(ReadInst16_1(pc));
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
GateRef module = GetModuleFromFunction(currentFunc);
GateRef result = GetArrayLiteralFromConstPool(glue, constpool, imm, module);
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateArrayWithBuffer), { result });
NewObjectStubBuilder newBuilder(this);
GateRef res = newBuilder.CreateArrayWithBuffer(glue, imm, currentFunc);
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(CREATEARRAYWITHBUFFER_IMM8_ID16));
}
@ -3790,9 +3760,9 @@ DECLARE_ASM_HANDLER(HandleCreatearraywithbufferImm16Id16)
{
GateRef imm = ZExtInt16ToInt32(ReadInst16_2(pc));
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
GateRef module = GetModuleFromFunction(currentFunc);
GateRef result = GetArrayLiteralFromConstPool(glue, constpool, imm, module);
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateArrayWithBuffer), { result });
NewObjectStubBuilder newBuilder(this);
GateRef res = newBuilder.CreateArrayWithBuffer(glue, imm, currentFunc);
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(CREATEARRAYWITHBUFFER_IMM16_ID16));
}
@ -3800,9 +3770,9 @@ DECLARE_ASM_HANDLER(HandleDeprecatedCreatearraywithbufferPrefImm16)
{
GateRef imm = ZExtInt16ToInt32(ReadInst16_1(pc));
GateRef currentFunc = GetFunctionFromFrame(GetFrame(sp));
GateRef module = GetModuleFromFunction(currentFunc);
GateRef result = GetArrayLiteralFromConstPool(glue, constpool, imm, module);
GateRef res = CallRuntime(glue, RTSTUB_ID(CreateArrayWithBuffer), { result });
NewObjectStubBuilder newBuilder(this);
GateRef res = newBuilder.CreateArrayWithBuffer(glue, imm, currentFunc);
CHECK_EXCEPTION_WITH_ACC(res, INT_PTR(DEPRECATED_CREATEARRAYWITHBUFFER_PREF_IMM16));
}

View File

@ -512,16 +512,21 @@ LLVMValueRef LLVMIRBuilder::GetFunctionFromGlobalValue([[maybe_unused]] LLVMValu
return callee;
}
bool LLVMIRBuilder::IsInterpreted()
bool LLVMIRBuilder::IsInterpreted() const
{
return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
}
bool LLVMIRBuilder::IsOptimized()
bool LLVMIRBuilder::IsOptimized() const
{
return circuit_->GetFrameType() == FrameType::OPTIMIZED_FRAME;
}
bool LLVMIRBuilder::IsOptimizedJSFunction() const
{
return circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME;
}
void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &inList)
{
ASSERT(llvmModule_ != nullptr);
@ -532,13 +537,19 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
auto kind = GetCallExceptionKind(stubIndex, OpCode::RUNTIME_CALL);
size_t actualNumArgs = 0;
LLVMValueRef pcOffset = LLVMConstInt(LLVMInt32Type(), 0, 0);
ComputeArgCountAndPCOffset(actualNumArgs, pcOffset, inList, kind);
std::vector<LLVMValueRef> params;
params.push_back(glue); // glue
const int index = static_cast<int>(acc_.GetConstantValue(inList[static_cast<int>(CallInputs::TARGET)]));
params.push_back(LLVMConstInt(LLVMInt64Type(), index, 0)); // target
params.push_back(LLVMConstInt(LLVMInt64Type(),
inList.size() - static_cast<size_t>(CallInputs::FIRST_PARAMETER), 0)); // argc
for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < inList.size(); ++paraIdx) {
actualNumArgs - static_cast<size_t>(CallInputs::FIRST_PARAMETER), 0)); // argc
for (size_t paraIdx = static_cast<size_t>(CallInputs::FIRST_PARAMETER); paraIdx < actualNumArgs; ++paraIdx) {
GateRef gateTmp = inList[paraIdx];
params.push_back(gate2LValue_[gateTmp]);
}
@ -547,7 +558,18 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
std::string targetName = RuntimeStubCSigns::GetRTName(index);
LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset, targetName);
callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
LLVMValueRef runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), inList.size(), "");
LLVMValueRef runtimeCall = nullptr;
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
std::vector<LLVMValueRef> values;
auto pcIndex = LLVMConstInt(LLVMInt64Type(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
values.push_back(pcIndex);
values.push_back(pcOffset);
runtimeCall = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs,
"", values.data(), values.size());
} else {
runtimeCall = LLVMBuildCall2(builder_, funcType, callee, params.data(), actualNumArgs, "");
}
if (!compCfg_->Is32Bit()) { // Arm32 not support webkit jscc calling convention
LLVMSetInstructionCallConv(runtimeCall, LLVMWebKitJSCallConv);
}
@ -686,12 +708,13 @@ LLVMValueRef LLVMIRBuilder::GetBuiltinsStubOffset(LLVMValueRef glue)
return LLVMConstInt(glueType, JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()), 0);
}
void LLVMIRBuilder::ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset,
void LLVMIRBuilder::ComputeArgCountAndPCOffset(size_t &actualNumArgs, LLVMValueRef &pcOffset,
const std::vector<GateRef> &inList, CallExceptionKind kind)
{
if (kind == CallExceptionKind::HAS_BC_OFFSET) {
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
actualNumArgs = inList.size() - 1;
bcOffset = gate2LValue_[inList[actualNumArgs]];
pcOffset = gate2LValue_[inList[actualNumArgs]];
ASSERT(acc_.GetOpCode(inList[actualNumArgs]) == OpCode::CONSTANT);
} else {
actualNumArgs = inList.size();
}
@ -699,9 +722,11 @@ void LLVMIRBuilder::ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueR
LLVMIRBuilder::CallExceptionKind LLVMIRBuilder::GetCallExceptionKind(size_t index, OpCode op) const
{
bool hasBcOffset = (callConv_ == CallSignature::CallConv::WebKitJSCallConv && op == OpCode::NOGC_RUNTIME_CALL &&
index == RTSTUB_ID(JSCall));
return hasBcOffset ? CallExceptionKind::HAS_BC_OFFSET : CallExceptionKind::NO_BC_OFFSET;
bool hasPcOffset = IsOptimizedJSFunction() &&
((op == OpCode::NOGC_RUNTIME_CALL && (kungfu::RuntimeStubCSigns::IsAsmStub(index))) ||
(op == OpCode::CALL) ||
(op == OpCode::RUNTIME_CALL));
return hasPcOffset ? CallExceptionKind::HAS_PC_OFFSET : CallExceptionKind::NO_PC_OFFSET;
}
void LLVMIRBuilder::UpdateLeaveFrame(LLVMValueRef glue)
@ -724,13 +749,14 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
LLVMValueRef rtoffset;
LLVMValueRef rtbaseoffset;
LLVMValueRef callee;
CallExceptionKind kind = CallExceptionKind::NO_BC_OFFSET;
CallExceptionKind kind = CallExceptionKind::NO_PC_OFFSET;
if (op == OpCode::CALL) {
const size_t index = acc_.GetConstantValue(inList[targetIndex]);
calleeDescriptor = CommonStubCSigns::Get(index);
rtoffset = GetCoStubOffset(glue, index);
rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
callee = GetFunction(glue, calleeDescriptor, rtbaseoffset);
kind = GetCallExceptionKind(index, op);
} else if (op == OpCode::NOGC_RUNTIME_CALL) {
UpdateLeaveFrame(glue);
const size_t index = acc_.GetConstantValue(inList[targetIndex]);
@ -765,8 +791,8 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
int extraParameterCnt = 0;
size_t actualNumArgs = 0;
LLVMValueRef bcOffset = LLVMConstInt(LLVMInt32Type(), 0, 0);
ComputeArgCountAndBCOffset(actualNumArgs, bcOffset, inList, kind);
LLVMValueRef pcOffset = LLVMConstInt(LLVMInt32Type(), 0, 0);
ComputeArgCountAndPCOffset(actualNumArgs, pcOffset, inList, kind);
// then push the actual parameter for js function call
for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
@ -790,11 +816,11 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
LLVMValueRef call = nullptr;
LLVMTypeRef funcType = llvmModule_->GenerateFuncType(params, calleeDescriptor);
callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
if (kind == CallExceptionKind::HAS_BC_OFFSET) {
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
std::vector<LLVMValueRef> values;
auto bcIndex = LLVMConstInt(LLVMInt64Type(), static_cast<int>(SpecVregIndex::BC_OFFSET_INDEX), 1);
values.push_back(bcIndex);
values.push_back(bcOffset);
auto pcIndex = LLVMConstInt(LLVMInt64Type(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
values.push_back(pcIndex);
values.push_back(pcOffset);
call = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt,
"", values.data(), values.size());
} else {

View File

@ -302,8 +302,9 @@ private:
const std::string &realName = "") const;
LLVMValueRef GetFunctionFromGlobalValue(LLVMValueRef glue, const CallSignature *signature,
LLVMValueRef reloc) const;
bool IsInterpreted();
bool IsOptimized();
bool IsInterpreted() const;
bool IsOptimized() const;
bool IsOptimizedJSFunction() const;
void SetGCLeafFunction(LLVMValueRef call);
void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call);
bool IsHeapPointerType(LLVMTypeRef valueType);
@ -316,8 +317,8 @@ private:
FIRST_PARAMETER
};
enum class CallExceptionKind : bool {
HAS_BC_OFFSET = true,
NO_BC_OFFSET = false
HAS_PC_OFFSET = true,
NO_PC_OFFSET = false
};
LLVMRealPredicate ConvertLLVMPredicateFromFCMP(FCmpCondition cond);
LLVMIntPredicate ConvertLLVMPredicateFromICMP(ICmpCondition cond);
@ -330,7 +331,7 @@ private:
LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue);
LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue);
CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector<GateRef> &inList,
void ComputeArgCountAndPCOffset(size_t &actualNumArgs, LLVMValueRef &pcOffset, const std::vector<GateRef> &inList,
CallExceptionKind kind);
void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);

View File

@ -105,6 +105,23 @@ void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hc
}
}
GateRef NewObjectStubBuilder::NewJSObject(GateRef glue, GateRef hclass)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
SetGlue(glue);
NewJSObject(&result, &exit, hclass);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
void NewObjectStubBuilder::NewArgumentsList(Variable *result, Label *exit,
GateRef sp, GateRef startIdx, GateRef numArgs)
{
@ -394,4 +411,58 @@ GateRef NewObjectStubBuilder::NewThisObjectChecked(GateRef glue, GateRef ctor)
env->SubCfgExit();
return ret;
}
GateRef NewObjectStubBuilder::CreateEmptyArray(GateRef glue)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
GateRef glueGlobalEnvOffset = IntPtr(JSThread::GlueData::GetGlueGlobalEnvOffset(env->Is32Bit()));
GateRef glueGlobalEnv = Load(VariableType::NATIVE_POINTER(), glue, glueGlobalEnvOffset);
auto arrayFunc = GetGlobalEnvValue(VariableType::JS_ANY(), glueGlobalEnv, GlobalEnv::ARRAY_FUNCTION_INDEX);
auto hclass = Load(VariableType::JS_POINTER(), arrayFunc, IntPtr(JSFunction::PROTO_OR_DYNCLASS_OFFSET));
GateRef size = GetObjectSizeFromHClass(hclass);
auto emptyArray = GetGlobalConstantValue(VariableType::JS_POINTER(), glue, ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX);
SetParameters(glue, size);
NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, emptyArray, hclass, true);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef NewObjectStubBuilder::CreateArrayWithBuffer(GateRef glue, GateRef index, GateRef jsFunc)
{
(void)glue;
(void)index;
(void)jsFunc;
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
GateRef method = GetMethodFromFunction(jsFunc);
GateRef constPool = Load(VariableType::JS_ANY(), method, IntPtr(Method::CONSTANT_POOL_OFFSET));
GateRef module = GetModuleFromFunction(jsFunc);
auto obj = GetArrayLiteralFromConstPool(glue, constPool, index, module);
auto hclass = LoadHClass(obj);
GateRef size = GetObjectSizeFromHClass(hclass);
SetParameters(glue, size);
NewJSArrayLiteral(&result, &exit, RegionSpaceFlag::IN_YOUNG_SPACE, obj, hclass, false);
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
} // namespace panda::ecmascript::kungfu

View File

@ -35,13 +35,14 @@ public:
size_ = size;
}
void SetGule(GateRef glue)
void SetGlue(GateRef glue)
{
glue_ = glue;
}
void NewLexicalEnv(Variable *result, Label *exit, GateRef numSlots, GateRef parent);
void NewJSObject(Variable *result, Label *exit, GateRef hclass);
GateRef NewJSObject(GateRef glue, GateRef hclass);
void NewArgumentsList(Variable *result, Label *exit, GateRef sp, GateRef startIdx, GateRef numArgs);
void NewArgumentsObj(Variable *result, Label *exit, GateRef argumentsList, GateRef numArgs);
void AllocLineStringObject(Variable *result, Label *exit, GateRef length, bool compressed);
@ -51,6 +52,9 @@ public:
void InitializeWithSpeicalValue(Label *exit, GateRef object, GateRef value, GateRef start, GateRef end);
GateRef FastNewThisObject(GateRef glue, GateRef ctor);
GateRef NewThisObjectChecked(GateRef glue, GateRef ctor);
GateRef CreateEmptyArray(GateRef glue);
GateRef CreateArrayWithBuffer(GateRef glue, GateRef index, GateRef jsFunc);
private:
void AllocateInYoung(Variable *result, Label *exit);
void InitializeTaggedArrayWithSpeicalValue(Label *exit,

View File

@ -81,6 +81,46 @@ GateRef OperationsStubBuilder::NotEqual(GateRef glue, GateRef left, GateRef righ
return ret;
}
GateRef OperationsStubBuilder::StrictEqual(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
Label notStrictEqual(env);
DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue());
Branch(FastStrictEqual(glue, left, right), &exit, &notStrictEqual);
Bind(&notStrictEqual);
{
result = TaggedFalse();
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef OperationsStubBuilder::StrictNotEqual(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label exit(env);
Label strictEqual(env);
DEFVARIABLE(result, VariableType::JS_ANY(), TaggedTrue());
Branch(FastStrictEqual(glue, left, right), &strictEqual, &exit);
Bind(&strictEqual);
{
result = TaggedFalse();
Jump(&exit);
}
Bind(&exit);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef OperationsStubBuilder::Less(GateRef glue, GateRef left, GateRef right)
{
auto env = GetEnvironment();

View File

@ -36,6 +36,8 @@ public:
// binary op
GateRef Equal(GateRef glue, GateRef left, GateRef right);
GateRef NotEqual(GateRef glue, GateRef left, GateRef right);
GateRef StrictEqual(GateRef glue, GateRef left, GateRef right);
GateRef StrictNotEqual(GateRef glue, GateRef left, GateRef right);
GateRef Less(GateRef glue, GateRef left, GateRef right);
GateRef LessEq(GateRef glue, GateRef left, GateRef right);
GateRef Greater(GateRef glue, GateRef left, GateRef right);

View File

@ -89,6 +89,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
}
Circuit circuit(vm_->GetNativeAreaAllocator(), cmpCfg->Is64Bit());
circuit.SetFrameType(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
BytecodeCircuitBuilder builder(jsPandaFile, methodLiteral, methodPCInfo, tsManager, &circuit,
info.GetByteCodes(), hasTypes, enableMethodLog && log_->OutputCIR(),
EnableTypeLowering(), fullName, recordName);

View File

@ -37,8 +37,20 @@ public:
NUM_OF_RTSTUBS_WITHOUT_GC
};
enum AsmStubID {
#define DEF_RUNTIME_STUB_ID(name) ASM_STUB_ID_##name,
RUNTIME_ASM_STUB_LIST(DEF_RUNTIME_STUB_ID)
#undef DEF_RUNTIME_STUB_ID
NUM_OF_ASM_STUBS
};
static void Initialize();
static bool IsAsmStub(uint32_t index)
{
return index < AsmStubID::NUM_OF_ASM_STUBS;
}
static void GetASMCSigns(std::vector<const CallSignature*>& callSigns);
static const CallSignature *Get(size_t index)
@ -63,6 +75,10 @@ RUNTIME_STUB_LIST(DEF_STUB_NAME)
private:
static CallSignature callSigns_[NUM_OF_RTSTUBS_WITHOUT_GC];
};
static_assert(static_cast<int>(kungfu::RuntimeStubCSigns::ID_CallRuntime) ==
static_cast<int>(kungfu::RuntimeStubCSigns::ASM_STUB_ID_CallRuntime));
static_assert(static_cast<int>(kungfu::RuntimeStubCSigns::ID_AsmInterpreterEntry) ==
static_cast<int>(kungfu::RuntimeStubCSigns::ASM_STUB_ID_AsmInterpreterEntry));
#define RTSTUB_ID(name) kungfu::RuntimeStubCSigns::ID_##name
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_RT_CALL_SIGNATURE_H

File diff suppressed because it is too large Load Diff

View File

@ -280,8 +280,8 @@ private:
void LowerDefineMethod(GateRef gate, GateRef jsFunc);
void LowerGetUnmappedArgs(GateRef gate, GateRef actualArgc);
void LowerCopyRestArgs(GateRef gate, GateRef actualArgc);
GateRef LowerCallRuntime(int index, const std::vector<GateRef> &args, bool useLabel = false);
GateRef LowerCallNGCRuntime(int index, const std::vector<GateRef> &args, bool useLabel = false);
GateRef LowerCallRuntime(GateRef gate, int index, const std::vector<GateRef> &args, bool useLabel = false);
GateRef LowerCallNGCRuntime(GateRef gate, int index, const std::vector<GateRef> &args, bool useLabel = false);
int32_t ComputeCallArgc(GateRef gate, EcmaOpcode op);
void LowerCreateAsyncGeneratorObj(GateRef gate);
void LowerAsyncGeneratorResolve(GateRef gate);

View File

@ -194,7 +194,7 @@ inline void StubBuilder::Bind(Label *label)
inline GateRef StubBuilder::CallRuntime(GateRef glue, int index, const std::initializer_list<GateRef>& args)
{
SavePcIfNeeded(glue);
GateRef result = env_->GetBuilder()->CallRuntime(glue, index, Gate::InvalidGateRef, args);
GateRef result = env_->GetBuilder()->CallRuntime(glue, index, Gate::InvalidGateRef, args, Circuit::NullGate());
return result;
}
@ -207,14 +207,14 @@ inline GateRef StubBuilder::CallRuntime(GateRef glue, int index, GateRef argc, G
inline GateRef StubBuilder::CallNGCRuntime(GateRef glue, int index, const std::initializer_list<GateRef>& args)
{
GateRef result = env_->GetBuilder()->CallNGCRuntime(glue, index, Gate::InvalidGateRef, args);
GateRef result = env_->GetBuilder()->CallNGCRuntime(glue, index, Gate::InvalidGateRef, args, Circuit::NullGate());
return result;
}
inline GateRef StubBuilder::CallStub(GateRef glue, int index, const std::initializer_list<GateRef>& args)
{
SavePcIfNeeded(glue);
GateRef result = env_->GetBuilder()->CallStub(glue, index, args);
GateRef result = env_->GetBuilder()->CallStub(glue, Circuit::NullGate(), index, args);
return result;
}
@ -2021,6 +2021,16 @@ inline GateRef StubBuilder::GetGlobalObject(GateRef glue)
return Load(VariableType::JS_ANY(), glue, offset);
}
inline GateRef StubBuilder::GetMethodFromFunction(GateRef function)
{
return env_->GetBuilder()->GetMethodFromFunction(function);
}
inline GateRef StubBuilder::GetModuleFromFunction(GateRef function)
{
return env_->GetBuilder()->GetModuleFromFunction(function);
}
inline GateRef StubBuilder::GetEntryIndexOfGlobalDictionary(GateRef entry)
{
return Int32Add(Int32(OrderTaggedHashTable<GlobalDictionary>::TABLE_HEADER_SIZE),

View File

@ -4331,23 +4331,29 @@ GateRef StubBuilder::GetGlobalOwnProperty(GateRef glue, GateRef receiver, GateRe
GateRef StubBuilder::GetStringFromConstPool(GateRef glue, GateRef constpool, GateRef index)
{
GateRef module = Circuit::NullGate();
return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::STRING);
GateRef hirGate = Circuit::NullGate();
return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, module, index, ConstPoolType::STRING);
}
GateRef StubBuilder::GetMethodFromConstPool(GateRef glue, GateRef constpool, GateRef index)
{
GateRef module = Circuit::NullGate();
return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::METHOD);
GateRef hirGate = Circuit::NullGate();
return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, module, index, ConstPoolType::METHOD);
}
GateRef StubBuilder::GetArrayLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
{
return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::ARRAY_LITERAL);
GateRef hirGate = Circuit::NullGate();
return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, module, index,
ConstPoolType::ARRAY_LITERAL);
}
GateRef StubBuilder::GetObjectLiteralFromConstPool(GateRef glue, GateRef constpool, GateRef index, GateRef module)
{
return env_->GetBuilder()->GetObjectFromConstPool(glue, constpool, module, index, ConstPoolType::OBJECT_LITERAL);
GateRef hirGate = Circuit::NullGate();
return env_->GetBuilder()->GetObjectFromConstPool(glue, hirGate, constpool, module, index,
ConstPoolType::OBJECT_LITERAL);
}
GateRef StubBuilder::JSAPIContainerGet(GateRef glue, GateRef receiver, GateRef index)

View File

@ -503,6 +503,8 @@ public:
inline GateRef GetBuiltinId(GateRef method);
void SetLexicalEnvToFunction(GateRef glue, GateRef object, GateRef lexicalEnv);
GateRef GetGlobalObject(GateRef glue);
GateRef GetMethodFromFunction(GateRef function);
GateRef GetModuleFromFunction(GateRef function);
GateRef GetEntryIndexOfGlobalDictionary(GateRef entry);
GateRef GetBoxFromGlobalDictionary(GateRef object, GateRef entry);
GateRef GetValueFromGlobalDictionary(GateRef object, GateRef entry);

View File

@ -33,13 +33,13 @@ void FooAOTStubBuilder::GenerateCircuit()
GateRef thisObj = TaggedArgument(5);
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
(void)calltarget;
GateRef barIndex = IntToTaggedInt(Int32(CommonStubCSigns::BarAOT));
GateRef numArgs = IntToTaggedInt(Int32(2));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef result =
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, barfunc, newtarget, thisObj, a, b, bcOffset});
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, barfunc, newtarget, thisObj, a, b, pcOffset});
Return(result);
}
@ -67,13 +67,13 @@ void Foo1AOTStubBuilder::GenerateCircuit()
GateRef thisObj = TaggedArgument(5);
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
(void)calltarget;
GateRef barIndex = IntToTaggedInt(Int32(CommonStubCSigns::Bar1AOT));
GateRef numArgs = IntToTaggedInt(Int32(3));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef result =
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, barfunc, newtarget, thisObj, a, b, bcOffset});
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, barfunc, newtarget, thisObj, a, b, pcOffset});
Return(result);
}
@ -108,14 +108,14 @@ void Foo2AOTStubBuilder::GenerateCircuit()
GateRef thisObj = TaggedArgument(5);
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
(void)calltarget;
GateRef actualArgC = Int64Add(argc, Int64(1));
GateRef barIndex = IntToTaggedInt(Int32(CommonStubCSigns::BarAOT));
GateRef numArgs = IntToTaggedInt(Int32(2));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, actualArgC, barfunc, newtarget, thisObj,
a, b, Undefined(), bcOffset});
a, b, Undefined(), pcOffset});
Return(result);
}
@ -129,12 +129,12 @@ void FooNativeAOTStubBuilder::GenerateCircuit()
GateRef thisObj = TaggedArgument(5);
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
(void)calltarget;
GateRef actualArgC = Int64Add(argc, Int64(1));
GateRef printfunc = CallRuntime(glue, RTSTUB_ID(GetPrintFunc), {});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, actualArgC, printfunc, newtarget, thisObj,
a, b, Undefined(), bcOffset});
a, b, Undefined(), pcOffset});
Return(result);
}
@ -149,16 +149,16 @@ void FooBoundAOTStubBuilder::GenerateCircuit()
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bindArguments = IntToTaggedInt(Int32(37));
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
(void)calltarget;
GateRef numArgs = IntToTaggedInt(Int32(2));
GateRef barIndex = IntToTaggedInt(Int32(CommonStubCSigns::BarAOT));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef bindfunc = CallRuntime(glue, RTSTUB_ID(GetBindFunc), {barfunc});
GateRef newjsfunc = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, Int64(5), bindfunc, newtarget, barfunc,
Int64(0x02), bindArguments, bcOffset});
Int64(0x02), bindArguments, pcOffset});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, newjsfunc, newtarget, thisObj,
a, b, bcOffset});
a, b, pcOffset});
Return(result);
}
@ -172,7 +172,7 @@ void FooProxyAOTStubBuilder::GenerateCircuit()
GateRef thisObj = TaggedArgument(5);
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
GateRef barIndex = IntToTaggedInt(Int32(CommonStubCSigns::BarAOT));
GateRef numArgs = IntToTaggedInt(Int32(2));
@ -180,7 +180,7 @@ void FooProxyAOTStubBuilder::GenerateCircuit()
GateRef proxyfunc = CallRuntime(glue, RTSTUB_ID(DefineProxyFunc), {barfunc});
GateRef result =
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset});
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, proxyfunc, newtarget, thisObj, a, b, pcOffset});
Return(result);
}
@ -194,7 +194,7 @@ void FooProxy2AOTStubBuilder::GenerateCircuit()
GateRef thisObj = TaggedArgument(5);
GateRef a = TaggedArgument(6);
GateRef b = TaggedArgument(7);
GateRef bcOffset = Int32(1);
GateRef pcOffset = Int32(1);
GateRef barIndex = IntToTaggedInt(Int32(CommonStubCSigns::Bar2AOT));
GateRef numArgs = IntToTaggedInt(Int32(2));
@ -203,7 +203,7 @@ void FooProxy2AOTStubBuilder::GenerateCircuit()
GateRef proxyfunc = CallRuntime(glue, RTSTUB_ID(DefineProxyFunc2), {barfunc, proxyHandler});
GateRef result =
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset});
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, env, argc, proxyfunc, newtarget, thisObj, a, b, pcOffset});
Return(result);
}

View File

@ -855,8 +855,6 @@ void TSTypeLowering::LowerTypedNewObjRange(GateRef gate)
for (size_t i = 1; i < range; ++i) { // 1:skip ctor
args.emplace_back(acc_.GetValueIn(gate, i));
}
GateRef bcIndex = builder_.Int64(acc_.GetBytecodeIndex(gate));
args.emplace_back(bcIndex);
GateRef constructGate = builder_.Construct(args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate);
@ -888,8 +886,6 @@ void TSTypeLowering::LowerTypedSuperCall(GateRef gate, GateRef ctor, GateRef new
for (size_t i = 0; i < range; ++i) {
args.emplace_back(acc_.GetValueIn(gate, i));
}
GateRef bcIndex = builder_.Int64(acc_.GetBytecodeIndex(gate));
args.emplace_back(bcIndex);
GateRef constructGate = builder_.Construct(args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate);
@ -955,7 +951,7 @@ void TSTypeLowering::AddProfiling(GateRef gate)
GateRef mode =
builder_.Int32ToTaggedInt(builder_.Int32(static_cast<int32_t>(OptCodeProfiler::Mode::TYPED_PATH)));
GateRef profiling = builder_.CallRuntime(glue_, RTSTUB_ID(ProfileOptimizedCode), acc_.GetDep(current),
{constOpcode, mode});
{ constOpcode, mode }, gate);
acc_.SetDep(current, profiling);
builder_.SetDepend(acc_.GetDep(gate)); // set gate depend: profiling or STATE_SPLIT
}

View File

@ -392,15 +392,16 @@ void TypeLowering::LowerTypedNegOverflowCheck(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
GateRef TypeLowering::LowerCallRuntime(GateRef glue, int index, const std::vector<GateRef> &args, bool useLabel)
GateRef TypeLowering::LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
bool useLabel)
{
if (useLabel) {
GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args);
GateRef result = builder_.CallRuntime(glue, index, Gate::InvalidGateRef, args, hirGate);
return result;
} else {
const CallSignature *cs = RuntimeStubCSigns::Get(RTSTUB_ID(CallRuntime));
GateRef target = builder_.IntPtr(index);
GateRef result = builder_.Call(cs, glue, target, dependEntry_, args);
GateRef result = builder_.Call(cs, glue, target, dependEntry_, args, hirGate);
return result;
}
}
@ -694,7 +695,7 @@ void TypeLowering::LowerHeapAllocateInYoung(GateRef gate, GateRef glue)
}
builder_.Bind(&callRuntime);
{
result = LowerCallRuntime(glue, RTSTUB_ID(AllocateInYoung), {builder_.ToTaggedInt(size)}, true);
result = LowerCallRuntime(glue, gate, RTSTUB_ID(AllocateInYoung), {builder_.ToTaggedInt(size)}, true);
builder_.Jump(&exit);
}
builder_.Bind(&exit);
@ -2586,7 +2587,8 @@ GateRef TypeLowering::ModNumbers(GateRef left, GateRef right, GateType leftType,
{
GateRef glue = acc_.GetGlueFromArgList();
result = builder_.CallNGCRuntime(
glue, RTSTUB_ID(FloatMod), Gate::InvalidGateRef, {*doubleLeft, *doubleRight});
glue, RTSTUB_ID(FloatMod), Gate::InvalidGateRef, {*doubleLeft, *doubleRight},
Circuit::NullGate());
builder_.Jump(&exit);
}
}
@ -2896,9 +2898,8 @@ void TypeLowering::LowerTypedNewAllocateThis(GateRef gate, GateRef glue)
GateRef frameState = GetFrameState(gate);
builder_.DeoptCheck(check, frameState);
NewObjectStubBuilder stubBuilder(&env);
stubBuilder.SetGule(glue);
stubBuilder.NewJSObject(&thisObj, &exit, protoOrHclass);
thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, { glue, protoOrHclass });
builder_.Jump(&exit);
}
builder_.Bind(&exit);
builder_.SetDepend(*thisObj);
@ -2925,9 +2926,8 @@ void TypeLowering::LowerTypedSuperAllocateThis(GateRef gate, GateRef glue)
GateRef frameState = GetFrameState(gate);
builder_.DeoptCheck(check, frameState);
NewObjectStubBuilder stubBuilder(&env);
stubBuilder.SetGule(glue);
stubBuilder.NewJSObject(&thisObj, &exit, protoOrHclass);
thisObj = builder_.CallStub(glue, gate, CommonStubCSigns::NewJSObject, { glue, protoOrHclass });
builder_.Jump(&exit);
}
builder_.Bind(&exit);
builder_.SetDepend(*thisObj);

View File

@ -204,7 +204,8 @@ private:
void LowerTypedSuperAllocateThis(GateRef gate, GateRef glue);
void LowerGetSuperConstructor(GateRef gate);
GateRef LowerCallRuntime(GateRef glue, int index, const std::vector<GateRef> &args, bool useLabel = false);
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
bool useLabel = false);
template<OpCode Op>
GateRef CalculateNumbers(GateRef left, GateRef right, GateType leftType, GateType rightType);

View File

@ -30,7 +30,7 @@ class JSThread;
enum class SpecVregIndex: int {
PC_INDEX = -1,
ACC_INDEX = -2,
BC_OFFSET_INDEX = -3,
PC_OFFSET_INDEX = -3,
};
struct Context {

View File

@ -744,19 +744,21 @@ void HeapSnapshot::AddTraceNodeId(MethodLiteral *methodLiteral)
int HeapSnapshot::AddTraceNode(int sequenceId, int size)
{
traceNodeIndex_.clear();
FrameHandler frameHandler(vm_->GetAssociatedJSThread());
for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
if (!frameHandler.IsJSFrame()) {
auto thread = vm_->GetJSThread();
JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
FrameIterator it(current, thread);
for (; !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
if (!it.IsJSFrame()) {
continue;
}
auto method = frameHandler.CheckAndGetMethod();
auto method = it.CheckAndGetMethod();
if (method == nullptr || method->IsNativeWithCallField()) {
continue;
}
MethodLiteral *methodLiteral = method->GetMethodLiteral();
if (stackInfo_.count(methodLiteral) == 0) {
AddMethodInfo(methodLiteral, frameHandler, method->GetJSPandaFile(), sequenceId);
AddMethodInfo(methodLiteral, it, method->GetJSPandaFile(), sequenceId);
}
AddTraceNodeId(methodLiteral);
}
@ -775,7 +777,7 @@ int HeapSnapshot::AddTraceNode(int sequenceId, int size)
}
void HeapSnapshot::AddMethodInfo(MethodLiteral *methodLiteral,
const FrameHandler &frameHandler,
const FrameIterator &it,
const JSPandaFile *jsPandaFile,
int sequenceId)
{
@ -819,7 +821,7 @@ void HeapSnapshot::AddMethodInfo(MethodLiteral *methodLiteral,
columnNumber = column + 1;
return true;
};
uint32_t offset = frameHandler.GetBytecodeOffset();
uint32_t offset = it.GetBytecodeOffset();
if (!debugExtractor->MatchLineWithOffset(callbackLineFunc, methodId, offset) ||
!debugExtractor->MatchColumnWithOffset(callbackColumnFunc, methodId, offset)) {
codeEntry.lineNumber = 0;

View File

@ -380,7 +380,7 @@ public:
bool FinishSnapshot();
void PushHeapStat(Stream* stream);
int AddTraceNode(int sequenceId, int size);
void AddMethodInfo(MethodLiteral *methodLiteral, const FrameHandler &frameHandler,
void AddMethodInfo(MethodLiteral *methodLiteral, const FrameIterator &it,
const JSPandaFile *jsPandaFile, int sequenceId);
void AddTraceNodeId(MethodLiteral *methodLiteral);

View File

@ -67,17 +67,18 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset)
std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative)
{
std::string data;
FrameHandler frameHandler(thread);
for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
if (!frameHandler.IsJSFrame()) {
JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
FrameIterator it(current, thread);
for (; !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
if (!it.IsJSFrame()) {
continue;
}
auto method = frameHandler.CheckAndGetMethod();
auto method = it.CheckAndGetMethod();
if (method == nullptr) {
continue;
}
if (!method->IsNativeWithCallField()) {
auto pcOffset = frameHandler.GetBytecodeOffset();
auto pcOffset = it.GetBytecodeOffset();
data += BuildMethodTrace(method, pcOffset);
} else if (needNative) {
auto addr = method->GetNativePointer();
@ -98,14 +99,15 @@ std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative)
std::vector<struct JsFrameInfo> JsStackInfo::BuildJsStackInfo(JSThread *thread)
{
FrameHandler frameHandler(thread);
std::vector<struct JsFrameInfo> jsframe;
uintptr_t *native = nullptr;
for (; frameHandler.HasFrame(); frameHandler.PrevJSFrame()) {
if (!frameHandler.IsJSFrame()) {
JSTaggedType *current = const_cast<JSTaggedType *>(thread->GetCurrentFrame());
FrameIterator it(current, thread);
for (; !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
if (!it.IsJSFrame()) {
continue;
}
auto method = frameHandler.CheckAndGetMethod();
auto method = it.CheckAndGetMethod();
if (method == nullptr) {
continue;
}
@ -142,14 +144,14 @@ std::vector<struct JsFrameInfo> JsStackInfo::BuildJsStackInfo(JSThread *thread)
return true;
};
panda_file::File::EntityId methodId = method->GetMethodId();
uint32_t offset = frameHandler.GetBytecodeOffset();
uint32_t offset = it.GetBytecodeOffset();
if (!debugExtractor->MatchLineWithOffset(callbackLineFunc, methodId, offset) ||
!debugExtractor->MatchColumnWithOffset(callbackColumnFunc, methodId, offset)) {
frameInfo.pos = "?";
}
jsframe.push_back(frameInfo);
} else {
JSTaggedValue function = frameHandler.GetFunction();
JSTaggedValue function = it.GetFunction();
JSHandle<JSTaggedValue> extraInfoValue(
thread, JSFunction::Cast(function.GetTaggedObject())->GetFunctionExtraInfo());
if (extraInfoValue->IsJSNativePointer()) {

View File

@ -276,9 +276,6 @@
do { \
if (!(thread)->HasPendingException()) { \
(thread)->SetException(error); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
} \
return; \
} while (false)
@ -292,9 +289,6 @@
ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory(); \
JSHandle<JSObject> _error = _factory->GetJSError(type, message); \
(thread)->SetException(_error.GetTaggedValue()); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
return; \
} while (false)
@ -303,9 +297,6 @@
do { \
if (!(thread)->HasPendingException()) { \
(thread)->SetException(error); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
} \
return (value); \
} while (false)
@ -319,9 +310,6 @@
ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory(); \
JSHandle<JSObject> _error = _factory->GetJSError(errorType, message); \
(thread)->SetException(_error.GetTaggedValue()); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
return JSHandle<type>(thread, JSTaggedValue::Exception()); \
} while (false)
@ -334,9 +322,6 @@
ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory(); \
JSHandle<JSObject> _error = _factory->GetJSError(errorType, message); \
(thread)->SetException(_error.GetTaggedValue()); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
return (value); \
} while (false)

View File

@ -493,7 +493,6 @@ Expected<JSTaggedValue, bool> EcmaVM::InvokeEcmaEntrypoint(const JSPandaFile *js
JSTaggedValue result;
if (aotFileManager_->IsLoadMain(jsPandaFile, entryPoint.data())) {
thread_->SetPrintBCOffset(true);
EcmaRuntimeStatScope runtimeStatScope(this);
result = InvokeEcmaAotEntrypoint(func, global, jsPandaFile, entryPoint);
} else {
@ -673,11 +672,6 @@ void EcmaVM::HandleUncaughtException(JSTaggedValue exception)
thread_->ClearException();
if (exceptionHandle->IsJSError()) {
PrintJSErrorInfo(exceptionHandle);
if (thread_->IsPrintBCOffset() && exceptionBCList_.size() != 0) {
for (const auto &[methodName, bcOffset] : exceptionBCList_) {
LOG_ECMA(ERROR) << "Exception at function " << methodName << ": " << bcOffset;
}
}
return;
}
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread_, exceptionHandle);

View File

@ -395,21 +395,6 @@ public:
panda_file::File::EntityId id);
void CreateAllConstpool(const JSPandaFile *jsPandaFile);
void StoreBCOffsetInfo(const std::string& methodName, int32_t bcOffset)
{
exceptionBCList_.emplace_back(std::pair<std::string, int32_t>(methodName, bcOffset));
}
std::vector<std::pair<std::string, int32_t>> GetBCOffsetInfoList() const
{
return exceptionBCList_;
}
void ClearExceptionBCList()
{
exceptionBCList_.clear();
}
void WorkersetInfo(EcmaVM *hostVm, EcmaVM *workerVm)
{
os::memory::LockHolder lock(mutex_);
@ -660,7 +645,6 @@ private:
// atomics
bool AllowAtomicWait_ {true};
WaiterListNode waiterListNode_;
std::vector<std::pair<std::string, int32_t>> exceptionBCList_;
// CJS resolve path Callbacks
ResolvePathCallback resolvePathCallback_ {nullptr};

View File

@ -379,6 +379,15 @@ uint32_t FrameIterator::GetBytecodeOffset() const
auto offset = frame->GetPc() - method->GetBytecodeArray();
return static_cast<uint32_t>(offset);
}
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
auto frame = this->GetFrame<OptimizedJSFunctionFrame>();
kungfu::ConstInfo constInfo;
frame->CollectPcOffsetInfo(*this, constInfo);
if (!constInfo.empty()) {
return constInfo[0];
}
LOG_ECMA(FATAL) << "error: empty pcOffset in stackmap!";
}
default: {
return 0;
}
@ -437,7 +446,7 @@ ARK_INLINE void OptimizedFrame::GCIterate(const FrameIterator &it,
}
}
void FrameIterator::CollectBCOffsetInfo(kungfu::ConstInfo &info) const
void FrameIterator::CollectPcOffsetInfo(kungfu::ConstInfo &info) const
{
arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
}
@ -463,9 +472,9 @@ ARK_INLINE uintptr_t* OptimizedJSFunctionFrame::ComputePrevFrameSp(const FrameIt
}
void OptimizedJSFunctionFrame::CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const
void OptimizedJSFunctionFrame::CollectPcOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const
{
it.CollectBCOffsetInfo(info);
it.CollectPcOffsetInfo(info);
}
ARK_INLINE void OptimizedJSFunctionFrame::GCIterate(const FrameIterator &it,

View File

@ -412,7 +412,7 @@ public:
void GCIterate(const FrameIterator &it, const RootVisitor &visitor, const RootRangeVisitor &rangeVisitor,
const RootBaseAndDerivedVisitor &derivedVisitor) const;
void CollectBCOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const;
void CollectPcOffsetInfo(const FrameIterator &it, kungfu::ConstInfo &info) const;
inline JSTaggedValue GetEnv() const
{
@ -1409,7 +1409,7 @@ public:
return thread_;
}
bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
void CollectBCOffsetInfo(kungfu::ConstInfo &info) const;
void CollectPcOffsetInfo(kungfu::ConstInfo &info) const;
void CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const;
std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const;
int GetCallSiteDelta(uintptr_t retAddr) const;
@ -1429,10 +1429,26 @@ public:
return (type == FrameType::OPTIMIZED_FRAME);
}
bool IsInterpretedFrame(FrameType type) const
{
return (type >= FrameType::INTERPRETER_FIRST) && (type <= FrameType::INTERPRETER_LAST);
}
bool IsJSFrame() const
{
FrameType type = GetFrameType();
return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type);
}
bool IsOptimizedJSFunctionFrame(FrameType type) const
{
return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME;
}
bool IsOptimizedJSFunctionFrame() const
{
FrameType type = GetFrameType();
return (type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
return IsOptimizedJSFunctionFrame(type);
}
private:

View File

@ -168,7 +168,7 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle<JSTaggedValue> receiver, JSHandle
ObjectOperator op(GetThread(), receiver, key);
auto result = JSHandle<JSTaggedValue>(thread_, JSObject::GetProperty(GetThread(), &op));
if (!op.IsFound() && kind == ICKind::NamedGlobalTryLoadIC) {
return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not definded");
return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined");
}
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(GetThread());
// ic-switch

View File

@ -127,7 +127,7 @@ JSTaggedValue FrameHandler::GetAcc() const
uint32_t FrameHandler::GetBytecodeOffset() const
{
ASSERT(IsJSFrame());
ASSERT(IsInterpretedFrame());
Method *method = GetMethod();
auto offset = GetPc() - method->GetBytecodeArray();
return static_cast<uint32_t>(offset);
@ -438,58 +438,4 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &vis
}
}
}
std::string FrameBcCollector::GetAotExceptionFuncName(JSTaggedType* argv) const
{
JSTaggedValue func = JSTaggedValue(*(argv)); // 3: skip returnaddr and argc
Method *method = JSFunction::Cast(func.GetTaggedObject())->GetCallTarget();
return method->GetMethodName();
}
void FrameBcCollector::CollectBCOffsetInfo()
{
thread_->GetEcmaVM()->ClearExceptionBCList();
JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
FrameIterator it(current, thread_);
it.Advance<GCVisitedFlag::VISITED>();
for (; !it.Done(); it.Advance<GCVisitedFlag::VISITED>()) {
FrameType type = it.GetFrameType();
switch (type) {
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
auto frame = it.GetFrame<OptimizedJSFunctionFrame>();
kungfu::ConstInfo constInfo;
frame->CollectBCOffsetInfo(it, constInfo);
if (!constInfo.empty()) {
auto name = GetAotExceptionFuncName(frame->GetArgv(it));
thread_->GetEcmaVM()->StoreBCOffsetInfo(name, constInfo[0]);
}
break;
}
case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
case FrameType::BUILTIN_CALL_LEAVE_FRAME:
case FrameType::LEAVE_FRAME:
case FrameType::OPTIMIZED_ENTRY_FRAME:
case FrameType::ASM_INTERPRETER_BRIDGE_FRAME:
case FrameType::ASM_INTERPRETER_ENTRY_FRAME:
case FrameType::ASM_INTERPRETER_FRAME:
case FrameType::INTERPRETER_CONSTRUCTOR_FRAME:
case FrameType::INTERPRETER_FRAME:
case FrameType::INTERPRETER_FAST_NEW_FRAME:
case FrameType::OPTIMIZED_FRAME:
case FrameType::OPTIMIZED_JS_FUNCTION_UNFOLD_ARGV_FRAME:
case FrameType::LEAVE_FRAME_WITH_ARGV:
case FrameType::BUILTIN_FRAME_WITH_ARGV:
case FrameType::BUILTIN_ENTRY_FRAME:
case FrameType::BUILTIN_FRAME:
case FrameType::INTERPRETER_ENTRY_FRAME: {
break;
}
default: {
LOG_FULL(FATAL) << "frame type error!";
UNREACHABLE();
}
}
}
}
} // namespace panda::ecmascript

View File

@ -84,6 +84,12 @@ public:
return IsJSFrame(type);
}
bool IsOptimizedJSFunctionFrame() const
{
FrameType type = GetFrameType();
return type == FrameType::OPTIMIZED_JS_FUNCTION_FRAME;
}
bool IsJSFrame(FrameType type) const
{
return IsInterpretedFrame(type) || IsOptimizedJSFunctionFrame(type);
@ -253,19 +259,6 @@ private:
JSThread *thread_ {nullptr};
const JSTaggedType *oldSp_ {nullptr};
};
class FrameBcCollector {
public:
explicit FrameBcCollector(const JSThread *thread) : thread_(thread)
{
}
~FrameBcCollector() = default;
// for collecting bc offset in aot
void CollectBCOffsetInfo();
private:
std::string GetAotExceptionFuncName(JSTaggedType* fp) const;
const JSThread *thread_ {nullptr};
};
}; // namespace ecmascript
} // namespace panda
#endif // ECMASCRIPT_INTERPRETER_FRAME_HANDLER_H

View File

@ -493,12 +493,6 @@ bool JSThread::CpuProfilerCheckJSTaggedType(JSTaggedType value) const
return true;
}
void JSThread::CollectBCOffsetInfo()
{
FrameBcCollector collector(this);
collector.CollectBCOffsetInfo();
}
// static
size_t JSThread::GetAsmStackLimit()
{

View File

@ -555,18 +555,6 @@ public:
bool IsLegalSp(uintptr_t sp) const;
bool IsPrintBCOffset() const
{
return enablePrintBCOffset_;
}
void SetPrintBCOffset(bool flag)
{
enablePrintBCOffset_ = flag;
}
void CollectBCOffsetInfo();
void SetCheckAndCallEnterState(bool state)
{
finalizationCheckState_ = state;
@ -861,7 +849,6 @@ private:
bool runtimeState_ {false};
bool isAsmInterpreter_ {false};
VmThreadControl *vmThreadControl_ {nullptr};
bool enablePrintBCOffset_ {false};
bool stableArrayElementsGuardians_ {true};
bool finalizationCheckState_ {false};

View File

@ -75,7 +75,7 @@ void ArkStackMapParser::GetConstInfo(uintptr_t callSiteAddr, ConstInfo &info, ui
}
ARKDeopt target;
OffsetType id = static_cast<OffsetType>(SpecVregIndex::BC_OFFSET_INDEX);
OffsetType id = static_cast<OffsetType>(SpecVregIndex::PC_OFFSET_INDEX);
target.Id = id;
auto it = std::lower_bound(deopts.begin(), deopts.end(), target,
[](const ARKDeopt& a, const ARKDeopt& b) {

View File

@ -115,9 +115,9 @@ HWTEST_F_L0(JSCollatorTest, InitializeCollatorAndGetIcuCollator)
JSHandle<JSCollator> collator =
JSHandle<JSCollator>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
JSHandle<JSTaggedValue> localeStr = thread->GlobalConstants()->GetHandledEnUsString();
JSHandle<JSTaggedValue> undefindedHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> undefinedHandle(thread, JSTaggedValue::Undefined());
JSHandle<JSCollator> initCollator = JSCollator::InitializeCollator(thread, collator, localeStr, undefindedHandle);
JSHandle<JSCollator> initCollator = JSCollator::InitializeCollator(thread, collator, localeStr, undefinedHandle);
EXPECT_EQ(JSTaggedValue::SameValue(collator.GetTaggedValue(), initCollator.GetTaggedValue()), true);
// check attributes
EXPECT_TRUE(initCollator->GetBoundCompare().IsUndefined());

View File

@ -70,7 +70,17 @@ group("ark_aot_test") {
"div:divAotAction",
"duplicatefunctions:duplicatefunctionsAotAction",
"duplicatekey:duplicatekeyAotAction",
"exceptionhandler:exceptionhandlerAotAction",
"exception_case1:exceptionhandlerAotAction",
# "exception_case10:exceptionhandlerAotAction",
"exception_case2:exceptionhandlerAotAction",
"exception_case3:exceptionhandlerAotAction",
"exception_case4:exceptionhandlerAotAction",
"exception_case5:exceptionhandlerAotAction",
"exception_case6:exceptionhandlerAotAction",
"exception_case7:exceptionhandlerAotAction",
"exception_case8:exceptionhandlerAotAction",
"exception_case9:exceptionhandlerAotAction",
"exp:expAotAction",
"forloop:forloopAotAction",
"framestatesasync:framestatesasyncAotAction",

View File

@ -27,4 +27,3 @@ true
true
xxxx
TypeError: CallObj is NonCallable
Exception at function func_main_0: 310

View File

@ -1,4 +1,4 @@
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@ -13,7 +13,7 @@
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_test_action("exceptionhandler") {
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@ -13,14 +13,22 @@
* limitations under the License.
*/
declare function print(str:string):string;
try {
function foo() {
JSON.parse("[1, 2");
}
foo();
} catch(e) {
print(e);
}
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -1,4 +1,4 @@
# Copyright (c) 2022 Huawei Device Co., Ltd.
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@ -12,5 +12,6 @@
# limitations under the License.
SyntaxError: Unexpected Array in JSON
Exception at function foo: 7
Exception at function func_main_0: 9
exceptionhandler.js:18:18
exceptionhandler.js:20:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function foo() {
a.b
}
function bar() {
foo()
}
bar(...[1, 2])
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ReferenceError: a is not defined
exceptionhandler.js:18:18
exceptionhandler.js:21:21
exceptionhandler.js:23:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function foo(a) {
b.c;
}
foo(1, 2);
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ReferenceError: b is not defined
exceptionhandler.js:18:18
exceptionhandler.js:20:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function foo(a, b, c) {
d.e;
}
foo(1)
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ReferenceError: d is not defined
exceptionhandler.js:18:18
exceptionhandler.js:20:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function foo() {
new Array(111111111111111111111)
}
foo();
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
RangeError: The length is out of range.
exceptionhandler.js:18:18
exceptionhandler.js:20:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
var foo = 1;
foo();
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,16 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
TypeError: CallObj is NonCallable
exceptionhandler.js:18:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function foo(a, b, c) {
d.e;
}
var bar = foo.bind(undefined, [2, 3])
bar(1);
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ReferenceError: d is not defined
exceptionhandler.js:18:18
exceptionhandler.js:21:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
const handler = {
get: function(obj, prop) {
return a.b
}
}
const p = new Proxy({}, handler)
p.c
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,17 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ReferenceError: a is not defined
exceptionhandler.js:19:19
exceptionhandler.js:23:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function bar() {
JSON.parse("[1, 2");
}
function foo(a, b, c) {
bar.apply(undefined, [])
}
foo(1);
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
SyntaxError: Unexpected Array in JSON
exceptionhandler.js:18:18
exceptionhandler.js:22:22
exceptionhandler.js:24:1

View File

@ -0,0 +1,19 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("exceptionhandler") {
deps = []
is_disable_type_lowering = true
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
try {
function foo() {
a.b
}
let o = {
get name() {
foo()
},
set name(a) {}
}
o.name
} catch (e) {
print(e)
let stack = e.stack
let array = stack.split('\n')
for (let line of array) {
let start = line.lastIndexOf('/') + 1
let end = line.length - 1
if (start < end) {
print(line.slice(start, end))
} else {
print(line)
}
}
}

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
ReferenceError: a is not defined
exceptionhandler.js:18:18
exceptionhandler.js:22:22
exceptionhandler.js:26:1