Some TsAot Inline Modification

1. Resolves conflicts between inline and loop optimizations
2. Adds an inline target check to prevent changes
3. Modify the framestate metadata structure
4. Add inline testcase

ISSUE:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I73MZY

Signed-off-by: ginxu <xujie101@huawei.com>
Change-Id: I4256b3edce3e901afb67d48b0e649f39f6c251a4
This commit is contained in:
ginxu 2023-05-18 11:24:10 +08:00
parent b266e4cbc8
commit d88428b060
32 changed files with 347 additions and 80 deletions

View File

@ -530,14 +530,16 @@ void BytecodeCircuitBuilder::BuildCircuitArgs()
void BytecodeCircuitBuilder::BuildFrameArgs()
{
size_t numArgs = static_cast<size_t>(FrameArgIdx::NUM_OF_ARGS);
auto metaData = circuit_->FrameArgs();
size_t numArgs = static_cast<size_t>(FrameArgIdx::NUM_OF_ARGS) + metaData->GetInFrameStateCount();
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);
GateRef frameArgs = circuit_->NewGate(circuit_->FrameArgs(), args);
args[idx++] = circuit_->ReplaceableGate();
GateRef frameArgs = circuit_->NewGate(metaData, args);
argAcc_.SetFrameArgs(frameArgs);
}

View File

@ -464,21 +464,16 @@ public:
return hasTryCatch_;
}
GateRef GetFrameStateByIndex(size_t idx) const
{
return frameStateBuilder_.GetFrameStateByIndex(idx);
}
size_t GetNumOfFrameState() const
{
return frameStateBuilder_.GetNumOfFrameState();
}
bool EnableLoopOptimization() const
{
return (!HasTryCatch()) && (loopHeads_.size() != 0);
}
GateRef GetFrameArgs() const
{
return argAcc_.GetFrameArgs();
}
private:
void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
void BuildCatchBlocks(const ExceptionInfo &Exception);

View File

@ -169,6 +169,8 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::WIDE_NEWOBJRANGE_PREF_IMM16_V8:
case EcmaOpcode::SUPERCALLTHISRANGE_IMM8_IMM8_V8:
case EcmaOpcode::WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8:
flags |= BytecodeFlags::SUPPORT_DEOPT;
break;
case EcmaOpcode::CALLTHIS1_IMM8_V8_V8:
case EcmaOpcode::CALLARG0_IMM8:
case EcmaOpcode::CALLARG1_IMM8_V8:
@ -180,6 +182,7 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::CALLTHIS3_IMM8_V8_V8_V8_V8:
case EcmaOpcode::CALLTHISRANGE_IMM8_IMM8_V8:
flags |= BytecodeFlags::SUPPORT_DEOPT;
kind = BytecodeKind::CALL_BC;
break;
case EcmaOpcode::RETURN:
flags |= BytecodeFlags::READ_ACC;
@ -356,7 +359,8 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
kind == BytecodeKind::THROW_BC ||
kind == BytecodeKind::RESUME ||
kind == BytecodeKind::SUSPEND ||
kind == BytecodeKind::GENERATOR_RESOLVE) {
kind == BytecodeKind::GENERATOR_RESOLVE ||
kind == BytecodeKind::CALL_BC) {
flags |= BytecodeFlags::GENERAL_BC;
}
auto size = inst.GetSize();

View File

