mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
AOT callstack supports inline functions
1.Add frame args chain on bytecodes which can throw 2.Record inline method offsets in frame args 3.Push method offsets of inlined methods into stackmaps when callout aot 4.Collect inline method offsets and output them 5.Fix literal offsets error before try-catch 6.Add testcases Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I7Z24N?from=project-issue Signed-off-by: zhangyukun8 <zhangyukun8@huawei.com> Change-Id: I7f4927a2dfc6a71e44b59cb392acb9b2d3f408e2
This commit is contained in:
parent
a8d2a0828e
commit
f31710d73d
@ -3731,6 +3731,8 @@ JSHandle<JSObject> Builtins::InitializeArkTools(const JSHandle<GlobalEnv> &env)
|
||||
SetFunction(env, tools, "isNotHoleProperty", builtins::BuiltinsArkTools::IsNotHoleProperty,
|
||||
FunctionLength::TWO);
|
||||
SetFunction(env, tools, "forceFullGC", builtins::BuiltinsArkTools::ForceFullGC, FunctionLength::ZERO);
|
||||
SetFunction(env, tools, "hiddenStackSourceFile", builtins::BuiltinsArkTools::HiddenStackSourceFile,
|
||||
FunctionLength::ZERO);
|
||||
SetFunction(env, tools, "removeAOTFlag", builtins::BuiltinsArkTools::RemoveAOTFlag, FunctionLength::ONE);
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
SetFunction(env, tools, "startCpuProf", builtins::BuiltinsArkTools::StartCpuProfiler, FunctionLength::ZERO);
|
||||
|
@ -146,6 +146,15 @@ JSTaggedValue BuiltinsArkTools::IsNotHoleProperty(EcmaRuntimeCallInfo *info)
|
||||
return GetTaggedBoolean(attr.IsNotHole());
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::HiddenStackSourceFile(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
[[maybe_unused]] DisallowGarbageCollection noGc;
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
thread->SetEnableStackSourceFile(false);
|
||||
return JSTaggedValue::True();
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::ExcutePendingJob(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
|
||||
static JSTaggedValue ForceFullGC(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue HiddenStackSourceFile(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue RemoveAOTFlag(EcmaRuntimeCallInfo *info);
|
||||
|
||||
#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
|
||||
|
@ -156,8 +156,14 @@ GateRef ArgumentAccessor::GetFrameArgsIn(GateRef gate, FrameArgIdx idx)
|
||||
ASSERT(gateAcc.GetOpCode(gate) == OpCode::JS_BYTECODE || gateAcc.GetOpCode(gate) == OpCode::FRAME_STATE);
|
||||
GateRef frameArgs = Circuit::NullGate();
|
||||
if (gateAcc.GetOpCode(gate) == OpCode::JS_BYTECODE) {
|
||||
frameArgs = gateAcc.GetFrameState(gate);
|
||||
ASSERT(gateAcc.GetOpCode(frameArgs) == OpCode::FRAME_ARGS);
|
||||
GateRef frameState = gateAcc.GetFrameState(gate);
|
||||
OpCode op = gateAcc.GetOpCode(frameState);
|
||||
if (op == OpCode::FRAME_STATE) {
|
||||
frameArgs = gateAcc.GetValueIn(frameState, 0); // 0: frame args
|
||||
} else {
|
||||
ASSERT(op == OpCode::FRAME_ARGS);
|
||||
frameArgs = frameState;
|
||||
}
|
||||
} else {
|
||||
frameArgs = gateAcc.GetValueIn(gate, 0); // 0: frame args
|
||||
}
|
||||
|
@ -538,14 +538,16 @@ void BytecodeCircuitBuilder::BuildCircuitArgs()
|
||||
|
||||
void BytecodeCircuitBuilder::BuildFrameArgs()
|
||||
{
|
||||
auto metaData = circuit_->FrameArgs();
|
||||
size_t numArgs = static_cast<size_t>(FrameArgIdx::NUM_OF_ARGS);
|
||||
UInt32PairAccessor accessor(0, 0);
|
||||
auto metaData = circuit_->FrameArgs(accessor.ToValue());
|
||||
size_t numArgs = metaData->GetNumIns();
|
||||
std::vector<GateRef> args(numArgs, Circuit::NullGate());
|
||||
size_t idx = 0;
|
||||
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::FUNC);
|
||||
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
|
||||
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
|
||||
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::ACTUAL_ARGC);
|
||||
args[idx++] = GetPreFrameArgs();
|
||||
GateRef frameArgs = circuit_->NewGate(metaData, args);
|
||||
argAcc_.SetFrameArgs(frameArgs);
|
||||
}
|
||||
@ -883,7 +885,7 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
|
||||
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
|
||||
GateRef gate = 0;
|
||||
bool writable = !bytecodeInfo.NoSideEffects();
|
||||
bool hasFrameState = bytecodeInfo.HasFrameArgs();
|
||||
bool hasFrameState = bytecodeInfo.HasFrameState();
|
||||
size_t pcOffset = GetPcOffset(iterator.Index());
|
||||
auto meta = circuit_->JSBytecode(numValueInputs, bytecodeInfo.GetOpcode(), pcOffset, writable, hasFrameState);
|
||||
std::vector<GateRef> inList = CreateGateInList(bytecodeInfo, meta);
|
||||
|
@ -280,6 +280,7 @@ public:
|
||||
loopExitToVregGate_(circuit->chunk()),
|
||||
loopExitToAccGate_(circuit->chunk()),
|
||||
preFrameState_(circuit_->GetRoot()),
|
||||
preFrameArgs_(circuit_->GetRoot()),
|
||||
isInline_(isInline)
|
||||
{
|
||||
}
|
||||
@ -532,6 +533,16 @@ public:
|
||||
preFrameState_ = gate;
|
||||
}
|
||||
|
||||
GateRef GetPreFrameArgs() const
|
||||
{
|
||||
return preFrameArgs_;
|
||||
}
|
||||
|
||||
void SetPreFrameArgs(GateRef gate)
|
||||
{
|
||||
preFrameArgs_ = gate;
|
||||
}
|
||||
|
||||
const ChunkVector<size_t>& GetDfsList() const
|
||||
{
|
||||
return dfsList_;
|
||||
@ -635,6 +646,7 @@ private:
|
||||
ChunkMap<std::pair<GateRef, uint16_t>, GateRef> loopExitToVregGate_;
|
||||
ChunkMap<GateRef, GateRef> loopExitToAccGate_;
|
||||
GateRef preFrameState_ {Circuit::NullGate()};
|
||||
GateRef preFrameArgs_ {Circuit::NullGate()};
|
||||
bool isInline_ {false};
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -94,17 +94,50 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
|
||||
}
|
||||
|
||||
switch (inst.GetOpcode()) {
|
||||
case EcmaOpcode::MOV_V4_V4:
|
||||
case EcmaOpcode::MOV_V8_V8:
|
||||
case EcmaOpcode::MOV_V16_V16:
|
||||
case EcmaOpcode::STA_V8:
|
||||
case EcmaOpcode::LDA_V8:
|
||||
case EcmaOpcode::LDNAN:
|
||||
case EcmaOpcode::LDINFINITY:
|
||||
case EcmaOpcode::LDUNDEFINED:
|
||||
case EcmaOpcode::LDNULL:
|
||||
case EcmaOpcode::LDTRUE:
|
||||
case EcmaOpcode::LDFALSE:
|
||||
case EcmaOpcode::LDHOLE:
|
||||
case EcmaOpcode::LDAI_IMM32:
|
||||
case EcmaOpcode::FLDAI_IMM64:
|
||||
case EcmaOpcode::LDFUNCTION:
|
||||
case EcmaOpcode::LDA_STR_ID16:
|
||||
case EcmaOpcode::TYPEOF_IMM8:
|
||||
case EcmaOpcode::TYPEOF_IMM16:
|
||||
case EcmaOpcode::ISTRUE:
|
||||
case EcmaOpcode::ISFALSE:
|
||||
case EcmaOpcode::JEQZ_IMM8:
|
||||
case EcmaOpcode::JEQZ_IMM16:
|
||||
case EcmaOpcode::JEQZ_IMM32:
|
||||
case EcmaOpcode::JNEZ_IMM8:
|
||||
case EcmaOpcode::JNEZ_IMM16:
|
||||
case EcmaOpcode::JNEZ_IMM32:
|
||||
case EcmaOpcode::JMP_IMM8:
|
||||
case EcmaOpcode::JMP_IMM16:
|
||||
case EcmaOpcode::JMP_IMM32:
|
||||
case EcmaOpcode::STMODULEVAR_IMM8:
|
||||
case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16:
|
||||
case EcmaOpcode::LDEXTERNALMODULEVAR_IMM8:
|
||||
case EcmaOpcode::WIDE_LDEXTERNALMODULEVAR_PREF_IMM16:
|
||||
case EcmaOpcode::NEWLEXENV_IMM8:
|
||||
case EcmaOpcode::WIDE_NEWLEXENV_PREF_IMM16:
|
||||
case EcmaOpcode::POPLEXENV:
|
||||
case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16:
|
||||
case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16:
|
||||
case EcmaOpcode::ASYNCFUNCTIONENTER:
|
||||
case EcmaOpcode::SETGENERATORSTATE_IMM8:
|
||||
case EcmaOpcode::GETRESUMEMODE:
|
||||
case EcmaOpcode::RESUMEGENERATOR:
|
||||
case EcmaOpcode::RETURN:
|
||||
case EcmaOpcode::RETURNUNDEFINED:
|
||||
case EcmaOpcode::LDLEXVAR_IMM4_IMM4:
|
||||
case EcmaOpcode::LDLEXVAR_IMM8_IMM8:
|
||||
case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
|
||||
@ -118,7 +151,14 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
|
||||
case EcmaOpcode::CREATEEMPTYOBJECT:
|
||||
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
|
||||
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
|
||||
case EcmaOpcode::SETGENERATORSTATE_IMM8:
|
||||
case EcmaOpcode::CREATEITERRESULTOBJ_V8_V8:
|
||||
case EcmaOpcode::DEFINEFUNC_IMM8_ID16_IMM8:
|
||||
case EcmaOpcode::DEFINEFUNC_IMM16_ID16_IMM8:
|
||||
case EcmaOpcode::DEFINEMETHOD_IMM8_ID16_IMM8:
|
||||
case EcmaOpcode::DEFINEMETHOD_IMM16_ID16_IMM8:
|
||||
case EcmaOpcode::GETUNMAPPEDARGS:
|
||||
case EcmaOpcode::DEBUGGER:
|
||||
case EcmaOpcode::NOP:
|
||||
flags |= BytecodeFlags::NO_THROW;
|
||||
break;
|
||||
default:
|
||||
|
@ -685,6 +685,11 @@ public:
|
||||
return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn();
|
||||
}
|
||||
|
||||
bool HasFrameState() const
|
||||
{
|
||||
return HasFrameArgs() || !NoThrow();
|
||||
}
|
||||
|
||||
bool IsCall() const
|
||||
{
|
||||
return metaData_.IsCall();
|
||||
|
@ -1237,6 +1237,7 @@ inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, const std::vect
|
||||
std::vector<GateRef> inList { currentControl, currentDepend };
|
||||
inList.insert(inList.end(), args.begin(), args.end());
|
||||
inList.push_back(Int8(static_cast<int8_t>(id)));
|
||||
AppendFrameArgs(inList, hirGate);
|
||||
|
||||
auto builtinOp = TypedCallOperator(hirGate, MachineType::I64, inList);
|
||||
currentLabel->SetControl(builtinOp);
|
||||
|
@ -601,7 +601,7 @@ GateRef CircuitBuilder::GetSuperConstructor(GateRef ctor)
|
||||
GateRef CircuitBuilder::TypedCallOperator(GateRef hirGate, MachineType type, const std::vector<GateRef> &inList)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
auto numValueIn = inList.size() - 2; // 2: state & depend
|
||||
auto numValueIn = inList.size() - 3; // 3: state & depend & frame state
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(hirGate);
|
||||
ASSERT(pcOffset != 0);
|
||||
return GetCircuit()->NewGate(circuit_->TypedCallBuiltin(numValueIn, pcOffset), type, inList.size(), inList.data(),
|
||||
@ -1050,6 +1050,9 @@ GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef targ
|
||||
inputs.insert(inputs.end(), args.begin(), args.end());
|
||||
auto numValuesIn = args.size() + 2; // 2: target & glue
|
||||
if (GetCircuit()->IsOptimizedJSFunctionFrame() && hirGate != Circuit::NullGate()) {
|
||||
AppendFrameArgs(inputs, hirGate);
|
||||
numValuesIn += 1;
|
||||
|
||||
GateRef pcOffset = Int64(acc_.TryGetPcOffset(hirGate));
|
||||
inputs.emplace_back(pcOffset);
|
||||
numValuesIn += 1;
|
||||
@ -1112,6 +1115,8 @@ GateRef CircuitBuilder::NoLabelCallRuntime(GateRef glue, GateRef depend, size_t
|
||||
std::vector<GateRef> inputs { depend, target, glue };
|
||||
inputs.insert(inputs.end(), args.begin(), args.end());
|
||||
auto numValuesIn = args.size() + 2; // 2: target & glue
|
||||
inputs.emplace_back(IntPtr(0)); // framestate slot
|
||||
numValuesIn += 1;
|
||||
GateRef pcOffset = Int64(acc_.TryGetPcOffset(hirGate));
|
||||
inputs.emplace_back(pcOffset);
|
||||
numValuesIn += 1;
|
||||
@ -1264,6 +1269,16 @@ GateRef CircuitBuilder::ConvertHoleAsUndefined(GateRef receiver)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CircuitBuilder::AppendFrameArgs(std::vector<GateRef> &args, GateRef hirGate)
|
||||
{
|
||||
GateRef frameArgs = acc_.GetFrameArgs(hirGate);
|
||||
if (frameArgs == Circuit::NullGate()) {
|
||||
args.emplace_back(IntPtr(0));
|
||||
} else {
|
||||
args.emplace_back(frameArgs);
|
||||
}
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(hirGate) == OpCode::JS_BYTECODE);
|
||||
@ -1275,6 +1290,7 @@ GateRef CircuitBuilder::Construct(GateRef hirGate, std::vector<GateRef> args)
|
||||
ASSERT(pcOffset != 0);
|
||||
args.insert(args.begin(), currentDepend);
|
||||
args.insert(args.begin(), currentControl);
|
||||
AppendFrameArgs(args, hirGate);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->Construct(bitfield, pcOffset), MachineType::I64,
|
||||
args.size(), args.data(), GateType::AnyType());
|
||||
currentLabel->SetControl(callGate);
|
||||
@ -1293,6 +1309,7 @@ GateRef CircuitBuilder::TypedCall(GateRef hirGate, std::vector<GateRef> args, bo
|
||||
ASSERT(pcOffset != 0);
|
||||
args.insert(args.begin(), currentDepend);
|
||||
args.insert(args.begin(), currentControl);
|
||||
AppendFrameArgs(args, hirGate);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->TypedCall(bitfield, pcOffset, isNoGC), MachineType::I64,
|
||||
args.size(), args.data(), GateType::AnyType());
|
||||
currentLabel->SetControl(callGate);
|
||||
@ -1311,6 +1328,7 @@ GateRef CircuitBuilder::TypedFastCall(GateRef hirGate, std::vector<GateRef> args
|
||||
ASSERT(pcOffset != 0);
|
||||
args.insert(args.begin(), currentDepend);
|
||||
args.insert(args.begin(), currentControl);
|
||||
AppendFrameArgs(args, hirGate);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->TypedFastCall(bitfield, pcOffset, isNoGC), MachineType::I64,
|
||||
args.size(), args.data(), GateType::AnyType());
|
||||
currentLabel->SetControl(callGate);
|
||||
@ -1328,9 +1346,12 @@ GateRef CircuitBuilder::CallGetter(GateRef hirGate, GateRef receiver, GateRef pr
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
std::vector<GateRef> args = { currentControl, currentDepend, receiver, propertyLookupResult };
|
||||
AppendFrameArgs(args, hirGate);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->CallGetter(pcOffset),
|
||||
MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, propertyLookupResult },
|
||||
args.size(),
|
||||
args.data(),
|
||||
GateType::AnyType(),
|
||||
comment);
|
||||
currentLabel->SetControl(callGate);
|
||||
@ -1348,9 +1369,12 @@ GateRef CircuitBuilder::CallSetter(GateRef hirGate, GateRef receiver, GateRef pr
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
std::vector<GateRef> args = { currentControl, currentDepend, receiver, propertyLookupResult, value };
|
||||
AppendFrameArgs(args, hirGate);
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->CallSetter(pcOffset),
|
||||
MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, propertyLookupResult, value },
|
||||
args.size(),
|
||||
args.data(),
|
||||
GateType::AnyType(),
|
||||
comment);
|
||||
currentLabel->SetControl(callGate);
|
||||
|
@ -324,6 +324,7 @@ public:
|
||||
GateRef InsertTypedBinaryop(GateRef left, GateRef right, GateType leftType, GateType rightType,
|
||||
GateType gateType, PGOSampleType sampleType, TypedBinOp op);
|
||||
GateRef InsertRangeCheckPredicate(GateRef left, TypedBinOp cond, GateRef right);
|
||||
void AppendFrameArgs(std::vector<GateRef> &args, GateRef hirGate);
|
||||
GateRef TypedConditionJump(MachineType type, TypedJumpOp jumpOp, BranchKind branchKind, GateType typeVal,
|
||||
const std::vector<GateRef>& inList);
|
||||
GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState);
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
|
||||
virtual void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
|
||||
const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile,
|
||||
const std::string &methodName) = 0;
|
||||
const std::string &methodName, bool enableOptInlining) = 0;
|
||||
};
|
||||
|
||||
class CodeGenerator {
|
||||
@ -57,9 +57,9 @@ public:
|
||||
}
|
||||
|
||||
void Run(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
|
||||
const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile)
|
||||
const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, bool enableOptInlining)
|
||||
{
|
||||
impl_->GenerateCode(circuit, graph, cfg, methodLiteral, jsPandaFile, methodName_);
|
||||
impl_->GenerateCode(circuit, graph, cfg, methodLiteral, jsPandaFile, methodName_, enableOptInlining);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -57,6 +57,11 @@ GateRef FrameStateBuilder::BuildFrameValues(FrameStateInfo *stateInfo)
|
||||
return circuit_->NewGate(circuit_->FrameValues(frameStateInputs), inList);
|
||||
}
|
||||
|
||||
GateRef FrameStateBuilder::BuildEmptyFrameValues()
|
||||
{
|
||||
return circuit_->NewGate(circuit_->FrameValues(0), {});
|
||||
}
|
||||
|
||||
GateRef FrameStateBuilder::BuildFrameStateGate(size_t pcOffset, GateRef frameValues, FrameStateOutput output)
|
||||
{
|
||||
GateRef frameArgs = builder_->GetFrameArgs();
|
||||
|
@ -107,6 +107,7 @@ private:
|
||||
void UpdateVirtualRegister(size_t id, size_t index, GateRef gate);
|
||||
GateRef BuildFrameStateGate(size_t pcOffset, GateRef frameValues, FrameStateOutput output);
|
||||
GateRef BuildFrameValues(FrameStateInfo *stateInfo);
|
||||
GateRef BuildEmptyFrameValues();
|
||||
|
||||
FrameStateInfo *CreateEmptyStateInfo();
|
||||
void BuildPostOrderList(size_t size);
|
||||
|
@ -434,6 +434,48 @@ uint32_t GateAccessor::TryGetPcOffset(GateRef gate) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t GateAccessor::TryGetMethodOffset(GateRef gate) const
|
||||
{
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
OpCode op = GetOpCode(gate);
|
||||
switch (op) {
|
||||
case OpCode::FRAME_ARGS: {
|
||||
UInt32PairAccessor accessor(gatePtr->GetOneParameterMetaData()->GetValue());
|
||||
return accessor.GetFirstValue();
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GateRef GateAccessor::GetFrameArgs(GateRef gate) const
|
||||
{
|
||||
if (!HasFrameState(gate)) {
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
if (GetOpCode(gate) == OpCode::FRAME_STATE) {
|
||||
return GetValueIn(gate, 0); // 0: frame args
|
||||
}
|
||||
GateRef frameState = GetFrameState(gate);
|
||||
OpCode op = GetOpCode(frameState);
|
||||
if (op == OpCode::FRAME_ARGS) {
|
||||
return frameState;
|
||||
}
|
||||
if (op == OpCode::FRAME_STATE) {
|
||||
return GetValueIn(frameState, 0); // 0: frame args
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
void GateAccessor::UpdateMethodOffset(GateRef gate, uint32_t methodOffset)
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::FRAME_ARGS);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
UInt32PairAccessor accessor(methodOffset, 0);
|
||||
const_cast<OneParameterMetaData *>(gatePtr->GetOneParameterMetaData())->SetValue(accessor.ToValue());
|
||||
}
|
||||
|
||||
PGOSampleType GateAccessor::TryGetPGOType(GateRef gate) const
|
||||
{
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
@ -1306,6 +1348,20 @@ void GateAccessor::GetStateInAndDependIn(GateRef insertAfter, GateRef &stateIn,
|
||||
ASSERT(GetDependCount(dependIn) > 0);
|
||||
}
|
||||
|
||||
size_t GateAccessor::GetFrameDepth(GateRef gate, OpCode op)
|
||||
{
|
||||
if (GetOpCode(gate) != op) {
|
||||
return 0;
|
||||
}
|
||||
size_t depth = 0;
|
||||
GateRef prev = GetFrameState(gate);
|
||||
while ((GetOpCode(prev) == op)) {
|
||||
depth++;
|
||||
prev = GetFrameState(prev);
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
GateRef GateAccessor::GetFrameState(GateRef gate) const
|
||||
{
|
||||
ASSERT(HasFrameState(gate));
|
||||
|
@ -410,6 +410,9 @@ public:
|
||||
bool TypedCallIsNoGC(GateRef gate) const;
|
||||
bool IsNoGC(GateRef gate) const;
|
||||
uint32_t TryGetPcOffset(GateRef gate) const;
|
||||
uint32_t TryGetMethodOffset(GateRef gate) const;
|
||||
GateRef GetFrameArgs(GateRef gate) const;
|
||||
void UpdateMethodOffset(GateRef gate, uint32_t methodOffset);
|
||||
PGOSampleType TryGetPGOType(GateRef gate) const;
|
||||
void TrySetPGOType(GateRef gate, PGOSampleType type);
|
||||
ElementsKind TryGetElementsKind(GateRef gate) const;
|
||||
@ -553,6 +556,7 @@ public:
|
||||
return gate == GetStateRoot();
|
||||
}
|
||||
|
||||
size_t GetFrameDepth(GateRef gate, OpCode op);
|
||||
GateRef GetFrameState(GateRef gate) const;
|
||||
void ReplaceFrameStateIn(GateRef gate, GateRef in);
|
||||
bool HasFrameState(GateRef gate) const;
|
||||
|
@ -316,7 +316,6 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(CheckSafePointAndStackOver, CHECK_SAFEPOINT_AND_STACKOVER, GateFlags::NO_WRITE, 1, 1, 0) \
|
||||
V(Dead, DEAD, GateFlags::NONE_FLAG, 0, 0, 0) \
|
||||
V(FrameArgs, FRAME_ARGS, GateFlags::NONE_FLAG, 0, 0, 4) \
|
||||
V(GetEnv, GET_ENV, GateFlags::NONE_FLAG, 0, 0, 1) \
|
||||
V(ConvertHoleAsUndefined, CONVERT_HOLE_AS_UNDEFINED, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(StartAllocate, START_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \
|
||||
@ -340,17 +339,17 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
|
||||
V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
|
||||
V(TypedCallBuiltin, TYPED_CALL_BUILTIN, GateFlags::NO_WRITE, 1, 1, value) \
|
||||
V(Construct, CONSTRUCT, GateFlags::NONE_FLAG, 1, 1, value)
|
||||
#define GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
|
||||
V(TypedCallBuiltin, TYPED_CALL_BUILTIN, GateFlags::CHECKABLE, 1, 1, value) \
|
||||
V(Construct, CONSTRUCT, GateFlags::HAS_FRAME_STATE, 1, 1, value)
|
||||
|
||||
#define GATE_META_DATA_LIST_FOR_CALL(V) \
|
||||
V(TypedCall, TYPEDCALL, GateFlags::NONE_FLAG, 1, 1, value) \
|
||||
V(TypedFastCall, TYPEDFASTCALL, GateFlags::NONE_FLAG, 1, 1, value)
|
||||
V(TypedCall, TYPEDCALL, GateFlags::HAS_FRAME_STATE, 1, 1, value) \
|
||||
V(TypedFastCall, TYPEDFASTCALL, GateFlags::HAS_FRAME_STATE, 1, 1, value)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(V) \
|
||||
V(CallGetter, CALL_GETTER, GateFlags::NONE_FLAG, 1, 1, 2) \
|
||||
V(CallSetter, CALL_SETTER, GateFlags::NONE_FLAG, 1, 1, 3)
|
||||
V(CallGetter, CALL_GETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 2) \
|
||||
V(CallSetter, CALL_SETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 3)
|
||||
|
||||
#define GATE_META_DATA_LIST_WITH_SIZE(V) \
|
||||
V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0) \
|
||||
@ -389,6 +388,7 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(GetGlobalEnvObj, GET_GLOBAL_ENV_OBJ, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(GetGlobalEnvObjHClass, GET_GLOBAL_ENV_OBJ_HCLASS, GateFlags::NO_WRITE, 0, 1, 1) \
|
||||
V(GetGlobalConstantValue, GET_GLOBAL_CONSTANT_VALUE, GateFlags::NO_WRITE, 0, 1, 0) \
|
||||
V(FrameArgs, FRAME_ARGS, GateFlags::HAS_FRAME_STATE, 0, 0, 4) \
|
||||
V(FrameState, FRAME_STATE, GateFlags::HAS_FRAME_STATE, 0, 0, 2) \
|
||||
V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 0) \
|
||||
V(CreateArrayWithBuffer, CREATE_ARRAY_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
|
@ -225,7 +225,8 @@ void LLVMIRGeneratorImpl::GenerateCodeForStub(Circuit *circuit, const ControlFlo
|
||||
|
||||
void LLVMIRGeneratorImpl::GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
|
||||
const panda::ecmascript::MethodLiteral *methodLiteral,
|
||||
const JSPandaFile *jsPandaFile, const std::string &methodName)
|
||||
const JSPandaFile *jsPandaFile, const std::string &methodName,
|
||||
bool enableOptInlining)
|
||||
{
|
||||
auto function = module_->AddFunc(methodLiteral, jsPandaFile);
|
||||
circuit->SetFrameType(FrameType::OPTIMIZED_JS_FUNCTION_FRAME);
|
||||
@ -236,7 +237,7 @@ void LLVMIRGeneratorImpl::GenerateCode(Circuit *circuit, const ControlFlowGraph
|
||||
conv = CallSignature::CallConv::WebKitJSCallConv;
|
||||
}
|
||||
LLVMIRBuilder builder(&graph, circuit, module_, function, cfg, conv,
|
||||
enableLog_, methodLiteral->IsFastCall(), methodName);
|
||||
enableLog_, methodLiteral->IsFastCall(), methodName, enableOptInlining);
|
||||
builder.Build();
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,8 @@ public:
|
||||
void GenerateCodeForStub(Circuit *circuit, const ControlFlowGraph &graph, size_t index,
|
||||
const CompilationConfig *cfg) override;
|
||||
void GenerateCode(Circuit *circuit, const ControlFlowGraph &graph, const CompilationConfig *cfg,
|
||||
const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, const std::string &methodName) override;
|
||||
const MethodLiteral *methodLiteral, const JSPandaFile *jsPandaFile, const std::string &methodName,
|
||||
bool enableOptInlining) override;
|
||||
|
||||
bool IsLogEnabled() const
|
||||
{
|
||||
|
@ -59,10 +59,10 @@ namespace panda::ecmascript::kungfu {
|
||||
LLVMIRBuilder::LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
|
||||
LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg,
|
||||
CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot,
|
||||
const std::string &funcName)
|
||||
const std::string &funcName, bool enableOptInlining)
|
||||
: compCfg_(cfg), scheduledGates_(schedule), circuit_(circuit), acc_(circuit), module_(module->GetModule()),
|
||||
function_(function), llvmModule_(module), callConv_(callConv), enableLog_(enableLog),
|
||||
isFastCallAot_(isFastCallAot)
|
||||
isFastCallAot_(isFastCallAot), enableOptInlining_(enableOptInlining)
|
||||
{
|
||||
ASSERT(compCfg_->Is64Bit());
|
||||
context_ = module->GetContext();
|
||||
@ -568,7 +568,8 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
|
||||
|
||||
size_t actualNumArgs = 0;
|
||||
LLVMValueRef pcOffset = LLVMConstInt(GetInt32T(), 0, 0);
|
||||
ComputeArgCountAndPCOffset(actualNumArgs, pcOffset, inList, kind);
|
||||
GateRef frameArgs = Circuit::NullGate();
|
||||
ComputeArgCountAndExtraInfo(actualNumArgs, pcOffset, frameArgs, inList, kind);
|
||||
|
||||
std::vector<LLVMValueRef> params;
|
||||
params.push_back(glue); // glue
|
||||
@ -588,9 +589,7 @@ void LLVMIRBuilder::VisitRuntimeCall(GateRef gate, const std::vector<GateRef> &i
|
||||
LLVMValueRef runtimeCall = nullptr;
|
||||
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
|
||||
std::vector<LLVMValueRef> values;
|
||||
auto pcIndex = LLVMConstInt(GetInt64T(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
values.push_back(pcIndex);
|
||||
values.push_back(pcOffset);
|
||||
CollectExraCallSiteInfo(values, pcOffset, frameArgs);
|
||||
runtimeCall = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs,
|
||||
"", values.data(), values.size());
|
||||
} else {
|
||||
@ -753,13 +752,14 @@ LLVMValueRef LLVMIRBuilder::GetBuiltinsStubOffset(LLVMValueRef glue)
|
||||
return LLVMConstInt(glueType, JSThread::GlueData::GetBuiltinsStubEntriesOffset(compCfg_->Is32Bit()), 0);
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::ComputeArgCountAndPCOffset(size_t &actualNumArgs, LLVMValueRef &pcOffset,
|
||||
const std::vector<GateRef> &inList, CallExceptionKind kind)
|
||||
void LLVMIRBuilder::ComputeArgCountAndExtraInfo(size_t &actualNumArgs, LLVMValueRef &pcOffset, GateRef &frameArgs,
|
||||
const std::vector<GateRef> &inList, CallExceptionKind kind)
|
||||
{
|
||||
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
|
||||
actualNumArgs = inList.size() - 1;
|
||||
pcOffset = gate2LValue_[inList[actualNumArgs]];
|
||||
ASSERT(acc_.GetOpCode(inList[actualNumArgs]) == OpCode::CONSTANT);
|
||||
actualNumArgs = inList.size() - 2; // 2: pcOffset and frameArgs
|
||||
pcOffset = gate2LValue_[inList[actualNumArgs + 1]];
|
||||
frameArgs = inList[actualNumArgs];
|
||||
ASSERT(acc_.GetOpCode(inList[actualNumArgs + 1]) == OpCode::CONSTANT);
|
||||
} else {
|
||||
actualNumArgs = inList.size();
|
||||
}
|
||||
@ -806,6 +806,47 @@ void LLVMIRBuilder::VisitReadSp(GateRef gate)
|
||||
gate2LValue_[gate] = spValue;
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::CollectExraCallSiteInfo(std::vector<LLVMValueRef> &values, LLVMValueRef pcOffset,
|
||||
GateRef frameArgs)
|
||||
{
|
||||
// pc offset
|
||||
auto pcIndex = LLVMConstInt(GetInt64T(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
values.push_back(pcIndex);
|
||||
values.push_back(pcOffset);
|
||||
|
||||
if (!enableOptInlining_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (frameArgs == Circuit::NullGate()) {
|
||||
return;
|
||||
}
|
||||
if (acc_.GetOpCode(frameArgs) != OpCode::FRAME_ARGS) {
|
||||
return;
|
||||
}
|
||||
uint32_t maxDepth = acc_.GetFrameDepth(frameArgs, OpCode::FRAME_ARGS);
|
||||
if (maxDepth == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
maxDepth = std::min(maxDepth, MAX_METHOD_OFFSET_NUM);
|
||||
size_t shift = Deoptimizier::ComputeShift(MAX_METHOD_OFFSET_NUM);
|
||||
ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
|
||||
for (int32_t curDepth = static_cast<int32_t>(maxDepth - 1); curDepth >= 0; curDepth--) {
|
||||
ASSERT(acc_.GetOpCode(frameArgs) == OpCode::FRAME_ARGS);
|
||||
// method id
|
||||
uint32_t methodOffset = acc_.TryGetMethodOffset(frameArgs);
|
||||
frameArgs = acc_.GetFrameState(frameArgs);
|
||||
if (methodOffset == FrameStateOutput::INVALID_INDEX) {
|
||||
methodOffset = 0;
|
||||
}
|
||||
int32_t specCallTargetIndex = static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) - curDepth;
|
||||
int32_t encodeIndex = Deoptimizier::EncodeDeoptVregIndex(specCallTargetIndex, curDepth, shift);
|
||||
values.emplace_back(LLVMConstInt(GetInt32T(), encodeIndex, false));
|
||||
values.emplace_back(LLVMConstInt(GetInt32T(), methodOffset, false));
|
||||
}
|
||||
}
|
||||
|
||||
void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList, OpCode op)
|
||||
{
|
||||
size_t targetIndex = static_cast<size_t>(CallInputs::TARGET);
|
||||
@ -877,7 +918,8 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
int extraParameterCnt = 0;
|
||||
size_t actualNumArgs = 0;
|
||||
LLVMValueRef pcOffset = LLVMConstInt(GetInt32T(), 0, 0);
|
||||
ComputeArgCountAndPCOffset(actualNumArgs, pcOffset, inList, kind);
|
||||
GateRef frameArgs = Circuit::NullGate();
|
||||
ComputeArgCountAndExtraInfo(actualNumArgs, pcOffset, frameArgs, inList, kind);
|
||||
|
||||
// then push the actual parameter for js function call
|
||||
for (size_t paraIdx = firstArg + 1; paraIdx < actualNumArgs; ++paraIdx) {
|
||||
@ -903,9 +945,7 @@ void LLVMIRBuilder::VisitCall(GateRef gate, const std::vector<GateRef> &inList,
|
||||
callee = LLVMBuildPointerCast(builder_, callee, LLVMPointerType(funcType, 0), "");
|
||||
if (kind == CallExceptionKind::HAS_PC_OFFSET) {
|
||||
std::vector<LLVMValueRef> values;
|
||||
auto pcIndex = LLVMConstInt(GetInt64T(), static_cast<int>(SpecVregIndex::PC_OFFSET_INDEX), 1);
|
||||
values.push_back(pcIndex);
|
||||
values.push_back(pcOffset);
|
||||
CollectExraCallSiteInfo(values, pcOffset, frameArgs);
|
||||
call = LLVMBuildCall3(builder_, funcType, callee, params.data(), actualNumArgs - firstArg + extraParameterCnt,
|
||||
"", values.data(), values.size());
|
||||
} else {
|
||||
@ -2342,15 +2382,10 @@ void LLVMIRBuilder::VisitDeoptCheck(GateRef gate)
|
||||
LLVMTypeRef funcType = GetExperimentalDeoptTy();
|
||||
|
||||
std::vector<LLVMValueRef> values;
|
||||
size_t maxDepth = 0;
|
||||
GateRef frameState = acc_.GetFrameState(deoptFrameState);
|
||||
while ((acc_.GetOpCode(frameState) == OpCode::FRAME_STATE)) {
|
||||
maxDepth++;
|
||||
frameState = acc_.GetFrameState(frameState);
|
||||
}
|
||||
size_t maxDepth = acc_.GetFrameDepth(deoptFrameState, OpCode::FRAME_STATE);
|
||||
params.push_back(ConvertInt32ToTaggedInt(LLVMConstInt(GetInt32T(), static_cast<uint32_t>(maxDepth), false)));
|
||||
size_t shift = Deoptimizier::ComputeShift(maxDepth);
|
||||
frameState = deoptFrameState;
|
||||
GateRef frameState = deoptFrameState;
|
||||
ArgumentAccessor argAcc(const_cast<Circuit *>(circuit_));
|
||||
for (int32_t curDepth = static_cast<int32_t>(maxDepth); curDepth >= 0; curDepth--) {
|
||||
ASSERT(acc_.GetOpCode(frameState) == OpCode::FRAME_STATE);
|
||||
|
@ -366,7 +366,8 @@ class LLVMIRBuilder {
|
||||
public:
|
||||
LLVMIRBuilder(const std::vector<std::vector<GateRef>> *schedule, Circuit *circuit,
|
||||
LLVMModule *module, LLVMValueRef function, const CompilationConfig *cfg,
|
||||
CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot, const std::string &funcName);
|
||||
CallSignature::CallConv callConv, bool enableLog, bool isFastCallAot, const std::string &funcName,
|
||||
bool enableOptInlining = false);
|
||||
~LLVMIRBuilder();
|
||||
void Build();
|
||||
|
||||
@ -418,6 +419,8 @@ private:
|
||||
const std::string &realName = "") const;
|
||||
LLVMValueRef GetCallee(const std::vector<GateRef> &inList, const CallSignature *signature,
|
||||
const std::string &realName = "");
|
||||
void CollectExraCallSiteInfo(std::vector<LLVMValueRef> &values, LLVMValueRef pcOffset,
|
||||
GateRef frameState);
|
||||
LLVMValueRef GetFunctionFromGlobalValue(LLVMValueRef glue, const CallSignature *signature,
|
||||
LLVMValueRef reloc) const;
|
||||
bool IsInterpreted() const;
|
||||
@ -513,7 +516,7 @@ private:
|
||||
LLVMValueRef GetBuiltinsStubOffset(LLVMValueRef glue);
|
||||
LLVMValueRef GetBaseOffset(GateRef gate, LLVMValueRef glue);
|
||||
CallExceptionKind GetCallExceptionKind(size_t index, OpCode op) const;
|
||||
void ComputeArgCountAndPCOffset(size_t &actualNumArgs, LLVMValueRef &pcOffset,
|
||||
void ComputeArgCountAndExtraInfo(size_t &actualNumArgs, LLVMValueRef &pcOffset, GateRef &frameArgs,
|
||||
const std::vector<GateRef> &inList, CallExceptionKind kind);
|
||||
void SaveLexicalEnvOnOptJSFuncFrame(LLVMValueRef value);
|
||||
void SaveJSFuncOnOptJSFuncFrame(LLVMValueRef value);
|
||||
@ -560,6 +563,7 @@ private:
|
||||
bool enableLog_ {false};
|
||||
bool isFastCallAot_ {false};
|
||||
LLVMMetadataRef dFuncMD_ {nullptr};
|
||||
bool enableOptInlining_ {false};
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_LLVM_IR_BUILDER_H
|
||||
|
@ -598,10 +598,12 @@ public:
|
||||
auto module = data->GetAotModule();
|
||||
TimeScope timescope("LLVMIRGenPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
|
||||
bool enableLog = data->GetLog()->EnableMethodCIRLog() || data->GetLog()->OutputASM();
|
||||
PassOptions *passOptions = data->GetPassOptions();
|
||||
bool enableOptInlining = passOptions->EnableOptInlining() && passOptions->EnableTypeLowering();
|
||||
CreateCodeGen(module, enableLog);
|
||||
CodeGenerator codegen(llvmImpl_, data->GetMethodName());
|
||||
codegen.Run(data->GetCircuit(), data->GetConstScheduleResult(), data->GetCompilerConfig(),
|
||||
data->GetMethodLiteral(), data->GetJSPandaFile());
|
||||
data->GetMethodLiteral(), data->GetJSPandaFile(), enableOptInlining);
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
|
@ -56,7 +56,7 @@ HWTEST_F_L0(LoweringRelateGateTests, TypeCheckFramework)
|
||||
auto arg0 = builder.Arguments(0);
|
||||
auto pcGate = circuit.GetConstantGate(MachineType::I64, 0, GateType::NJSValue());
|
||||
auto frameArgs = circuit.NewGate(
|
||||
circuit.FrameArgs(), {builder.Arguments(3), builder.Arguments(4), builder.Arguments(5), builder.Arguments(2)});
|
||||
circuit.FrameArgs(0), {builder.Arguments(3), builder.Arguments(4), builder.Arguments(5), builder.Arguments(2)});
|
||||
auto frameState = circuit.NewGate(circuit.FrameState(1), {pcGate, frameArgs});
|
||||
auto stateSplit = circuit.NewGate(circuit.StateSplit(), {state, depend, frameState});
|
||||
builder.SetDepend(stateSplit);
|
||||
|
@ -35,6 +35,32 @@ void TSInlineLowering::RunTSInlineLowering()
|
||||
workList.pop();
|
||||
TryInline(info, workList);
|
||||
}
|
||||
CollectInlineInfo();
|
||||
}
|
||||
|
||||
void TSInlineLowering::CollectInlineInfo()
|
||||
{
|
||||
std::vector<GateRef> gateList;
|
||||
circuit_->GetAllGates(gateList);
|
||||
for (const auto &gate : gateList) {
|
||||
auto op = acc_.GetOpCode(gate);
|
||||
if (op == OpCode::FRAME_ARGS) {
|
||||
GetInlinedMethodId(gate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TSInlineLowering::GetInlinedMethodId(GateRef gate)
|
||||
{
|
||||
ASSERT(acc_.GetOpCode(gate) == OpCode::FRAME_ARGS);
|
||||
GateRef func = acc_.GetValueIn(gate, static_cast<size_t>(FrameArgIdx::FUNC));
|
||||
uint32_t methodOffset = 0;
|
||||
auto funcType = acc_.GetGateType(func);
|
||||
if (tsManager_->IsFunctionTypeKind(funcType)) {
|
||||
GlobalTSTypeRef gt = funcType.GetGTRef();
|
||||
methodOffset = tsManager_->GetFuncMethodOffset(gt);
|
||||
}
|
||||
acc_.UpdateMethodOffset(gate, methodOffset);
|
||||
}
|
||||
|
||||
void TSInlineLowering::CandidateInlineCall(GateRef gate, ChunkQueue<CallGateInfo> &workList)
|
||||
@ -533,6 +559,8 @@ void TSInlineLowering::BuildFrameStateChain(CallGateInfo &info, BytecodeCircuitB
|
||||
GateRef preFrameState = GetFrameState(info);
|
||||
ASSERT(acc_.GetOpCode(preFrameState) == OpCode::FRAME_STATE);
|
||||
builder.SetPreFrameState(preFrameState);
|
||||
GateRef frameArgs = acc_.GetFrameArgs(preFrameState);
|
||||
builder.SetPreFrameArgs(frameArgs);
|
||||
}
|
||||
|
||||
bool TSInlineLowering::FilterCallInTryCatch(GateRef gate)
|
||||
|
@ -169,6 +169,8 @@ private:
|
||||
return kind == CallKind::CALL_SETTER;
|
||||
}
|
||||
|
||||
void CollectInlineInfo();
|
||||
void GetInlinedMethodId(GateRef gate);
|
||||
void CandidateInlineCall(GateRef gate, ChunkQueue<CallGateInfo> &workList);
|
||||
void TryInline(CallGateInfo &info, ChunkQueue<CallGateInfo> &workList);
|
||||
bool FilterInlinedMethod(MethodLiteral* method, std::vector<const uint8_t*> pcOffsets);
|
||||
|
@ -94,7 +94,7 @@ void TypeRecorder::CollectLiteralGT(TSManager *tsManager, TypeLocation &loc, Glo
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytecodes_->GetOpcode(pcOffsets_[bcIdx]) == EcmaOpcode::STA_V8) {
|
||||
while (bytecodes_->GetOpcode(pcOffsets_[bcIdx]) == EcmaOpcode::STA_V8) {
|
||||
// bcIndex of literal marked in es2abc maybe in the next bc whose opcode should be sta.
|
||||
bcIdx--;
|
||||
loc.SetBcIdx(bcIdx);
|
||||
|
@ -33,8 +33,16 @@ enum class SpecVregIndex: int {
|
||||
NEWTARGET_INDEX = -5,
|
||||
THIS_OBJECT_INDEX = -6,
|
||||
ACTUAL_ARGC_INDEX = -7,
|
||||
FIRST_METHOD_OFFSET_INDEX = -8,
|
||||
PADDING1 = -9,
|
||||
PADDING2 = -10,
|
||||
PADDING3 = -11,
|
||||
MAX_METHOD_OFFSET_INDEX = -12,
|
||||
};
|
||||
|
||||
static constexpr uint32_t MAX_METHOD_OFFSET_NUM = static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) -
|
||||
static_cast<int32_t>(SpecVregIndex::MAX_METHOD_OFFSET_INDEX) + 1;
|
||||
|
||||
struct Context {
|
||||
uintptr_t callsiteSp;
|
||||
uintptr_t callsiteFp;
|
||||
|
@ -27,7 +27,7 @@
|
||||
#endif
|
||||
|
||||
namespace panda::ecmascript {
|
||||
std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset)
|
||||
std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile)
|
||||
{
|
||||
std::string data;
|
||||
data.append(" at ");
|
||||
@ -40,12 +40,17 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset)
|
||||
// source file
|
||||
DebugInfoExtractor *debugExtractor =
|
||||
JSPandaFileManager::GetInstance()->GetJSPtExtractor(method->GetJSPandaFile());
|
||||
const std::string &sourceFile = debugExtractor->GetSourceFile(method->GetMethodId());
|
||||
if (sourceFile.empty()) {
|
||||
data.push_back('?');
|
||||
if (enableStackSourceFile) {
|
||||
const std::string &sourceFile = debugExtractor->GetSourceFile(method->GetMethodId());
|
||||
if (sourceFile.empty()) {
|
||||
data.push_back('?');
|
||||
} else {
|
||||
data += sourceFile;
|
||||
}
|
||||
} else {
|
||||
data += sourceFile;
|
||||
data.append("hidden");
|
||||
}
|
||||
|
||||
data.push_back(':');
|
||||
// line number and column number
|
||||
auto callbackLineFunc = [&data](int32_t line) -> bool {
|
||||
@ -67,6 +72,32 @@ std::string JsStackInfo::BuildMethodTrace(Method *method, uint32_t pcOffset)
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string JsStackInfo::BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets)
|
||||
{
|
||||
std::string data;
|
||||
std::map<uint32_t, uint32_t>::reverse_iterator it;
|
||||
for (it = methodOffsets.rbegin(); it != methodOffsets.rend(); it++) {
|
||||
uint32_t methodId = it->second;
|
||||
std::string name;
|
||||
if (methodId == 0) {
|
||||
name = "unknown";
|
||||
} else {
|
||||
name = std::string(MethodLiteral::GetMethodName(pf, EntityId(methodId)));
|
||||
if (name == "") {
|
||||
name = "anonymous";
|
||||
}
|
||||
}
|
||||
data.append(" at ");
|
||||
data.append(name);
|
||||
data.append(" (maybe inlined).");
|
||||
data.append(" depth: ");
|
||||
data.append(std::to_string(it->first));
|
||||
|
||||
data.push_back('\n');
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative)
|
||||
{
|
||||
std::string data;
|
||||
@ -82,7 +113,10 @@ std::string JsStackInfo::BuildJsStackTrace(JSThread *thread, bool needNative)
|
||||
}
|
||||
if (!method->IsNativeWithCallField()) {
|
||||
auto pcOffset = it.GetBytecodeOffset();
|
||||
data += BuildMethodTrace(method, pcOffset);
|
||||
const JSPandaFile *pf = method->GetJSPandaFile();
|
||||
std::map<uint32_t, uint32_t> methodOffsets = it.GetInlinedMethodInfo();
|
||||
data += BuildInlinedMethodTrace(pf, methodOffsets);
|
||||
data += BuildMethodTrace(method, pcOffset, thread->GetEnableStackSourceFile());
|
||||
} else if (needNative) {
|
||||
auto addr = method->GetNativePointer();
|
||||
std::stringstream strm;
|
||||
|
@ -29,9 +29,10 @@ struct JsFrameInfo {
|
||||
};
|
||||
class JsStackInfo {
|
||||
public:
|
||||
static std::string BuildInlinedMethodTrace(const JSPandaFile *pf, std::map<uint32_t, uint32_t> &methodOffsets);
|
||||
static std::string BuildJsStackTrace(JSThread *thread, bool needNative);
|
||||
static std::vector<JsFrameInfo> BuildJsStackInfo(JSThread *thread);
|
||||
static std::string BuildMethodTrace(Method *method, uint32_t pcOffset);
|
||||
static std::string BuildMethodTrace(Method *method, uint32_t pcOffset, bool enableStackSourceFile = true);
|
||||
static AOTFileManager *loader;
|
||||
};
|
||||
void CrashCallback(char *buf, size_t len, void *ucontext);
|
||||
|
@ -394,6 +394,22 @@ uintptr_t FrameIterator::GetPrevFrameCallSiteSp() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<uint32_t, uint32_t> FrameIterator::GetInlinedMethodInfo()
|
||||
{
|
||||
std::map<uint32_t, uint32_t> inlineMethodInfos;
|
||||
FrameType type = this->GetFrameType();
|
||||
switch (type) {
|
||||
case FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME:
|
||||
case FrameType::OPTIMIZED_JS_FUNCTION_FRAME: {
|
||||
CollectMethodOffsetInfo(inlineMethodInfos);
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return inlineMethodInfos;
|
||||
}
|
||||
|
||||
uint32_t FrameIterator::GetBytecodeOffset() const
|
||||
{
|
||||
FrameType type = this->GetFrameType();
|
||||
@ -486,6 +502,11 @@ void FrameIterator::CollectPcOffsetInfo(ConstInfo &info) const
|
||||
arkStackMapParser_->GetConstInfo(optimizedReturnAddr_, info, stackMapAddr_);
|
||||
}
|
||||
|
||||
void FrameIterator::CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &info) const
|
||||
{
|
||||
arkStackMapParser_->GetMethodOffsetInfo(optimizedReturnAddr_, info, stackMapAddr_);
|
||||
}
|
||||
|
||||
void FrameIterator::CollectArkDeopt(std::vector<kungfu::ARKDeopt>& deopts) const
|
||||
{
|
||||
arkStackMapParser_->GetArkDeopt(optimizedReturnAddr_, stackMapAddr_, deopts);
|
||||
|
@ -1625,6 +1625,7 @@ public:
|
||||
int ComputeDelta() const;
|
||||
template <GCVisitedFlag GCVisit = GCVisitedFlag::IGNORED>
|
||||
void Advance();
|
||||
std::map<uint32_t, uint32_t> GetInlinedMethodInfo();
|
||||
uint32_t GetBytecodeOffset() const;
|
||||
uintptr_t GetPrevFrameCallSiteSp() const;
|
||||
uintptr_t GetPrevFrame() const;
|
||||
@ -1642,6 +1643,7 @@ public:
|
||||
}
|
||||
bool IteratorStackMap(const RootVisitor &visitor, const RootBaseAndDerivedVisitor &derivedVisitor) const;
|
||||
void CollectPcOffsetInfo(ConstInfo &info) const;
|
||||
void CollectMethodOffsetInfo(std::map<uint32_t, uint32_t> &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;
|
||||
|
@ -527,6 +527,16 @@ public:
|
||||
return vmThreadControl_;
|
||||
}
|
||||
|
||||
void SetEnableStackSourceFile(bool value)
|
||||
{
|
||||
enableStackSourceFile_ = value;
|
||||
}
|
||||
|
||||
bool GetEnableStackSourceFile() const
|
||||
{
|
||||
return enableStackSourceFile_;
|
||||
}
|
||||
|
||||
static constexpr size_t GetGlueDataOffset()
|
||||
{
|
||||
return MEMBER_OFFSET(JSThread, glueData_);
|
||||
@ -993,6 +1003,7 @@ private:
|
||||
bool runtimeState_ {false};
|
||||
bool isAsmInterpreter_ {false};
|
||||
VmThreadControl *vmThreadControl_ {nullptr};
|
||||
bool enableStackSourceFile_ {true};
|
||||
|
||||
// CpuProfiler
|
||||
bool isProfiling_ {false};
|
||||
|
@ -91,6 +91,35 @@ void ArkStackMapParser::GetConstInfo(uintptr_t callSiteAddr, LLVMStackMapType::C
|
||||
info.emplace_back(v);
|
||||
}
|
||||
|
||||
void ArkStackMapParser::GetMethodOffsetInfo(uintptr_t callSiteAddr, std::map<uint32_t, uint32_t>& info,
|
||||
uint8_t *stackmapAddr) const
|
||||
{
|
||||
std::vector<ARKDeopt> deopts;
|
||||
GetArkDeopt(callSiteAddr, stackmapAddr, deopts);
|
||||
if (deopts.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ARKDeopt target;
|
||||
size_t shift = Deoptimizier::ComputeShift(MAX_METHOD_OFFSET_NUM);
|
||||
LLVMStackMapType::VRegId startId = static_cast<LLVMStackMapType::VRegId>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX);
|
||||
for (int i = MAX_METHOD_OFFSET_NUM - 1; i >= 0; i--) {
|
||||
LLVMStackMapType::VRegId id = startId - i;
|
||||
target.id = Deoptimizier::EncodeDeoptVregIndex(id, i, shift);
|
||||
auto it = std::lower_bound(deopts.begin(), deopts.end(), target,
|
||||
[](const ARKDeopt& a, const ARKDeopt& b) {
|
||||
return a.id < b.id;
|
||||
});
|
||||
if (it == deopts.end() || (it->id > target.id)) {
|
||||
continue;
|
||||
}
|
||||
ASSERT(it->kind == LocationTy::Kind::CONSTANT);
|
||||
ASSERT(std::holds_alternative<LLVMStackMapType::IntType>(it->value));
|
||||
auto v = std::get<LLVMStackMapType::IntType>(it->value);
|
||||
info[static_cast<int32_t>(SpecVregIndex::FIRST_METHOD_OFFSET_INDEX) - id] = v;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t ArkStackMapParser::GetStackSlotAddress(const LLVMStackMapType::DwarfRegAndOffsetType info,
|
||||
uintptr_t callSiteSp, uintptr_t callsiteFp) const
|
||||
{
|
||||
|
@ -38,6 +38,8 @@ public:
|
||||
enableLog_ = false;
|
||||
}
|
||||
void GetConstInfo(uintptr_t callsite, LLVMStackMapType::ConstInfo& info, uint8_t *stackmapAddr = nullptr) const;
|
||||
void GetMethodOffsetInfo(uintptr_t callSiteAddr, std::map<uint32_t, uint32_t>& info,
|
||||
uint8_t *stackmapAddr) const;
|
||||
bool IteratorStackMap(const RootVisitor& visitor,
|
||||
const RootBaseAndDerivedVisitor& derivedVisitor,
|
||||
uintptr_t callSiteAddr, uintptr_t callsiteFp,
|
||||
|
@ -211,6 +211,14 @@ group("ark_aot_ts_test") {
|
||||
"ts_inline_change_target",
|
||||
"ts_inline_deopt",
|
||||
"ts_inline_deopt_loop",
|
||||
"ts_inline_exception1",
|
||||
"ts_inline_exception2",
|
||||
"ts_inline_exception3",
|
||||
"ts_inline_exception4",
|
||||
"ts_inline_exception5",
|
||||
"ts_inline_exception6",
|
||||
"ts_inline_exception7",
|
||||
"ts_inline_exception8",
|
||||
"ts_inline_extends",
|
||||
"ts_inline_loop",
|
||||
"ts_inline_max_call",
|
||||
|
19
test/aottest/ts_inline_exception1/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception1/BUILD.gn
Normal 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_test_action("ts_inline_exception1") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
18
test/aottest/ts_inline_exception1/expect_output.txt
Normal file
18
test/aottest/ts_inline_exception1/expect_output.txt
Normal 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: b is not defined
|
||||
at foo1 (maybe inlined). depth: 0
|
||||
at foo2 (hidden:26:26)
|
||||
at func_main_0 (hidden:28:1)
|
||||
|
32
test/aottest/ts_inline_exception1/ts_inline_exception1.ts
Normal file
32
test/aottest/ts_inline_exception1/ts_inline_exception1.ts
Normal 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
try {
|
||||
function foo1() {
|
||||
b.c
|
||||
}
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
foo2()
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
19
test/aottest/ts_inline_exception2/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception2/BUILD.gn
Normal 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_test_action("ts_inline_exception2") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
22
test/aottest/ts_inline_exception2/expect_output.txt
Normal file
22
test/aottest/ts_inline_exception2/expect_output.txt
Normal file
@ -0,0 +1,22 @@
|
||||
# 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
|
||||
at foo1 (maybe inlined). depth: 4
|
||||
at foo2 (maybe inlined). depth: 3
|
||||
at foo3 (maybe inlined). depth: 2
|
||||
at foo4 (maybe inlined). depth: 1
|
||||
at foo5 (maybe inlined). depth: 0
|
||||
at foo6 (hidden:40:40)
|
||||
at func_main_0 (hidden:42:1)
|
||||
|
53
test/aottest/ts_inline_exception2/ts_inline_exception2.ts
Normal file
53
test/aottest/ts_inline_exception2/ts_inline_exception2.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
|
||||
try {
|
||||
let a = {}
|
||||
function foo1() {
|
||||
a()
|
||||
}
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
function foo3() {
|
||||
foo2()
|
||||
}
|
||||
function foo4() {
|
||||
foo3()
|
||||
}
|
||||
function foo5() {
|
||||
foo4()
|
||||
}
|
||||
function foo6() {
|
||||
foo5()
|
||||
}
|
||||
foo6()
|
||||
function foo7() {
|
||||
foo6()
|
||||
}
|
||||
function foo8() {
|
||||
foo7()
|
||||
}
|
||||
foo8()
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
19
test/aottest/ts_inline_exception3/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception3/BUILD.gn
Normal 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_test_action("ts_inline_exception3") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
20
test/aottest/ts_inline_exception3/expect_output.txt
Normal file
20
test/aottest/ts_inline_exception3/expect_output.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# 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
|
||||
at foo1 (maybe inlined). depth: 2
|
||||
at foo3 (maybe inlined). depth: 1
|
||||
at foo4 (maybe inlined). depth: 0
|
||||
at foo5 (hidden:36:36)
|
||||
at func_main_0 (hidden:38:1)
|
||||
|
42
test/aottest/ts_inline_exception3/ts_inline_exception3.ts
Normal file
42
test/aottest/ts_inline_exception3/ts_inline_exception3.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
|
||||
try {
|
||||
function foo1() {
|
||||
JSON.parse("[1, 2");
|
||||
}
|
||||
function foo2() {
|
||||
}
|
||||
function foo3() {
|
||||
foo2()
|
||||
foo1()
|
||||
}
|
||||
function foo4() {
|
||||
foo3()
|
||||
}
|
||||
function foo5() {
|
||||
foo4()
|
||||
}
|
||||
foo5()
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
19
test/aottest/ts_inline_exception4/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception4/BUILD.gn
Normal 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_test_action("ts_inline_exception4") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
21
test/aottest/ts_inline_exception4/expect_output.txt
Normal file
21
test/aottest/ts_inline_exception4/expect_output.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# 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: c is not defined
|
||||
at anonymous (hidden:23:23)
|
||||
at foo1 (maybe inlined). depth: 1
|
||||
at foo2 (maybe inlined). depth: 0
|
||||
at foo3 (hidden:35:35)
|
||||
at foo4 (hidden:38:38)
|
||||
at func_main_0 (hidden:41:1)
|
||||
|
45
test/aottest/ts_inline_exception4/ts_inline_exception4.ts
Normal file
45
test/aottest/ts_inline_exception4/ts_inline_exception4.ts
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
const o = {
|
||||
[Symbol.toPrimitive] () {
|
||||
c
|
||||
return 1
|
||||
}
|
||||
}
|
||||
try {
|
||||
function foo1() {
|
||||
if (o == 1) {}
|
||||
}
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
function foo3(a) {
|
||||
foo2()
|
||||
}
|
||||
function foo4() {
|
||||
foo3()
|
||||
}
|
||||
|
||||
foo4()
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
19
test/aottest/ts_inline_exception5/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception5/BUILD.gn
Normal 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_test_action("ts_inline_exception5") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
20
test/aottest/ts_inline_exception5/expect_output.txt
Normal file
20
test/aottest/ts_inline_exception5/expect_output.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# 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: Invalid array length
|
||||
at foo1 (maybe inlined). depth: 1
|
||||
at foo2 (maybe inlined). depth: 0
|
||||
at foo3 (hidden:30:30)
|
||||
at foo4 (hidden:33:33)
|
||||
at func_main_0 (hidden:35:1)
|
||||
|
39
test/aottest/ts_inline_exception5/ts_inline_exception5.ts
Normal file
39
test/aottest/ts_inline_exception5/ts_inline_exception5.ts
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
|
||||
try {
|
||||
function foo1() {
|
||||
new Array(111111111111111111111)
|
||||
}
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
function foo3(a) {
|
||||
foo2()
|
||||
}
|
||||
function foo4() {
|
||||
foo3()
|
||||
}
|
||||
foo4()
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
19
test/aottest/ts_inline_exception6/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception6/BUILD.gn
Normal 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_test_action("ts_inline_exception6") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
22
test/aottest/ts_inline_exception6/expect_output.txt
Normal file
22
test/aottest/ts_inline_exception6/expect_output.txt
Normal file
@ -0,0 +1,22 @@
|
||||
# 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: c is not defined
|
||||
at foo1 (maybe inlined). depth: 0
|
||||
at foo2 (hidden:27:27)
|
||||
at foo3 (hidden:31:31)
|
||||
at foo4 (hidden:34:34)
|
||||
at foo5 (maybe inlined). depth: 0
|
||||
at foo6 (hidden:40:40)
|
||||
at func_main_0 (hidden:42:1)
|
||||
|
46
test/aottest/ts_inline_exception6/ts_inline_exception6.ts
Normal file
46
test/aottest/ts_inline_exception6/ts_inline_exception6.ts
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
|
||||
try {
|
||||
function foo1() {
|
||||
c
|
||||
}
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
function foo3(a: number): number {
|
||||
let b: number = a + 1
|
||||
foo2()
|
||||
}
|
||||
function foo4() {
|
||||
foo3(<number><Object>'a', 1)
|
||||
}
|
||||
function foo5() {
|
||||
foo4(1)
|
||||
}
|
||||
function foo6() {
|
||||
foo5()
|
||||
}
|
||||
foo6(1)
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
21
test/aottest/ts_inline_exception7/BUILD.gn
Normal file
21
test/aottest/ts_inline_exception7/BUILD.gn
Normal file
@ -0,0 +1,21 @@
|
||||
# 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_test_action("ts_inline_exception7") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_opt_inlining = true
|
||||
is_enable_trace_deopt = true
|
||||
}
|
20
test/aottest/ts_inline_exception7/expect_output.txt
Normal file
20
test/aottest/ts_inline_exception7/expect_output.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# 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
|
||||
at Student (hidden:26:26)
|
||||
at foo1 (maybe inlined). depth: 1
|
||||
at foo2 (maybe inlined). depth: 0
|
||||
at foo3 (hidden:40:40)
|
||||
at func_main_0 (hidden:43:1)
|
||||
|
47
test/aottest/ts_inline_exception7/ts_inline_exception7.ts
Normal file
47
test/aottest/ts_inline_exception7/ts_inline_exception7.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
try {
|
||||
class Student {
|
||||
name : string;
|
||||
constructor(name:string) {
|
||||
this.name = name;
|
||||
JSON.parse("[1, 2");
|
||||
}
|
||||
}
|
||||
|
||||
function foo1() {
|
||||
let stu = new Student("xiaoming");
|
||||
let ans = stu.name
|
||||
}
|
||||
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
|
||||
function foo3() {
|
||||
foo2()
|
||||
}
|
||||
|
||||
foo3(1)
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
19
test/aottest/ts_inline_exception8/BUILD.gn
Normal file
19
test/aottest/ts_inline_exception8/BUILD.gn
Normal 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_test_action("ts_inline_exception8") {
|
||||
deps = []
|
||||
is_enable_opt_inlining = true
|
||||
}
|
20
test/aottest/ts_inline_exception8/expect_output.txt
Normal file
20
test/aottest/ts_inline_exception8/expect_output.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
0
|
||||
ReferenceError: a is not defined
|
||||
at name (hidden:25:25)
|
||||
at foo1 (maybe inlined). depth: 0
|
||||
at foo2 (hidden:34:34)
|
||||
at func_main_0 (hidden:37:1)
|
||||
|
41
test/aottest/ts_inline_exception8/ts_inline_exception8.ts
Normal file
41
test/aottest/ts_inline_exception8/ts_inline_exception8.ts
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare function print(arg:any):string;
|
||||
declare class ArkTools {
|
||||
static hiddenStackSourceFile(): boolean;
|
||||
}
|
||||
ArkTools.hiddenStackSourceFile()
|
||||
class A {
|
||||
constructor() {}
|
||||
get name() {
|
||||
print(arguments.length)
|
||||
a.b
|
||||
}
|
||||
set name(a) {}
|
||||
}
|
||||
let ins = new A()
|
||||
function foo1() {
|
||||
ins.name
|
||||
}
|
||||
function foo2() {
|
||||
foo1()
|
||||
}
|
||||
try {
|
||||
foo2()
|
||||
} catch (e) {
|
||||
print(e)
|
||||
print(e.stack)
|
||||
}
|
Loading…
Reference in New Issue
Block a user