mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Support loop hoist for TryLdGlobalByName
Issue: https://gitee.com/open_harmony/dashboard?issue_id=I8RSIT Signed-off-by: weng-xi <wengxi1@huawei.com> Change-Id: If784f048754bf1d92e586de2fce035274ff4f646
This commit is contained in:
parent
d6bd761bff
commit
47157ac405
@ -111,7 +111,7 @@ public:
|
||||
BuiltinIndex(const BuiltinIndex&) = delete;
|
||||
BuiltinIndex& operator=(const BuiltinIndex&) = delete;
|
||||
|
||||
static const int32_t NOT_FOUND = -1;
|
||||
static const size_t NOT_FOUND = -1;
|
||||
|
||||
static BuiltinIndex& GetInstance()
|
||||
{
|
||||
@ -126,20 +126,25 @@ public:
|
||||
return sizeof(JSTaggedValue) * (index * 2); // 2 is size of BuiltinEntries
|
||||
}
|
||||
|
||||
int32_t GetBuiltinIndex(JSTaggedValue key) const
|
||||
size_t GetBuiltinBoxOffset(size_t index)
|
||||
{
|
||||
return sizeof(JSTaggedValue) * (index * 2); // 2 is size of BuiltinEntries
|
||||
}
|
||||
|
||||
size_t GetBuiltinIndex(JSTaggedValue key) const
|
||||
{
|
||||
auto ecmaString = EcmaString::Cast(key.GetTaggedObject());
|
||||
auto str = std::string(ConvertToString(ecmaString));
|
||||
return GetBuiltinIndex(str);
|
||||
}
|
||||
|
||||
int32_t GetBuiltinIndex(const std::string& key) const
|
||||
size_t GetBuiltinIndex(const std::string& key) const
|
||||
{
|
||||
auto it = builtinIndex_.find(key);
|
||||
if (it == builtinIndex_.end()) {
|
||||
return NOT_FOUND;
|
||||
} else {
|
||||
return static_cast<int32_t>(it->second);
|
||||
return static_cast<size_t>(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,6 +364,17 @@ JSTaggedValue BuiltinsArkTools::IsAOTDeoptimized(EcmaRuntimeCallInfo *info)
|
||||
return JSTaggedValue(false);
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::PrintLoopHoistProfilerAndReset(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
JSThread *thread = info->GetThread();
|
||||
LoopHoistProfiler *profiler = thread->GetCurrentEcmaContext()->GetLoopHoistProfiler();
|
||||
if (profiler != nullptr) {
|
||||
profiler->PrintAndReset();
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsArkTools::GetElementsKind(EcmaRuntimeCallInfo *info)
|
||||
{
|
||||
ASSERT(info);
|
||||
|
@ -44,7 +44,8 @@
|
||||
V("timeInUs", TimeInUs, 0, INVALID) \
|
||||
V("getElementsKind", GetElementsKind, 1, INVALID) \
|
||||
V("isAOTCompiled", IsAOTCompiled, 1, INVALID) \
|
||||
V("isAOTDeoptimized", IsAOTDeoptimized, 1, INVALID)
|
||||
V("isAOTDeoptimized", IsAOTDeoptimized, 1, INVALID) \
|
||||
V("printLoopHoistProfilerAndReset", PrintLoopHoistProfilerAndReset, 0, INVALID)
|
||||
|
||||
#define BUILTIN_ARK_TOOLS_FUNCTIONS_REGRESS(V) \
|
||||
V("prepareFunctionForOptimization", PrepareFunctionForOptimization, 1, INVALID) \
|
||||
@ -182,6 +183,8 @@ public:
|
||||
// ArkTools.GetElementsKind(array)
|
||||
static JSTaggedValue GetElementsKind(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue PrintLoopHoistProfilerAndReset(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue IsRegExpReplaceDetectorValid(EcmaRuntimeCallInfo *info);
|
||||
|
||||
static JSTaggedValue IsSymbolIteratorDetectorValid(EcmaRuntimeCallInfo *info);
|
||||
|
@ -442,7 +442,7 @@ public:
|
||||
|
||||
// ************************************************************* Middle IR **********************************************************************************
|
||||
GateRef HeapObjectCheck(GateRef gate, GateRef frameState);
|
||||
GateRef ProtoChangeMarkerCheck(GateRef gate, GateRef frameState);
|
||||
GateRef ProtoChangeMarkerCheck(GateRef gate);
|
||||
GateRef StableArrayCheck(GateRef gate, ElementsKind kind, ArrayMetaDataAccessor::Mode mode);
|
||||
GateRef COWArrayCheck(GateRef gate);
|
||||
GateRef EcmaStringCheck(GateRef gate);
|
||||
@ -569,6 +569,12 @@ public:
|
||||
GateRef IsSpecificObjectType(GateRef obj, JSType type);
|
||||
GateRef IsMarkerCellValid(GateRef cell);
|
||||
GateRef IsMarkerCellValidOp(GateRef cell);
|
||||
GateRef MonoLoadPropertyOnProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex);
|
||||
GateRef MonoCallGetterOnProto(GateRef gate, GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex);
|
||||
GateRef MonoStorePropertyLookUpProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex,
|
||||
GateRef value);
|
||||
GateRef MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex,
|
||||
GateRef value, GateRef key);
|
||||
|
||||
// bit operation
|
||||
inline GateRef TaggedIsInt(GateRef x);
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
profiling_ = options->GetOptCodeProfiler();
|
||||
stressDeopt_ = options->GetStressDeopt();
|
||||
verifyVTable_ = options->GetVerifyVTable();
|
||||
loopHoistProfiling_ = options->GetLoopHoistProfiler();
|
||||
}
|
||||
}
|
||||
~CompilationConfig() = default;
|
||||
@ -86,6 +87,11 @@ public:
|
||||
return verifyVTable_;
|
||||
}
|
||||
|
||||
bool IsLoopHoistProfiling() const
|
||||
{
|
||||
return loopHoistProfiling_;
|
||||
}
|
||||
|
||||
private:
|
||||
inline Triple GetTripleFromString(const std::string &triple)
|
||||
{
|
||||
@ -109,6 +115,7 @@ private:
|
||||
bool profiling_ {false};
|
||||
bool stressDeopt_ {false};
|
||||
bool verifyVTable_ {false};
|
||||
bool loopHoistProfiling_ {false};
|
||||
};
|
||||
|
||||
class Label {
|
||||
|
@ -89,6 +89,9 @@ GateRef EarlyElimination::VisitGate(GateRef gate)
|
||||
case OpCode::TYPE_OF_CHECK:
|
||||
case OpCode::ARRAY_CONSTRUCTOR_CHECK:
|
||||
case OpCode::OBJECT_CONSTRUCTOR_CHECK:
|
||||
case OpCode::PROTO_CHANGE_MARKER_CHECK:
|
||||
case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
|
||||
case OpCode::LOAD_BUILTIN_OBJECT:
|
||||
return TryEliminateGate(gate);
|
||||
case OpCode::STATE_SPLIT:
|
||||
return TryEliminateFrameState(gate);
|
||||
@ -232,6 +235,8 @@ DependInfoNode* EarlyElimination::UpdateWrite(GateRef gate, DependInfoNode* depe
|
||||
case OpCode::STORE_CONST_OFFSET:
|
||||
case OpCode::STORE_ELEMENT:
|
||||
case OpCode::STORE_MEMORY:
|
||||
case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
|
||||
case OpCode::MONO_STORE_PROPERTY:
|
||||
return dependInfo->UpdateStoreProperty(this, gate);
|
||||
default:
|
||||
return new (chunk_) DependInfoNode(chunk_);
|
||||
@ -273,6 +278,12 @@ bool EarlyElimination::MayAccessOneMemory(GateRef lhs, GateRef rhs)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OpCode::LOAD_PROPERTY:
|
||||
case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
|
||||
if (acc_.GetGateType(lhs).Value() != acc_.GetGateType(rhs).Value()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -378,6 +389,12 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OpCode::LOAD_BUILTIN_OBJECT: {
|
||||
if (acc_.GetIndex(lhs) != acc_.GetIndex(rhs)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1857,4 +1857,20 @@ bool GateAccessor::IsCreateArray(GateRef gate) const
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
|
||||
void GateAccessor::SetStoreNoBarrier(GateRef gate, bool isNoBarrier)
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO ||
|
||||
GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
const_cast<BoolMetaData *>(gatePtr->GetBoolMetaData())->SetBool(isNoBarrier);
|
||||
}
|
||||
|
||||
bool GateAccessor::IsNoBarrier(GateRef gate) const
|
||||
{
|
||||
ASSERT(GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO ||
|
||||
GetOpCode(gate) == OpCode::MONO_STORE_PROPERTY);
|
||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||
return gatePtr->GetBoolMetaData()->GetBool();
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -603,6 +603,8 @@ public:
|
||||
bool IsLoopBackUse(GateRef gate, const UseIterator &useIt) const;
|
||||
void GetOutStates(GateRef gate, std::vector<GateRef>& outStates) const;
|
||||
bool IsCreateArray(GateRef gate) const;
|
||||
void SetStoreNoBarrier(GateRef gate, bool isNoBarrier);
|
||||
bool IsNoBarrier(GateRef gate) const;
|
||||
|
||||
private:
|
||||
const GateMetaData *GetMetaData(GateRef gate) const;
|
||||
|
@ -43,7 +43,8 @@ namespace panda::ecmascript::kungfu {
|
||||
|
||||
#define HCR_GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(V) \
|
||||
V(CallGetter, CALL_GETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 3) \
|
||||
V(CallSetter, CALL_SETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 4)
|
||||
V(CallSetter, CALL_SETTER, GateFlags::HAS_FRAME_STATE, 1, 1, 4) \
|
||||
V(MonoCallGetterOnProto, MONO_CALL_GETTER_ON_PROTO, GateFlags::HAS_FRAME_STATE, 1, 1, 4)
|
||||
|
||||
#define HCR_GATE_META_DATA_LIST_WITH_VALUE(V) \
|
||||
V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 1) \
|
||||
|
@ -67,11 +67,12 @@ GateRef CircuitBuilder::HeapObjectCheck(GateRef gate, GateRef frameState)
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::ProtoChangeMarkerCheck(GateRef gate, GateRef frameState)
|
||||
GateRef CircuitBuilder::ProtoChangeMarkerCheck(GateRef gate)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->ProtoChangeMarkerCheck(),
|
||||
MachineType::I1,
|
||||
{currentControl, currentDepend, gate, frameState},
|
||||
@ -1241,4 +1242,70 @@ GateRef CircuitBuilder::ObjectConstructorCheck(GateRef gate)
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::MonoLoadPropertyOnProto(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
auto ret = GetCircuit()->NewGate(circuit_->MonoLoadPropertyOnProto(), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc,
|
||||
frameState },
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::MonoCallGetterOnProto(GateRef gate, GateRef receiver, GateRef plrGate, GateRef jsFunc,
|
||||
size_t hclassIndex)
|
||||
{
|
||||
uint64_t pcOffset = acc_.TryGetPcOffset(gate);
|
||||
ASSERT(pcOffset != 0);
|
||||
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
std::vector<GateRef> args = { currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc,
|
||||
frameState };
|
||||
auto callGate = GetCircuit()->NewGate(circuit_->MonoCallGetterOnProto(pcOffset),
|
||||
MachineType::I64,
|
||||
args.size(),
|
||||
args.data(),
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(callGate);
|
||||
currentLabel->SetDepend(callGate);
|
||||
return callGate;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::MonoStorePropertyLookUpProto(GateRef receiver, GateRef plrGate, GateRef jsFunc,
|
||||
size_t hclassIndex, GateRef value)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
auto ret = GetCircuit()->NewGate(circuit_->MonoStorePropertyLookUpProto(false), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc, value, frameState},
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::MonoStoreProperty(GateRef receiver, GateRef plrGate, GateRef jsFunc, size_t hclassIndex,
|
||||
GateRef value, GateRef key)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto ret = GetCircuit()->NewGate(circuit_->MonoStoreProperty(false), MachineType::I64,
|
||||
{ currentControl, currentDepend, receiver, plrGate, Int32(hclassIndex), jsFunc, value, key },
|
||||
GateType::AnyType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -42,9 +42,6 @@ GateRef MCRLowering::VisitGate(GateRef gate)
|
||||
case OpCode::HEAP_OBJECT_CHECK:
|
||||
LowerHeapObjectCheck(gate);
|
||||
break;
|
||||
case OpCode::PROTO_CHANGE_MARKER_CHECK:
|
||||
LowerProtoChangeMarkerCheck(gate);
|
||||
break;
|
||||
case OpCode::LOAD_CONST_OFFSET:
|
||||
LowerLoadConstOffset(gate);
|
||||
break;
|
||||
@ -179,20 +176,6 @@ void MCRLowering::LowerHeapObjectCheck(GateRef gate)
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void MCRLowering::LowerProtoChangeMarkerCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef marker = acc_.GetValueIn(gate, 0);
|
||||
|
||||
builder_.DeoptCheck(builder_.TaggedIsNotNull(marker), frameState, DeoptType::PROTOTYPECHANGED);
|
||||
auto hasChanged = builder_.GetHasChanged(marker);
|
||||
builder_.DeoptCheck(builder_.BoolNot(hasChanged), frameState,
|
||||
DeoptType::PROTOTYPECHANGED);
|
||||
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void MCRLowering::LowerTaggedIsHeapObject(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
|
@ -39,7 +39,6 @@ private:
|
||||
void DeleteStateSplit(GateRef gate);
|
||||
void LowerArrayGuardianCheck(GateRef gate);
|
||||
void LowerHeapObjectCheck(GateRef gate);
|
||||
void LowerProtoChangeMarkerCheck(GateRef gate);
|
||||
void LowerTaggedIsHeapObject(GateRef gate);
|
||||
void LowerIsMarkerCellValid(GateRef gate);
|
||||
void LowerIsSpecificObjectType(GateRef gate);
|
||||
|
@ -54,6 +54,7 @@ namespace panda::ecmascript::kungfu {
|
||||
V(ArrayConstructorCheck, ARRAY_CONSTRUCTOR_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(ObjectConstructorCheck, OBJECT_CONSTRUCTOR_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(MonoLoadPropertyOnProto, MONO_LOAD_PROPERTY_ON_PROTO, GateFlags::CHECKABLE, 1, 1, 4) \
|
||||
MCR_BINARY_GATE_META_DATA_CACHE_LIST(V)
|
||||
|
||||
#define MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
|
||||
@ -85,7 +86,9 @@ namespace panda::ecmascript::kungfu {
|
||||
V(LoadBuiltinObject, LOAD_BUILTIN_OBJECT, GateFlags::CHECKABLE, 1, 1, 0)
|
||||
|
||||
#define MCR_GATE_META_DATA_LIST_WITH_BOOL(V) \
|
||||
V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2)
|
||||
V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \
|
||||
V(MonoStorePropertyLookUpProto, MONO_STORE_PROPERTY_LOOK_UP_PROTO, GateFlags::HAS_FRAME_STATE, 1, 1, 5) \
|
||||
V(MonoStoreProperty, MONO_STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 6)
|
||||
|
||||
#define MCR_GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \
|
||||
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
|
@ -102,6 +102,10 @@ void NumberSpeculativeLowering::VisitGate(GateRef gate)
|
||||
VisitLoadProperty(gate);
|
||||
break;
|
||||
}
|
||||
case OpCode::MONO_LOAD_PROPERTY_ON_PROTO: {
|
||||
VisitLoadPropertyOnProto(gate);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -972,4 +976,68 @@ void NumberSpeculativeLowering::VisitStringAdd(GateRef gate)
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void NumberSpeculativeLowering::VisitLoadPropertyOnProto(GateRef gate)
|
||||
{
|
||||
TypeInfo output = GetOutputType(gate);
|
||||
if (output == TypeInfo::INT32 || output == TypeInfo::FLOAT64) {
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
|
||||
GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
|
||||
GateRef jsFunc = acc_.GetValueIn(gate, 3); // 3: jsFunc
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
GateRef result = Circuit::NullGate();
|
||||
ASSERT(plr.IsLocal() || plr.IsFunction());
|
||||
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
|
||||
GateRef constPool = builder_.GetConstPool(jsFunc);
|
||||
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||
Label exit(&builder_);
|
||||
Label loopHead(&builder_);
|
||||
Label loadHolder(&builder_);
|
||||
Label lookUpProto(&builder_);
|
||||
builder_.Jump(&loopHead);
|
||||
|
||||
builder_.LoopBegin(&loopHead);
|
||||
builder_.DeoptCheck(builder_.TaggedIsNotNull(*current), frameState, DeoptType::INCONSISTENTHCLASS);
|
||||
auto curHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), *current, TaggedObject::HCLASS_OFFSET);
|
||||
builder_.Branch(builder_.Equal(curHC, holderHC), &loadHolder, &lookUpProto);
|
||||
|
||||
builder_.Bind(&lookUpProto);
|
||||
current = builder_.LoadConstOffset(VariableType::JS_ANY(), curHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
builder_.LoopEnd(&loopHead);
|
||||
|
||||
builder_.Bind(&loadHolder);
|
||||
if (output == TypeInfo::FLOAT64) {
|
||||
if (plr.IsInlinedProps()) {
|
||||
result = builder_.LoadConstOffset(VariableType::FLOAT64(), *current, plr.GetOffset());
|
||||
} else {
|
||||
auto properties =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), *current, JSObject::PROPERTIES_OFFSET);
|
||||
result = builder_.GetValueFromTaggedArray(
|
||||
VariableType::FLOAT64(), properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
acc_.SetMachineType(gate, MachineType::F64);
|
||||
} else {
|
||||
if (plr.IsInlinedProps()) {
|
||||
result = builder_.LoadConstOffset(VariableType::INT32(), *current, plr.GetOffset());
|
||||
} else {
|
||||
auto properties =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), *current, JSObject::PROPERTIES_OFFSET);
|
||||
result = builder_.GetValueFromTaggedArray(
|
||||
VariableType::INT32(), properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
acc_.SetMachineType(gate, MachineType::I32);
|
||||
}
|
||||
builder_.Jump(&exit);
|
||||
builder_.Bind(&exit);
|
||||
acc_.SetGateType(gate, GateType::NJSValue());
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -54,6 +54,7 @@ private:
|
||||
void VisitLoadStringLength(GateRef gate);
|
||||
void VisitLoadElement(GateRef gate);
|
||||
void VisitLoadProperty(GateRef gate);
|
||||
void VisitLoadPropertyOnProto(GateRef gate);
|
||||
|
||||
template<TypedBinOp Op>
|
||||
void VisitNumberCalculate(GateRef gate);
|
||||
|
@ -104,6 +104,13 @@ GateRef NumberSpeculativeRetype::VisitGate(GateRef gate)
|
||||
return VisitStoreProperty(gate);
|
||||
case OpCode::LOAD_PROPERTY:
|
||||
return VisitLoadProperty(gate);
|
||||
case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
|
||||
return VisitMonoLoadPropertyOnProto(gate);
|
||||
case OpCode::MONO_CALL_GETTER_ON_PROTO:
|
||||
return VisitMonoCallGetterOnProto(gate);
|
||||
case OpCode::MONO_STORE_PROPERTY:
|
||||
case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
|
||||
return VisitMonoStoreProperty(gate);
|
||||
case OpCode::VALUE_SELECTOR:
|
||||
return VisitPhi(gate);
|
||||
case OpCode::CONSTANT:
|
||||
@ -1232,6 +1239,92 @@ GateRef NumberSpeculativeRetype::VisitNumberMod(GateRef gate)
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitMonoLoadPropertyOnProto(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
return SetOutputType(gate, plr.GetRepresentation());
|
||||
}
|
||||
|
||||
ASSERT(IsConvert());
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
|
||||
continue;
|
||||
}
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
|
||||
}
|
||||
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitMonoCallGetterOnProto(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
return SetOutputType(gate, GateType::AnyType());
|
||||
}
|
||||
if (IsConvert()) {
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
|
||||
continue;
|
||||
}
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
|
||||
}
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetype::VisitMonoStoreProperty(GateRef gate)
|
||||
{
|
||||
if (IsRetype()) {
|
||||
return SetOutputType(gate, GateType::AnyType());
|
||||
}
|
||||
ASSERT(IsConvert());
|
||||
|
||||
GateRef value = acc_.GetValueIn(gate, 4); // 4: value
|
||||
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
if (plr.IsAccessor()) {
|
||||
size_t valueNum = acc_.GetNumValueIn(gate);
|
||||
for (size_t i = 0; i < valueNum; ++i) {
|
||||
if (i == PROPERTY_LOOKUP_RESULT_INDEX || i == HCLASS_INDEX) {
|
||||
continue;
|
||||
}
|
||||
GateRef input = acc_.GetValueIn(gate, i);
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(input), i);
|
||||
}
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
if (plr.GetRepresentation() == Representation::DOUBLE) {
|
||||
acc_.SetStoreNoBarrier(gate, true);
|
||||
acc_.ReplaceValueIn(
|
||||
gate, CheckAndConvertToFloat64(value, GateType::NumberType(), ConvertSupport::DISABLE), 4); // 4: value
|
||||
} else if (plr.GetRepresentation() == Representation::INT) {
|
||||
acc_.SetStoreNoBarrier(gate, true);
|
||||
acc_.ReplaceValueIn(
|
||||
gate, CheckAndConvertToInt32(value, GateType::IntType(), ConvertSupport::DISABLE), 4); // 4: value
|
||||
} else {
|
||||
TypeInfo valueType = GetOutputTypeInfo(value);
|
||||
if (valueType == TypeInfo::INT1 || valueType == TypeInfo::INT32 || valueType == TypeInfo::FLOAT64) {
|
||||
acc_.SetStoreNoBarrier(gate, true);
|
||||
}
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(value), 4); // 4: value
|
||||
}
|
||||
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0); // receiver
|
||||
acc_.ReplaceValueIn(gate, ConvertToTagged(receiver), 0);
|
||||
acc_.ReplaceStateIn(gate, builder_.GetState());
|
||||
acc_.ReplaceDependIn(gate, builder_.GetDepend());
|
||||
return Circuit::NullGate();
|
||||
}
|
||||
|
||||
GateRef NumberSpeculativeRetypeManager::VisitGate(GateRef gate)
|
||||
{
|
||||
retype_->setState(state_);
|
||||
|
@ -99,6 +99,9 @@ private:
|
||||
|
||||
GateRef VisitStringCompare(GateRef gate);
|
||||
GateRef VisitStringAdd(GateRef gate);
|
||||
GateRef VisitMonoLoadPropertyOnProto(GateRef gate);
|
||||
GateRef VisitMonoCallGetterOnProto(GateRef gate);
|
||||
GateRef VisitMonoStoreProperty(GateRef gate);
|
||||
|
||||
void ConvertForBinaryOp(GateRef gate);
|
||||
void ConvertForCompareOp(GateRef gate);
|
||||
@ -141,6 +144,7 @@ private:
|
||||
}
|
||||
|
||||
static constexpr size_t PROPERTY_LOOKUP_RESULT_INDEX = 1;
|
||||
static constexpr size_t HCLASS_INDEX = 2;
|
||||
Circuit *circuit_ {nullptr};
|
||||
GateAccessor acc_;
|
||||
CircuitBuilder builder_;
|
||||
|
@ -322,6 +322,11 @@ public:
|
||||
return value_;
|
||||
}
|
||||
|
||||
void SetBool(bool value)
|
||||
{
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
private:
|
||||
bool value_ { false };
|
||||
};
|
||||
|
@ -453,6 +453,9 @@ void TypeBytecodeLowering::LowerTypedLdObjByName(GateRef gate)
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
LoadObjByNameTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
|
||||
|
||||
if (TryLowerTypedLdobjBynameFromGloablBuiltin(gate)) {
|
||||
return;
|
||||
}
|
||||
if (TryLowerTypedLdObjByNameForBuiltin(gate)) {
|
||||
return;
|
||||
}
|
||||
@ -470,6 +473,28 @@ void TypeBytecodeLowering::LowerTypedLdObjByName(GateRef gate)
|
||||
}
|
||||
Label exit(&builder_);
|
||||
AddProfiling(gate);
|
||||
if (tacc.IsMono()) {
|
||||
GateRef receiver = tacc.GetReceiver();
|
||||
builder_.ObjectTypeCheck(acc_.GetGateType(gate), true, receiver,
|
||||
builder_.Int32(tacc.GetExpectedHClassIndex(0)));
|
||||
if (tacc.IsReceiverEqHolder(0)) {
|
||||
result = BuildNamedPropertyAccess(gate, receiver, receiver, tacc.GetAccessInfo(0).Plr());
|
||||
} else {
|
||||
builder_.ProtoChangeMarkerCheck(receiver);
|
||||
PropertyLookupResult plr = tacc.GetAccessInfo(0).Plr();
|
||||
GateRef plrGate = builder_.Int32(plr.GetData());
|
||||
GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
|
||||
size_t holderHClassIndex = tacc.GetAccessInfo(0).HClassIndex();
|
||||
if (LIKELY(!plr.IsAccessor())) {
|
||||
result = builder_.MonoLoadPropertyOnProto(receiver, plrGate, jsFunc, holderHClassIndex);
|
||||
} else {
|
||||
result = builder_.MonoCallGetterOnProto(gate, receiver, plrGate, jsFunc, holderHClassIndex);
|
||||
}
|
||||
}
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), *result);
|
||||
DeleteConstDataIfNoUser(tacc.GetKey());
|
||||
return;
|
||||
}
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), tacc.GetReceiver(),
|
||||
TaggedObject::HCLASS_OFFSET);
|
||||
for (size_t i = 0; i < typeCount; ++i) {
|
||||
@ -489,13 +514,9 @@ void TypeBytecodeLowering::LowerTypedLdObjByName(GateRef gate)
|
||||
builder_.Jump(&exit);
|
||||
} else {
|
||||
// prototype change marker check
|
||||
builder_.ProtoChangeMarkerCheck(tacc.GetReceiver());
|
||||
// lookup from receiver for holder
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
auto protoHClass =
|
||||
builder_.LoadConstOffset(VariableType::JS_POINTER(), prototype, TaggedObject::HCLASS_OFFSET);
|
||||
auto marker =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), protoHClass, JSHClass::PROTO_CHANGE_MARKER_OFFSET);
|
||||
builder_.ProtoChangeMarkerCheck(marker, acc_.FindNearestFrameState(builder_.GetDepend()));
|
||||
|
||||
// lookup from receiver for holder
|
||||
ObjectAccessTypeInfoAccessor::ObjectAccessInfo info = tacc.GetAccessInfo(i);
|
||||
auto holderHC = builder_.GetHClassGateFromIndex(gate, info.HClassIndex());
|
||||
@ -545,6 +566,34 @@ void TypeBytecodeLowering::LowerTypedStObjByName(GateRef gate)
|
||||
Label exit(&builder_);
|
||||
AddProfiling(gate);
|
||||
|
||||
if (tacc.IsMono()) {
|
||||
GateRef receiver = tacc.GetReceiver();
|
||||
builder_.ObjectTypeCheck(acc_.GetGateType(gate), true, receiver,
|
||||
builder_.Int32(tacc.GetExpectedHClassIndex(0)));
|
||||
if (tacc.IsReceiverNoEqNewHolder(0)) {
|
||||
builder_.ProtoChangeMarkerCheck(tacc.GetReceiver());
|
||||
PropertyLookupResult plr = tacc.GetAccessInfo(0).Plr();
|
||||
GateRef plrGate = builder_.Int32(plr.GetData());
|
||||
GateRef jsFunc = argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC);
|
||||
size_t holderHClassIndex = tacc.GetAccessInfo(0).HClassIndex();
|
||||
GateRef value = tacc.GetValue();
|
||||
if (tacc.IsHolderEqNewHolder(0)) {
|
||||
builder_.MonoStorePropertyLookUpProto(tacc.GetReceiver(), plrGate, jsFunc, holderHClassIndex, value);
|
||||
} else {
|
||||
auto propKey = builder_.LoadObjectFromConstPool(argAcc_.GetFrameArgsIn(gate, FrameArgIdx::FUNC),
|
||||
tacc.GetKey());
|
||||
builder_.MonoStoreProperty(tacc.GetReceiver(), plrGate, jsFunc, holderHClassIndex, value,
|
||||
propKey);
|
||||
}
|
||||
} else if (tacc.IsReceiverEqHolder(0)) {
|
||||
BuildNamedPropertyAccess(gate, tacc.GetReceiver(), tacc.GetReceiver(),
|
||||
tacc.GetValue(), tacc.GetAccessInfo(0).Plr());
|
||||
}
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
|
||||
DeleteConstDataIfNoUser(tacc.GetKey());
|
||||
return;
|
||||
}
|
||||
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), tacc.GetReceiver(),
|
||||
TaggedObject::HCLASS_OFFSET);
|
||||
for (size_t i = 0; i < typeCount; ++i) {
|
||||
@ -558,14 +607,8 @@ void TypeBytecodeLowering::LowerTypedStObjByName(GateRef gate)
|
||||
acc_.FindNearestFrameState(builder_.GetDepend()), DeoptType::INCONSISTENTHCLASS);
|
||||
}
|
||||
if (tacc.IsReceiverNoEqNewHolder(i)) {
|
||||
// prototype change marker check
|
||||
builder_.ProtoChangeMarkerCheck(tacc.GetReceiver());
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
auto protoHClass =
|
||||
builder_.LoadConstOffset(VariableType::JS_POINTER(), prototype, TaggedObject::HCLASS_OFFSET);
|
||||
auto marker =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), protoHClass, JSHClass::PROTO_CHANGE_MARKER_OFFSET);
|
||||
builder_.ProtoChangeMarkerCheck(marker, acc_.FindNearestFrameState(builder_.GetDepend()));
|
||||
|
||||
if (tacc.IsHolderEqNewHolder(i)) {
|
||||
// lookup from receiver for holder
|
||||
auto holderHC = builder_.GetHClassGateFromIndex(gate, tacc.GetAccessInfo(i).HClassIndex());
|
||||
@ -753,6 +796,34 @@ bool TypeBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(const LoadBulitinO
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeBytecodeLowering::TryLowerTypedLdobjBynameFromGloablBuiltin(GateRef gate)
|
||||
{
|
||||
LoadBulitinObjTypeInfoAccessor tacc(thread_, circuit_, gate, chunk_);
|
||||
GateRef receiver = tacc.GetReceiver();
|
||||
if (acc_.GetOpCode(receiver) != OpCode::LOAD_BUILTIN_OBJECT) {
|
||||
return false;
|
||||
}
|
||||
JSHandle<GlobalEnv> globalEnv = thread_->GetEcmaVM()->GetGlobalEnv();
|
||||
uint64_t index = acc_.TryGetValue(receiver);
|
||||
BuiltinType type = static_cast<BuiltinType>(index);
|
||||
if (type == BuiltinType::BT_MATH) {
|
||||
auto math = globalEnv->GetMathFunction();
|
||||
JSHClass *hclass = math.GetTaggedValue().GetTaggedObject()->GetClass();
|
||||
JSTaggedValue key = tacc.GetKeyTaggedValue();
|
||||
PropertyLookupResult plr = JSHClass::LookupPropertyInBuiltinHClass(thread_, hclass, key);
|
||||
if (!plr.IsFound() || plr.IsAccessor()) {
|
||||
return false;
|
||||
}
|
||||
AddProfiling(gate);
|
||||
GateRef plrGate = builder_.Int32(plr.GetData());
|
||||
GateRef result = builder_.LoadProperty(receiver, plrGate, plr.IsFunction());
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
|
||||
DeleteConstDataIfNoUser(tacc.GetKey());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TypeBytecodeLowering::LowerTypedLdArrayLength(const LoadBulitinObjTypeInfoAccessor &tacc)
|
||||
{
|
||||
GateRef gate = tacc.GetGate();
|
||||
@ -1727,7 +1798,7 @@ void TypeBytecodeLowering::LowerTypedTryLdGlobalByName(GateRef gate)
|
||||
return;
|
||||
}
|
||||
AddProfiling(gate);
|
||||
GateRef result = builder_.LoadBuiltinObject(static_cast<uint64_t>(builtin.GetBuiltinBoxOffset(key)));
|
||||
GateRef result = builder_.LoadBuiltinObject(index);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
|
||||
DeleteConstDataIfNoUser(tacc.GetKey());
|
||||
}
|
||||
@ -1753,13 +1824,7 @@ void TypeBytecodeLowering::LowerInstanceOf(GateRef gate)
|
||||
GateRef target = tacc.GetTarget();
|
||||
|
||||
builder_.ObjectTypeCheck(acc_.GetGateType(gate), true, target, expectedHCIndexes[0]);
|
||||
auto ctorHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), target, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), ctorHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
auto protoHClass =
|
||||
builder_.LoadConstOffset(VariableType::JS_POINTER(), prototype, TaggedObject::HCLASS_OFFSET);
|
||||
auto marker =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), protoHClass, JSHClass::PROTO_CHANGE_MARKER_OFFSET);
|
||||
builder_.ProtoChangeMarkerCheck(marker, acc_.FindNearestFrameState(builder_.GetDepend()));
|
||||
builder_.ProtoChangeMarkerCheck(target);
|
||||
|
||||
result = builder_.OrdinaryHasInstance(obj, target);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), *result);
|
||||
|
@ -203,6 +203,7 @@ private:
|
||||
BuiltinsStubCSigns::ID id, bool isThrow);
|
||||
void DeleteConstDataIfNoUser(GateRef gate);
|
||||
bool TryLowerNewBuiltinConstructor(GateRef gate);
|
||||
bool TryLowerTypedLdobjBynameFromGloablBuiltin(GateRef gate);
|
||||
|
||||
void AddProfiling(GateRef gate);
|
||||
|
||||
|
@ -162,6 +162,21 @@ GateRef TypeHCRLowering::VisitGate(GateRef gate)
|
||||
case OpCode::ORDINARY_HAS_INSTANCE:
|
||||
LowerOrdinaryHasInstance(gate, glue);
|
||||
break;
|
||||
case OpCode::PROTO_CHANGE_MARKER_CHECK:
|
||||
LowerProtoChangeMarkerCheck(gate);
|
||||
break;
|
||||
case OpCode::MONO_CALL_GETTER_ON_PROTO:
|
||||
LowerMonoCallGetterOnProto(gate, glue);
|
||||
break;
|
||||
case OpCode::MONO_LOAD_PROPERTY_ON_PROTO:
|
||||
LowerMonoLoadPropertyOnProto(gate);
|
||||
break;
|
||||
case OpCode::MONO_STORE_PROPERTY_LOOK_UP_PROTO:
|
||||
LowerMonoStorePropertyLookUpProto(gate, glue);
|
||||
break;
|
||||
case OpCode::MONO_STORE_PROPERTY:
|
||||
LowerMonoStoreProperty(gate, glue);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -691,32 +706,14 @@ GateRef TypeHCRLowering::GetObjectFromConstPool(GateRef jsFunc, GateRef index)
|
||||
void TypeHCRLowering::LowerLoadProperty(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
AddProfiling(gate);
|
||||
ASSERT(acc_.GetNumValueIn(gate) == 2); // 2: receiver, plr
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1);
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
ASSERT(plr.IsLocal() || plr.IsFunction());
|
||||
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (plr.IsNotHole()) {
|
||||
ASSERT(plr.IsLocal());
|
||||
if (plr.IsInlinedProps()) {
|
||||
result = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset());
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
|
||||
result = builder_.GetValueFromTaggedArray(properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
} else if (plr.IsLocal()) {
|
||||
if (plr.IsInlinedProps()) {
|
||||
result = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, plr.GetOffset());
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
|
||||
result = builder_.GetValueFromTaggedArray(properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
result = builder_.ConvertHoleAsUndefined(result);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
GateRef result = LoadPropertyFromHolder(receiver, plr);
|
||||
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
@ -730,26 +727,7 @@ void TypeHCRLowering::LowerCallGetter(GateRef gate, GateRef glue)
|
||||
GateRef holder = acc_.GetValueIn(gate, 2);
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
|
||||
GateRef accessor = Circuit::NullGate();
|
||||
if (plr.IsNotHole()) {
|
||||
ASSERT(plr.IsLocal());
|
||||
if (plr.IsInlinedProps()) {
|
||||
accessor = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
|
||||
accessor = builder_.GetValueFromTaggedArray(properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
} else if (plr.IsLocal()) {
|
||||
if (plr.IsInlinedProps()) {
|
||||
accessor = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
|
||||
accessor = builder_.GetValueFromTaggedArray(properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
accessor = builder_.ConvertHoleAsUndefined(accessor);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
GateRef accessor = LoadPropertyFromHolder(holder, plr);
|
||||
|
||||
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
|
||||
Label isInternalAccessor(&builder_);
|
||||
@ -2200,9 +2178,11 @@ void TypeHCRLowering::ReplaceGateWithPendingException(GateRef glue, GateRef gate
|
||||
void TypeHCRLowering::LowerLoadBuiltinObject(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
AddProfiling(gate);
|
||||
GateRef glue = acc_.GetGlueFromArgList();
|
||||
auto builtinEntriesOffset = JSThread::GlueData::GetBuiltinEntriesOffset(false);
|
||||
auto boxOffset = builtinEntriesOffset + acc_.GetIndex(gate);
|
||||
size_t index = acc_.GetIndex(gate);
|
||||
auto boxOffset = builtinEntriesOffset + BuiltinIndex::GetInstance().GetBuiltinBoxOffset(index);
|
||||
GateRef box = builder_.LoadConstOffset(VariableType::JS_POINTER(), glue, boxOffset);
|
||||
GateRef builtin = builder_.LoadConstOffset(VariableType::JS_POINTER(), box, PropertyBox::VALUE_OFFSET);
|
||||
auto frameState = GetFrameState(gate);
|
||||
@ -2353,4 +2333,367 @@ void TypeHCRLowering::LowerOrdinaryHasInstance(GateRef gate, GateRef glue)
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
void TypeHCRLowering::LowerProtoChangeMarkerCheck(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
auto hclass = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), hclass, JSHClass::PROTOTYPE_OFFSET);
|
||||
auto protoHClass = builder_.LoadConstOffset(VariableType::JS_POINTER(), prototype, TaggedObject::HCLASS_OFFSET);
|
||||
auto marker = builder_.LoadConstOffset(VariableType::JS_ANY(), protoHClass, JSHClass::PROTO_CHANGE_MARKER_OFFSET);
|
||||
auto notNull = builder_.TaggedIsNotNull(marker);
|
||||
auto hasChanged = builder_.GetHasChanged(marker);
|
||||
auto check = builder_.BoolAnd(builder_.BoolNot(hasChanged), notNull);
|
||||
builder_.DeoptCheck(check, frameState, DeoptType::PROTOTYPECHANGED);
|
||||
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeHCRLowering::LowerMonoLoadPropertyOnProto(GateRef gate)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
|
||||
GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
|
||||
GateRef jsFunc = acc_.GetValueIn(gate, 3); // 3: jsFunc
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
GateRef result = Circuit::NullGate();
|
||||
ASSERT(plr.IsLocal() || plr.IsFunction());
|
||||
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
|
||||
// lookup from receiver for holder
|
||||
GateRef constPool = builder_.GetConstPool(jsFunc);
|
||||
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||
Label exit(&builder_);
|
||||
Label loopHead(&builder_);
|
||||
Label loadHolder(&builder_);
|
||||
Label lookUpProto(&builder_);
|
||||
builder_.Jump(&loopHead);
|
||||
|
||||
builder_.LoopBegin(&loopHead);
|
||||
builder_.DeoptCheck(builder_.TaggedIsNotNull(*current), frameState, DeoptType::INCONSISTENTHCLASS);
|
||||
auto curHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), *current, TaggedObject::HCLASS_OFFSET);
|
||||
builder_.Branch(builder_.Equal(curHC, holderHC), &loadHolder, &lookUpProto);
|
||||
|
||||
builder_.Bind(&lookUpProto);
|
||||
current = builder_.LoadConstOffset(VariableType::JS_ANY(), curHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
builder_.LoopEnd(&loopHead);
|
||||
|
||||
builder_.Bind(&loadHolder);
|
||||
result = LoadPropertyFromHolder(*current, plr);
|
||||
builder_.Jump(&exit);
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
|
||||
}
|
||||
|
||||
void TypeHCRLowering::LowerMonoCallGetterOnProto(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
|
||||
GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
|
||||
GateRef jsFunc = acc_.GetValueIn(gate, 3); // 3: jsFunc
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
GateRef accessor = Circuit::NullGate();
|
||||
GateRef holder = Circuit::NullGate();
|
||||
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
|
||||
// lookup from receiver for holder
|
||||
GateRef constPool = builder_.GetConstPool(jsFunc);
|
||||
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||
Label exitLoad(&builder_);
|
||||
Label loopHead(&builder_);
|
||||
Label loadHolder(&builder_);
|
||||
Label lookUpProto(&builder_);
|
||||
builder_.Jump(&loopHead);
|
||||
|
||||
builder_.LoopBegin(&loopHead);
|
||||
builder_.DeoptCheck(builder_.TaggedIsNotNull(*current), frameState, DeoptType::INCONSISTENTHCLASS);
|
||||
auto curHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), *current, TaggedObject::HCLASS_OFFSET);
|
||||
builder_.Branch(builder_.Equal(curHC, holderHC), &loadHolder, &lookUpProto);
|
||||
|
||||
builder_.Bind(&lookUpProto);
|
||||
current = builder_.LoadConstOffset(VariableType::JS_ANY(), curHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
builder_.LoopEnd(&loopHead);
|
||||
|
||||
builder_.Bind(&loadHolder);
|
||||
holder = *current;
|
||||
accessor = LoadPropertyFromHolder(holder, plr);
|
||||
builder_.Jump(&exitLoad);
|
||||
builder_.Bind(&exitLoad);
|
||||
DEFVALUE(result, (&builder_), VariableType::JS_ANY(), builder_.UndefineConstant());
|
||||
Label isInternalAccessor(&builder_);
|
||||
Label notInternalAccessor(&builder_);
|
||||
Label callGetter(&builder_);
|
||||
Label exit(&builder_);
|
||||
builder_.Branch(builder_.IsAccessorInternal(accessor), &isInternalAccessor, ¬InternalAccessor);
|
||||
{
|
||||
builder_.Bind(&isInternalAccessor);
|
||||
{
|
||||
result = builder_.CallRuntime(glue, RTSTUB_ID(CallInternalGetter),
|
||||
Gate::InvalidGateRef, { accessor, holder }, gate);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬InternalAccessor);
|
||||
{
|
||||
GateRef getter = builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::GETTER_OFFSET);
|
||||
builder_.Branch(builder_.IsSpecial(getter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callGetter);
|
||||
builder_.Bind(&callGetter);
|
||||
{
|
||||
result = CallAccessor(glue, gate, getter, receiver, AccessorMode::GETTER);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
ReplaceHirWithPendingException(gate, glue, builder_.GetState(), builder_.GetDepend(), *result);
|
||||
}
|
||||
|
||||
GateRef TypeHCRLowering::LoadPropertyFromHolder(GateRef holder, PropertyLookupResult plr)
|
||||
{
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (plr.IsNotHole()) {
|
||||
ASSERT(plr.IsLocal());
|
||||
if (plr.IsInlinedProps()) {
|
||||
result = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
|
||||
result = builder_.GetValueFromTaggedArray(properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
} else if (plr.IsLocal()) {
|
||||
if (plr.IsInlinedProps()) {
|
||||
result = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset());
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
|
||||
result = builder_.GetValueFromTaggedArray(properties, builder_.Int32(plr.GetOffset()));
|
||||
}
|
||||
result = builder_.ConvertHoleAsUndefined(result);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TypeHCRLowering::LowerMonoStorePropertyLookUpProto(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef frameState = acc_.GetFrameState(gate);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
|
||||
GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
|
||||
GateRef jsFunc = acc_.GetValueIn(gate, 3); // 3: jsFunc
|
||||
GateRef value = acc_.GetValueIn(gate, 4); // 4: value
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
bool noBarrier = acc_.IsNoBarrier(gate);
|
||||
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
// lookup from receiver for holder
|
||||
GateRef constPool = builder_.GetConstPool(jsFunc);
|
||||
auto holderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
||||
DEFVALUE(current, (&builder_), VariableType::JS_ANY(), prototype);
|
||||
Label exit(&builder_);
|
||||
Label loopHead(&builder_);
|
||||
Label loadHolder(&builder_);
|
||||
Label lookUpProto(&builder_);
|
||||
builder_.Jump(&loopHead);
|
||||
|
||||
builder_.LoopBegin(&loopHead);
|
||||
builder_.DeoptCheck(builder_.TaggedIsNotNull(*current), frameState, DeoptType::INCONSISTENTHCLASS);
|
||||
auto curHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), *current,
|
||||
TaggedObject::HCLASS_OFFSET);
|
||||
builder_.Branch(builder_.Equal(curHC, holderHC), &loadHolder, &lookUpProto);
|
||||
|
||||
builder_.Bind(&lookUpProto);
|
||||
current = builder_.LoadConstOffset(VariableType::JS_ANY(), curHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
builder_.LoopEnd(&loopHead);
|
||||
|
||||
builder_.Bind(&loadHolder);
|
||||
if (!plr.IsAccessor()) {
|
||||
StorePropertyOnHolder(*current, value, plr, noBarrier);
|
||||
builder_.Jump(&exit);
|
||||
} else {
|
||||
GateRef accessor = LoadPropertyFromHolder(*current, plr);
|
||||
Label isInternalAccessor(&builder_);
|
||||
Label notInternalAccessor(&builder_);
|
||||
Label callSetter(&builder_);
|
||||
builder_.Branch(builder_.IsAccessorInternal(accessor), &isInternalAccessor, ¬InternalAccessor);
|
||||
{
|
||||
builder_.Bind(&isInternalAccessor);
|
||||
{
|
||||
builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
|
||||
Gate::InvalidGateRef, { receiver, accessor, value }, gate);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬InternalAccessor);
|
||||
{
|
||||
GateRef setter =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
|
||||
builder_.Branch(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
|
||||
builder_.Bind(&callSetter);
|
||||
{
|
||||
CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeHCRLowering::LowerMonoStoreProperty(GateRef gate, GateRef glue)
|
||||
{
|
||||
Environment env(gate, circuit_, &builder_);
|
||||
GateRef receiver = acc_.GetValueIn(gate, 0);
|
||||
GateRef propertyLookupResult = acc_.GetValueIn(gate, 1); // 1: propertyLookupResult
|
||||
GateRef hclassIndex = acc_.GetValueIn(gate, 2); // 2: hclassIndex
|
||||
GateRef jsFunc = acc_.GetValueIn(gate, 3); // 3: jsFunc
|
||||
GateRef value = acc_.GetValueIn(gate, 4); // 4: value
|
||||
GateRef key = acc_.GetValueIn(gate, 5); // 5: key
|
||||
PropertyLookupResult plr(acc_.TryGetValue(propertyLookupResult));
|
||||
bool noBarrier = acc_.IsNoBarrier(gate);
|
||||
auto receiverHC = builder_.LoadConstOffset(VariableType::JS_POINTER(), receiver, TaggedObject::HCLASS_OFFSET);
|
||||
auto prototype = builder_.LoadConstOffset(VariableType::JS_ANY(), receiverHC, JSHClass::PROTOTYPE_OFFSET);
|
||||
// transition happened
|
||||
Label exit(&builder_);
|
||||
Label notProto(&builder_);
|
||||
Label isProto(&builder_);
|
||||
GateRef constPool = builder_.GetConstPool(jsFunc);
|
||||
auto newHolderHC = builder_.LoadHClassFromConstpool(constPool, acc_.GetConstantValue(hclassIndex));
|
||||
builder_.StoreConstOffset(VariableType::JS_ANY(), newHolderHC, JSHClass::PROTOTYPE_OFFSET, prototype);
|
||||
builder_.Branch(builder_.IsProtoTypeHClass(receiverHC), &isProto, ¬Proto,
|
||||
BranchWeight::ONE_WEIGHT, BranchWeight::DEOPT_WEIGHT);
|
||||
builder_.Bind(&isProto);
|
||||
builder_.CallRuntime(glue, RTSTUB_ID(UpdateAOTHClass), Gate::InvalidGateRef,
|
||||
{ receiverHC, newHolderHC, key }, gate);
|
||||
builder_.Jump(¬Proto);
|
||||
builder_.Bind(¬Proto);
|
||||
MemoryOrder order = MemoryOrder::Create(MemoryOrder::MEMORY_ORDER_RELEASE);
|
||||
builder_.StoreConstOffset(VariableType::JS_ANY(), receiver, TaggedObject::HCLASS_OFFSET, newHolderHC, order);
|
||||
if (!plr.IsInlinedProps()) {
|
||||
auto properties =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), receiver, JSObject::PROPERTIES_OFFSET);
|
||||
auto capacity = builder_.LoadConstOffset(VariableType::INT32(), properties, TaggedArray::LENGTH_OFFSET);
|
||||
auto index = builder_.Int32(plr.GetOffset());
|
||||
Label needExtend(&builder_);
|
||||
Label notExtend(&builder_);
|
||||
builder_.Branch(builder_.Int32UnsignedLessThan(index, capacity), ¬Extend, &needExtend);
|
||||
builder_.Bind(¬Extend);
|
||||
{
|
||||
if (!plr.IsAccessor()) {
|
||||
StorePropertyOnHolder(receiver, value, plr, noBarrier);
|
||||
builder_.Jump(&exit);
|
||||
} else {
|
||||
GateRef accessor = LoadPropertyFromHolder(receiver, plr);
|
||||
Label isInternalAccessor(&builder_);
|
||||
Label notInternalAccessor(&builder_);
|
||||
Label callSetter(&builder_);
|
||||
builder_.Branch(builder_.IsAccessorInternal(accessor), &isInternalAccessor, ¬InternalAccessor);
|
||||
{
|
||||
builder_.Bind(&isInternalAccessor);
|
||||
{
|
||||
builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
|
||||
Gate::InvalidGateRef, { receiver, accessor, value }, gate);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬InternalAccessor);
|
||||
{
|
||||
GateRef setter =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
|
||||
builder_.Branch(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
|
||||
builder_.Bind(&callSetter);
|
||||
{
|
||||
CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
builder_.Bind(&needExtend);
|
||||
{
|
||||
builder_.CallRuntime(glue,
|
||||
RTSTUB_ID(PropertiesSetValue),
|
||||
Gate::InvalidGateRef,
|
||||
{ receiver, value, properties, builder_.Int32ToTaggedInt(capacity),
|
||||
builder_.Int32ToTaggedInt(index) }, gate);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
} else {
|
||||
if (!plr.IsAccessor()) {
|
||||
StorePropertyOnHolder(receiver, value, plr, noBarrier);
|
||||
builder_.Jump(&exit);
|
||||
} else {
|
||||
GateRef accessor = LoadPropertyFromHolder(receiver, plr);
|
||||
Label isInternalAccessor(&builder_);
|
||||
Label notInternalAccessor(&builder_);
|
||||
Label callSetter(&builder_);
|
||||
builder_.Branch(builder_.IsAccessorInternal(accessor), &isInternalAccessor, ¬InternalAccessor);
|
||||
{
|
||||
builder_.Bind(&isInternalAccessor);
|
||||
{
|
||||
builder_.CallRuntime(glue, RTSTUB_ID(CallInternalSetter),
|
||||
Gate::InvalidGateRef, { receiver, accessor, value }, gate);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
builder_.Bind(¬InternalAccessor);
|
||||
{
|
||||
GateRef setter =
|
||||
builder_.LoadConstOffset(VariableType::JS_ANY(), accessor, AccessorData::SETTER_OFFSET);
|
||||
builder_.Branch(builder_.IsSpecial(setter, JSTaggedValue::VALUE_UNDEFINED), &exit, &callSetter);
|
||||
builder_.Bind(&callSetter);
|
||||
{
|
||||
CallAccessor(glue, gate, setter, receiver, AccessorMode::SETTER, value);
|
||||
builder_.Jump(&exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
builder_.Bind(&exit);
|
||||
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), Circuit::NullGate());
|
||||
}
|
||||
|
||||
void TypeHCRLowering::StorePropertyOnHolder(GateRef holder, GateRef value, PropertyLookupResult plr, bool noBarrier)
|
||||
{
|
||||
if (!noBarrier) {
|
||||
if (plr.IsInlinedProps()) {
|
||||
builder_.StoreConstOffset(VariableType::JS_ANY(), holder, plr.GetOffset(), value);
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
|
||||
builder_.SetValueToTaggedArray(
|
||||
VariableType::JS_ANY(), acc_.GetGlueFromArgList(), properties, builder_.Int32(plr.GetOffset()), value);
|
||||
}
|
||||
} else {
|
||||
if (plr.IsInlinedProps()) {
|
||||
builder_.StoreConstOffset(GetVarType(plr), holder, plr.GetOffset(), value);
|
||||
} else {
|
||||
auto properties = builder_.LoadConstOffset(VariableType::JS_ANY(), holder, JSObject::PROPERTIES_OFFSET);
|
||||
builder_.SetValueToTaggedArray(
|
||||
GetVarType(plr), acc_.GetGlueFromArgList(), properties, builder_.Int32(plr.GetOffset()), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypeHCRLowering::AddProfiling(GateRef gate)
|
||||
{
|
||||
if (IsLoopHoistProfiling()) {
|
||||
OpCode opcode = acc_.GetOpCode(gate);
|
||||
auto opcodeGate = builder_.Int32(static_cast<uint32_t>(opcode));
|
||||
GateRef constOpcode = builder_.Int32ToTaggedInt(opcodeGate);
|
||||
builder_.CallRuntime(acc_.GetGlueFromArgList(), RTSTUB_ID(ProfileLoopHoist),
|
||||
Gate::InvalidGateRef, { constOpcode }, gate);
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -112,6 +112,9 @@ public:
|
||||
tsManager_(tsManager),
|
||||
enableLoweringBuiltin_(enableLoweringBuiltin)
|
||||
{
|
||||
if (cmpCfg != nullptr) {
|
||||
loopHoistProfiling_ =cmpCfg->IsLoopHoistProfiling();
|
||||
}
|
||||
}
|
||||
|
||||
~TypeHCRLowering() = default;
|
||||
@ -206,6 +209,11 @@ private:
|
||||
GateRef NewJSPrimitiveRef(PrimitiveType type, GateRef glue, GateRef value);
|
||||
void ReplaceGateWithPendingException(GateRef glue, GateRef gate, GateRef state, GateRef depend, GateRef value);
|
||||
void LowerOrdinaryHasInstance(GateRef gate, GateRef glue);
|
||||
void LowerProtoChangeMarkerCheck(GateRef gate);
|
||||
void LowerMonoCallGetterOnProto(GateRef gate, GateRef glue);
|
||||
void LowerMonoLoadPropertyOnProto(GateRef gate);
|
||||
void LowerMonoStorePropertyLookUpProto(GateRef gate, GateRef glue);
|
||||
void LowerMonoStoreProperty(GateRef gate, GateRef glue);
|
||||
|
||||
GateRef LowerCallRuntime(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
|
||||
bool useLabel = false);
|
||||
@ -242,6 +250,15 @@ private:
|
||||
GateRef LoadFromConstPool(GateRef jsFunc, size_t index, size_t valVecType);
|
||||
GateRef LoadFromVTable(GateRef receiver, size_t index);
|
||||
GateRef GetLengthFromString(GateRef gate);
|
||||
GateRef LoadPropertyFromHolder(GateRef holder, PropertyLookupResult plr);
|
||||
void StorePropertyOnHolder(GateRef holder, GateRef value, PropertyLookupResult plr, bool needBarrier);
|
||||
|
||||
void AddProfiling(GateRef gate);
|
||||
|
||||
bool IsLoopHoistProfiling() const
|
||||
{
|
||||
return loopHoistProfiling_;
|
||||
}
|
||||
|
||||
Circuit *circuit_;
|
||||
GateAccessor acc_;
|
||||
@ -249,6 +266,7 @@ private:
|
||||
GateRef dependEntry_;
|
||||
[[maybe_unused]] TSManager *tsManager_ {nullptr};
|
||||
bool enableLoweringBuiltin_ {false};
|
||||
bool loopHoistProfiling_ {false};
|
||||
};
|
||||
} // panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_TYPE_HCR_LOWERING_H
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "ecmascript/compiler/bytecodes.h"
|
||||
#include "ecmascript/compiler/ecma_opcode_des.h"
|
||||
#include "ecmascript/compiler/share_opcodes.h"
|
||||
|
||||
// bcIndex bytecode count fast slow typerate
|
||||
// ====================(print all)=======================
|
||||
@ -204,5 +205,41 @@ private:
|
||||
std::map<uint64_t, Name> methodIdToName_;
|
||||
std::vector<CString> abcNames_;
|
||||
};
|
||||
|
||||
class LoopHoistProfiler {
|
||||
public:
|
||||
using OpCode = kungfu::OpCode;
|
||||
|
||||
LoopHoistProfiler()
|
||||
{
|
||||
profMap_ = {
|
||||
{ OpCode::LOAD_BUILTIN_OBJECT, 0 },
|
||||
{ OpCode::LOAD_PROPERTY, 0}
|
||||
};
|
||||
}
|
||||
|
||||
void Update (OpCode opcode)
|
||||
{
|
||||
if (opcode == OpCode::LOAD_BUILTIN_OBJECT ||
|
||||
opcode == OpCode::LOAD_PROPERTY) {
|
||||
profMap_.at(opcode)++;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintAndReset()
|
||||
{
|
||||
LOG_TRACE(INFO) << "LoopHoistProfiler:";
|
||||
LOG_TRACE(INFO) << "Opcode: LOAD_BUILTIN_OBJECT Count:"
|
||||
<< profMap_.at(OpCode::LOAD_BUILTIN_OBJECT);
|
||||
profMap_.at(OpCode::LOAD_BUILTIN_OBJECT) = 0;
|
||||
|
||||
LOG_TRACE(INFO) << "Opcode: LOAD_PROPERTY Count:"
|
||||
<< profMap_.at(OpCode::LOAD_PROPERTY);
|
||||
profMap_.at(OpCode::LOAD_PROPERTY) = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<OpCode, uint64_t> profMap_;
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
#endif // ECMASCRIPT_DFX_VMSTAT_OPT_CODE_PROFILER_H
|
||||
|
@ -123,6 +123,9 @@ bool EcmaContext::Initialize()
|
||||
tsManager_ = new TSManager(vm_);
|
||||
ptManager_ = new kungfu::PGOTypeManager(vm_);
|
||||
optCodeProfiler_ = new OptCodeProfiler();
|
||||
if (vm_->GetJSOptions().GetLoopHoistProfiler()) {
|
||||
loopHoistProfiler_ = new LoopHoistProfiler();
|
||||
}
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
@ -210,6 +213,10 @@ EcmaContext::~EcmaContext()
|
||||
delete optCodeProfiler_;
|
||||
optCodeProfiler_ = nullptr;
|
||||
}
|
||||
if (loopHoistProfiler_ != nullptr) {
|
||||
delete loopHoistProfiler_;
|
||||
loopHoistProfiler_ = nullptr;
|
||||
}
|
||||
if (moduleManager_ != nullptr) {
|
||||
delete moduleManager_;
|
||||
moduleManager_ = nullptr;
|
||||
|
@ -292,6 +292,11 @@ public:
|
||||
return optCodeProfiler_;
|
||||
}
|
||||
|
||||
LoopHoistProfiler *GetLoopHoistProfiler() const
|
||||
{
|
||||
return loopHoistProfiler_;
|
||||
}
|
||||
|
||||
// For icu objects cache
|
||||
void SetIcuFormatterToCache(IcuFormatterType type, const std::string &locale, void *icuObj,
|
||||
IcuDeleteEntry deleteEntry = nullptr)
|
||||
@ -558,6 +563,9 @@ private:
|
||||
// opt code Profiler
|
||||
OptCodeProfiler *optCodeProfiler_ {nullptr};
|
||||
|
||||
// opt code loop hoist
|
||||
LoopHoistProfiler *loopHoistProfiler_ {nullptr};
|
||||
|
||||
// For icu objects cache
|
||||
struct IcuFormatter {
|
||||
std::string locale;
|
||||
|
@ -154,10 +154,6 @@ bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle<JSObject> &sel
|
||||
func->SetProtoOrHClass(thread, newClass);
|
||||
} else {
|
||||
func->SetFunctionPrototype(thread, value.GetTaggedValue());
|
||||
if (thread->GetEcmaVM()->IsEnablePGOProfiler() && value->IsECMAObject()) {
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(func.GetTaggedType(),
|
||||
JSTaggedType(value->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1203,4 +1203,45 @@ CString JSHClass::DumpToString(JSTaggedType hclassVal)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PropertyLookupResult JSHClass::LookupPropertyInBuiltinHClass(const JSThread *thread, JSHClass *hclass,
|
||||
JSTaggedValue key)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
|
||||
PropertyLookupResult result;
|
||||
if (hclass->IsDictionaryMode()) {
|
||||
result.SetIsFound(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
int entry = JSHClass::FindPropertyEntry(thread, hclass, key);
|
||||
// found in local
|
||||
if (entry != -1) {
|
||||
result.SetIsFound(true);
|
||||
result.SetIsLocal(true);
|
||||
PropertyAttributes attr = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject())->GetAttr(entry);
|
||||
if (attr.IsInlinedProps()) {
|
||||
result.SetIsInlinedProps(true);
|
||||
result.SetOffset(hclass->GetInlinedPropertiesOffset(entry));
|
||||
} else {
|
||||
result.SetIsInlinedProps(false);
|
||||
result.SetOffset(attr.GetOffset() - hclass->GetInlinedProperties());
|
||||
}
|
||||
|
||||
if (attr.IsNotHole()) {
|
||||
result.SetIsNotHole(true);
|
||||
}
|
||||
if (attr.IsAccessor()) {
|
||||
result.SetIsAccessor(true);
|
||||
}
|
||||
result.SetRepresentation(attr.GetRepresentation());
|
||||
result.SetIsWritable(attr.IsWritable());
|
||||
return result;
|
||||
}
|
||||
|
||||
// not fuond
|
||||
result.SetIsFound(false);
|
||||
return result;
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -1772,6 +1772,8 @@ public:
|
||||
static PropertyLookupResult LookupPropertyInPGOHClass(const JSThread *thread, JSHClass *hclass, JSTaggedValue key);
|
||||
static PropertyLookupResult LookupPropertyInBuiltinPrototypeHClass(const JSThread *thread, JSHClass *hclass,
|
||||
JSTaggedValue key);
|
||||
static PropertyLookupResult LookupPropertyInBuiltinHClass(const JSThread *thread, JSHClass *hclass,
|
||||
JSTaggedValue key);
|
||||
|
||||
static constexpr size_t PROTOTYPE_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(Proto, PROTOTYPE_OFFSET, LAYOUT_OFFSET);
|
||||
|
@ -162,7 +162,8 @@ const std::string PUBLIC_API HELP_OPTION_MSG =
|
||||
"--compiler-enable-jit: Enable jit: Default: 'false'\n"
|
||||
"--compiler-jit-hotness-threshold: Set hotness threshold for jit. Default: '2'\n"
|
||||
"--compiler-force-jit-compile-main: Enable jit compile main function: Default: 'false'\n"
|
||||
"--compiler-trace-jit: Enable trace jit: Default: 'false'\n\n";
|
||||
"--compiler-trace-jit: Enable trace jit: Default: 'false'\n\n"
|
||||
"--compiler-loop-hoist-profiler: Enable loop hoist IR Statistics for aot runtime. Default: 'false'\n";
|
||||
|
||||
bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
{
|
||||
@ -266,6 +267,7 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
{"compiler-enable-jit", required_argument, nullptr, OPTION_COMPILER_ENABLE_JIT},
|
||||
{"compiler-jit-hotness-threshold", required_argument, nullptr, OPTION_COMPILER_JIT_HOTNESS_THRESHOLD},
|
||||
{"compiler-force-jit-compile-main", required_argument, nullptr, OPTION_COMPILER_FORCE_JIT_COMPILE_MAIN},
|
||||
{"compiler-loop-hoist-profiler", required_argument, nullptr, OPTION_COMPILER_LOOP_HOIST_PROFILER},
|
||||
{nullptr, 0, nullptr, 0},
|
||||
};
|
||||
|
||||
@ -934,6 +936,14 @@ bool JSRuntimeOptions::ParseCommand(const int argc, const char **argv)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case OPTION_COMPILER_LOOP_HOIST_PROFILER:
|
||||
ret = ParseBoolParam(&argBool);
|
||||
if (ret) {
|
||||
SetLoopHoistProfiler(argBool);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ECMA(ERROR) << "Invalid option\n";
|
||||
return false;
|
||||
|
@ -159,6 +159,7 @@ enum CommandValues {
|
||||
OPTION_COMPILER_FORCE_JIT_COMPILE_MAIN,
|
||||
OPTION_COMPILER_TRACE_JIT,
|
||||
OPTION_ENABLE_ELEMENTSKIND,
|
||||
OPTION_COMPILER_LOOP_HOIST_PROFILER,
|
||||
};
|
||||
|
||||
class PUBLIC_API JSRuntimeOptions {
|
||||
@ -1412,6 +1413,16 @@ public:
|
||||
return enableLiteCG_;
|
||||
}
|
||||
|
||||
void SetLoopHoistProfiler(bool value)
|
||||
{
|
||||
enableLoopHoistProfiler_ = value;
|
||||
}
|
||||
|
||||
bool GetLoopHoistProfiler() const
|
||||
{
|
||||
return enableLoopHoistProfiler_;
|
||||
}
|
||||
|
||||
private:
|
||||
static bool StartsWith(const std::string &haystack, const std::string &needle)
|
||||
{
|
||||
@ -1528,6 +1539,7 @@ private:
|
||||
bool enableNativeInline_ {false};
|
||||
bool enableLoweringBuiltin_ {false};
|
||||
bool enableLiteCG_ {false};
|
||||
bool enableLoopHoistProfiler_ {false};
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -108,6 +108,9 @@ void PGOProfiler::ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcV
|
||||
return;
|
||||
}
|
||||
auto ctorFunc = JSFunction::Cast(ctorValue.GetTaggedObject());
|
||||
if (!FunctionKindVerify(ctorFunc)) {
|
||||
return;
|
||||
}
|
||||
auto ctorMethodValue = ctorFunc->GetMethod();
|
||||
if (!ctorMethodValue.IsMethod()) {
|
||||
return;
|
||||
|
@ -2462,6 +2462,17 @@ DEF_RUNTIME_STUBS(ProfileOptimizedCode)
|
||||
return JSTaggedValue::Undefined().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(ProfileLoopHoist)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(ProfileOptimizedCode);
|
||||
kungfu::OpCode opcode = static_cast<kungfu::OpCode>(GetArg(argv, argc, 0).GetInt());
|
||||
LoopHoistProfiler *profiler = thread->GetCurrentEcmaContext()->GetLoopHoistProfiler();
|
||||
if (profiler != nullptr) {
|
||||
profiler->Update(opcode);
|
||||
}
|
||||
return JSTaggedValue::Undefined().GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(VerifyVTableLoading)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(VerifyVTableLoading);
|
||||
|
@ -341,6 +341,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(JSObjectGetMethod) \
|
||||
V(DebugAOTPrint) \
|
||||
V(ProfileOptimizedCode) \
|
||||
V(ProfileLoopHoist) \
|
||||
V(VerifyVTableLoading) \
|
||||
V(VerifyVTableStoring) \
|
||||
V(GetMethodFromCache) \
|
||||
|
@ -165,6 +165,7 @@ group("ark_aot_ts_test") {
|
||||
"lexenv_specialization_noopt",
|
||||
"load_local_module_var",
|
||||
"logic_op",
|
||||
"loop_hoist",
|
||||
"loop_peeling",
|
||||
"loop_phi",
|
||||
"loop_with_variable_exchange",
|
||||
|
25
test/aottest/loop_hoist/BUILD.gn
Normal file
25
test/aottest/loop_hoist/BUILD.gn
Normal file
@ -0,0 +1,25 @@
|
||||
# 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("loop_hoist") {
|
||||
deps = []
|
||||
is_only_typed_path = true
|
||||
is_enable_builtins_dts = true
|
||||
is_enable_pgo = true
|
||||
is_enable_opt_loop_peeling = true
|
||||
is_enable_lowering_builtin = true
|
||||
is_enable_loop_hoist_profiler = true
|
||||
log_option = " --log-info=trace"
|
||||
}
|
31
test/aottest/loop_hoist/expect_output.txt
Normal file
31
test/aottest/loop_hoist/expect_output.txt
Normal file
@ -0,0 +1,31 @@
|
||||
# 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] LoopHoistProfiler:
|
||||
[trace] Opcode: LOAD_BUILTIN_OBJECT Count:1
|
||||
[trace] Opcode: LOAD_PROPERTY Count:0
|
||||
[trace] LoopHoistProfiler:
|
||||
[trace] Opcode: LOAD_BUILTIN_OBJECT Count:1
|
||||
[trace] Opcode: LOAD_PROPERTY Count:0
|
||||
[trace] LoopHoistProfiler:
|
||||
[trace] Opcode: LOAD_BUILTIN_OBJECT Count:1
|
||||
[trace] Opcode: LOAD_PROPERTY Count:1
|
||||
[trace] LoopHoistProfiler:
|
||||
[trace] Opcode: LOAD_BUILTIN_OBJECT Count:1
|
||||
[trace] Opcode: LOAD_PROPERTY Count:1
|
||||
[trace] LoopHoistProfiler:
|
||||
[trace] Opcode: LOAD_BUILTIN_OBJECT Count:1
|
||||
[trace] Opcode: LOAD_PROPERTY Count:1
|
||||
[trace] LoopHoistProfiler:
|
||||
[trace] Opcode: LOAD_BUILTIN_OBJECT Count:1
|
||||
[trace] Opcode: LOAD_PROPERTY Count:1
|
51
test/aottest/loop_hoist/loop_hoist.ts
Normal file
51
test/aottest/loop_hoist/loop_hoist.ts
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 var ArkTools:any;
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
Math;
|
||||
}
|
||||
ArkTools.printLoopHoistProfilerAndReset();
|
||||
|
||||
for (let i = 0; i < 1; ++i) {
|
||||
for (let j = 0; j < 10; ++j) {
|
||||
Math;
|
||||
}
|
||||
}
|
||||
ArkTools.printLoopHoistProfilerAndReset();
|
||||
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
Math.sqrt;
|
||||
}
|
||||
ArkTools.printLoopHoistProfilerAndReset();
|
||||
|
||||
for (let i = 0; i < 1; ++i) {
|
||||
for (let j = 0; j < 10; ++j) {
|
||||
Math.sqrt;
|
||||
}
|
||||
}
|
||||
ArkTools.printLoopHoistProfilerAndReset();
|
||||
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
Math.sqrt(4);
|
||||
}
|
||||
ArkTools.printLoopHoistProfilerAndReset();
|
||||
|
||||
for (let i = 0; i < 1; ++i) {
|
||||
for (let j = 0; j < 10; ++j) {
|
||||
Math.sqrt(4);
|
||||
}
|
||||
}
|
||||
ArkTools.printLoopHoistProfilerAndReset();
|
13
test/aottest/loop_hoist/pgo_expect_output.txt
Normal file
13
test/aottest/loop_hoist/pgo_expect_output.txt
Normal file
@ -0,0 +1,13 @@
|
||||
# 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.
|
||||
|
@ -695,6 +695,16 @@ template("host_aot_js_test_action") {
|
||||
" --compiler-opt-inlining=true --compiler-opt-type-lowering=true"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_loop_hoist_profiler) &&
|
||||
invoker.is_enable_loop_hoist_profiler) {
|
||||
_aot_compile_options_ += " --compiler-loop-hoist-profiler=true "
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_lowering_builtin) &&
|
||||
invoker.is_enable_lowering_builtin) {
|
||||
_aot_compile_options_ += " --compiler-enable-lowering-builtin=true"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_native_inline) &&
|
||||
invoker.is_enable_native_inline) {
|
||||
_aot_compile_options_ += " --compiler-enable-native-inline"
|
||||
@ -772,6 +782,20 @@ template("host_aot_js_test_action") {
|
||||
_aot_run_options_ += " --enable-force-gc=false"
|
||||
}
|
||||
|
||||
if (defined(invoker.log_option)) {
|
||||
_aot_run_options_ += invoker.log_option
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_loop_hoist_profiler) &&
|
||||
invoker.is_enable_loop_hoist_profiler) {
|
||||
_aot_run_options_ += " --compiler-loop-hoist-profiler=ture"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_lowering_builtin) &&
|
||||
invoker.is_enable_lowering_builtin) {
|
||||
_aot_run_options_ += " --compiler-enable-lowering-builtin=true"
|
||||
}
|
||||
|
||||
_icu_data_path_options_ =
|
||||
" --icu-data-path=" + rebase_path("//third_party/icu/ohos_icu4j/data")
|
||||
_aot_run_options_ += _icu_data_path_options_
|
||||
@ -834,6 +858,16 @@ template("host_aot_js_test_action") {
|
||||
_aot_run_options_ += invoker.log_option
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_loop_hoist_profiler) &&
|
||||
invoker.is_enable_loop_hoist_profiler) {
|
||||
_aot_run_options_ += " --compiler-loop-hoist-profiler=ture"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_lowering_builtin) &&
|
||||
invoker.is_enable_lowering_builtin) {
|
||||
_aot_run_options_ += " --compiler-enable-lowering-builtin=true"
|
||||
}
|
||||
|
||||
_icu_data_path_options_ =
|
||||
" --icu-data-path=" + rebase_path("//third_party/icu/ohos_icu4j/data")
|
||||
_aot_run_options_ += _icu_data_path_options_
|
||||
@ -1011,6 +1045,16 @@ template("host_aot_test_action") {
|
||||
" --compiler-opt-inlining=true --compiler-opt-type-lowering=true"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_loop_hoist_profiler) &&
|
||||
invoker.is_enable_loop_hoist_profiler) {
|
||||
_aot_compile_options_ += " --compiler-loop-hoist-profiler=true "
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_lowering_builtin) &&
|
||||
invoker.is_enable_lowering_builtin) {
|
||||
_aot_compile_options_ += " --compiler-enable-lowering-builtin=true"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_native_inline) &&
|
||||
invoker.is_enable_native_inline) {
|
||||
_aot_compile_options_ += " --compiler-enable-native-inline"
|
||||
@ -1185,6 +1229,16 @@ template("host_aot_test_action") {
|
||||
_aot_run_options_ += invoker.log_option
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_loop_hoist_profiler) &&
|
||||
invoker.is_enable_loop_hoist_profiler) {
|
||||
_aot_run_options_ += " --compiler-loop-hoist-profiler=ture"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_lowering_builtin) &&
|
||||
invoker.is_enable_lowering_builtin) {
|
||||
_aot_run_options_ += " --compiler-enable-lowering-builtin=true"
|
||||
}
|
||||
|
||||
args = [
|
||||
"--script-file",
|
||||
rebase_path(_root_out_dir_) + "/arkcompiler/ets_runtime/ark_js_vm",
|
||||
@ -1246,6 +1300,16 @@ template("host_aot_test_action") {
|
||||
}
|
||||
_aot_run_options_ += " --enable-context=true"
|
||||
|
||||
if (defined(invoker.is_enable_loop_hoist_profiler) &&
|
||||
invoker.is_enable_loop_hoist_profiler) {
|
||||
_aot_run_options_ += " --compiler-loop-hoist-profiler=ture"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_lowering_builtin) &&
|
||||
invoker.is_enable_lowering_builtin) {
|
||||
_aot_run_options_ += " --compiler-enable-lowering-builtin=true"
|
||||
}
|
||||
|
||||
args = [
|
||||
"--script-file",
|
||||
rebase_path(_root_out_dir_) + "/arkcompiler/ets_runtime/ark_js_vm",
|
||||
|
Loading…
Reference in New Issue
Block a user