mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
description: update hotness counter for AOT
issues: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I6DDSA Signed-off-by: K0u1hw <wangchunyang15@huawei.com> Change-Id: I1094ac0d31cb466cbabd6159faf150a507652635
This commit is contained in:
parent
f706569cf4
commit
f16ff2a015
@ -52,6 +52,40 @@ void BytecodeCircuitBuilder::BuildRegionInfo()
|
||||
}
|
||||
}
|
||||
|
||||
int32_t BytecodeCircuitBuilder::GetJumpOffset(uint32_t bcIndex) const
|
||||
{
|
||||
auto pc = GetPCByIndex(bcIndex);
|
||||
auto &info = GetBytecodeInfo(bcIndex);
|
||||
int32_t offset = 0;
|
||||
switch (info.GetOpcode()) {
|
||||
case EcmaOpcode::JEQZ_IMM8:
|
||||
case EcmaOpcode::JNEZ_IMM8:
|
||||
case EcmaOpcode::JMP_IMM8:
|
||||
offset = static_cast<int8_t>(READ_INST_8_0());
|
||||
break;
|
||||
case EcmaOpcode::JNEZ_IMM16:
|
||||
case EcmaOpcode::JEQZ_IMM16:
|
||||
case EcmaOpcode::JMP_IMM16:
|
||||
offset = static_cast<int16_t>(READ_INST_16_0());
|
||||
break;
|
||||
case EcmaOpcode::JMP_IMM32:
|
||||
case EcmaOpcode::JNEZ_IMM32:
|
||||
case EcmaOpcode::JEQZ_IMM32:
|
||||
offset = static_cast<int32_t>(READ_INST_32_0());
|
||||
break;
|
||||
case EcmaOpcode::RETURN:
|
||||
case EcmaOpcode::RETURNUNDEFINED:
|
||||
case EcmaOpcode::SUSPENDGENERATOR_V8:
|
||||
case EcmaOpcode::DEPRECATED_SUSPENDGENERATOR_PREF_V8_V8:
|
||||
offset = -(static_cast<int32_t>(pc - GetFirstPC()));
|
||||
break;
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::CollectRegionInfo(uint32_t bcIndex)
|
||||
{
|
||||
@ -797,8 +831,17 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
|
||||
gate = circuit_->NewGate(meta, MachineType::NOVALUE, inList.size(),
|
||||
inList.data(), GateType::Empty());
|
||||
}
|
||||
gateAcc_.NewIn(gate, 0, state);
|
||||
gateAcc_.NewIn(gate, 1, depend);
|
||||
if (bytecodeInfo.IsSuspend()) {
|
||||
auto offsetGate = circuit_->GetConstantGate(MachineType::I32,
|
||||
GetJumpOffset(iterator.Index()),
|
||||
GateType::NJSValue());
|
||||
auto updateHotness = circuit_->NewGate(circuit_->UpdateHotness(), {state, depend, offsetGate});
|
||||
gateAcc_.NewIn(gate, 0, updateHotness);
|
||||
gateAcc_.NewIn(gate, 1, updateHotness);
|
||||
} else {
|
||||
gateAcc_.NewIn(gate, 0, state);
|
||||
gateAcc_.NewIn(gate, 1, depend);
|
||||
}
|
||||
state = gate;
|
||||
if (!bb.catchs.empty()) {
|
||||
auto ifSuccess = circuit_->NewGate(circuit_->IfSuccess(), {gate});
|
||||
@ -851,6 +894,7 @@ void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, GateRef &state, GateRef
|
||||
auto &iterator = bb.GetBytecodeIterator();
|
||||
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
|
||||
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
|
||||
auto offset = GetJumpOffset(iterator.Index());
|
||||
if (bytecodeInfo.IsCondJump()) {
|
||||
ASSERT(!bytecodeInfo.Deopt());
|
||||
auto meta = circuit_->JSBytecode(numValueInputs,
|
||||
@ -861,14 +905,22 @@ void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, GateRef &state, GateRef
|
||||
gateAcc_.NewIn(gate, 1, depend);
|
||||
auto ifTrue = circuit_->NewGate(circuit_->IfTrue(), {gate});
|
||||
auto trueRelay = circuit_->NewGate(circuit_->DependRelay(), {ifTrue, gate});
|
||||
if (offset < 0) {
|
||||
// place update hotness Gate when offset is negative.
|
||||
auto offsetGate = circuit_->GetConstantGate(MachineType::I32,
|
||||
offset,
|
||||
GateType::NJSValue());
|
||||
ifTrue = circuit_->NewGate(circuit_->UpdateHotness(), {ifTrue, trueRelay, offsetGate});
|
||||
trueRelay = ifTrue;
|
||||
}
|
||||
auto ifFalse = circuit_->NewGate(circuit_->IfFalse(), {gate});
|
||||
auto falseRelay = circuit_->NewGate(circuit_->DependRelay(), {ifFalse, gate});
|
||||
if (bb.succs.size() == 1) {
|
||||
auto &bbNext = bb.succs[0];
|
||||
ASSERT(bbNext->id == bb.id + 1);
|
||||
auto isLoopBack = bbNext->loopbackBlocks.count(bb.id);
|
||||
SetBlockPred(*bbNext, ifFalse, trueRelay, isLoopBack);
|
||||
SetBlockPred(*bbNext, ifTrue, falseRelay, isLoopBack);
|
||||
SetBlockPred(*bbNext, ifFalse, falseRelay, isLoopBack);
|
||||
SetBlockPred(*bbNext, ifTrue, trueRelay, isLoopBack);
|
||||
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), false});
|
||||
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), false});
|
||||
} else {
|
||||
@ -894,7 +946,16 @@ void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, GateRef &state, GateRef
|
||||
ASSERT(bb.succs.size() == 1);
|
||||
auto &bbNext = bb.succs.at(0);
|
||||
auto isLoopBack = bbNext->loopbackBlocks.count(bb.id);
|
||||
SetBlockPred(*bbNext, state, depend, isLoopBack);
|
||||
if (offset < 0) {
|
||||
// place update hotness Gate when offset is negative.
|
||||
auto offsetGate = circuit_->GetConstantGate(MachineType::I32,
|
||||
offset,
|
||||
GateType::NJSValue());
|
||||
auto updateHotness = circuit_->NewGate(circuit_->UpdateHotness(), {state, depend, offsetGate});
|
||||
SetBlockPred(*bbNext, updateHotness, updateHotness, isLoopBack);
|
||||
} else {
|
||||
SetBlockPred(*bbNext, state, depend, isLoopBack);
|
||||
}
|
||||
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), false});
|
||||
}
|
||||
}
|
||||
@ -904,10 +965,14 @@ void BytecodeCircuitBuilder::NewReturn(BytecodeRegion &bb, GateRef &state, GateR
|
||||
ASSERT(bb.succs.empty());
|
||||
auto &iterator = bb.GetBytecodeIterator();
|
||||
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
|
||||
auto offsetGate = circuit_->GetConstantGate(MachineType::I32,
|
||||
GetJumpOffset(iterator.Index()),
|
||||
GateType::NJSValue());
|
||||
auto updateHotness = circuit_->NewGate(circuit_->UpdateHotness(), {state, depend, offsetGate});
|
||||
if (bytecodeInfo.GetOpcode() == EcmaOpcode::RETURN) {
|
||||
// handle return.dyn bytecode
|
||||
auto gate = circuit_->NewGate(circuit_->Return(),
|
||||
{ state, depend, Circuit::NullGate(), circuit_->GetReturnRoot() });
|
||||
{ updateHotness, updateHotness, Circuit::NullGate(), circuit_->GetReturnRoot() });
|
||||
byteCodeToJSGate_[iterator.Index()] = gate;
|
||||
} else if (bytecodeInfo.GetOpcode() == EcmaOpcode::RETURNUNDEFINED) {
|
||||
// handle returnundefined bytecode
|
||||
@ -915,7 +980,7 @@ void BytecodeCircuitBuilder::NewReturn(BytecodeRegion &bb, GateRef &state, GateR
|
||||
JSTaggedValue::VALUE_UNDEFINED,
|
||||
GateType::TaggedValue());
|
||||
auto gate = circuit_->NewGate(circuit_->Return(),
|
||||
{ state, depend, constant, circuit_->GetReturnRoot() });
|
||||
{ updateHotness, updateHotness, constant, circuit_->GetReturnRoot() });
|
||||
byteCodeToJSGate_[iterator.Index()] = gate;
|
||||
}
|
||||
}
|
||||
|
@ -277,6 +277,7 @@ public:
|
||||
NO_COPY_SEMANTIC(BytecodeCircuitBuilder);
|
||||
NO_MOVE_SEMANTIC(BytecodeCircuitBuilder);
|
||||
void PUBLIC_API BytecodeToCircuit();
|
||||
int32_t GetJumpOffset(uint32_t bcIndex) const;
|
||||
void CollectRegionInfo(uint32_t bcIndex);
|
||||
|
||||
[[nodiscard]] Circuit* GetCircuit() const
|
||||
@ -381,6 +382,11 @@ public:
|
||||
return pcOffsets_[index];
|
||||
}
|
||||
|
||||
const uint8_t *GetFirstPC() const
|
||||
{
|
||||
return GetPCByIndex(0);
|
||||
}
|
||||
|
||||
const uint8_t *GetLastPC() const
|
||||
{
|
||||
return GetPCByIndex(GetLastBcIndex());
|
||||
|
@ -142,9 +142,11 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
|
||||
break;
|
||||
case EcmaOpcode::SUSPENDGENERATOR_V8:
|
||||
flags |= BytecodeFlags::READ_THIS_OBJECT;
|
||||
[[fallthrough]];
|
||||
case EcmaOpcode::DEPRECATED_SUSPENDGENERATOR_PREF_V8_V8:
|
||||
kind = BytecodeKind::SUSPEND;
|
||||
break;
|
||||
case EcmaOpcode::RESUMEGENERATOR:
|
||||
kind = BytecodeKind::GENERATOR;
|
||||
kind = BytecodeKind::RESUME;
|
||||
break;
|
||||
case EcmaOpcode::DEBUGGER:
|
||||
case EcmaOpcode::NOP:
|
||||
@ -176,7 +178,8 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
|
||||
|
||||
if (kind == BytecodeKind::GENERAL ||
|
||||
kind == BytecodeKind::THROW_BC ||
|
||||
kind == BytecodeKind::GENERATOR) {
|
||||
kind == BytecodeKind::RESUME ||
|
||||
kind == BytecodeKind::SUSPEND) {
|
||||
flags |= BytecodeFlags::GENERAL_BC;
|
||||
}
|
||||
auto size = inst.GetSize();
|
||||
|
@ -51,7 +51,8 @@ enum BytecodeKind : uint32_t {
|
||||
CONDITIONAL_JUMP,
|
||||
MOV,
|
||||
SET_CONSTANT,
|
||||
GENERATOR,
|
||||
SUSPEND,
|
||||
RESUME,
|
||||
DISCARDED,
|
||||
};
|
||||
|
||||
@ -117,6 +118,11 @@ public:
|
||||
return GetKind() == BytecodeKind::JUMP_IMM;
|
||||
}
|
||||
|
||||
bool IsSuspend() const
|
||||
{
|
||||
return GetKind() == BytecodeKind::SUSPEND;
|
||||
}
|
||||
|
||||
bool IsSetConstant() const
|
||||
{
|
||||
return GetKind() == BytecodeKind::SET_CONSTANT;
|
||||
@ -139,7 +145,7 @@ public:
|
||||
|
||||
bool IsGeneratorRelative() const
|
||||
{
|
||||
return GetKind() == BytecodeKind::GENERATOR;
|
||||
return (GetKind() == BytecodeKind::RESUME) || (GetKind() == BytecodeKind::SUSPEND);
|
||||
}
|
||||
|
||||
bool IsDiscarded() const
|
||||
@ -481,6 +487,11 @@ public:
|
||||
return metaData_.IsThrow();
|
||||
}
|
||||
|
||||
bool IsSuspend() const
|
||||
{
|
||||
return metaData_.IsSuspend();
|
||||
}
|
||||
|
||||
bool IsDiscarded() const
|
||||
{
|
||||
return metaData_.IsDiscarded();
|
||||
|
@ -103,6 +103,7 @@ class Variable;
|
||||
V(TruncInt64ToInt1, Trunc, MachineType::I1) \
|
||||
V(TruncInt64ToInt16, Trunc, MachineType::I16) \
|
||||
V(TruncInt32ToInt1, Trunc, MachineType::I1) \
|
||||
V(TruncInt32ToInt16, Trunc, MachineType::I16) \
|
||||
V(TruncFloatToInt64, TruncFloatToInt64, MachineType::I64) \
|
||||
V(ExtFloat32ToDouble, Fext, MachineType::F64) \
|
||||
V(TruncDoubleToFloat32, Ftrunc, MachineType::F32) \
|
||||
|
@ -205,6 +205,7 @@ std::string MachineTypeToStr(MachineType machineType);
|
||||
V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(UpdateHotness, UPDATE_HOTNESS, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
BINARY_GATE_META_DATA_CACHE_LIST(V) \
|
||||
UNARY_GATE_META_DATA_CACHE_LIST(V)
|
||||
|
||||
|
@ -53,6 +53,8 @@ void SlowPathLowering::CallRuntimeLowering()
|
||||
LowerDeoptCheck(gate);
|
||||
} else if (op == OpCode::CONSTRUCT) {
|
||||
LowerConstruct(gate);
|
||||
} else if (op == OpCode::UPDATE_HOTNESS) {
|
||||
LowerUpdateHotness(gate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3674,4 +3676,28 @@ void SlowPathLowering::LowerConstruct(GateRef gate)
|
||||
GateRef constructGate = builder_.Call(cs, glue_, target, depend, args);
|
||||
ReplaceHirToJSCall(gate, constructGate);
|
||||
}
|
||||
|
||||
void SlowPathLowering::LowerUpdateHotness(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef jsFunc = argAcc_.GetCommonArgGate(CommonArgIdx::FUNC);
|
||||
GateRef method = builder_.Load(VariableType::JS_ANY(), jsFunc, builder_.IntPtr(JSFunctionBase::METHOD_OFFSET));
|
||||
GateRef hotness = builder_.Load(VariableType::INT16(), method, builder_.IntPtr(Method::LITERAL_INFO_OFFSET));
|
||||
GateRef value = builder_.ZExtInt16ToInt32(hotness);
|
||||
GateRef offset = acc_.GetValueIn(gate, 0);
|
||||
GateRef newValue = builder_.Int32Add(value, offset);
|
||||
DEFVAlUE(newHotness, (&builder_), VariableType::INT16(), builder_.TruncInt32ToInt16(newValue));
|
||||
Label slowPath(&builder_);
|
||||
Label dispatch(&builder_);
|
||||
builder_.Branch(builder_.Int32LessThan(newValue, builder_.Int32(0)), &slowPath, &dispatch);
|
||||
builder_.Bind(&slowPath);
|
||||
{
|
||||
builder_.CallRuntime(glue_, RTSTUB_ID(UpdateHotnessCounter), Circuit::NullGate(), { jsFunc });
|
||||
newHotness = builder_.Int16(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD);
|
||||
builder_.Jump(&dispatch);
|
||||
}
|
||||
builder_.Bind(&dispatch);
|
||||
builder_.Store(VariableType::VOID(), glue_, method, builder_.IntPtr(Method::LITERAL_INFO_OFFSET), *newHotness);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -303,6 +303,7 @@ private:
|
||||
void LowerConstPoolData(GateRef gate);
|
||||
void LowerDeoptCheck(GateRef gate);
|
||||
void LowerConstruct(GateRef gate);
|
||||
void LowerUpdateHotness(GateRef gate);
|
||||
|
||||
TSManager *tsManager_ {nullptr};
|
||||
const MethodLiteral *methodLiteral_ {nullptr};
|
||||
|
@ -11,4 +11,4 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
9000003000000.25
|
||||
90300.25
|
||||
|
@ -22,4 +22,4 @@ function foo(n: number) {
|
||||
return x;
|
||||
}
|
||||
|
||||
print(foo(3000000));
|
||||
print(foo(300));
|
Loading…
Reference in New Issue
Block a user