@ -63,6 +63,7 @@ enum BytecodeKind : uint32_t {
RESUME,
GENERATOR_RESOLVE,
DISCARDED,
CALL_BC,
};
class BytecodeMetaData {
@ -209,6 +210,11 @@ public:
return value_ == 0;
}
bool IsCall() const
{
return GetKind() == BytecodeKind::CALL_BC;
}
private:
BytecodeMetaData() = default;
DEFAULT_NOEXCEPT_MOVE_SEMANTIC(BytecodeMetaData);
@ -630,6 +636,11 @@ public:
return HasFuncIn() || HasNewTargetIn() || ThisObjectIn() || HasArgcIn();
}
bool IsCall() const
{
return metaData_.IsCall();
}
inline EcmaOpcode GetOpcode() const
{
return metaData_.GetOpcode();

View File

@ -177,7 +177,7 @@ public:
GateRef DeadGate()
{
if (dead_ == 0) {
if (dead_ == NullGate()) {
dead_ = NewGate(Dead(), MachineType::NOVALUE, GateType::Empty());
}
return dead_;
@ -196,6 +196,14 @@ public:
bool GetDebugInfo(GateRef g, size_t &index) const;
GateRef ReplaceableGate()
{
if (replaceable_ == NullGate()) {
replaceable_ = NewGate(Replaceable(), MachineType::NOVALUE, GateType::Empty());
}
return replaceable_;
}
private:
static const size_t CIRCUIT_SPACE = 1U << 30U; // 1GB
@ -251,8 +259,9 @@ private:
bool isArch64_ { false };
Chunk chunk_;
GateRef root_ { 0 };
GateRef dead_ { 0 };
GateRef root_ { NullGate() };
GateRef dead_ { NullGate() };
GateRef replaceable_ { NullGate() };
GateMetaBuilder metaBuilder_;
ChunkMap<GateRef, size_t> gateToDInfo_;
DebugInfo* debugInfo_ {nullptr};

View File

@ -1029,6 +1029,16 @@ inline GateRef CircuitBuilder::TypedCallBuiltin(GateRef hirGate, GateRef x, Buil
return numberMathOp;
}
inline GateRef CircuitBuilder::GetMethodId(GateRef func)
{
GateRef method = GetMethodFromFunction(func);
GateRef literalInfoOffset = IntPtr(Method::LITERAL_INFO_OFFSET);
GateRef LiteralInfo = Load(VariableType::INT64(), method, literalInfoOffset);
GateRef methodId = Int64And(Int64LSR(LiteralInfo, Int64(MethodLiteral::MethodIdBits::START_BIT)),
Int64((1LLU << MethodLiteral::MethodIdBits::SIZE) - 1));
return methodId;
}
void Label::Seal()
{
return impl_->Seal();

View File

@ -434,7 +434,7 @@ GateRef CircuitBuilder::DeoptCheck(GateRef condition, GateRef frameState, DeoptT
std::vector<GateRef> vec{frameState};
auto it = vec.begin();
GateRef preFrameState = acc_.GetPreFrameState(frameState);
while (preFrameState != Circuit::NullGate()) {
while (acc_.GetOpCode(preFrameState) != OpCode::REPLACEABLE) {
vec.insert(it, preFrameState);
preFrameState = acc_.GetPreFrameState(preFrameState);
}

View File

@ -592,6 +592,7 @@ public:
GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index);
GateRef GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index);
GateRef IsBase(GateRef ctor);
inline GateRef GetMethodId(GateRef func);
private:
#define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \

View File

@ -75,7 +75,6 @@ void FrameStateBuilder::BindStateSplit(GateRef state, GateRef depend,
size_t pcOffset, FrameStateInfo *stateInfo)
{
GateRef frameState = FrameState(pcOffset, stateInfo);
frameStateList_.emplace_back(frameState);
GateRef stateSplit = circuit_->NewGate(circuit_->StateSplit(), {state, depend, frameState});
auto uses = gateAcc_.Uses(depend);
for (auto useIt = uses.begin(); useIt != uses.end();) {
@ -98,7 +97,6 @@ void FrameStateBuilder::BindStateSplit(GateRef gate, size_t pcOffset, FrameState
state = gateAcc_.GetState(state);
}
GateRef frameState = FrameState(pcOffset, stateInfo);
frameStateList_.emplace_back(frameState);
GateRef stateSplit = circuit_->NewGate(circuit_->StateSplit(), {state, depend, frameState});
gateAcc_.ReplaceDependIn(gate, stateSplit);
if (builder_->IsLogEnabled()) {
@ -344,7 +342,6 @@ void FrameStateBuilder::BuildFrameState(GateRef frameArgs)
bcEndStateInfos_.resize(builder_->GetLastBcIndex() + 1, nullptr); // 1: +1 pcOffsets size
auto size = builder_->GetBasicBlockCount();
bbBeginStateInfos_.resize(size, nullptr);
frameStateList_.clear();
liveOutResult_ = CreateEmptyStateInfo();
BuildPostOrderList(size);
ComputeLiveState();
@ -443,6 +440,9 @@ void FrameStateBuilder::BindStateSplit(size_t size)
builder_->EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
auto &iterator = bb.GetBytecodeIterator();
auto index = iterator.Index();
if (bytecodeInfo.IsCall()) {
needStateSplit = true;
}
if (needStateSplit && NeedBindStateSplit(bb, bytecodeInfo, index)) {
auto pcOffset = builder_->GetPcOffset(index);
auto stateInfo = GetCurrentFrameInfo(bb, index);

View File

@ -76,14 +76,6 @@ public:
~FrameStateBuilder();
void BuildFrameState(GateRef frameArgs);
GateRef GetFrameStateByIndex(size_t idx) const
{
return frameStateList_.at(idx);
}
size_t GetNumOfFrameState() const
{
return frameStateList_.size();
}
private:
GateRef ValuesAt(size_t index) const
@ -156,7 +148,6 @@ private:
std::vector<FrameStateInfo *> bcEndStateInfos_;
std::vector<FrameStateInfo *> bbBeginStateInfos_;
std::vector<size_t> postOrderList_;
std::vector<GateRef> frameStateList_;
};
} // panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_FRAME_STATE_H

View File

@ -1132,18 +1132,12 @@ bool ConstGateAccessor::IsSchedulable(GateRef g) const
return GetMetaData(g)->IsSchedulable();
}
void GateAccessor::SetPreFrameState(GateRef gate, GateRef preFrameState)
{
ASSERT(GetOpCode(gate) == OpCode::FRAME_STATE && GetOpCode(preFrameState) == OpCode::FRAME_STATE);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
const_cast<FrameStateMetaData *>(gatePtr->GetFrameStateMetaData())->SetPreFrameState(preFrameState);
}
GateRef GateAccessor::GetPreFrameState(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::FRAME_STATE);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
return gatePtr->GetFrameStateMetaData()->GetPreFrameState();
GateRef frameArgs = GetFrameState(gate);
GateRef preFrameState = GetFrameState(frameArgs);
return preFrameState;
}
void GateAccessor::SetInlineCallFrameStateFlag(GateRef gate, bool isInline)
@ -1163,13 +1157,13 @@ bool GateAccessor::IsInlineCallFrameState(GateRef gate) const
size_t GateAccessor::GetFrameStateDepth(GateRef gate) const
{
ASSERT(GetOpCode(gate) == OpCode::FRAME_STATE);
Gate *gatePtr = circuit_->LoadGatePtr(gate);
GateRef preFrameState = gatePtr->GetFrameStateMetaData()->GetPreFrameState();
GateRef frameArgs = GetFrameState(gate);
GateRef preFrameState = GetFrameState(frameArgs);
size_t depth = 0;
while (preFrameState != Circuit::NullGate()) {
while (GetOpCode(preFrameState) != OpCode::REPLACEABLE) {
if (GetOpCode(preFrameState) == OpCode::FRAME_STATE) {
Gate *preGatePtr = circuit_->LoadGatePtr(preFrameState);
preFrameState = preGatePtr->GetFrameStateMetaData()->GetPreFrameState();
frameArgs = GetFrameState(preFrameState);
preFrameState = GetFrameState(frameArgs);
depth++;
} else {
break;

View File

@ -99,6 +99,7 @@ enum class DeoptType : uint8_t {
DIVZERO,
NEGTIVEINDEX,
LARGEINDEX,
INLINEFAIL,
};
enum class ICmpCondition : uint8_t {
@ -227,9 +228,10 @@ std::string MachineTypeToStr(MachineType machineType);
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
V(UpdateHotness, UPDATE_HOTNESS, 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(FrameArgs, FRAME_ARGS, GateFlags::HAS_FRAME_STATE, 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(Replaceable, REPLACEABLE, GateFlags::NONE_FLAG, 0, 0, 0) \
BINARY_GATE_META_DATA_CACHE_LIST(V) \
UNARY_GATE_META_DATA_CACHE_LIST(V)
@ -272,7 +274,8 @@ std::string MachineTypeToStr(MachineType machineType);
V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1) \
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
V(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1)
V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(JSInlineTargetTypeCheck, JSINLINETARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2)
#define GATE_META_DATA_LIST_WITH_VALUE(V) \
V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \
@ -697,12 +700,10 @@ private:
class FrameStateMetaData : public GateMetaData {
public:
static constexpr GateRef invalidGate = -1;
FrameStateMetaData(uint64_t value)
: GateMetaData(OpCode::FRAME_STATE, GateFlags::HAS_FRAME_STATE, 0, 0, value)
{
SetKind(GateMetaData::Kind::FRAME_STATE);
preFrameState_ = invalidGate;
isInlineCallFrameState_ = false;
}
@ -722,18 +723,7 @@ public:
isInlineCallFrameState_ = isInline;
}
GateRef GetPreFrameState() const
{
return preFrameState_;
}
void SetPreFrameState(GateRef preFrameState)
{
preFrameState_ = preFrameState;
}
private:
GateRef preFrameState_ {0};
bool isInlineCallFrameState_ {false};
};

View File

@ -218,7 +218,7 @@ void LLVMIRBuilder::InitializeHandlers()
OpCode::ARG_LIST, OpCode::THROW,
OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY,
OpCode::FRAME_STATE, OpCode::STATE_SPLIT, OpCode::FRAME_ARGS,
OpCode::LOOP_EXIT_DEPEND, OpCode::LOOP_EXIT, OpCode::FRAME_STATE_CHAIN
OpCode::LOOP_EXIT_DEPEND, OpCode::LOOP_EXIT, OpCode::FRAME_STATE_CHAIN, OpCode::REPLACEABLE
};
}

View File

@ -266,7 +266,8 @@ public:
{
TimeScope timescope("TSInlineLoweringPass", data->GetMethodName(), data->GetMethodOffset(), data->GetLog());
bool enableLog = data->GetLog()->EnableMethodCIRLog();
TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName());
TSInlineLowering inlining(data->GetCircuit(), data->GetPassContext(), enableLog, data->GetMethodName(),
data->GetNativeAreaAllocator());
inlining.RunTSInlineLowering();
return true;
}

View File

@ -117,7 +117,7 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &gen)
if (data.IsTypeAbort()) {
return;
}
if (passOptions_->EnableOptInlining()) {
if (passOptions_->EnableOptInlining() && passOptions_->EnableTypeLowering()) {
pipeline.RunPass<TSInlineLoweringPass>();
}
pipeline.RunPass<AsyncFunctionLoweringPass>();

View File

@ -47,10 +47,8 @@ void StateSplitLinearizer::Run()
void StateSplitLinearizer::VisitGate(GateRef gate)
{
if (acc_.GetOpCode(gate) == OpCode::STATE_SPLIT) {
frameState_ = acc_.GetFrameState(gate);
} else if (acc_.GetOpCode(gate) == OpCode::CHECK_AND_CONVERT) {
ASSERT(acc_.FindNearestFrameState(gate) == frameState_);
if (acc_.GetOpCode(gate) == OpCode::CHECK_AND_CONVERT) {
frameState_ = acc_.FindNearestFrameState(gate);
genericTypeLowering_.LowerCheckAndConvert(gate, frameState_);
}
}

View File

@ -91,6 +91,7 @@ void TSInlineLowering::TryInline(GateRef gate, bool isCallThis)
if (inlineSuccess_) {
GateRef glue = acc_.GetGlueFromArgList();
CircuitRootScope scope(circuit_);
InlineFuncCheck(gate);
InlineCall(methodInfo, methodPcInfo, inlinedMethod, gate);
ReplaceCallInput(gate, isCallThis, glue);
inlinedCall_++;
@ -178,8 +179,11 @@ void TSInlineLowering::InlineCall(MethodInfo &methodInfo, MethodPcInfo &methodPC
PassData data(&builder, circuit_, ctx_, log, fullName,
&methodInfo, hasTyps, recordName,
method, method->GetMethodId().GetOffset());
method, method->GetMethodId().GetOffset(), nativeAreaAllocator_);
PassRunner<PassData> pipeline(&data);
if (builder.EnableLoopOptimization()) {
pipeline.RunPass<LoopOptimizationPass>();
}
pipeline.RunPass<TypeInferPass>();
}
@ -342,6 +346,24 @@ void TSInlineLowering::LowerToInlineCall(GateRef callGate, const std::vector<Gat
RemoveRoot();
}
void TSInlineLowering::InlineFuncCheck(GateRef gate)
{
GateRef callState = acc_.GetState(gate);
GateRef callDepend = acc_.GetDep(gate);
ASSERT(acc_.HasFrameState(callDepend));
GateRef frameState = acc_.GetFrameState(callDepend);
size_t funcIndex = acc_.GetNumValueIn(gate) - 1;
GateRef inlineFunc = acc_.GetValueIn(gate, funcIndex);
auto type = acc_.GetGateType(inlineFunc);
GlobalTSTypeRef funcGt = type.GetGTRef();
auto methodOffset = tsManager_->GetFuncMethodOffset(funcGt);
GateRef ret = circuit_->NewGate(circuit_->JSInlineTargetTypeCheck(static_cast<size_t>(type.Value())),
MachineType::I1, {callState, callDepend, inlineFunc, builder_.IntPtr(methodOffset), frameState},
GateType::NJSValue());
acc_.ReplaceStateIn(gate, ret);
acc_.ReplaceDependIn(gate, ret);
}
void TSInlineLowering::RemoveRoot()
{
GateRef circuitRoot = acc_.GetCircuitRoot();
@ -355,15 +377,14 @@ void TSInlineLowering::RemoveRoot()
void TSInlineLowering::BuildFrameStateChain(GateRef gate, BytecodeCircuitBuilder &builder)
{
size_t size = builder.GetNumOfFrameState();
GateRef depend = acc_.GetDep(gate);
GateRef preFrameState = acc_.FindNearestFrameState(depend);
GateRef check = acc_.GetDep(gate);
GateRef stateSplit = acc_.GetDep(check);
ASSERT(acc_.GetOpCode(stateSplit) == OpCode::STATE_SPLIT);
GateRef preFrameState = acc_.FindNearestFrameState(stateSplit);
ASSERT(acc_.GetOpCode(preFrameState) == OpCode::FRAME_STATE);
acc_.SetInlineCallFrameStateFlag(preFrameState, true);
for (size_t i = 0; i < size; i++) {
GateRef curFrameState = builder.GetFrameStateByIndex(i);
acc_.SetPreFrameState(curFrameState, preFrameState);
}
GateRef frameArgs = builder.GetFrameArgs();
acc_.ReplaceFrameStateIn(frameArgs, preFrameState);
}
bool TSInlineLowering::FilterCallInTryCatch(GateRef gate)

View File

@ -45,7 +45,8 @@ private:
class TSInlineLowering {
public:
static constexpr size_t MAX_INLINE_CALL_ALLOWED = 5;
TSInlineLowering(Circuit *circuit, PassContext *ctx, bool enableLog, const std::string& name)
TSInlineLowering(Circuit *circuit, PassContext *ctx, bool enableLog, const std::string& name,
NativeAreaAllocator* nativeAreaAllocator)
: circuit_(circuit),
acc_(circuit),
builder_(circuit, ctx->GetCompilerConfig()),
@ -55,7 +56,8 @@ public:
methodName_(name),
enableTypeLowering_(ctx->GetEcmaVM()->GetJSOptions().IsEnableTypeLowering()),
traceInline_(ctx->GetEcmaVM()->GetJSOptions().GetTraceInline()),
maxInlineBytecodesCount_(ctx->GetEcmaVM()->GetJSOptions().GetMaxInlineBytecodes()) {}
maxInlineBytecodesCount_(ctx->GetEcmaVM()->GetJSOptions().GetMaxInlineBytecodes()),
nativeAreaAllocator_(nativeAreaAllocator) {}
~TSInlineLowering() = default;
@ -91,6 +93,7 @@ private:
void RemoveRoot();
void BuildFrameStateChain(GateRef gate, BytecodeCircuitBuilder &builder);
GateRef TraceInlineFunction(GateRef glue, GateRef depend, std::vector<GateRef> &args, GateRef callGate);
void InlineFuncCheck(GateRef gate);
Circuit *circuit_ {nullptr};
GateAccessor acc_;
@ -104,6 +107,7 @@ private:
bool inlineSuccess_ {false};
bool traceInline_ {false};
size_t maxInlineBytecodesCount_ {0};
NativeAreaAllocator *nativeAreaAllocator_ {nullptr};
};
} // panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_TS_INLINE_LOWERING_H

View File

@ -71,6 +71,9 @@ void TypeLowering::LowerType(GateRef gate)
case OpCode::TYPED_CALL_CHECK:
LowerCallTargetCheck(gate);
break;
case OpCode::JSINLINETARGET_TYPE_CHECK:
LowerJSInlineTargetTypeCheck(gate);
break;
case OpCode::TYPED_BINARY_OP:
LowerTypedBinaryOp(gate);
break;
@ -1043,6 +1046,20 @@ void TypeLowering::LowerCallTargetCheck(GateRef gate)
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypeLowering::LowerJSInlineTargetTypeCheck(GateRef gate)
{
Environment env(gate, circuit_, &builder_);
GateRef frameState = GetFrameState(gate);
auto func = acc_.GetValueIn(gate, 0);
GateRef isObj = builder_.TaggedIsHeapObject(func);
GateRef isJsFunc = builder_.IsJSFunction(func);
GateRef checkFunc = builder_.BoolAnd(isObj, isJsFunc);
GateRef GetMethodId = builder_.GetMethodId(func);
GateRef check = builder_.BoolAnd(checkFunc, builder_.Equal(GetMethodId, acc_.GetValueIn(gate, 1)));
builder_.DeoptCheck(check, frameState, DeoptType::INLINEFAIL);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
}
void TypeLowering::LowerTypedNewAllocateThis(GateRef gate, GateRef glue)
{
Environment env(gate, circuit_, &builder_);

View File

@ -161,6 +161,7 @@ private:
void LowerTypedNewAllocateThis(GateRef gate, GateRef glue);
void LowerTypedSuperAllocateThis(GateRef gate, GateRef glue);
void LowerGetSuperConstructor(GateRef gate);
void LowerJSInlineTargetTypeCheck(GateRef gate);
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
bool useLabel = false);

View File

@ -424,7 +424,7 @@ std::string Deoptimizier::DisplayItems(DeoptType type)
return "NOT F32ARRAY";
case DeoptType::INCONSISTENTHCLASS:
return "INCONSISTENT HCLASS";
case kungfu::DeoptType::NOTNEWOBJ:
case DeoptType::NOTNEWOBJ:
return "NOT NEWOBJ TYPE";
case DeoptType::NOTARRAYIDX:
return "NOT ARRAY IDX";
@ -438,8 +438,10 @@ std::string Deoptimizier::DisplayItems(DeoptType type)
return "NOT NEG OVERFLOW";
case DeoptType::NOTCALLTGT:
return "NOT CALL TARGET";
case kungfu::DeoptType::NOTJSCALLTGT:
case DeoptType::NOTJSCALLTGT:
return "NOT JS CALL TARGET";
case DeoptType::INLINEFAIL:
return "INLINE FAILED";
default: {
return "NOT CHECK";
}

View File

@ -181,7 +181,10 @@ group("ark_aot_ts_test") {
"try_catch_finally",
"trystglobalbynameprefid32",
"ts_inline",
"ts_inline_change_target",
"ts_inline_deopt",
"ts_inline_extends",
"ts_inline_loop",
"ts_inline_max_call",
"typeof",
"xor",

View 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_change_target") {
deps = []
is_enable_opt_inlining = true
is_enable_inline_trace = true
log_option = " --log-info=trace"
}

View File

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

View File

@ -0,0 +1,33 @@
/*
* 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;
class A {
foo () {
print("foo");
}
}
let a = new A();
a.foo();
function bar()
{
print("bar");
}
let p = A.prototype;
Object.defineProperty(p, "foo", {value:bar});
a.foo();

View 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_extends") {
deps = []
is_enable_opt_inlining = true
is_enable_inline_trace = true
log_option = " --log-info=trace"
}

View File

@ -0,0 +1,15 @@
# 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.
[trace] aot inline function name: foo@ts_inline_extends caller function name: func_main_0@ts_inline_extends
B.run

View 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;
class A {
run() {
print("A.run")
}
}
class B extends A {
run() {
print("B.run")
}
}
class C {
obj: A
constructor(obj: A) {
this.obj = obj
}
foo() {
this.obj.run()
}
}
let b = new B()
let c = new C(b)
c.foo();

View 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_loop") {
deps = []
is_enable_opt_inlining = true
is_enable_inline_trace = true
log_option = " --log-info=trace"
}

View File

@ -0,0 +1,15 @@
# 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.
[trace] aot inline function name: loop@ts_inline_loop caller function name: func_main_0@ts_inline_loop
128

View File

@ -0,0 +1,26 @@
/*
* 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;
function loop(arg : number) : number {
let a = arg;
while (a < 100) {
a = a * 2;
}
return a;
}
print(loop(1));

View File

@ -395,7 +395,8 @@ template("host_aot_js_test_action") {
if (defined(invoker.is_enable_opt_inlining) &&
invoker.is_enable_opt_inlining) {
_aot_compile_options_ += " --compiler-opt-inlining=true"
_aot_compile_options_ +=
" --compiler-opt-inlining=true --compiler-opt-type-lowering=true"
}
if (defined(invoker.is_enable_inline_trace) &&
@ -605,7 +606,8 @@ template("host_aot_test_action") {
}
if (defined(invoker.is_enable_opt_inlining) &&
invoker.is_enable_opt_inlining) {
_aot_compile_options_ += " --compiler-opt-inlining=true"
_aot_compile_options_ +=
" --compiler-opt-inlining=true --compiler-opt-type-lowering=true"
}
if (defined(invoker.is_enable_inline_trace) &&
@ -679,7 +681,8 @@ template("host_aot_test_action") {
if (defined(invoker.is_enable_opt_inlining) &&
invoker.is_enable_opt_inlining) {
_aot_compile_options_ += " --compiler-opt-inlining=true"
_aot_compile_options_ +=
" --compiler-opt-inlining=true --compiler-opt-type-lowering=true"
}
if (defined(invoker.is_enable_inline_trace) &&