PGO collect builtin typedArrayOnHeap HClass

Signed-off-by: chenhantao <chenhantao3@huawei.com>
Change-Id: Icb1a5d715d6f574189faf58348af8fcd1a4e74f9
This commit is contained in:
chenhantao 2024-04-01 16:23:04 +08:00
parent 0962df8dfe
commit 43d09b5710
10 changed files with 109 additions and 7 deletions

View File

@ -2217,6 +2217,8 @@ void Builtins::Initialize##Type(const JSHandle<GlobalEnv> &env, const JSHandle<J
arrayFunction->SetProtoOrHClass(thread_, arrFuncInstanceHClass.GetTaggedValue()); \
SetConstant(arrFuncPrototype, "BYTES_PER_ELEMENT", JSTaggedValue(bytesPerElement)); \
SetConstant(JSHandle<JSObject>(arrayFunction), "BYTES_PER_ELEMENT", JSTaggedValue(bytesPerElement)); \
/* %TypedArray%.protoofprototype (where %TypedArray% is one of Int8Array, Uint8Array, etc.) */ \
JSTaggedValue protoOfPrototypeValue = arrFuncPrototype->GetJSHClass()->GetPrototype(); \
env->Set##Type##Function(thread_, arrayFunction); \
env->Set##Type##FunctionPrototype(thread_, arrFuncPrototypeValue); \
env->Set##Type##RootHclass(thread_, arrFuncInstanceHClass); \
@ -2225,7 +2227,9 @@ void Builtins::Initialize##Type(const JSHandle<GlobalEnv> &env, const JSHandle<J
thread_->SetInitialBuiltinHClass(BuiltinTypeId::TYPE, \
arrayFunction->GetJSHClass(), \
*arrFuncInstanceHClass, \
arrFuncPrototype->GetJSHClass()); \
arrFuncPrototype->GetJSHClass(), \
protoOfPrototypeValue.IsHeapObject() ? protoOfPrototypeValue.GetTaggedObject()->GetClass() : nullptr, \
*arrFuncInstanceHClassOnHeap); \
}
BUILTIN_TYPED_ARRAY_TYPES(BUILTIN_TYPED_ARRAY_DEFINE_INITIALIZE)

View File

@ -500,7 +500,7 @@ void JSThread::ResetGuardians()
void JSThread::SetInitialBuiltinHClass(
BuiltinTypeId type, JSHClass *builtinHClass, JSHClass *instanceHClass,
JSHClass *prototypeHClass, JSHClass *prototypeOfPrototypeHClass)
JSHClass *prototypeHClass, JSHClass *prototypeOfPrototypeHClass, JSHClass *extraHClass)
{
size_t index = BuiltinHClassEntries::GetEntryIndex(type);
auto &entry = glueData_.builtinHClassEntries_.entries[index];
@ -509,11 +509,13 @@ void JSThread::SetInitialBuiltinHClass(
<< ", builtinHClass = " << builtinHClass
<< ", instanceHClass = " << instanceHClass
<< ", prototypeHClass = " << prototypeHClass
<< ", prototypeOfPrototypeHClass = " << prototypeOfPrototypeHClass;
<< ", prototypeOfPrototypeHClass = " << prototypeOfPrototypeHClass
<< ", extraHClass = " << extraHClass;
entry.builtinHClass = builtinHClass;
entry.instanceHClass = instanceHClass;
entry.prototypeHClass = prototypeHClass;
entry.prototypeOfPrototypeHClass = prototypeOfPrototypeHClass;
entry.extraHClass = extraHClass;
}
JSHClass *JSThread::GetBuiltinHClass(BuiltinTypeId type) const
@ -528,6 +530,12 @@ JSHClass *JSThread::GetBuiltinInstanceHClass(BuiltinTypeId type) const
return glueData_.builtinHClassEntries_.entries[index].instanceHClass;
}
JSHClass *JSThread::GetBuiltinExtraHClass(BuiltinTypeId type) const
{
size_t index = BuiltinHClassEntries::GetEntryIndex(type);
return glueData_.builtinHClassEntries_.entries[index].extraHClass;
}
JSHClass *JSThread::GetArrayInstanceHClass(ElementsKind kind) const
{
auto iter = GetArrayHClassIndexMap().find(kind);

View File

@ -280,11 +280,13 @@ public:
void SetInitialBuiltinHClass(
BuiltinTypeId type, JSHClass *builtinHClass, JSHClass *instanceHClass,
JSHClass *prototypeHClass, JSHClass *prototypeOfPrototypeHClass = nullptr);
JSHClass *prototypeHClass, JSHClass *prototypeOfPrototypeHClass = nullptr,
JSHClass *extraHClass = nullptr);
JSHClass *GetBuiltinHClass(BuiltinTypeId type) const;
JSHClass *GetBuiltinInstanceHClass(BuiltinTypeId type) const;
JSHClass *GetBuiltinExtraHClass(BuiltinTypeId type) const;
JSHClass *GetArrayInstanceHClass(ElementsKind kind) const;
PUBLIC_API JSHClass *GetBuiltinPrototypeHClass(BuiltinTypeId type) const;

View File

