TSAOT Exception Handler

1. Throw JS exception in tsaot
2. Print bcoffset when occur JS exception

issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5AMHL

Signed-off-by: xujie <xujie101@huawei.com>
Change-Id: I046d76c092a399354ddcdedd859f0c1e622387c2
This commit is contained in:
xujie 2022-06-10 15:22:21 +08:00
parent 6eaee6c7e7
commit 81a69cf09f
23 changed files with 475 additions and 107 deletions

View File

@ -485,6 +485,16 @@ 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

@ -16,6 +16,7 @@
#include "bytecode_circuit_builder.h"
#include "ecmascript/base/number_helper.h"
#include "ecmascript/ts_types/ts_loader.h"
#include "ecmascript/compiler/gate_accessor.h"
namespace panda::ecmascript::kungfu {
void BytecodeCircuitBuilder::BytecodeToCircuit()
@ -24,17 +25,22 @@ void BytecodeCircuitBuilder::BytecodeToCircuit()
auto prePc = curPc;
std::map<uint8_t *, uint8_t *> byteCodeCurPrePc;
std::vector<CfgInfo> bytecodeBlockInfos;
int32_t offsetIndex = 1;
auto startPc = curPc;
bytecodeBlockInfos.emplace_back(startPc, SplitKind::START, std::vector<uint8_t *>(1, startPc));
byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(curPc, prePc));
byteCodeCurPrePc[curPc] = prePc;
pcToBCOffset_[curPc]=offsetIndex++;
for (size_t i = 1; i < pcArray_.size() - 1; i++) {
curPc = pcArray_[i];
byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(curPc, prePc));
byteCodeCurPrePc[curPc] = prePc;
pcToBCOffset_[curPc]=offsetIndex++;
prePc = curPc;
CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
}
// handle empty
byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(pcArray_[pcArray_.size() - 1], prePc));
uint8_t *emptyPc = pcArray_.back();
byteCodeCurPrePc[emptyPc] = prePc;
pcToBCOffset_[emptyPc] = offsetIndex++;
// collect try catch block info
auto exceptionInfo = CollectTryCatchBlockInfo(byteCodeCurPrePc, bytecodeBlockInfos);
@ -1966,9 +1972,10 @@ void BytecodeCircuitBuilder::BuildBlockCircuitHead()
std::vector<GateRef> BytecodeCircuitBuilder::CreateGateInList(const BytecodeInfo &info)
{
size_t numValueInputs = (info.accIn ? 1 : 0) + info.inputs.size();
size_t numValueInputs = info.ComputeValueInputCount();
const size_t length = 2; // 2: state and depend on input
std::vector<GateRef> inList(length + numValueInputs, Circuit::NullGate());
const size_t numBCOffsetInput = info.ComputeBCOffsetInputCount();
std::vector<GateRef> inList(length + numValueInputs + numBCOffsetInput, Circuit::NullGate());
for (size_t i = 0; i < info.inputs.size(); i++) {
const auto &input = info.inputs[i];
if (std::holds_alternative<MethodId>(input)) {
@ -2083,7 +2090,7 @@ GateRef BytecodeCircuitBuilder::NewConst(const BytecodeInfo &info)
void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, const uint8_t *pc, GateRef &state, GateRef &depend)
{
auto bytecodeInfo = GetBytecodeInfo(pc);
size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.inputs.size();
size_t numValueInputs = bytecodeInfo.ComputeTotalValueCount();
GateRef gate = 0;
std::vector<GateRef> inList = CreateGateInList(bytecodeInfo);
if (!bytecodeInfo.vregOut.empty() || bytecodeInfo.accOut) {
@ -2093,6 +2100,8 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, const uint8_t *pc, Ga
gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::NOVALUE, numValueInputs,
inList, GateType::Empty());
}
// 1: store bcoffset in the end.
AddBytecodeOffsetInfo(gate, bytecodeInfo, numValueInputs + 1, const_cast<uint8_t *>(pc));
circuit_.NewIn(gate, 0, state);
circuit_.NewIn(gate, 1, depend);
auto ifSuccess = circuit_.NewGate(OpCode(OpCode::IF_SUCCESS), 0, {gate}, GateType::Empty());
@ -2141,7 +2150,7 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, const uint8_t *pc, Ga
void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, const uint8_t *pc, GateRef &state, GateRef &depend)
{
auto bytecodeInfo = GetBytecodeInfo(pc);
size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.inputs.size();
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
if (bytecodeInfo.IsCondJump()) {
GateRef gate = 0;
gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::NOVALUE, numValueInputs,
@ -2460,8 +2469,8 @@ void BytecodeCircuitBuilder::BuildCircuit()
}
const auto &[id, pc] = it->second;
auto bytecodeInfo = GetBytecodeInfo(pc);
[[maybe_unused]] size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.inputs.size();
[[maybe_unused]] size_t numValueOutputs = (bytecodeInfo.accOut ? 1 : 0) + bytecodeInfo.vregOut.size();
[[maybe_unused]] size_t numValueInputs = bytecodeInfo.ComputeTotalValueCount();
[[maybe_unused]] size_t numValueOutputs = bytecodeInfo.ComputeOutCount() + bytecodeInfo.vregOut.size();
ASSERT(numValueInputs == valueCount);
ASSERT(numValueOutputs <= 1);
auto stateCount = circuit_.GetOpCode(gate).GetStateCount(circuit_.GetBitField(gate));
@ -2492,6 +2501,19 @@ size_t BytecodeCircuitBuilder::GetFunctionArgIndex(size_t currentVreg, size_t nu
return (currentVreg - numVregs + CommonArgIdx::NUM_OF_ARGS);
}
void BytecodeCircuitBuilder::AddBytecodeOffsetInfo(GateRef &gate, const BytecodeInfo &info, size_t bcOffsetIndex,
uint8_t *pc)
{
if (info.IsCall()) {
GateAccessor acc(&circuit_);
auto bcOffset = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I64,
pcToBCOffset_[pc],
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
GateType::NJSValue());
acc.NewIn(gate, bcOffsetIndex, bcOffset);
}
}
void BytecodeCircuitBuilder::PrintCollectBlockInfo(std::vector<CfgInfo> &bytecodeBlockInfos)
{
for (auto iter = bytecodeBlockInfos.cbegin(); iter != bytecodeBlockInfos.cend(); iter++) {

View File

@ -323,6 +323,42 @@ struct BytecodeInfo {
{
return !IsMov() && !IsJump() && !IsReturn() && !IsSetConstant() && !IsDiscarded();
}
bool IsCall() const
{
auto ecmaOpcode = static_cast<EcmaOpcode>(opcode);
switch (ecmaOpcode) {
case EcmaOpcode::CALLARG0DYN_PREF_V8:
case EcmaOpcode::CALLARG1DYN_PREF_V8_V8:
case EcmaOpcode::CALLARGS2DYN_PREF_V8_V8_V8:
case EcmaOpcode::CALLARGS3DYN_PREF_V8_V8_V8_V8:
case EcmaOpcode::CALLITHISRANGEDYN_PREF_IMM16_V8:
case EcmaOpcode::CALLIRANGEDYN_PREF_IMM16_V8:
return true;
default:
return false;
}
}
size_t ComputeBCOffsetInputCount() const
{
return IsCall() ? 1 : 0;
}
size_t ComputeValueInputCount() const
{
return (accIn ? 1 : 0) + inputs.size();
}
size_t ComputeOutCount() const
{
return accOut ? 1 : 0;
}
size_t ComputeTotalValueCount() const
{
return ComputeValueInputCount() + ComputeBCOffsetInputCount();
}
};
enum BytecodeOffset {
@ -444,6 +480,7 @@ private:
void NewJump(BytecodeRegion &bb, const uint8_t *pc, GateRef &state, GateRef &depend);
void NewReturn(BytecodeRegion &bb, const uint8_t *pc, GateRef &state, GateRef &depend);
void NewByteCode(BytecodeRegion &bb, const uint8_t *pc, GateRef &state, GateRef &depend);
void AddBytecodeOffsetInfo(GateRef &gate, const BytecodeInfo &info, size_t bcOffsetIndex, uint8_t *pc);
void BuildSubCircuit();
GateRef NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc);
GateRef RenameVariable(const size_t bbId, const uint8_t *end,
@ -474,6 +511,7 @@ private:
const std::vector<uint8_t *> pcArray_;
JSHandle<JSTaggedValue> constantPool_;
bool enableLog_ {false};
std::map<uint8_t *, int32_t> pcToBCOffset_;
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H

View File

@ -175,4 +175,9 @@ void GateAccessor::DecreaseIn(UsesIterator &useIt)
circuit_->DecreaseIn(*useIt, idx);
useIt.SetChanged();
}
void GateAccessor::NewIn(GateRef gate, size_t idx, GateRef in)
{
circuit_->NewIn(gate, idx, in);
}
}

View File

@ -335,6 +335,7 @@ public:
void DeleteIn(UsesIterator &useIt);
void DeleteGate(UsesIterator &useIt);
void DecreaseIn(UsesIterator &useIt);
void NewIn(GateRef gate, size_t idx, GateRef in);
private:
[[nodiscard]] ConstUsesIterator ConstUseBegin(GateRef gate) const

View File

@ -509,50 +509,11 @@ void LLVMIRBuilder::HandleRuntimeCall(GateRef gate)
VisitRuntimeCall(gate, ins);
}
LLVMValueRef LLVMIRBuilder::GetFunction(LLVMValueRef glue, StubIdType id, bool isDebug)
LLVMValueRef LLVMIRBuilder::GetFunction(LLVMValueRef glue, const CallSignature *signature, LLVMValueRef rtbaseoffset)
{
const CallSignature *signature;
int index = 0;
if (std::holds_alternative<RuntimeStubCSigns::ID>(id)) {
signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(id));
index = static_cast<int>(std::get<RuntimeStubCSigns::ID>(id));
} else if (std::holds_alternative<CommonStubCSigns::ID>(id)) {
signature = CommonStubCSigns::Get(std::get<CommonStubCSigns::ID>(id));
index = static_cast<int>(std::get<CommonStubCSigns::ID>(id));
} else if (std::holds_alternative<LLVMValueRef>(id)) {
signature = BytecodeStubCSigns::BCHandler();
} else {
UNREACHABLE();
}
LLVMTypeRef rtfuncType = llvmModule_->GetFuncType(signature);
LLVMTypeRef rtfuncTypePtr = LLVMPointerType(rtfuncType, 0);
LLVMTypeRef glueType = LLVMTypeOf(glue);
LLVMValueRef rtoffset;
LLVMValueRef rtbaseoffset;
if (std::holds_alternative<RuntimeStubCSigns::ID>(id)) {
rtoffset = LLVMConstInt(glueType,
static_cast<int>(JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit())) +
index * slotSize_, 0);
rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
} else if (std::holds_alternative<CommonStubCSigns::ID>(id)) {
rtoffset = LLVMConstInt(glueType, JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) +
static_cast<size_t>(index * slotSize_), 0);
rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
} else if (std::holds_alternative<LLVMValueRef>(id)) {
LLVMValueRef bytecodeoffset;
if (isDebug) {
bytecodeoffset = LLVMConstInt(glueType,
JSThread::GlueData::GetBCDebuggerStubEntriesOffset(compCfg_->Is32Bit()), 0);
} else {
bytecodeoffset = LLVMConstInt(glueType,
JSThread::GlueData::GetBCStubEntriesOffset(compCfg_->Is32Bit()), 0);
}
LLVMValueRef opcodeOffset = std::get<LLVMValueRef>(id);
rtbaseoffset = LLVMBuildAdd(
builder_, glue, LLVMBuildAdd(builder_, bytecodeoffset, opcodeOffset, ""), "");
} else {
UNREACHABLE();
}
LLVMValueRef rtbaseAddr = LLVMBuildIntToPtr(builder_, rtbaseoffset, LLVMPointerType(glueType, 0), "");
LLVMValueRef llvmAddr = LLVMBuildLoad(builder_, rtbaseAddr, "");
LLVMValueRef callee = LLVMBuildIntToPtr(builder_, llvmAddr, rtfuncTypePtr, "cast");
@ -574,8 +535,12 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
{
ASSERT(llvmModule_ != nullptr);
StubIdType stubId = RTSTUB_ID(CallRuntime);
LLVMValueRef glue = gate2LValue_[inList[static_cast<size_t>(CallInputs::GLUE)]];
LLVMValueRef callee = GetFunction(glue, stubId);
LLVMValueRef glue = GetGlue(inList);
int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
LLVMValueRef rtoffset = GetRTStubOffset(glue, stubIndex);
LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset);
std::vector<LLVMValueRef> params;
params.push_back(glue); // glue
@ -603,8 +568,13 @@ void LLVMIRBuilder::HandleRuntimeCallWithArgv(GateRef gate)
void LLVMIRBuilder::VisitRuntimeCallWithArgv(GateRef gate, const std::vector<GateRef> &inList)
{
assert(IsOptimized() == true);
LLVMValueRef glue = gate2LValue_[inList[static_cast<size_t>(CallInputs::GLUE)]];
LLVMValueRef callee = GetFunction(glue, RTSTUB_ID(CallRuntimeWithArgv));
StubIdType stubId = RTSTUB_ID(CallRuntimeWithArgv);
LLVMValueRef glue = GetGlue(inList);
int stubIndex = static_cast<int>(std::get<RuntimeStubCSigns::ID>(stubId));
LLVMValueRef rtoffset = GetRTStubOffset(glue, stubIndex);
LLVMValueRef rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
const CallSignature *signature = RuntimeStubCSigns::Get(std::get<RuntimeStubCSigns::ID>(stubId));
LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset);
std::vector<LLVMValueRef> params;
params.push_back(glue); // glue
@ -668,20 +638,72 @@ void LLVMIRBuilder::SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMV
}
}
LLVMValueRef LLVMIRBuilder::GetGlue(const std::vector<GateRef> &inList)
{
return gate2LValue_[inList[static_cast<size_t>(CallInputs::GLUE)]];
}
LLVMValueRef LLVMIRBuilder::GetRTStubOffset(LLVMValueRef glue, int index)
{
LLVMTypeRef glueType = LLVMTypeOf(glue);
return LLVMConstInt(glueType,
static_cast<int>(JSThread::GlueData::GetRTStubEntriesOffset(compCfg_->Is32Bit())) + index * slotSize_, 0);
}
LLVMValueRef LLVMIRBuilder::GetCoStubOffset(LLVMValueRef glue, int index)
{
LLVMTypeRef glueType = LLVMTypeOf(glue);
return LLVMConstInt(glueType, JSThread::GlueData::GetCOStubEntriesOffset(compCfg_->Is32Bit()) +
static_cast<size_t>(index * slotSize_), 0);
}
LLVMValueRef LLVMIRBuilder::GetBCStubOffset(LLVMValueRef glue)
{
LLVMTypeRef glueType = LLVMTypeOf(glue);
return LLVMConstInt(glueType, JSThread::GlueData::GetBCStubEntriesOffset(compCfg_->Is32Bit()), 0);
}
LLVMValueRef LLVMIRBuilder::GetBCDebugStubOffset(LLVMValueRef glue)
{
LLVMTypeRef glueType = LLVMTypeOf(glue);
return LLVMConstInt(glueType, JSThread::GlueData::GetBCDebuggerStubEntriesOffset(compCfg_->Is32Bit()), 0);
}
// Only related to the call bytecode in Aot can record bcoffset
bool LLVMIRBuilder::NeedBCOffset(OpCode op)
{
return callConv_ == CallSignature::CallConv::WebKitJSCallConv && op == OpCode::NOGC_RUNTIME_CALL;
}
void LLVMIRBuilder::ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset,
const std::vector<GateRef> &inList, OpCode op)
{
if (NeedBCOffset(op)) {
actualNumArgs = inList.size() - 1;
bcOffset = gate2LValue_[inList[actualNumArgs]];
} else {
actualNumArgs = inList.size();
}
}
void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
{
static_assert(static_cast<size_t>(CallInputs::FIRST_PARAMETER) == 3);
const size_t index = circuit_->GetBitField(inList[static_cast<size_t>(CallInputs::TARGET)]);
const CallSignature *calleeDescriptor = (op == OpCode::CALL)
? CommonStubCSigns::Get(index)
: RuntimeStubCSigns::Get(index);
StubIdType stubId = static_cast<RuntimeStubCSigns::ID>(index);
const CallSignature *calleeDescriptor = nullptr;
LLVMValueRef glue = GetGlue(inList);
LLVMValueRef rtoffset;
LLVMValueRef rtbaseoffset;
if (op == OpCode::CALL) {
stubId = static_cast<CommonStubCSigns::ID>(index);
calleeDescriptor = CommonStubCSigns::Get(index);
rtoffset = GetCoStubOffset(glue, index);
rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
} else {
calleeDescriptor = RuntimeStubCSigns::Get(index);
rtoffset = GetRTStubOffset(glue, index);
rtbaseoffset = LLVMBuildAdd(builder_, glue, rtoffset, "");
}
LLVMValueRef glue = gate2LValue_[inList[static_cast<size_t>(CallInputs::GLUE)]];
LLVMValueRef callee = GetFunction(glue, stubId);
LLVMValueRef callee = GetFunction(glue, calleeDescriptor, rtbaseoffset);
std::vector<LLVMValueRef> params;
const size_t firstArg = static_cast<size_t>(CallInputs::FIRST_PARAMETER);
@ -698,13 +720,27 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
extraParameterCnt += CompilationConfig::FAKE_REGISTER_PARAMTERS_ARM32;
}
}
size_t actualNumArgs = 0;
LLVMValueRef bcOffset = LLVMConstInt(LLVMInt32Type(), 0, 0);
ComputeArgCountAndBCOffset(actualNumArgs, bcOffset, inList, op);
// then push the actual parameter for js function call
for (size_t paraIdx = firstArg + 1; paraIdx < inList.size(); ++paraIdx) {
for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
GateRef gateTmp = inList[paraIdx];
params.push_back(gate2LValue_[gateTmp]);
}
LLVMValueRef call = LLVMBuildCall(builder_, callee, params.data(),
inList.size() - firstArg + extraParameterCnt, "");
LLVMValueRef call = 0;
if (NeedBCOffset(op)) {
LLVMTypeRef funcType = llvmModule_->GetFuncType(calleeDescriptor);
std::vector<LLVMValueRef> values;
values.push_back(bcOffset);
call = LLVMBuildCall3(
builder_, funcType, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt, "", values.data(),
values.size());
} else {
call = LLVMBuildCall(builder_, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt, "");
}
SetCallConvAttr(calleeDescriptor, call);
gate2LValue_[gate] = call;
return;
@ -720,8 +756,11 @@ void LLVMIRBuilder::VisitBytecodeCall(GateRef gate, const std::vector<GateRef> &
// start index of bytecode handler csign in llvmModule
LLVMValueRef glue = gate2LValue_[inList[glueIndex]];
StubIdType stubId = opcodeOffset;
LLVMValueRef callee = GetFunction(glue, stubId);
LLVMValueRef bytecodeoffset = GetBCStubOffset(glue);
LLVMValueRef rtbaseoffset = LLVMBuildAdd(
builder_, glue, LLVMBuildAdd(builder_, bytecodeoffset, opcodeOffset, ""), "");
const CallSignature *signature = BytecodeStubCSigns::BCHandler();
LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset);
std::vector<LLVMValueRef> params;
for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) {
@ -745,8 +784,11 @@ void LLVMIRBuilder::VisitDebuggerBytecodeCall(GateRef gate, const std::vector<Ga
// start index of bytecode handler csign in llvmModule
LLVMValueRef glue = gate2LValue_[inList[glueIndex]];
StubIdType stubId = opcodeOffset;
LLVMValueRef callee = GetFunction(glue, stubId, true);
LLVMValueRef bytecodeoffset = GetBCDebugStubOffset(glue);
LLVMValueRef rtbaseoffset = LLVMBuildAdd(
builder_, glue, LLVMBuildAdd(builder_, bytecodeoffset, opcodeOffset, ""), "");
const CallSignature *signature = BytecodeStubCSigns::BCHandler();
LLVMValueRef callee = GetFunction(glue, signature, rtbaseoffset);
std::vector<LLVMValueRef> params;
for (size_t paraIdx = paraStartIndex; paraIdx < inList.size(); ++paraIdx) {

View File

@ -289,13 +289,21 @@ private:
{
return enableLog_;
}
LLVMValueRef GetFunction(LLVMValueRef glue, StubIdType id, bool isDebug = false);
LLVMValueRef GetFunction(LLVMValueRef glue, const CallSignature *signature, LLVMValueRef rtbaseoffset);
bool IsInterpreted();
bool IsOptimized();
void SetGCLeafFunction(LLVMValueRef call);
void SetCallConvAttr(const CallSignature *calleeDescriptor, LLVMValueRef call);
private:
LLVMValueRef GetGlue(const std::vector<GateRef> &inList);
LLVMValueRef GetRTStubOffset(LLVMValueRef glue, int index);
LLVMValueRef GetCoStubOffset(LLVMValueRef glue, int index);
LLVMValueRef GetBCStubOffset(LLVMValueRef glue);
LLVMValueRef GetBCDebugStubOffset(LLVMValueRef glue);
bool NeedBCOffset(OpCode op);
void ComputeArgCountAndBCOffset(size_t &actualNumArgs, LLVMValueRef &bcOffset, const std::vector<GateRef> &inList,
OpCode op);
const CompilationConfig *compCfg_ {nullptr};
const std::vector<std::vector<GateRef>> *scheduledGates_ {nullptr};
const Circuit *circuit_ {nullptr};

View File

@ -48,6 +48,14 @@ void SlowPathLowering::CallRuntimeLowering()
}
}
int32_t SlowPathLowering::ComputeCallArgc(GateRef gate, EcmaOpcode op)
{
if (op == EcmaOpcode::CALLITHISRANGEDYN_PREF_IMM16_V8) {
return acc_.GetNumValueIn(gate) + NUM_MANDATORY_JSFUNC_ARGS - 3; // 3: calltarget, this and bcoffset
}
return acc_.GetNumValueIn(gate) + NUM_MANDATORY_JSFUNC_ARGS - 2; // 2: calltarget and bcoffset
}
void SlowPathLowering::ReplaceHirControlGate(GateAccessor::UsesIterator &useIt, GateRef newGate, bool noThrow)
{
GateAccessor acc(circuit_);
@ -796,40 +804,47 @@ void SlowPathLowering::LowerToJSCall(GateRef gate, GateRef glue, const std::vect
void SlowPathLowering::LowerCallArg0Dyn(GateRef gate, GateRef glue)
{
ASSERT(acc_.GetNumValueIn(gate) == 1);
GateRef actualArgc = builder_.Int32(acc_.GetNumValueIn(gate) - 1 + NUM_MANDATORY_JSFUNC_ARGS);
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARG0DYN_PREF_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
LowerToJSCall(gate, glue, {glue, actualArgc, acc_.GetValueIn(gate, 0), newTarget, thisObj});
LowerToJSCall(gate, glue, {glue, actualArgc, acc_.GetValueIn(gate, 0), newTarget, thisObj,
acc_.GetValueIn(gate, 1)});
}
void SlowPathLowering::LowerCallArg1Dyn(GateRef gate, GateRef glue)
{
// 2: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 2);
GateRef actualArgc = builder_.Int32(acc_.GetNumValueIn(gate) - 1 + NUM_MANDATORY_JSFUNC_ARGS);
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
LowerToJSCall(gate, glue, {glue, actualArgc,
acc_.GetValueIn(gate, 0), newTarget, thisObj, acc_.GetValueIn(gate, 1)});
}
void SlowPathLowering::LowerCallArgs2Dyn(GateRef gate, GateRef glue)
{
// 3: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 3);
GateRef actualArgc = builder_.Int32(acc_.GetNumValueIn(gate) - 1 + NUM_MANDATORY_JSFUNC_ARGS);
// 2: func and bcoffset
GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARG1DYN_PREF_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
LowerToJSCall(gate, glue, {glue, actualArgc,
acc_.GetValueIn(gate, 0), newTarget, thisObj, acc_.GetValueIn(gate, 1), acc_.GetValueIn(gate, 2)});
}
void SlowPathLowering::LowerCallArgs3Dyn(GateRef gate, GateRef glue)
void SlowPathLowering::LowerCallArgs2Dyn(GateRef gate, GateRef glue)
{
// 4: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 4);
GateRef actualArgc = builder_.Int32(acc_.GetNumValueIn(gate) - 1 + NUM_MANDATORY_JSFUNC_ARGS);
// 2: func and bcoffset
GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARGS2DYN_PREF_V8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
LowerToJSCall(gate, glue, {glue, actualArgc,
acc_.GetValueIn(gate, 0), newTarget, thisObj, acc_.GetValueIn(gate, 1), acc_.GetValueIn(gate, 2),
acc_.GetValueIn(gate, 3)});
}
void SlowPathLowering::LowerCallArgs3Dyn(GateRef gate, GateRef glue)
{
// 5: number of value inputs
ASSERT(acc_.GetNumValueIn(gate) == 5);
// 2: func and bcoffset
GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLARGS3DYN_PREF_V8_V8_V8_V8));
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();
LowerToJSCall(gate, glue, {glue, actualArgc,
@ -842,9 +857,8 @@ void SlowPathLowering::LowerCallIThisRangeDyn(GateRef gate, GateRef glue)
std::vector<GateRef> vec;
// The first register input is callTarget, second is thisObj and other inputs are common args.
size_t fixedInputsNum = 2;
size_t numArgs = acc_.GetNumValueIn(gate) - fixedInputsNum;
ASSERT(numArgs >= 0);
GateRef actualArgc = builder_.Int32(numArgs + NUM_MANDATORY_JSFUNC_ARGS);
ASSERT(acc_.GetNumValueIn(gate) - fixedInputsNum >= 0);
GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLITHISRANGEDYN_PREF_IMM16_V8));
GateRef callTarget = acc_.GetValueIn(gate, 0);
GateRef thisObj = acc_.GetValueIn(gate, 1);
GateRef newTarget = builder_.Undefined();
@ -875,7 +889,7 @@ void SlowPathLowering::LowerCallIRangeDyn(GateRef gate, GateRef glue)
{
std::vector<GateRef> vec;
size_t numArgs = acc_.GetNumValueIn(gate) - 1;
GateRef actualArgc = builder_.Int32(numArgs + NUM_MANDATORY_JSFUNC_ARGS);
GateRef actualArgc = builder_.Int32(ComputeCallArgc(gate, EcmaOpcode::CALLIRANGEDYN_PREF_IMM16_V8));
GateRef callTarget = acc_.GetValueIn(gate, 0);
GateRef newTarget = builder_.Undefined();
GateRef thisObj = builder_.Undefined();

View File

@ -263,6 +263,7 @@ private:
void LowerGetUnmappedArgs(GateRef gate, GateRef glue);
void LowerCopyRestArgs(GateRef gate, GateRef glue);
GateRef LowerCallRuntime(GateRef glue, int index, const std::vector<GateRef> &args, bool useLabel = false);
int32_t ComputeCallArgc(GateRef gate, EcmaOpcode op);
BytecodeCircuitBuilder *bcBuilder_;
Circuit *circuit_;

View File

@ -33,11 +33,12 @@ void FooAOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef thisObj = TaggedArgument(4);
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bcOffset = Int32Argument(1);
(void)calltarget;
GateRef barIndex = IntBuildTaggedWithNoGC(Int32(CommonStubCSigns::BarAOT));
GateRef numArgs = IntBuildTaggedWithNoGC(Int32(2));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, barfunc, newtarget, thisObj, a, b});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, barfunc, newtarget, thisObj, a, b, bcOffset});
Return(result);
}
@ -65,11 +66,12 @@ void Foo1AOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef thisObj = TaggedArgument(4);
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bcOffset = Int32Argument(1);
(void)calltarget;
GateRef barIndex = IntBuildTaggedTypeWithNoGC(Int32(CommonStubCSigns::Bar1AOT));
GateRef numArgs = IntBuildTaggedTypeWithNoGC(Int32(3));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, barfunc, newtarget, thisObj, a, b});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, barfunc, newtarget, thisObj, a, b, bcOffset});
Return(result);
}
@ -103,13 +105,14 @@ void Foo2AOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef thisObj = TaggedArgument(4);
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bcOffset = Int32Argument(1);
(void)calltarget;
GateRef actualArgC = Int32Add(argc, Int32(1));
GateRef barIndex = IntBuildTaggedTypeWithNoGC(Int32(CommonStubCSigns::BarAOT));
GateRef numArgs = IntBuildTaggedTypeWithNoGC(Int32(2));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, actualArgC, barfunc, newtarget, thisObj,
a, b, Undefined()});
a, b, Undefined(), bcOffset});
Return(result);
}
@ -123,11 +126,12 @@ void FooNativeAOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef thisObj = TaggedArgument(4);
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bcOffset = Int32Argument(1);
(void)calltarget;
GateRef actualArgC = Int32Add(argc, Int32(1));
GateRef printfunc = CallRuntime(glue, RTSTUB_ID(GetPrintFunc), {});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, actualArgC, printfunc, newtarget, thisObj,
a, b, Undefined()});
a, b, Undefined(), bcOffset});
Return(result);
}
@ -142,15 +146,16 @@ void FooBoundAOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bindArguments = IntBuildTaggedTypeWithNoGC(Int32(37));
GateRef bcOffset = Int32Argument(1);
(void)calltarget;
GateRef numArgs = IntBuildTaggedTypeWithNoGC(Int32(2));
GateRef barIndex = IntBuildTaggedTypeWithNoGC(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, Int32(5), bindfunc, newtarget, barfunc,
Int64(0x02), bindArguments});
Int64(0x02), bindArguments, bcOffset});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, newjsfunc, newtarget, thisObj,
a, b});
a, b, bcOffset});
Return(result);
}
@ -164,13 +169,15 @@ void FooProxyAOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef thisObj = TaggedArgument(4);
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bcOffset = Int32Argument(1);
GateRef barIndex = IntBuildTaggedTypeWithNoGC(Int32(CommonStubCSigns::BarAOT));
GateRef numArgs = IntBuildTaggedTypeWithNoGC(Int32(2));
GateRef barfunc = CallRuntime(glue, RTSTUB_ID(DefineAotFunc), {barIndex, numArgs});
GateRef proxyfunc = CallRuntime(glue, RTSTUB_ID(DefineProxyFunc), {barfunc});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, proxyfunc, newtarget, thisObj, a, b});
GateRef result =
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset});
Return(result);
}
@ -184,6 +191,7 @@ void FooProxy2AOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef thisObj = TaggedArgument(4);
GateRef a = TaggedArgument(5);
GateRef b = TaggedArgument(6);
GateRef bcOffset = Int32Argument(1);
GateRef barIndex = IntBuildTaggedTypeWithNoGC(Int32(CommonStubCSigns::Bar2AOT));
GateRef numArgs = IntBuildTaggedTypeWithNoGC(Int32(2));
@ -191,7 +199,8 @@ void FooProxy2AOTStub::GenerateCircuit(const CompilationConfig *cfg)
GateRef proxyHandler = CallRuntime(glue, RTSTUB_ID(DefineProxyHandler), {barfunc});
GateRef proxyfunc = CallRuntime(glue, RTSTUB_ID(DefineProxyFunc2), {barfunc, proxyHandler});
GateRef result = CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, proxyfunc, newtarget, thisObj, a, b});
GateRef result =
CallNGCRuntime(glue, RTSTUB_ID(JSCall), {glue, argc, proxyfunc, newtarget, thisObj, a, b, bcOffset});
Return(result);
}

