mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
Fix(Aot): Support ldobjbyValue and string.length fastpath by pgotype
Issue: #I8HJDP Change-Id: I80eb3096f8e3c40218ae1142194b5b5d4a5afb1d Signed-off-by: yingguofeng@huawei.com <yingguofeng@huawei.com>
This commit is contained in:
parent
c544e90445
commit
82336875e9
@ -440,7 +440,7 @@ public:
|
||||
GateRef RangeGuard(GateRef gate, uint32_t left, uint32_t right);
|
||||
GateRef BuiltinPrototypeHClassCheck(GateRef gate, BuiltinTypeId type);
|
||||
GateRef OrdinaryHasInstanceCheck(GateRef target, GateRef jsFunc, std::vector<GateRef> &expectedHCIndexes);
|
||||
GateRef IndexCheck(GateType type, GateRef gate, GateRef index);
|
||||
GateRef IndexCheck(GateRef gate, GateRef index);
|
||||
GateRef ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex);
|
||||
GateRef ObjectTypeCompare(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex);
|
||||
GateRef TryPrimitiveTypeCheck(GateType type, GateRef gate);
|
||||
|
@ -324,7 +324,6 @@ bool EarlyElimination::CheckReplacement(GateRef lhs, GateRef rhs)
|
||||
break;
|
||||
}
|
||||
case OpCode::TYPED_ARRAY_CHECK:
|
||||
case OpCode::INDEX_CHECK:
|
||||
case OpCode::TYPE_OF_CHECK: {
|
||||
if (acc_.GetParamGateType(lhs) != acc_.GetParamGateType(rhs)) {
|
||||
return false;
|
||||
|
@ -234,13 +234,13 @@ GateRef CircuitBuilder::BuiltinPrototypeHClassCheck(GateRef gate, BuiltinTypeId
|
||||
return ret;
|
||||
}
|
||||
|
||||
GateRef CircuitBuilder::IndexCheck(GateType type, GateRef gate, GateRef index)
|
||||
GateRef CircuitBuilder::IndexCheck(GateRef gate, GateRef index)
|
||||
{
|
||||
auto currentLabel = env_->GetCurrentLabel();
|
||||
auto currentControl = currentLabel->GetControl();
|
||||
auto currentDepend = currentLabel->GetDepend();
|
||||
auto frameState = acc_.FindNearestFrameState(currentDepend);
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->IndexCheck(static_cast<size_t>(type.Value())),
|
||||
GateRef ret = GetCircuit()->NewGate(circuit_->IndexCheck(),
|
||||
MachineType::I64, {currentControl, currentDepend, gate, index, frameState}, GateType::IntType());
|
||||
currentLabel->SetControl(ret);
|
||||
currentLabel->SetDepend(ret);
|
||||
|
@ -53,6 +53,7 @@ namespace panda::ecmascript::kungfu {
|
||||
V(InlineAccessorCheck, INLINE_ACCESSOR_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
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) \
|
||||
MCR_BINARY_GATE_META_DATA_CACHE_LIST(V)
|
||||
|
||||
#define MCR_GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \
|
||||
@ -90,7 +91,6 @@ namespace panda::ecmascript::kungfu {
|
||||
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
|
||||
V(LoadTypedArrayLength, LOAD_TYPED_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
|
||||
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
|
||||
|
@ -56,8 +56,8 @@ std::vector<ElementsKind> PGOTypeRecorder::GetElementsKindsForUser(int32_t offse
|
||||
for (uint32_t i = 0; i < rwType.GetCount(); i++) {
|
||||
PGOObjectInfo info = rwType.GetObjectInfo(i);
|
||||
auto profileType = info.GetProfileType();
|
||||
if (profileType.IsElementType()) {
|
||||
elementsKinds.emplace_back(ElementsKind(profileType.GetId()));
|
||||
if (profileType.IsBuiltinsArray()) {
|
||||
elementsKinds.emplace_back(profileType.GetElementsKind());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1048,6 +1048,18 @@ GateRef TypeBytecodeLowering::BuildNamedPropertyAccess(
|
||||
|
||||
bool TypeBytecodeLowering::TryLowerTypedLdObjByNameForBuiltin(GateRef gate, GateType receiverType, JSTaggedValue key)
|
||||
{
|
||||
ChunkVector<ProfileType> types(chunk_);
|
||||
FetchBuiltinsTypes(gate, types);
|
||||
// Just supported mono.
|
||||
if (types.size() == 1) {
|
||||
if (types[0].IsBuiltinsString()) {
|
||||
return TryLowerTypedLdObjByNameForBuiltin(gate, key, BuiltinTypeId::STRING);
|
||||
}
|
||||
if (types[0].IsBuiltinsArray()) {
|
||||
return TryLowerTypedLdObjByNameForBuiltin(gate, key, BuiltinTypeId::ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
// String: primitive string type only
|
||||
// e.g. let s1 = "ABC"; // OK
|
||||
// let s2 = new String("DEF"); // Not included, whose type is JSType::JS_PRIMITIVE_REF
|
||||
@ -1239,7 +1251,7 @@ void TypeBytecodeLowering::LowerTypedStObjByIndex(GateRef gate)
|
||||
index = builder_.Int32(indexValue);
|
||||
auto length = builder_.LoadTypedArrayLength(receiverType, receiver);
|
||||
if (!Uncheck()) {
|
||||
builder_.IndexCheck(receiverType, length, index);
|
||||
builder_.IndexCheck(length, index);
|
||||
}
|
||||
|
||||
if (tsManager_->IsBuiltinInstanceType(BuiltinTypeId::FLOAT32_ARRAY, receiverType)) {
|
||||
@ -1267,22 +1279,34 @@ void TypeBytecodeLowering::LowerTypedLdObjByValue(GateRef gate, bool isThis)
|
||||
receiver = acc_.GetValueIn(gate, 1);
|
||||
propKey = acc_.GetValueIn(gate, 2); // 2: the third parameter
|
||||
}
|
||||
ChunkVector<ProfileType> types(chunk_);
|
||||
FetchBuiltinsTypes(gate, types);
|
||||
GateRef result = Circuit::NullGate();
|
||||
// Just supported mono.
|
||||
if (types.size() == 1) {
|
||||
if (types[0].IsBuiltinsString()) {
|
||||
AddProfiling(gate);
|
||||
acc_.SetGateType(propKey, GateType::NumberType());
|
||||
result = LoadStringByIndex(receiver, propKey);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
|
||||
return;
|
||||
} else if (types[0].IsBuiltinsArray()) {
|
||||
AddProfiling(gate);
|
||||
ElementsKind kind = acc_.TryGetArrayElementsKind(gate);
|
||||
acc_.SetGateType(propKey, GateType::NumberType());
|
||||
result = LoadJSArrayByIndex(receiver, propKey, kind);
|
||||
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
GateType propKeyType = acc_.GetGateType(propKey);
|
||||
receiverType = tsManager_->TryNarrowUnionType(receiverType);
|
||||
if (!propKeyType.IsNumberType()) {
|
||||
return; // slowpath
|
||||
}
|
||||
|
||||
GateRef result = Circuit::NullGate();
|
||||
if (receiverType.IsStringType()) {
|
||||
AddProfiling(gate);
|
||||
result = LoadStringByIndex(receiver, propKey);
|
||||
} else if (tsManager_->IsArrayTypeKind(receiverType)) {
|
||||
AddProfiling(gate);
|
||||
ElementsKind kind = acc_.TryGetArrayElementsKind(gate);
|
||||
result = LoadJSArrayByIndex(receiver, propKey, kind);
|
||||
} else if (tsManager_->IsValidTypedArrayType(receiverType)) {
|
||||
if (tsManager_->IsValidTypedArrayType(receiverType)) {
|
||||
AddProfiling(gate);
|
||||
result = LoadTypedArrayByIndex(receiver, propKey);
|
||||
} else {
|
||||
@ -1294,11 +1318,9 @@ void TypeBytecodeLowering::LowerTypedLdObjByValue(GateRef gate, bool isThis)
|
||||
GateRef TypeBytecodeLowering::LoadStringByIndex(GateRef receiver, GateRef propKey)
|
||||
{
|
||||
if (!Uncheck()) {
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
receiverType = tsManager_->TryNarrowUnionType(receiverType);
|
||||
builder_.EcmaStringCheck(receiver);
|
||||
GateRef length = builder_.LoadStringLength(receiver);
|
||||
propKey = builder_.IndexCheck(receiverType, length, propKey);
|
||||
propKey = builder_.IndexCheck(length, propKey);
|
||||
receiver = builder_.FlattenTreeStringCheck(receiver);
|
||||
}
|
||||
return builder_.LoadElement<TypedLoadOp::STRING_LOAD_ELEMENT>(receiver, propKey);
|
||||
@ -1307,13 +1329,11 @@ GateRef TypeBytecodeLowering::LoadStringByIndex(GateRef receiver, GateRef propKe
|
||||
GateRef TypeBytecodeLowering::LoadJSArrayByIndex(GateRef receiver, GateRef propKey, ElementsKind kind)
|
||||
{
|
||||
if (!Uncheck()) {
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
receiverType = tsManager_->TryNarrowUnionType(receiverType);
|
||||
if (!IsCreateArray(receiver)) {
|
||||
builder_.StableArrayCheck(receiver, kind, ArrayMetaDataAccessor::Mode::LOAD_ELEMENT);
|
||||
}
|
||||
GateRef length = builder_.LoadArrayLength(receiver);
|
||||
propKey = builder_.IndexCheck(receiverType, length, propKey);
|
||||
propKey = builder_.IndexCheck(length, propKey);
|
||||
}
|
||||
|
||||
GateRef result = Circuit::NullGate();
|
||||
@ -1338,7 +1358,7 @@ GateRef TypeBytecodeLowering::LoadTypedArrayByIndex(GateRef receiver, GateRef pr
|
||||
if (!Uncheck()) {
|
||||
builder_.TypedArrayCheck(receiverType, receiver);
|
||||
GateRef length = builder_.LoadTypedArrayLength(receiverType, receiver);
|
||||
propKey = builder_.IndexCheck(receiverType, length, propKey);
|
||||
propKey = builder_.IndexCheck(length, propKey);
|
||||
}
|
||||
auto builtinTypeId = tsManager_->GetTypedArrayBuiltinId(receiverType);
|
||||
switch (builtinTypeId) {
|
||||
@ -1371,13 +1391,11 @@ GateRef TypeBytecodeLowering::LoadTypedArrayByIndex(GateRef receiver, GateRef pr
|
||||
void TypeBytecodeLowering::StoreJSArrayByIndex(GateRef receiver, GateRef propKey, GateRef value, ElementsKind kind)
|
||||
{
|
||||
if (!Uncheck()) {
|
||||
GateType receiverType = acc_.GetGateType(receiver);
|
||||
receiverType = tsManager_->TryNarrowUnionType(receiverType);
|
||||
if (!IsCreateArray(receiver)) {
|
||||
builder_.StableArrayCheck(receiver, kind, ArrayMetaDataAccessor::Mode::STORE_ELEMENT);
|
||||
}
|
||||
GateRef length = builder_.LoadArrayLength(receiver);
|
||||
builder_.IndexCheck(receiverType, length, propKey);
|
||||
builder_.IndexCheck(length, propKey);
|
||||
builder_.COWArrayCheck(receiver);
|
||||
|
||||
if (Elements::IsObject(kind)) {
|
||||
@ -1396,7 +1414,7 @@ void TypeBytecodeLowering::StoreTypedArrayByIndex(GateRef receiver, GateRef prop
|
||||
if (!Uncheck()) {
|
||||
builder_.TypedArrayCheck(receiverType, receiver);
|
||||
GateRef length = builder_.LoadTypedArrayLength(receiverType, receiver);
|
||||
propKey = builder_.IndexCheck(receiverType, length, propKey);
|
||||
propKey = builder_.IndexCheck(length, propKey);
|
||||
}
|
||||
|
||||
auto builtinTypeId = tsManager_->GetTypedArrayBuiltinId(receiverType);
|
||||
@ -2032,11 +2050,25 @@ void TypeBytecodeLowering::AddProfiling(GateRef gate)
|
||||
}
|
||||
}
|
||||
|
||||
void TypeBytecodeLowering::FetchBuiltinsTypes(GateRef gate, ChunkVector<ProfileType> &types)
|
||||
{
|
||||
const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate).GetPGORWOpType();
|
||||
for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
|
||||
auto temp = pgoTypes->GetObjectInfo(i);
|
||||
if (temp.GetReceiverType().IsBuiltinsType()) {
|
||||
types.emplace_back(temp.GetReceiverType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypeBytecodeLowering::FetchPGORWTypesDual(GateRef gate, ChunkVector<std::pair<ProfileTyper, ProfileTyper>> &types)
|
||||
{
|
||||
const PGORWOpType *pgoTypes = acc_.TryGetPGOType(gate).GetPGORWOpType();
|
||||
for (uint32_t i = 0; i < pgoTypes->GetCount(); ++i) {
|
||||
auto temp = pgoTypes->GetObjectInfo(i);
|
||||
if (temp.GetReceiverType().IsBuiltinsType()) {
|
||||
continue;
|
||||
}
|
||||
types.emplace_back(std::make_pair(
|
||||
std::make_pair(temp.GetReceiverRootType(), temp.GetReceiverType()),
|
||||
std::make_pair(temp.GetHoldRootType(), temp.GetHoldType())
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "ecmascript/compiler/builtins/builtins_call_signature.h"
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
#include "ecmascript/compiler/circuit_builder-inl.h"
|
||||
#include "ecmascript/compiler/pgo_type/pgo_type_manager.h"
|
||||
#include "ecmascript/compiler/object_access_helper.h"
|
||||
#include "ecmascript/compiler/pass_manager.h"
|
||||
#include "ecmascript/enum_conversion.h"
|
||||
@ -41,6 +42,7 @@ public:
|
||||
builder_(circuit, ctx->GetCompilerConfig()),
|
||||
dependEntry_(circuit->GetDependRoot()),
|
||||
tsManager_(ctx->GetTSManager()),
|
||||
ptManager_(ctx->GetPTManager()),
|
||||
chunk_(chunk),
|
||||
enableLog_(enableLog),
|
||||
enableTypeLog_(enableTypeLog),
|
||||
@ -190,6 +192,7 @@ private:
|
||||
void DeleteConstDataIfNoUser(GateRef gate);
|
||||
bool TryLowerNewBuiltinConstructor(GateRef gate);
|
||||
|
||||
void FetchBuiltinsTypes(GateRef gate, ChunkVector<ProfileType> &types);
|
||||
void FetchPGORWTypesDual(GateRef gate, ChunkVector<std::pair<ProfileTyper, ProfileTyper>> &types);
|
||||
void AddProfiling(GateRef gate);
|
||||
|
||||
@ -203,6 +206,7 @@ private:
|
||||
CircuitBuilder builder_;
|
||||
GateRef dependEntry_ {Gate::InvalidGateRef};
|
||||
TSManager *tsManager_ {nullptr};
|
||||
PGOTypeManager *ptManager_ {nullptr};
|
||||
Chunk *chunk_ {nullptr};
|
||||
bool enableLog_ {false};
|
||||
bool enableTypeLog_ {false};
|
||||
|
@ -81,6 +81,11 @@ public:
|
||||
}
|
||||
|
||||
static inline bool IsElement(uint32_t handler)
|
||||
{
|
||||
return IsNormalElement(handler) || IsStringElement(handler) || IsTypedArrayElement(handler);
|
||||
}
|
||||
|
||||
static inline bool IsNormalElement(uint32_t handler)
|
||||
{
|
||||
return GetKind(handler) == HandlerKind::ELEMENT;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::TryLoadICByValue(JSThread *thread, JSTag
|
||||
if (receiver.IsHeapObject()) {
|
||||
auto hclass = receiver.GetTaggedObject()->GetClass();
|
||||
if (firstValue.GetWeakReferentUnChecked() == hclass) {
|
||||
if (HandlerBase::IsElement(secondValue.GetInt())) {
|
||||
if (HandlerBase::IsNormalElement(secondValue.GetInt())) {
|
||||
return LoadElement(JSObject::Cast(receiver.GetTaggedObject()), key);
|
||||
} else if (HandlerBase::IsTypedArrayElement(secondValue.GetInt())) {
|
||||
return LoadTypedArrayElement(thread, receiver, key);
|
||||
|
@ -65,7 +65,7 @@ HWTEST_F_L0(ICHandlerTest, LoadElement)
|
||||
JSHandle<JSTaggedValue> handleKey(factory->NewFromASCII("key"));
|
||||
ObjectOperator handleOp(thread, handleKey);
|
||||
JSTaggedValue result = LoadHandler::LoadElement(thread, handleOp).GetTaggedValue();
|
||||
EXPECT_TRUE(HandlerBase::IsElement(result.GetInt()));
|
||||
EXPECT_TRUE(HandlerBase::IsNormalElement(result.GetInt()));
|
||||
EXPECT_EQ(HandlerBase::GetKind(result.GetInt()), HandlerKind::ELEMENT);
|
||||
}
|
||||
|
||||
|
@ -443,7 +443,7 @@ void JSHClass::ShouldUpdateProtoClass(const JSThread *thread, const JSHandle<JST
|
||||
#endif
|
||||
JSObject::Cast(proto->GetTaggedObject())->SynchronizedSetClass(*newProtoClass);
|
||||
newProtoClass->SetIsPrototype(true);
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->UpdateProfileType(*hclass, *newProtoClass);
|
||||
thread->GetEcmaVM()->GetPGOProfiler()->UpdateRootProfileType(*hclass, *newProtoClass);
|
||||
} else {
|
||||
hclass->SetIsPrototype(true);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ecmascript/ic/profile_type_info.h"
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "ecmascript/js_function.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
#include "ecmascript/log_wrapper.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_context.h"
|
||||
@ -152,7 +153,7 @@ void PGOProfiler::ProfileDefineGetterSetter(
|
||||
AddTranstionLayout(receverHClass, holderHClass);
|
||||
}
|
||||
|
||||
void PGOProfiler::UpdateProfileType(JSHClass *oldHClass, JSHClass *newHClass)
|
||||
void PGOProfiler::UpdateRootProfileType(JSHClass *oldHClass, JSHClass *newHClass)
|
||||
{
|
||||
if (!isEnable_) {
|
||||
return;
|
||||
@ -163,12 +164,14 @@ void PGOProfiler::UpdateProfileType(JSHClass *oldHClass, JSHClass *newHClass)
|
||||
return;
|
||||
}
|
||||
auto generator = iter->second;
|
||||
generator->UpdateProfileType(JSTaggedType(oldHClass), JSTaggedType(newHClass));
|
||||
if (oldRootHClass == oldHClass) {
|
||||
auto rootProfileType = generator->GetProfileType(JSTaggedType(oldRootHClass));
|
||||
if (rootProfileType.IsNone()) {
|
||||
tracedProfiles_.erase(iter);
|
||||
auto newRootHClass = JSHClass::FindRootHClass(newHClass);
|
||||
tracedProfiles_.emplace(JSTaggedType(newRootHClass), generator);
|
||||
return;
|
||||
}
|
||||
tracedProfiles_.erase(iter);
|
||||
newHClass->SetParent(vm_->GetJSThread(), JSTaggedValue::Undefined());
|
||||
InsertProfileType(JSTaggedType(newHClass), JSTaggedType(newHClass), rootProfileType);
|
||||
}
|
||||
|
||||
void PGOProfiler::UpdateTrackElementsKind(JSTaggedValue trackInfoVal, ElementsKind newKind)
|
||||
@ -770,7 +773,10 @@ void PGOProfiler::DumpICByNameWithHandler(ApEntityId abcId, const CString &recor
|
||||
if (HandlerBase::IsNonExist(handlerInfo)) {
|
||||
return;
|
||||
}
|
||||
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass);
|
||||
if (HandlerBase::IsField(handlerInfo)) {
|
||||
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass);
|
||||
}
|
||||
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
} else if (secondValue.IsPrototypeHandler()) {
|
||||
auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = prototypeHandler->GetProtoCell();
|
||||
@ -854,8 +860,8 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco
|
||||
if (type == BCType::LOAD) {
|
||||
if (secondValue.IsInt()) {
|
||||
auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
|
||||
if (HandlerBase::IsJSArray(handlerInfo) || HandlerBase::IsTypedArrayElement(handlerInfo)) {
|
||||
AddElementInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
if (HandlerBase::IsElement(handlerInfo)) {
|
||||
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
return;
|
||||
}
|
||||
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass);
|
||||
@ -864,8 +870,8 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco
|
||||
}
|
||||
if (secondValue.IsInt()) {
|
||||
auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
|
||||
if (HandlerBase::IsJSArray(handlerInfo) || HandlerBase::IsTypedArrayElement(handlerInfo)) {
|
||||
AddElementInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
if (HandlerBase::IsElement(handlerInfo)) {
|
||||
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
return;
|
||||
}
|
||||
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, hclass);
|
||||
@ -878,8 +884,8 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco
|
||||
auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt());
|
||||
if (transitionHClassVal.IsJSHClass()) {
|
||||
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
|
||||
if (HandlerBase::IsJSArray(handlerInfo)) {
|
||||
AddElementInfo(abcId, recordName, methodId, bcOffset, transitionHClass);
|
||||
if (HandlerBase::IsElement(handlerInfo)) {
|
||||
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, transitionHClass);
|
||||
return;
|
||||
}
|
||||
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass);
|
||||
@ -894,8 +900,8 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco
|
||||
auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt());
|
||||
if (transitionHClassVal.IsJSHClass()) {
|
||||
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
|
||||
if (HandlerBase::IsJSArray(handlerInfo)) {
|
||||
AddElementInfo(abcId, recordName, methodId, bcOffset, transitionHClass);
|
||||
if (HandlerBase::IsElement(handlerInfo)) {
|
||||
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, transitionHClass);
|
||||
return;
|
||||
}
|
||||
AddObjectInfo(abcId, recordName, methodId, bcOffset, hclass, hclass, transitionHClass);
|
||||
@ -913,8 +919,8 @@ void PGOProfiler::DumpICByValueWithHandler(ApEntityId abcId, const CString &reco
|
||||
JSTaggedValue handlerInfoValue = prototypeHandler->GetHandlerInfo();
|
||||
ASSERT(handlerInfoValue.IsInt());
|
||||
auto handlerInfo = static_cast<uint32_t>(handlerInfoValue.GetInt());
|
||||
if (HandlerBase::IsJSArray(handlerInfo)) {
|
||||
AddElementInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
if (HandlerBase::IsElement(handlerInfo)) {
|
||||
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, hclass);
|
||||
return;
|
||||
}
|
||||
auto holder = prototypeHandler->GetHolder();
|
||||
@ -983,16 +989,24 @@ void PGOProfiler::DumpDefineClass(ApEntityId abcId, const CString &recordName, E
|
||||
auto ctorHClass = ctorFunction->GetJSHClass();
|
||||
auto ctorRootHClass = JSTaggedType(JSHClass::FindRootHClass(ctorHClass));
|
||||
auto ctorType = GetProfileType(ctorRootHClass, ctorRootHClass);
|
||||
objDefType.SetCtorPt(ctorType);
|
||||
recordInfos_->AddRootLayout(ctorRootHClass, ctorType);
|
||||
if (ctorType.IsNone()) {
|
||||
LOG_ECMA(DEBUG) << "The profileType of constructor root hclass was not found.";
|
||||
} else {
|
||||
objDefType.SetCtorPt(ctorType);
|
||||
recordInfos_->AddRootLayout(ctorRootHClass, ctorType);
|
||||
}
|
||||
|
||||
if (protoOrHClass.IsJSObject()) {
|
||||
auto prototypeObj = JSObject::Cast(protoOrHClass);
|
||||
auto prototypeHClass = prototypeObj->GetClass();
|
||||
auto prototypeRootHClass = JSTaggedType(JSHClass::FindRootHClass(prototypeHClass));
|
||||
auto prototypeType = GetProfileType(prototypeRootHClass, prototypeRootHClass);
|
||||
objDefType.SetProtoTypePt(prototypeType);
|
||||
recordInfos_->AddRootLayout(prototypeRootHClass, prototypeType);
|
||||
if (prototypeType.IsNone()) {
|
||||
LOG_ECMA(DEBUG) << "The profileType of prototype root hclass was not found.";
|
||||
} else {
|
||||
objDefType.SetProtoTypePt(prototypeType);
|
||||
recordInfos_->AddRootLayout(prototypeRootHClass, prototypeType);
|
||||
}
|
||||
}
|
||||
|
||||
recordInfos_->AddDefine(recordType, methodId, bcOffset, objDefType);
|
||||
@ -1185,19 +1199,19 @@ void PGOProfiler::AddObjectInfoWithMega(
|
||||
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
|
||||
}
|
||||
|
||||
void PGOProfiler::AddElementInfo(
|
||||
void PGOProfiler::AddBuiltinsInfo(
|
||||
ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *receiver)
|
||||
{
|
||||
ProfileType recordType = GetRecordProfileType(abcId, recordName);
|
||||
if (receiver->IsJSArray()) {
|
||||
auto type = receiver->GetObjectType();
|
||||
auto elementsKind = receiver->GetElementsKind();
|
||||
auto profileType = ProfileType(abcId, static_cast<uint32_t>(elementsKind), ProfileType::Kind::ElementId);
|
||||
auto profileType = ProfileType::CreateBuiltinsArray(abcId, type, elementsKind);
|
||||
PGOObjectInfo info(profileType);
|
||||
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
|
||||
} else if (receiver->IsTypedArray()) {
|
||||
// Depend to TypedArray IC
|
||||
auto id = static_cast<uint32_t>(receiver->GetObjectType());
|
||||
PGOObjectInfo info(ProfileType(abcId, id, ProfileType::Kind::BuiltinsId));
|
||||
} else if (receiver->IsTypedArray() || receiver->IsString()) {
|
||||
auto type = receiver->GetObjectType();
|
||||
PGOObjectInfo info(ProfileType::CreateBuiltins(abcId, type));
|
||||
recordInfos_->AddObjectInfo(recordType, methodId, bcOffset, info);
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public:
|
||||
JSHClass *receverHClass, JSHClass *holderHClass, const JSHandle<JSTaggedValue> &func, int32_t pcOffset);
|
||||
void ProfileClassRootHClass(JSTaggedType ctor, JSTaggedType rootHcValue,
|
||||
ProfileType::Kind kind = ProfileType::Kind::ClassId);
|
||||
void UpdateProfileType(JSHClass *oldHClass, JSHClass *newHClass);
|
||||
void UpdateRootProfileType(JSHClass *oldHClass, JSHClass *newHClass);
|
||||
|
||||
void SetSaveTimestamp(std::chrono::system_clock::time_point timestamp)
|
||||
{
|
||||
@ -146,7 +146,7 @@ private:
|
||||
void AddObjectInfo(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset,
|
||||
JSHClass *receiver, JSHClass *hold, JSHClass *holdTra);
|
||||
void AddObjectInfoWithMega(ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset);
|
||||
void AddElementInfo(
|
||||
void AddBuiltinsInfo(
|
||||
ApEntityId abcId, const CString &recordName, EntityId methodId, int32_t bcOffset, JSHClass *receiver);
|
||||
|
||||
ProfileType GetProfileType(JSTaggedType root, JSTaggedType child);
|
||||
|
@ -935,21 +935,21 @@ HWTEST_F_L0(PGOProfilerTest, ArrayProfileTest)
|
||||
if (std::string(methodName) == "foo") {
|
||||
ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
|
||||
auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
|
||||
ASSERT_TRUE(classType.IsElementType());
|
||||
ASSERT_EQ(classType.GetId(), static_cast<uint32_t>(ElementsKind::NUMBER));
|
||||
ASSERT_TRUE(classType.IsBuiltinsArray());
|
||||
ASSERT_EQ(classType.GetElementsKind(), ElementsKind::NUMBER);
|
||||
|
||||
classType = pgoRWOpType.GetObjectInfo(1).GetProfileType();
|
||||
ASSERT_TRUE(classType.IsElementType());
|
||||
ASSERT_EQ(classType.GetId(), static_cast<uint32_t>(ElementsKind::HOLE_INT));
|
||||
ASSERT_TRUE(classType.IsBuiltinsArray());
|
||||
ASSERT_EQ(classType.GetElementsKind(), ElementsKind::HOLE_INT);
|
||||
|
||||
classType = pgoRWOpType.GetObjectInfo(2).GetProfileType();
|
||||
ASSERT_TRUE(classType.IsElementType());
|
||||
ASSERT_EQ(classType.GetId(), static_cast<uint32_t>(ElementsKind::TAGGED));
|
||||
ASSERT_TRUE(classType.IsBuiltinsArray());
|
||||
ASSERT_EQ(classType.GetElementsKind(), ElementsKind::TAGGED);
|
||||
} else if (std::string(methodName) == "foo1") {
|
||||
ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
|
||||
auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
|
||||
ASSERT_TRUE(classType.IsElementType());
|
||||
ASSERT_EQ(classType.GetId(), static_cast<uint32_t>(ElementsKind::TAGGED));
|
||||
ASSERT_TRUE(classType.IsBuiltinsArray());
|
||||
ASSERT_EQ(classType.GetElementsKind(), ElementsKind::TAGGED);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1107,39 +1107,6 @@ HWTEST_F_L0(PGOProfilerTest, MergeApSelfTwice)
|
||||
}
|
||||
#endif
|
||||
|
||||
HWTEST_F_L0(PGOProfilerTest, ClassTypeLegacyCheckForWideClassType)
|
||||
{
|
||||
PGOContextMock context(PGOProfilerHeader::RECORD_POOL_MINI_VERSION);
|
||||
ProfileTypeLegacy classTypeLegacy(0xafe, ProfileType::Kind::ElementId);
|
||||
auto &profileTypeRef = *(static_cast<ProfileTypeRef *>(static_cast<void *>(&classTypeLegacy)));
|
||||
ProfileType classType(context, profileTypeRef);
|
||||
ASSERT_EQ(classTypeLegacy.GetId(), 0xafe);
|
||||
ASSERT_EQ(classTypeLegacy.GetKind(), ProfileType::Kind::ElementId);
|
||||
ASSERT_EQ(classType.GetId(), 0xafe);
|
||||
ASSERT_EQ(classType.GetKind(), ProfileType::Kind::ElementId);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(PGOProfilerTest, PGOSampleTypeLegacyCheckForWideClassType)
|
||||
{
|
||||
PGOContextMock context(PGOProfilerHeader::RECORD_POOL_MINI_VERSION);
|
||||
PGOSampleTypeRef sampleTypeLegacyType(PGOSampleTypeRef::Type::NUMBER);
|
||||
PGOSampleType sampleType = PGOSampleType::ConvertFrom(context, sampleTypeLegacyType);
|
||||
ASSERT_TRUE(sampleTypeLegacyType.IsNumber());
|
||||
ASSERT_TRUE(sampleType.IsNumber());
|
||||
ASSERT_FALSE(sampleType.IsProfileType());
|
||||
|
||||
ProfileTypeLegacy classTypeLegacy(0xafe, ProfileType::Kind::ElementId);
|
||||
auto &profileTypeRef = *(static_cast<ProfileTypeRef *>(static_cast<void *>(&classTypeLegacy)));
|
||||
PGOSampleTypeRef sampleTypeLegacyClass(profileTypeRef);
|
||||
ASSERT_TRUE(sampleTypeLegacyClass.IsProfileType());
|
||||
|
||||
sampleType = PGOSampleType::ConvertFrom(context, sampleTypeLegacyClass);
|
||||
ASSERT_FALSE(sampleType.IsNumber());
|
||||
ASSERT_TRUE(sampleType.IsProfileType());
|
||||
ASSERT_EQ(sampleType.GetProfileType().GetId(), classTypeLegacy.GetId());
|
||||
ASSERT_EQ(sampleType.GetProfileType().GetKind(), classTypeLegacy.GetKind());
|
||||
}
|
||||
|
||||
HWTEST_F_L0(PGOProfilerTest, RuntimeMerge)
|
||||
{
|
||||
mkdir("ark-profiler19/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
|
@ -20,6 +20,9 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "ecmascript/builtin_entries.h"
|
||||
#include "ecmascript/elements.h"
|
||||
#include "ecmascript/js_hclass.h"
|
||||
#include "ecmascript/log.h"
|
||||
#include "ecmascript/log_wrapper.h"
|
||||
#include "ecmascript/pgo_profiler/pgo_context.h"
|
||||
@ -38,7 +41,6 @@ public:
|
||||
enum class Kind : uint8_t {
|
||||
ClassId,
|
||||
LiteralId,
|
||||
ElementId,
|
||||
BuiltinsId,
|
||||
LegacyKind = BuiltinsId,
|
||||
MethodId, // method offset of js function
|
||||
@ -63,6 +65,55 @@ public:
|
||||
using KindBits = AbcIdBits::NextField<Kind, KIND_BITFIELD_NUM>;
|
||||
using IsRootBits = KindBits::NextFlag;
|
||||
|
||||
class BuiltinsId {
|
||||
public:
|
||||
static constexpr uint32_t BUILTINS_ID_NUM = 16;
|
||||
using BuiltinsIdBits = BitField<JSType, 0, BUILTINS_ID_NUM>;
|
||||
|
||||
explicit BuiltinsId() = default;
|
||||
explicit BuiltinsId(uint32_t id) : id_(id) {}
|
||||
|
||||
uint32_t GetId() const
|
||||
{
|
||||
return id_;
|
||||
}
|
||||
|
||||
BuiltinsId SetBuiltinsId(JSType type)
|
||||
{
|
||||
id_ = BuiltinsIdBits::Update(id_, type);
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSType GetBuiltinsId() const
|
||||
{
|
||||
return BuiltinsIdBits::Decode(id_);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t id_ { 0 };
|
||||
};
|
||||
|
||||
class BuiltinsArrayId : public BuiltinsId {
|
||||
public:
|
||||
// BuilitinsArray second bit field
|
||||
static constexpr uint32_t ELEMENTS_KIND_BITFIELD_NUM = 5;
|
||||
using ElementsKindBits = BuiltinsIdBits::NextField<ElementsKind, ELEMENTS_KIND_BITFIELD_NUM>;
|
||||
|
||||
explicit BuiltinsArrayId() = default;
|
||||
explicit BuiltinsArrayId(uint32_t id) : BuiltinsId(id) {}
|
||||
|
||||
BuiltinsArrayId UpdateElementsKind(ElementsKind kind)
|
||||
{
|
||||
id_ = ElementsKindBits::Update(id_, kind);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ElementsKind GetElementsKind() const
|
||||
{
|
||||
return ElementsKindBits::Decode(id_);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(KindBits::IsValid(Kind::TotalKinds));
|
||||
|
||||
ProfileType() = default;
|
||||
@ -87,6 +138,18 @@ public:
|
||||
return type;
|
||||
}
|
||||
|
||||
static ProfileType CreateBuiltinsArray(ApEntityId abcId, JSType type, ElementsKind kind)
|
||||
{
|
||||
auto id = BuiltinsArrayId().UpdateElementsKind(kind).SetBuiltinsId(type).GetId();
|
||||
return ProfileType(abcId, id, Kind::BuiltinsId);
|
||||
}
|
||||
|
||||
static ProfileType CreateBuiltins(ApEntityId abcId, JSType type)
|
||||
{
|
||||
auto id = BuiltinsId().SetBuiltinsId(type).GetId();
|
||||
return ProfileType(abcId, id, Kind::BuiltinsId);
|
||||
}
|
||||
|
||||
ProfileType &Remap(const PGOContext &context);
|
||||
|
||||
bool IsNone() const
|
||||
@ -114,11 +177,6 @@ public:
|
||||
return GetKind() == Kind::ClassId;
|
||||
}
|
||||
|
||||
bool IsElementType() const
|
||||
{
|
||||
return GetKind() == Kind::ElementId;
|
||||
}
|
||||
|
||||
bool IsMethodId() const
|
||||
{
|
||||
return GetKind() == Kind::MethodId;
|
||||
@ -209,6 +267,47 @@ public:
|
||||
type_ = IsRootBits::Update(type_, root);
|
||||
}
|
||||
|
||||
JSType GetBuiltinsId() const
|
||||
{
|
||||
ASSERT(IsBuiltinsType());
|
||||
auto builtinsId = BuiltinsId(GetId());
|
||||
return builtinsId.GetBuiltinsId();
|
||||
}
|
||||
|
||||
ElementsKind GetElementsKind() const
|
||||
{
|
||||
ASSERT(IsBuiltinsArray());
|
||||
auto builtinsArrayId = BuiltinsArrayId(GetId());
|
||||
return builtinsArrayId.GetElementsKind();
|
||||
}
|
||||
|
||||
bool IsBuiltinsString() const
|
||||
{
|
||||
if (IsBuiltinsType()) {
|
||||
JSType type = GetBuiltinsId();
|
||||
return type >= JSType::STRING_FIRST && type <= JSType::STRING_LAST;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsBuiltinsArray() const
|
||||
{
|
||||
if (IsBuiltinsType()) {
|
||||
JSType type = GetBuiltinsId();
|
||||
return type == JSType::JS_ARRAY;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsBuiltinsTypeArray() const
|
||||
{
|
||||
if (IsBuiltinsType()) {
|
||||
JSType type = GetBuiltinsId();
|
||||
return type > JSType::JS_TYPED_ARRAY_FIRST && type <= JSType::JS_TYPED_ARRAY_LAST;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateId(uint64_t type)
|
||||
{
|
||||
@ -242,7 +341,7 @@ public:
|
||||
return typeId_ == 0;
|
||||
}
|
||||
|
||||
bool IsElementType() const
|
||||
bool IsBuiltinsArray() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -463,7 +463,7 @@ public:
|
||||
|
||||
bool InElement() const
|
||||
{
|
||||
return receiverType_.IsElementType();
|
||||
return receiverType_.IsBuiltinsArray();
|
||||
}
|
||||
|
||||
bool operator<(const PGOObjectTemplate &right) const
|
||||
|
@ -858,7 +858,7 @@ BuiltinTypeId TSManager::GetBuiltinTypeIdByJSType(JSType jsType)
|
||||
const kungfu::GateType TSManager::GetBuiltinsGateTypeByPt(ProfileType pgoType)
|
||||
{
|
||||
ASSERT(pgoType.IsBuiltinsType());
|
||||
JSType jsType = static_cast<JSType>(pgoType.GetId());
|
||||
JSType jsType = pgoType.GetBuiltinsId();
|
||||
|
||||
auto it = pgoBuiltinGTCache_.find(jsType);
|
||||
if (it != pgoBuiltinGTCache_.end()) {
|
||||
|
@ -193,6 +193,7 @@ group("ark_aot_ts_test") {
|
||||
"pgo_forof_typed_array",
|
||||
"pgo_function_operation",
|
||||
"pgo_function_prototype",
|
||||
"pgo_length",
|
||||
"pgo_objectliteral_operation",
|
||||
"pgo_call_deopt",
|
||||
"poplexenv",
|
||||
|
21
test/aottest/pgo_length/BUILD.gn
Normal file
21
test/aottest/pgo_length/BUILD.gn
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_aot_js_test_action("pgo_length") {
|
||||
deps = []
|
||||
is_enable_pgo = true
|
||||
is_enable_opt_inlining = true
|
||||
is_enable_trace_deopt = true
|
||||
}
|
17
test/aottest/pgo_length/expect_output.txt
Normal file
17
test/aottest/pgo_length/expect_output.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# 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.
|
||||
|
||||
11
|
||||
e
|
||||
3
|
||||
23
|
17
test/aottest/pgo_length/pgo_expect_output.txt
Normal file
17
test/aottest/pgo_length/pgo_expect_output.txt
Normal file
@ -0,0 +1,17 @@
|
||||
# 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.
|
||||
|
||||
11
|
||||
e
|
||||
3
|
||||
23
|
25
test/aottest/pgo_length/pgo_length.js
Normal file
25
test/aottest/pgo_length/pgo_length.js
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.
|
||||
*/
|
||||
|
||||
let string = "hello world"
|
||||
let array = [1, 23, 3]
|
||||
|
||||
function foo(p) {
|
||||
print(p.length)
|
||||
print(p[1])
|
||||
}
|
||||
|
||||
foo(string)
|
||||
foo(array)
|
@ -552,6 +552,7 @@ template("host_aot_js_test_action") {
|
||||
_test_aot_arg_ = "$target_out_dir/${_target_name_}"
|
||||
_test_aot_log_level = "info"
|
||||
_test_expect_path_ = "./expect_output.txt"
|
||||
_test_pgo_expect_path_ = "./pgo_expect_output.txt"
|
||||
|
||||
if (defined(invoker.is_common_js) && invoker.is_common_js) {
|
||||
extra_args = [ "--commonjs" ]
|
||||
@ -579,6 +580,60 @@ template("host_aot_js_test_action") {
|
||||
|
||||
_script_args_ = rebase_path(_test_abc_path_)
|
||||
|
||||
action("${_target_name_}PgoExecute") {
|
||||
testonly = true
|
||||
_host_jsvm_target_ =
|
||||
"$js_root/ecmascript/js_vm:ark_js_vm(${host_toolchain})"
|
||||
_root_out_dir_ = get_label_info(_host_jsvm_target_, "root_out_dir")
|
||||
|
||||
deps = [
|
||||
":gen_${_target_name_}_abc",
|
||||
_host_jsvm_target_,
|
||||
]
|
||||
deps += _deps_
|
||||
|
||||
script = "$js_root/script/run_ark_executable.py"
|
||||
|
||||
_aot_run_options_ =
|
||||
" --asm-interpreter=true" + " --entry-point=${_target_name_}" +
|
||||
" --enable-pgo-profiler=true" + " --compiler-pgo-profiler-path=" +
|
||||
rebase_path(_test_aot_arg_) + "/modules.ap"
|
||||
|
||||
if (defined(invoker.is_enable_enableArkTools) &&
|
||||
invoker.is_enable_enableArkTools) {
|
||||
_aot_run_options_ += " --enable-ark-tools=true"
|
||||
_aot_run_options_ += " --enable-force-gc=false"
|
||||
}
|
||||
|
||||
if (defined(invoker.log_option)) {
|
||||
_aot_run_options_ += invoker.log_option
|
||||
}
|
||||
|
||||
args = [
|
||||
"--script-file",
|
||||
rebase_path(_root_out_dir_) + "/arkcompiler/ets_runtime/ark_js_vm",
|
||||
"--script-options",
|
||||
_aot_run_options_,
|
||||
"--script-args",
|
||||
_script_args_,
|
||||
"--expect-file",
|
||||
rebase_path(_test_pgo_expect_path_),
|
||||
"--env-path",
|
||||
rebase_path(_root_out_dir_) + "/arkcompiler/ets_runtime:" +
|
||||
rebase_path(_root_out_dir_) + "/${_icu_path_}:" +
|
||||
rebase_path(_root_out_dir_) + "/thirdparty/zlib:" +
|
||||
rebase_path(_root_out_dir_) + "/resourceschedule/frame_aware_sched:" +
|
||||
rebase_path(_root_out_dir_) + "/hiviewdfx/hilog:" +
|
||||
rebase_path(_root_out_dir_) +
|
||||
"/thirdparty/bounds_checking_function:" +
|
||||
rebase_path("//prebuilts/clang/ohos/linux-x86_64/llvm/lib/"),
|
||||
]
|
||||
|
||||
inputs = [ _test_abc_path_ ]
|
||||
|
||||
outputs = [ "$target_out_dir/${_target_name_}/pgo" ]
|
||||
}
|
||||
|
||||
action("${_target_name_}AotCompileAction") {
|
||||
testonly = true
|
||||
|
||||
@ -590,11 +645,20 @@ template("host_aot_js_test_action") {
|
||||
]
|
||||
deps += _deps_
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
deps += [ ":${_target_name_}PgoExecute" ]
|
||||
}
|
||||
|
||||
script = "//arkcompiler/ets_runtime/script/run_ark_executable.py"
|
||||
|
||||
_aot_compile_options_ = " --aot-file=" + rebase_path(_test_aot_arg_) +
|
||||
" --log-level=" + _test_aot_log_level + " --log-components=compiler --compiler-opt-type-lowering=false --compiler-opt-inlining=false" + " --compiler-opt-loop-peeling=false"
|
||||
|
||||
if (defined(invoker.is_enable_pgo) && invoker.is_enable_pgo) {
|
||||
_aot_compile_options_ += " --compiler-pgo-profiler-path=" +
|
||||
rebase_path(_test_aot_arg_) + "/modules.ap"
|
||||
}
|
||||
|
||||
if (defined(invoker.is_enable_trace_deopt) &&
|
||||
invoker.is_enable_trace_deopt) {
|
||||
_aot_compile_options_ += " --compiler-trace-deopt=true"
|
||||
|
Loading…
Reference in New Issue
Block a user