@ -47,6 +47,8 @@ struct BuiltinHClassEntries {
JSHClass *prototypeHClass = nullptr;
// prototypeOfPrototypeHClass = HClass of X.prototype.prototype
JSHClass *prototypeOfPrototypeHClass = nullptr;
//extraHClass . In typedArray means instanceHClassOnHeap
JSHClass *extraHClass = nullptr;
};
Entry entries[N_ENTRIES];
@ -75,6 +77,12 @@ struct BuiltinHClassEntries {
return sizeof(Entry) * index + MEMBER_OFFSET(Entry, instanceHClass);
}
static size_t GetExtraHClassOffset(BuiltinTypeId type)
{
size_t index = GetEntryIndex(type);
return sizeof(Entry) * index + MEMBER_OFFSET(Entry, extraHClass);
}
static size_t GetPrototypeHClassOffset(BuiltinTypeId type)
{
size_t index = GetEntryIndex(type);

View File

@ -1450,21 +1450,39 @@ void PGOProfiler::AddBuiltinsInfoByNameInProt(ApEntityId abcId, const CString &r
}
auto exceptHoldHClass = thread->GetBuiltinPrototypeHClass(builtinsId.value());
auto exceptPrototypeOfPrototypeHClass =
thread->GetBuiltinPrototypeOfPrototypeHClass(builtinsId.value());
// iterator needs to find two layers of prototype
if (builtinsId == BuiltinTypeId::ARRAY_ITERATOR) {
auto exceptPrototypeOfPrototypeHClass =
thread->GetBuiltinPrototypeOfPrototypeHClass(builtinsId.value());
if ((exceptRecvHClass != receiver) ||
(exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold)) {
return;
}
} else if (IsTypedArrayType(builtinsId.value())) {
auto exceptRecvHClassOnHeap = thread->GetBuiltinExtraHClass(builtinsId.value());
ASSERT_PRINT(exceptRecvHClassOnHeap == nullptr || exceptRecvHClassOnHeap->IsOnHeapFromBitField(),
"must be on heap");
if (IsJSHClassNotEqual(receiver, hold, exceptRecvHClass, exceptRecvHClassOnHeap,
exceptHoldHClass, exceptPrototypeOfPrototypeHClass)) {
return;
}
} else if (exceptRecvHClass != receiver || exceptHoldHClass != hold) {
return ;
return;
}
AddBuiltinsInfo(abcId, recordName, methodId, bcOffset, receiver, receiver);
}
bool PGOProfiler::IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass,
JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass,
JSHClass *exceptPrototypeOfPrototypeHClass)
{
//exceptRecvHClass = IHC, exceptRecvHClassOnHeap = IHC OnHeap
//exceptHoldHClass = PHC, exceptPrototypeOfPrototypeHClass = HClass of X.prototype.prototype
return ((exceptRecvHClass != receiver && exceptRecvHClassOnHeap != receiver) ||
(exceptHoldHClass != hold && exceptPrototypeOfPrototypeHClass != hold));
}
void PGOProfiler::AddBuiltinsGlobalInfo(ApEntityId abcId, const CString &recordName, EntityId methodId,
int32_t bcOffset, ConstantIndex globalId)
{

View File

@ -173,6 +173,9 @@ private:
void UpdateExtraProfileTypeInfo(ApEntityId abcId, const CString& recordName, EntityId methodId, WorkNode* current);
WorkNode* PopFromProfileQueue();
void SaveProfiler(bool force);
bool IsJSHClassNotEqual(JSHClass *receiver, JSHClass *hold, JSHClass *exceptRecvHClass,
JSHClass *exceptRecvHClassOnHeap, JSHClass *exceptHoldHClass,
JSHClass *exceptPrototypeOfPrototypeHClass);
class PGOProfilerTask : public Task {
public:

View File

@ -30,6 +30,7 @@ test_js_files = [
"array_size_test",
"truck",
"vehicle",
"typedarray_length",
]
foreach(file, test_js_files) {

View File

@ -1218,4 +1218,34 @@ HWTEST_F_L0(PGOProfilerTest, ApVersionMatchCheck)
unlink("ark-ApVersionMatchCheck/modules.ap");
unlink("ark-ApVersionMatchCheck/");
}
HWTEST_F_L0(PGOProfilerTest, TypedArrayOnHeap)
{
mkdir("ark-profiler24/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
const char *targetRecordName = "typedarray_length";
ExecuteAndLoadJSPandaFile("ark-profiler24/", targetRecordName);
ASSERT_NE(pf_, nullptr);
uint32_t checksum = pf_->GetChecksum();
// Loader
PGOProfilerDecoder decoder("ark-profiler24/modules.ap", 1);
ASSERT_TRUE(decoder.LoadAndVerify(checksum));
auto methodLiterals = pf_->GetMethodLiteralMap();
for (auto iter : methodLiterals) {
auto methodLiteral = iter.second;
auto methodId = methodLiteral->GetMethodId();
auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
auto callback = [methodName](uint32_t offset, const PGOType *type) {
ASSERT_NE(offset, 0);
if (type->IsRwOpType() && std::string(methodName) == "test") {
auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
}
};
decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral,
callback);
}
unlink("ark-profiler24/modules.ap");
rmdir("ark-profiler24/");
}
} // namespace panda::test

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
class Items {
public static test(itemMap){
itemMap.forEach((value) => { // OneItem
value.length; // OneItem.value.length
});
}
}
let itemMap = new Map();
for (let i = 1; i < 10; i++) {
itemMap.set(i, new Int8Array(i * 6));
}
Items.test(itemMap)

View File

@ -730,6 +730,7 @@
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/array_size_test.abc -> /data/test" src="out"/>
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/truck.abc -> /data/test" src="out"/>
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/vehicle.abc -> /data/test" src="out"/>
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/typedarray_length.abc -> /data/test" src="out"/>
</preparer>
</target>
<target name="HeapTrackerFirstTest">