View File

@ -275,12 +275,15 @@
}
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define THROW_NEW_ERROR_AND_RETURN(thread, error) \
do { \
if (!(thread)->HasPendingException()) { \
(thread)->SetException(error); \
} \
return; \
#define THROW_NEW_ERROR_AND_RETURN(thread, error) \
do { \
if (!(thread)->HasPendingException()) { \
(thread)->SetException(error); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
} \
return; \
} while (false)
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
@ -292,6 +295,9 @@
ObjectFactory *_factory = (thread)->GetEcmaVM()->GetFactory(); \
JSHandle<JSObject> _error = _factory->GetJSError(type, message); \
(thread)->SetException(_error.GetTaggedValue()); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
return; \
} while (false)
@ -300,6 +306,9 @@
do { \
if (!(thread)->HasPendingException()) { \
(thread)->SetException(error); \
if ((thread)->IsPrintBCOffset()) { \
(thread)->CollectBCOffsetInfo(); \
} \
} \
return (value); \
} while (false)
@ -313,6 +322,9 @@
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

@ -391,6 +391,7 @@ Expected<JSTaggedValue, bool> EcmaVM::InvokeEcmaEntrypoint(const JSPandaFile *js
auto options = GetJSOptions();
if (options.EnableTSAot()) {
thread_->SetPrintBCOffset(true);
result = InvokeEcmaAotEntrypoint(func, jsPandaFile);
} else {
if (jsPandaFile->IsCjs()) {
@ -501,6 +502,11 @@ void EcmaVM::HandleUncaughtException(ObjectHeader *exception)
thread_->ClearException();
if (exceptionHandle->IsJSError()) {
PrintJSErrorInfo(exceptionHandle);
if (thread_->IsPrintBCOffset() && exceptionBCList_.size() != 0) {
for (auto info : exceptionBCList_) {
LOG(ERROR, RUNTIME) << "Exception at function " << info.first << ": " << info.second;
}
}
return;
}
JSHandle<EcmaString> result = JSTaggedValue::ToString(thread_, exceptionHandle);

View File

@ -328,6 +328,21 @@ public:
JSTaggedValue FindConstpool(const JSPandaFile *jsPandaFile);
void SetAOTFuncEntry(uint32_t hash, uint32_t methodId, uint64_t funcEntry);
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();
}
protected:
void HandleUncaughtException(ObjectHeader *exception);
@ -415,6 +430,7 @@ 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

@ -783,4 +783,103 @@ void FrameHandler::IterateFrameChain(JSTaggedType *start, const RootVisitor &v0,
}
}
}
std::string FrameHandler::GetAotExceptionFuncName(JSTaggedType* fp) const
{
ASSERT(FrameHandler::GetFrameType(fp) == FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
JSTaggedValue func = JSTaggedValue(*(fp + 3)); // 3: skip returnaddr and argc
JSMethod *method = JSFunction::Cast(func.GetTaggedObject())->GetMethod();
return method->GetMethodName();
}
void FrameHandler::CollectBCOffsetInfo()
{
thread_->GetEcmaVM()->ClearExceptionBCList();
JSTaggedType *current = const_cast<JSTaggedType *>(thread_->GetLastLeaveFrame());
while (current) {
FrameType type = FrameHandler::GetFrameType(current);
switch (type) {
case FrameType::OPTIMIZED_FRAME: {
auto frame = OptimizedFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::OPTIMIZED_JS_FUNCTION_ARGS_CONFIG_FRAME:
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
auto frame = OptimizedJSFunctionFrame::GetFrameFromSp(current);
auto returnAddr = reinterpret_cast<uintptr_t>(
*(reinterpret_cast<uintptr_t*>(const_cast<JSTaggedType *>(current)) + 1));
bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods();
auto constInfo = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).GetConstInfo(returnAddr);
if (!constInfo.empty()) {
auto prevFp = frame->GetPrevFrameFp();
auto name = GetAotExceptionFuncName(prevFp);
thread_->GetEcmaVM()->StoreBCOffsetInfo(name, constInfo[0]);
}
current = frame->GetPrevFrameFp();
break;
}
case FrameType::OPTIMIZED_ENTRY_FRAME: {
auto frame = OptimizedEntryFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::ASM_INTERPRETER_ENTRY_FRAME: {
auto frame = AsmInterpretedEntryFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::ASM_INTERPRETER_FRAME:
case FrameType::INTERPRETER_CONSTRUCTOR_FRAME: {
auto frame = AsmInterpretedFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::INTERPRETER_FRAME:
case FrameType::INTERPRETER_FAST_NEW_FRAME: {
auto frame = InterpretedFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::LEAVE_FRAME: {
auto frame = OptimizedLeaveFrame::GetFrameFromSp(current);
auto returnAddr = frame->returnAddr;
bool enableCompilerLog = thread_->GetEcmaVM()->GetJSOptions().WasSetlogCompiledMethods();
auto constInfo = kungfu::LLVMStackMapParser::GetInstance(enableCompilerLog).GetConstInfo(returnAddr);
if (!constInfo.empty()) {
auto prevFp = frame->GetPrevFrameFp();
auto name = GetAotExceptionFuncName(prevFp);
thread_->GetEcmaVM()->StoreBCOffsetInfo(name, constInfo[0]);
}
current = frame->GetPrevFrameFp();
break;
}
case FrameType::LEAVE_FRAME_WITH_ARGV: {
auto frame = OptimizedLeaveFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::BUILTIN_FRAME_WITH_ARGV: {
auto frame = BuiltinWithArgvFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::BUILTIN_ENTRY_FRAME:
case FrameType::BUILTIN_FRAME: {
auto frame = BuiltinFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
case FrameType::INTERPRETER_ENTRY_FRAME: {
auto frame = InterpretedEntryFrame::GetFrameFromSp(current);
current = frame->GetPrevFrameFp();
break;
}
default: {
LOG_ECMA(FATAL) << "frame type error!";
UNREACHABLE();
}
}
}
}
} // namespace panda::ecmascript

View File

@ -152,6 +152,10 @@ public:
void IterateRsp(const RootVisitor &v0, const RootRangeVisitor &v1);
void IterateSp(const RootVisitor &v0, const RootRangeVisitor &v1);
// for collecting bc offset in aot
void CollectBCOffsetInfo();
std::string GetAotExceptionFuncName(JSTaggedType* fp) const;
private:
FrameType GetFrameType() const
{

View File

@ -296,4 +296,10 @@ void JSThread::CheckJSTaggedType(JSTaggedType value) const
LOG(FATAL, RUNTIME) << "value:" << value << " is invalid!";
}
}
void JSThread::CollectBCOffsetInfo()
{
FrameHandler frameHandler(this);
frameHandler.CollectBCOffsetInfo();
}
} // namespace panda::ecmascript

View File

@ -490,6 +490,18 @@ public:
return reinterpret_cast<JSThread *>(glue - GetGlueDataOffset());
}
bool IsPrintBCOffset() const
{
return enablePrintBCOffset_;
}
void SetPrintBCOffset(bool flag)
{
enablePrintBCOffset_ = flag;
}
void CollectBCOffsetInfo();
struct GlueData : public base::AlignedStruct<JSTaggedValue::TaggedTypeSize(),
JSTaggedValue,
JSTaggedValue,
@ -641,6 +653,7 @@ private:
bool gcState_ {false};
bool isAsmInterpreter_ {false};
VmThreadControl *vmThreadControl_ {nullptr};
bool enablePrintBCOffset_ {false};
bool stableArrayElementsGuardians_ {true};
GlueData glueData_;

View File

@ -165,9 +165,10 @@ JSMethod *ObjectFactory::NewMethodForNativeFunction(const void *func)
return nativeMethods_.back();
}
JSMethod *ObjectFactory::NewMethodForAOTFunction(const void *func, size_t numArgs)
JSMethod *ObjectFactory::NewMethodForAOTFunction(const void *func, size_t numArgs, const JSPandaFile *pf,
uint32_t methodId)
{
auto method = vm_->GetChunk()->New<JSMethod>(nullptr, panda_file::File::EntityId(0)); // 0 : temporary file id
auto method = vm_->GetChunk()->New<JSMethod>(pf, panda_file::File::EntityId(methodId));
method->SetNativePointer(const_cast<void *>(func));
method->SetAotCodeBit(true);
method->SetNativeBit(false);

View File

@ -174,7 +174,7 @@ public:
void GenerateInternalNativeMethods();
JSMethod *GetMethodByIndex(MethodIndex idx);
JSMethod *NewMethodForNativeFunction(const void *func);
JSMethod *NewMethodForAOTFunction(const void *func, size_t numArgs);
JSMethod *NewMethodForAOTFunction(const void *func, size_t numArgs, const JSPandaFile *pf, uint32_t methodId);
JSHandle<ProfileTypeInfo> NewProfileTypeInfo(uint32_t length);
JSHandle<ConstantPool> NewConstantPool(uint32_t capacity);

View File

@ -29,6 +29,7 @@ group("ark_aot_test") {
# "definencfunc:definencfuncAotAction",
"delobjprop:delobjpropAotAction",
"div:divAotAction",
"exceptionhandler:exceptionhandlerAotAction",
"exp:expAotAction",
"helloaot:helloaotAotAction",
"inc:incAotAction",

View File

@ -0,0 +1,18 @@
# Copyright (c) 2022 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("//ark/js_runtime/test/test_helper.gni")
host_aot_test_action("exceptionhandler") {
deps = []
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2022 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.
*/
declare function print(str:string):string;
try {
function foo() {
JSON.parse("[1, 2");
}
foo();
} catch(e) {
print(e);
}

View File

@ -0,0 +1,16 @@
# Copyright (c) 2022 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
Exception at function foo: 9
Exception at function func_main_0: 11