!7368 [新需求]: 新增Cell类型,并适配缓存ProfileTypeInfo以提升性能

Merge pull request !7368 from 李晨帅/Cell
This commit is contained in:
openharmony_ci 2024-05-17 10:00:26 +00:00 committed by Gitee
commit d6de48e714
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
35 changed files with 467 additions and 94 deletions

View File

@ -107,8 +107,10 @@ void MacroAssemblerAArch64::MovParameterIntoParamReg(MacroParameter param, aarch
assembler.Ldur(LOCAL_SCOPE_REGISTER,
aarch64::MemoryOperand(aarch64::Register(aarch64::X29),
static_cast<int64_t>(FUNCTION_OFFSET_FROM_SP)));
assembler.Ldr(LOCAL_SCOPE_REGISTER,
aarch64::MemoryOperand(LOCAL_SCOPE_REGISTER, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
assembler.Ldr(paramReg,
aarch64::MemoryOperand(LOCAL_SCOPE_REGISTER, JSFunction::PROFILE_TYPE_INFO_OFFSET));
aarch64::MemoryOperand(LOCAL_SCOPE_REGISTER, ProfileTypeInfoCell::VALUE_OFFSET));
break;
}
case BaselineSpecialParameter::SP: {

View File

@ -129,7 +129,9 @@ void MacroAssemblerX64::MovParameterIntoParamReg(MacroParameter param, x64::Regi
case BaselineSpecialParameter::PROFILE_TYPE_INFO: {
assembler.Movq(x64::Operand(x64::rbp, FUNCTION_OFFSET_FROM_SP), LOCAL_SCOPE_REGISTER);
assembler.Movq(
x64::Operand(LOCAL_SCOPE_REGISTER, JSFunction::PROFILE_TYPE_INFO_OFFSET), paramReg);
x64::Operand(LOCAL_SCOPE_REGISTER, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET),
LOCAL_SCOPE_REGISTER);
assembler.Movq(x64::Operand(LOCAL_SCOPE_REGISTER, ProfileTypeInfoCell::VALUE_OFFSET), paramReg);
break;
}
case BaselineSpecialParameter::SP: {

View File

@ -57,7 +57,8 @@ GateRef BaselineStubBuilder::GetLastLeaveFrame(GateRef glue)
GateRef BaselineStubBuilder::GetProfileTypeInfoFromFunction(GateRef function)
{
return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::PROFILE_TYPE_INFO_OFFSET));
GateRef raw = Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
return Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
}
GateRef BaselineStubBuilder::GetModuleFromFunction(GateRef function)

View File

@ -3497,8 +3497,10 @@ void BaselineReturnStubBuilder::GenerateCircuit()
Load(VariableType::JS_ANY(), curFunction, IntPtr(JSFunctionBase::METHOD_OFFSET));
GateRef constpool =
Load(VariableType::JS_POINTER(), curMethod, IntPtr(Method::CONSTANT_POOL_OFFSET));
GateRef raw =
Load(VariableType::JS_POINTER(), curFunction, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
GateRef profileTypeInfo =
Load(VariableType::JS_POINTER(), curFunction, IntPtr(JSFunction::PROFILE_TYPE_INFO_OFFSET));
Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
GateRef hotnessCounter =
Load(VariableType::INT32(), curMethod, IntPtr(Method::LITERAL_INFO_OFFSET));
DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc);
@ -5672,8 +5674,10 @@ void BaselineReturnundefinedStubBuilder::GenerateCircuit()
Load(VariableType::JS_ANY(), curFunction, IntPtr(JSFunctionBase::METHOD_OFFSET));
GateRef constpool =
Load(VariableType::JS_POINTER(), curMethod, IntPtr(Method::CONSTANT_POOL_OFFSET));
GateRef raw =
Load(VariableType::JS_POINTER(), curFunction, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
GateRef profileTypeInfo =
Load(VariableType::JS_POINTER(), curFunction, IntPtr(JSFunction::PROFILE_TYPE_INFO_OFFSET));
Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
GateRef hotnessCounter =
Load(VariableType::INT16(), curMethod, IntPtr(Method::LITERAL_INFO_OFFSET));
DEFVARIABLE(varPc, VariableType::NATIVE_POINTER(), pc);

View File

@ -17,6 +17,7 @@
#define ECMASCRIPT_COMPILER_INTERPRETER_STUB_INL_H
#include "ecmascript/compiler/interpreter_stub.h"
#include "ecmascript/compiler/new_object_stub_builder.h"
#include "ecmascript/compiler/share_gate_meta_data.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/global_env.h"
@ -274,7 +275,8 @@ GateRef InterpreterStubBuilder::GetEnvFromFunction(GateRef function)
GateRef InterpreterStubBuilder::GetProfileTypeInfoFromFunction(GateRef function)
{
return Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::PROFILE_TYPE_INFO_OFFSET));
GateRef raw = Load(VariableType::JS_POINTER(), function, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
return Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
}
GateRef InterpreterStubBuilder::GetModuleFromFunction(GateRef function)
@ -538,6 +540,40 @@ GateRef InterpreterStubBuilder::GetCurrentFrame(GateRef glue)
return GetLastLeaveFrame(glue);
}
void InterpreterStubBuilder::UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
GateRef profileTypeInfo, GateRef slotId)
{
auto env = GetEnvironment();
Label subEntry(env);
env->SubCfgEntry(&subEntry);
Label profileTypeInfoNotUndefined(env);
Label slotValueUpdate(env);
Label slotValueNotUndefined(env);
Label profileTypeInfoEnd(env);
NewObjectStubBuilder newBuilder(this);
BRANCH(TaggedIsUndefined(profileTypeInfo), &profileTypeInfoEnd, &profileTypeInfoNotUndefined);
Bind(&profileTypeInfoNotUndefined);
{
GateRef slotValue = GetValueFromTaggedArray(profileTypeInfo, slotId);
BRANCH(TaggedIsUndefined(slotValue), &slotValueUpdate, &slotValueNotUndefined);
Bind(&slotValueUpdate);
{
GateRef newProfileTypeInfoCell = newBuilder.NewProfileTypeInfoCell(glue, Undefined());
SetValueToTaggedArray(VariableType::JS_ANY(), glue, profileTypeInfo, slotId, newProfileTypeInfoCell);
SetRawProfileTypeInfoToFunction(glue, function, newProfileTypeInfoCell);
Jump(&profileTypeInfoEnd);
}
Bind(&slotValueNotUndefined);
UpdateProfileTypeInfoCellType(glue, slotValue);
SetRawProfileTypeInfoToFunction(glue, function, slotValue);
Jump(&profileTypeInfoEnd);
}
Bind(&profileTypeInfoEnd);
env->SubCfgExit();
}
GateRef InterpreterStubBuilder::ReadInst32_0(GateRef pc)
{
GateRef currentInst = ZExtInt8ToInt32(ReadInst8_3(pc));

View File

@ -4583,6 +4583,10 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm8Id16Imm8)
GateRef currentFunc = GetFunctionFromFrame(frame);
SetModuleToFunction(glue, result, GetModuleFromFunction(currentFunc));
SetHomeObjectToFunction(glue, result, GetHomeObjectFromFunction(currentFunc));
#if ECMASCRIPT_ENABLE_IC
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
UpdateProfileTypeInfoCellToFunction(glue, result, profileTypeInfo, slotId);
#endif
callback.ProfileDefineClass(result);
varAcc = result;
DISPATCH_WITH_ACC(DEFINEFUNC_IMM8_ID16_IMM8);
@ -4608,6 +4612,10 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm16Id16Imm8)
GateRef currentFunc = GetFunctionFromFrame(frame);
SetHomeObjectToFunction(glue, result, GetHomeObjectFromFunction(currentFunc));
SetModuleToFunction(glue, result, GetModuleFromFunction(currentFunc));
#if ECMASCRIPT_ENABLE_IC
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
UpdateProfileTypeInfoCellToFunction(glue, result, profileTypeInfo, slotId);
#endif
varAcc = result;
callback.ProfileDefineClass(result);
DISPATCH_WITH_ACC(DEFINEFUNC_IMM16_ID16_IMM8);
@ -5167,6 +5175,10 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm8Id16Imm8ColdReload)
SetModuleToFunction(glue, result, GetModuleFromFunction(currentFunc));
CallRuntime(glue, RTSTUB_ID(SetPatchModule), { result });
SetHomeObjectToFunction(glue, result, GetHomeObjectFromFunction(currentFunc));
#if ECMASCRIPT_ENABLE_IC
GateRef slotId = ZExtInt8ToInt32(ReadInst8_0(pc));
UpdateProfileTypeInfoCellToFunction(glue, result, profileTypeInfo, slotId);
#endif
callback.ProfileDefineClass(result);
varAcc = result;
DISPATCH_WITH_ACC(DEFINEFUNC_IMM8_ID16_IMM8);
@ -5193,6 +5205,10 @@ DECLARE_ASM_HANDLER(HandleDefinefuncImm16Id16Imm8ColdReload)
SetHomeObjectToFunction(glue, result, GetHomeObjectFromFunction(currentFunc));
SetModuleToFunction(glue, result, GetModuleFromFunction(currentFunc));
CallRuntime(glue, RTSTUB_ID(SetPatchModule), { result });
#if ECMASCRIPT_ENABLE_IC
GateRef slotId = ZExtInt16ToInt32(ReadInst16_0(pc));
UpdateProfileTypeInfoCellToFunction(glue, result, profileTypeInfo, slotId);
#endif
varAcc = result;
callback.ProfileDefineClass(result);
DISPATCH_WITH_ACC(DEFINEFUNC_IMM16_ID16_IMM8);

View File

@ -175,6 +175,9 @@ public:
inline void SetFrameState(GateRef glue, GateRef sp, GateRef function, GateRef acc,
GateRef env, GateRef pc, GateRef prev, GateRef type);
inline void UpdateProfileTypeInfoCellToFunction(GateRef glue, GateRef function,
GateRef profileTypeInfo, GateRef slotId);
inline void CheckException(GateRef glue, GateRef sp, GateRef pc, GateRef constpool,
GateRef profileTypeInfo, GateRef acc, GateRef hotnessCounter,
GateRef res, GateRef offset);

View File

@ -116,11 +116,11 @@ void NewObjectStubBuilder::NewJSObject(Variable *result, Label *exit, GateRef hc
AllocateInYoung(result, &hasPendingException, &noException, hclass);
Bind(&noException);
{
if (order.Value() == MemoryOrder::NoBarrier().Value()) {
StoreHClassWithoutBarrier(glue_, result->ReadVariable(), hclass);
} else {
StoreHClass(glue_, result->ReadVariable(), hclass);
}
if (order.Value() == MemoryOrder::NoBarrier().Value()) {
StoreHClassWithoutBarrier(glue_, result->ReadVariable(), hclass);
} else {
StoreHClass(glue_, result->ReadVariable(), hclass);
}
DEFVARIABLE(initValue, VariableType::JS_ANY(), Undefined());
Label isTS(env);
Label initialize(env);
@ -668,7 +668,7 @@ GateRef NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef constpool, Gat
Bind(&afterAOTLiteral);
GateRef method = GetMethodFromConstPool(glue, constpool, index);
GateRef hclass = LoadHClassFromMethod(glue, method);
bool knownKind = JSFunction::IsNormalFunctionAndCanSkipWbWhenInitialization(targetKind);
bool knownKind = JSFunction::IsNormalFunctionAndCanSkipWbWhenInitialization(targetKind);
result = NewJSObject(glue, hclass, knownKind ? MemoryOrder::NoBarrier() : MemoryOrder::Default());
SetExtensibleToBitfield(glue, hclass, true);
SetCallableToBitfield(glue, hclass, true);
@ -723,14 +723,14 @@ void NewObjectStubBuilder::NewJSFunction(GateRef glue, GateRef jsFunc, GateRef i
Jump(failed);
}
Bind(&notException);
{
bool knownKind = JSFunction::IsNormalFunctionAndCanSkipWbWhenInitialization(targetKind);
{
bool knownKind = JSFunction::IsNormalFunctionAndCanSkipWbWhenInitialization(targetKind);
SetLengthToFunction(glue_, result->ReadVariable(), length);
SetLexicalEnvToFunction(glue_, result->ReadVariable(), lexEnv,
SetLexicalEnvToFunction(glue_, result->ReadVariable(), lexEnv,
knownKind ? MemoryOrder::NoBarrier() : MemoryOrder::Default());
SetModuleToFunction(glue_, result->ReadVariable(), GetModuleFromFunction(jsFunc),
SetModuleToFunction(glue_, result->ReadVariable(), GetModuleFromFunction(jsFunc),
knownKind ? MemoryOrder::NoBarrier() : MemoryOrder::Default());
SetHomeObjectToFunction(glue_, result->ReadVariable(), GetHomeObjectFromFunction(jsFunc),
SetHomeObjectToFunction(glue_, result->ReadVariable(), GetHomeObjectFromFunction(jsFunc),
knownKind ? MemoryOrder::NoBarrier() : MemoryOrder::Default());
Jump(success);
}
@ -753,50 +753,50 @@ void NewObjectStubBuilder::InitializeJSFunction(GateRef glue, GateRef func, Gate
DEFVARIABLE(thisObj, VariableType::JS_ANY(), Undefined());
GateRef hclass = LoadHClass(func);
if (JSFunction::IsNormalFunctionAndCanSkipWbWhenInitialization(getKind)) {
SetProtoOrHClassToFunction(glue, func, Hole(), MemoryOrder::NoBarrier());
SetWorkNodePointerToFunction(glue, func, NullPtr(), MemoryOrder::NoBarrier());
if (JSFunction::HasPrototype(getKind)) {
auto funcprotoAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_PROTOTYPE_ACCESSOR);
if (getKind == FunctionKind::BASE_CONSTRUCTOR || getKind == FunctionKind::GENERATOR_FUNCTION ||
getKind == FunctionKind::ASYNC_GENERATOR_FUNCTION) {
SetPropertyInlinedProps(glue, func, hclass, funcprotoAccessor,
Int32(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(), MemoryOrder::NoBarrier());
auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_NAME_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
if (getKind != FunctionKind::BASE_CONSTRUCTOR) {
thisObj = CallRuntime(glue, RTSTUB_ID(InitializeGeneratorFunction), {kind});
SetProtoOrHClassToFunction(glue, func, *thisObj);
}
} else if (!JSFunction::IsClassConstructor(getKind)) {
CallRuntime(glue, RTSTUB_ID(FunctionDefineOwnProperty), {func, funcprotoAccessor, kind});
}
Jump(&exit);
} else if (JSFunction::HasAccessor(getKind)) {
auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_NAME_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
Jump(&exit);
}
} else {
if (JSFunction::IsNormalFunctionAndCanSkipWbWhenInitialization(getKind)) {
SetProtoOrHClassToFunction(glue, func, Hole(), MemoryOrder::NoBarrier());
SetWorkNodePointerToFunction(glue, func, NullPtr(), MemoryOrder::NoBarrier());
if (JSFunction::HasPrototype(getKind)) {
auto funcprotoAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_PROTOTYPE_ACCESSOR);
if (getKind == FunctionKind::BASE_CONSTRUCTOR || getKind == FunctionKind::GENERATOR_FUNCTION ||
getKind == FunctionKind::ASYNC_GENERATOR_FUNCTION) {
SetPropertyInlinedProps(glue, func, hclass, funcprotoAccessor,
Int32(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(), MemoryOrder::NoBarrier());
auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_NAME_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
if (getKind != FunctionKind::BASE_CONSTRUCTOR) {
thisObj = CallRuntime(glue, RTSTUB_ID(InitializeGeneratorFunction), {kind});
SetProtoOrHClassToFunction(glue, func, *thisObj);
}
} else if (!JSFunction::IsClassConstructor(getKind)) {
CallRuntime(glue, RTSTUB_ID(FunctionDefineOwnProperty), {func, funcprotoAccessor, kind});
}
Jump(&exit);
} else if (JSFunction::HasAccessor(getKind)) {
auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_NAME_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
Jump(&exit);
}
} else {
SetLexicalEnvToFunction(glue, func, Undefined(), MemoryOrder::NoBarrier());
SetHomeObjectToFunction(glue, func, Undefined(), MemoryOrder::NoBarrier());
SetProtoOrHClassToFunction(glue, func, Hole(), MemoryOrder::NoBarrier());
@ -812,17 +812,17 @@ void NewObjectStubBuilder::InitializeJSFunction(GateRef glue, GateRef func, Gate
Bind(&isBase);
{
SetPropertyInlinedProps(glue, func, hclass, funcprotoAccessor,
Int32(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX),
Int32(JSFunction::PROTOTYPE_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(), MemoryOrder::NoBarrier());
auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_NAME_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX), VariableType::JS_ANY(),
MemoryOrder::NoBarrier());
BRANCH(IsGeneratorKind(kind), &isGenerator, &exit);
Bind(&isGenerator);
@ -849,18 +849,21 @@ void NewObjectStubBuilder::InitializeJSFunction(GateRef glue, GateRef func, Gate
{
auto funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_NAME_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX),
SetPropertyInlinedProps(glue, func, hclass, funcAccessor, Int32(JSFunction::NAME_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(), MemoryOrder::NoBarrier());
funcAccessor = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::FUNCTION_LENGTH_ACCESSOR);
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX),
SetPropertyInlinedProps(glue, func, hclass, funcAccessor,
Int32(JSFunction::LENGTH_INLINE_PROPERTY_INDEX),
VariableType::JS_ANY(), MemoryOrder::NoBarrier());
Jump(&exit);
}
}
}
}
Bind(&exit);
auto emptyProfileTypeInfoCell = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::EMPTY_PROFILE_TYPE_INFO_CELL_INDEX);
SetRawProfileTypeInfoToFunction(glue, func, emptyProfileTypeInfoCell);
env->SubCfgExit();
return;
}
@ -1850,6 +1853,28 @@ void NewObjectStubBuilder::NewByteArray(Variable *result, Label *exit, GateRef e
}
}
GateRef NewObjectStubBuilder::NewProfileTypeInfoCell(GateRef glue, GateRef value)
{
auto env = GetEnvironment();
Label entry(env);
env->SubCfgEntry(&entry);
Label initialize(env);
DEFVARIABLE(result, VariableType::JS_ANY(), Undefined());
auto hclass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX);
GateRef size = GetObjectSizeFromHClass(hclass);
SetParameters(glue, size);
HeapAlloc(&result, &initialize, RegionSpaceFlag::IN_YOUNG_SPACE, hclass);
Bind(&initialize);
StoreHClassWithoutBarrier(glue, *result, hclass);
SetValueToProfileTypeInfoCell(glue, *result, value);
auto ret = *result;
env->SubCfgExit();
return ret;
}
GateRef NewObjectStubBuilder::GetElementSizeFromType(GateRef glue, GateRef type)
{
auto env = GetEnvironment();

View File

@ -103,6 +103,7 @@ public:
GateRef beginIndex, GateRef arrayCls, GateRef buffer);
GateRef NewTypedArray(GateRef glue, GateRef srcTypedArray, GateRef srcType, GateRef length);
void NewByteArray(Variable *result, Label *exit, GateRef elementSize, GateRef length);
GateRef NewProfileTypeInfoCell(GateRef glue, GateRef value);
GateRef GetElementSizeFromType(GateRef glue, GateRef type);
GateRef GetOnHeapHClassFromType(GateRef glue, GateRef type);
private:

View File

@ -2855,6 +2855,53 @@ inline void StubBuilder::SetLengthToFunction(GateRef glue, GateRef function, Gat
Store(VariableType::INT32(), glue, function, offset, value, MemoryOrder::NoBarrier());
}
inline void StubBuilder::SetRawProfileTypeInfoToFunction(GateRef glue, GateRef function, GateRef value)
{
GateRef offset = IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET);
Store(VariableType::JS_ANY(), glue, function, offset, value);
}
inline void StubBuilder::SetValueToProfileTypeInfoCell(GateRef glue, GateRef profileTypeInfoCell, GateRef value)
{
GateRef offset = IntPtr(ProfileTypeInfoCell::VALUE_OFFSET);
Store(VariableType::JS_POINTER(), glue, profileTypeInfoCell, offset, value);
}
inline void StubBuilder::UpdateProfileTypeInfoCellType(GateRef glue, GateRef profileTypeInfoCell)
{
auto env = GetEnvironment();
Label subEntry(env);
env->SubCfgEntry(&subEntry);
// ProfileTypeInfoCell0 -> Cell1 -> CellN
Label isProfileTypeInfoCell0(env);
Label notProfileTypeInfoCell0(env);
Label isProfileTypeInfoCell1(env);
Label endProfileTypeInfoCellType(env);
GateRef objectType = GetObjectType(LoadHClass(profileTypeInfoCell));
BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::PROFILE_TYPE_INFO_CELL_0))),
&isProfileTypeInfoCell0, &notProfileTypeInfoCell0);
Bind(&isProfileTypeInfoCell0);
{
auto profileTypeInfoCell1Class = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::PROFILE_TYPE_INFO_CELL_1_CLASS_INDEX);
StoreHClassWithoutBarrier(glue, profileTypeInfoCell, profileTypeInfoCell1Class);
Jump(&endProfileTypeInfoCellType);
}
Bind(&notProfileTypeInfoCell0);
BRANCH(Int32Equal(objectType, Int32(static_cast<int32_t>(JSType::PROFILE_TYPE_INFO_CELL_1))),
&isProfileTypeInfoCell1, &endProfileTypeInfoCellType);
Bind(&isProfileTypeInfoCell1);
{
auto profileTypeInfoCellNClass = GetGlobalConstantValue(VariableType::JS_POINTER(), glue,
ConstantIndex::PROFILE_TYPE_INFO_CELL_N_CLASS_INDEX);
StoreHClassWithoutBarrier(glue, profileTypeInfoCell, profileTypeInfoCellNClass);
Jump(&endProfileTypeInfoCellType);
}
Bind(&endProfileTypeInfoCellType);
env->SubCfgExit();
}
inline GateRef StubBuilder::GetGlobalObject(GateRef glue)
{
GateRef offset = IntPtr(JSThread::GlueData::GetGlobalObjOffset(env_->Is32Bit()));
@ -3224,7 +3271,8 @@ inline GateRef StubBuilder::IsTypedArray(GateRef obj)
inline GateRef StubBuilder::GetProfileTypeInfo(GateRef jsFunc)
{
return Load(VariableType::JS_POINTER(), jsFunc, IntPtr(JSFunction::PROFILE_TYPE_INFO_OFFSET));
GateRef raw = Load(VariableType::JS_POINTER(), jsFunc, IntPtr(JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
return Load(VariableType::JS_POINTER(), raw, IntPtr(ProfileTypeInfoCell::VALUE_OFFSET));
}
inline void StubBuilder::CheckDetectorName(GateRef glue, GateRef key, Label *fallthrough, Label *slow)

View File

@ -697,6 +697,9 @@ public:
MemoryOrder order = MemoryOrder::Default());
void SetCodeEntryToFunction(GateRef glue, GateRef function, GateRef value);
void SetLengthToFunction(GateRef glue, GateRef function, GateRef value);
void SetRawProfileTypeInfoToFunction(GateRef glue, GateRef function, GateRef value);
void SetValueToProfileTypeInfoCell(GateRef glue, GateRef profileTypeInfoCell, GateRef value);
void UpdateProfileTypeInfoCellType(GateRef glue, GateRef profileTypeInfoCell);
GateRef GetGlobalObject(GateRef glue);
GateRef GetMethodFromFunction(GateRef function);
GateRef GetModuleFromFunction(GateRef function);

View File

@ -181,7 +181,8 @@ void AsmInterpreterCall::JSCallCommonEntry(ExtendedAssembler *assembler,
__ Mov(temp, callTargetRegister);
__ Ldr(Register(X20), MemoryOperand(methodRegister, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET));
// Reload constpool and profileInfo to make sure gc map work normally
__ Ldr(Register(X22), MemoryOperand(temp, JSFunction::PROFILE_TYPE_INFO_OFFSET));
__ Ldr(Register(X22), MemoryOperand(temp, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
__ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET));
__ Ldr(Register(X21), MemoryOperand(methodRegister, Method::CONSTANT_POOL_OFFSET));
__ Mov(temp, kungfu::BytecodeStubCSigns::ID_ThrowStackOverflowException);
@ -1193,7 +1194,8 @@ void AsmInterpreterCall::DispatchCall(ExtendedAssembler *assembler, Register pcR
} else {
ASSERT(accRegister == Register(X23));
}
__ Ldr(Register(X22), MemoryOperand(callTargetRegister, JSFunction::PROFILE_TYPE_INFO_OFFSET));
__ Ldr(Register(X22), MemoryOperand(callTargetRegister, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
__ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET));
__ Ldr(Register(X21), MemoryOperand(methodRegister, Method::CONSTANT_POOL_OFFSET));
__ Mov(Register(X20), pcRegister);
__ Mov(Register(FP), newSpRegister);
@ -1334,7 +1336,8 @@ void AsmInterpreterCall::CallBCStub(ExtendedAssembler *assembler, Register &newS
__ Mov(Register(FP), newSp); // FP - sp
__ Mov(Register(X20), pc); // X20 - pc
__ Ldr(Register(X21), MemoryOperand(method, Method::CONSTANT_POOL_OFFSET)); // X21 - constantpool
__ Ldr(Register(X22), MemoryOperand(callTarget, JSFunction::PROFILE_TYPE_INFO_OFFSET)); // X22 - profileTypeInfo
__ Ldr(Register(X22), MemoryOperand(callTarget, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET));
__ Ldr(Register(X22), MemoryOperand(Register(X22), ProfileTypeInfoCell::VALUE_OFFSET)); // X22 - profileTypeInfo
__ Mov(Register(X23), Immediate(JSTaggedValue::Hole().GetRawData())); // X23 - acc
__ Ldr(Register(X24), MemoryOperand(method, Method::LITERAL_INFO_OFFSET)); // X24 - hotnessCounter

View File

@ -330,7 +330,8 @@ void AsmInterpreterCall::JSCallCommonEntry(ExtendedAssembler *assembler,
__ Movq(callTargetRegister, tempRegister);
__ Movq(Operand(methodRegister, Method::NATIVE_POINTER_OR_BYTECODE_ARRAY_OFFSET), r12); // pc: r12
// Reload constpool and profileInfo to make sure gc map work normally
__ Movq(Operand(tempRegister, JSFunction::PROFILE_TYPE_INFO_OFFSET), r14); // profileTypeInfo: r14
__ Movq(Operand(tempRegister, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET), r14);
__ Movq(Operand(r14, ProfileTypeInfoCell::VALUE_OFFSET), r14); // profileTypeInfo: r14
__ Movq(Operand(methodRegister, Method::CONSTANT_POOL_OFFSET), rbx); // constantPool: rbx
__ Movq(kungfu::BytecodeStubCSigns::ID_ThrowStackOverflowException, tempRegister);
@ -762,7 +763,8 @@ void AsmInterpreterCall::DispatchCall(ExtendedAssembler *assembler, Register pcR
__ PushAlignBytes();
__ Bind(&dispatchCall);
// profileTypeInfo: r14
__ Movq(Operand(callTargetRegister, JSFunction::PROFILE_TYPE_INFO_OFFSET), r14);
__ Movq(Operand(callTargetRegister, JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET), r14);
__ Movq(Operand(r14, ProfileTypeInfoCell::VALUE_OFFSET), r14);
// glue may rdi
if (glueRegister != r13) {
__ Movq(glueRegister, r13);

View File

@ -544,6 +544,10 @@ CString JSHClass::DumpJSType(JSType type)
return "AOTLiteralInfo";
case JSType::CLASS_LITERAL:
return "ClassLiteral";
case JSType::PROFILE_TYPE_INFO_CELL_0:
case JSType::PROFILE_TYPE_INFO_CELL_1:
case JSType::PROFILE_TYPE_INFO_CELL_N:
return "ProfileTypeInfoCell";
case JSType::VTABLE:
return "VTable";
case JSType::SOURCE_TEXT_MODULE_RECORD:
@ -812,6 +816,11 @@ static void DumpObject(TaggedObject *obj, std::ostream &os)
case JSType::PROFILE_TYPE_INFO:
ProfileTypeInfo::Cast(obj)->Dump(os);
break;
case JSType::PROFILE_TYPE_INFO_CELL_0:
case JSType::PROFILE_TYPE_INFO_CELL_1:
case JSType::PROFILE_TYPE_INFO_CELL_N:
ProfileTypeInfoCell::Cast(obj)->Dump(os);
break;
case JSType::VTABLE:
VTable::Cast(obj)->Dump(os);
break;
@ -1743,6 +1752,14 @@ void ProfileTypeInfo::Dump(std::ostream &os) const
}
}
void ProfileTypeInfoCell::Dump(std::ostream &os) const
{
DISALLOW_GARBAGE_COLLECTION;
os << " - Value: ";
GetValue().Dump(os);
os << "\n";
}
void VTable::Dump(std::ostream &os) const
{
DISALLOW_GARBAGE_COLLECTION;
@ -1776,8 +1793,8 @@ void JSFunction::Dump(std::ostream &os) const
GetLexicalEnv().Dump(os);
os << "\n";
}
os << " - ProfileTypeInfo: ";
GetProfileTypeInfo().Dump(os);
os << " - RawProfileTypeInfo: ";
GetRawProfileTypeInfo().Dump(os);
os << "\n";
os << " - HomeObject: ";
GetHomeObject().Dump(os);
@ -2782,6 +2799,8 @@ void GlobalEnv::Dump(std::ostream &os) const
globalConst->GetEmptyString().Dump(os);
os << " - EmptyTaggedQueue: ";
globalConst->GetEmptyTaggedQueue().Dump(os);
os << " - EmptyProfileTypeInfoCell: ";
globalConst->GetEmptyProfileTypeInfoCell().Dump(os);
os << " - PrototypeString: ";
globalConst->GetPrototypeString().Dump(os);
os << " - HasInstanceSymbol: ";
@ -3988,6 +4007,11 @@ static void DumpObject(TaggedObject *obj, std::vector<Reference> &vec, bool isVm
case JSType::CONSTANT_POOL:
DumpConstantPoolClass(ConstantPool::Cast(obj), vec);
break;
case JSType::PROFILE_TYPE_INFO_CELL_0:
case JSType::PROFILE_TYPE_INFO_CELL_1:
case JSType::PROFILE_TYPE_INFO_CELL_N:
ProfileTypeInfoCell::Cast(obj)->DumpForSnapshot(vec);
break;
case JSType::VTABLE:
VTable::Cast(obj)->DumpForSnapshot(vec);
break;
@ -4795,7 +4819,7 @@ void JSFunction::DumpForSnapshot(std::vector<Reference> &vec) const
{
vec.emplace_back(CString("ProtoOrHClass"), GetProtoOrHClass());
vec.emplace_back(CString("LexicalEnv"), GetLexicalEnv());
vec.emplace_back(CString("ProfileTypeInfo"), GetProfileTypeInfo());
vec.emplace_back(CString("RawProfileTypeInfo"), GetRawProfileTypeInfo());
vec.emplace_back(CString("HomeObject"), GetHomeObject());
vec.emplace_back(CString("Module"), GetModule());
vec.emplace_back(CString("Method"), GetMethod());
@ -4836,6 +4860,11 @@ void ConstantPool::DumpForSnapshot(std::vector<Reference> &vec) const
DumpArrayClass(this, vec);
}
void ProfileTypeInfoCell::DumpForSnapshot(std::vector<Reference> &vec) const
{
vec.emplace_back(CString("Value"), GetValue());
}
void VTable::DumpForSnapshot(std::vector<Reference> &vec) const
{
DumpArrayClass(this, vec);

View File

@ -143,6 +143,12 @@ void GlobalEnvConstants::InitSharedRootsClasses(ObjectFactory *factory)
factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::PROFILE_TYPE_INFO));
SetConstant(ConstantIndex::AOT_LITERAL_INFO_CLASS_INDEX,
factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::AOT_LITERAL_INFO));
SetConstant(ConstantIndex::PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX,
factory->NewSEcmaReadOnlyHClass(hClass, ProfileTypeInfoCell::SIZE, JSType::PROFILE_TYPE_INFO_CELL_0));
SetConstant(ConstantIndex::PROFILE_TYPE_INFO_CELL_1_CLASS_INDEX,
factory->NewSEcmaReadOnlyHClass(hClass, ProfileTypeInfoCell::SIZE, JSType::PROFILE_TYPE_INFO_CELL_1));
SetConstant(ConstantIndex::PROFILE_TYPE_INFO_CELL_N_CLASS_INDEX,
factory->NewSEcmaReadOnlyHClass(hClass, ProfileTypeInfoCell::SIZE, JSType::PROFILE_TYPE_INFO_CELL_N));
SetConstant(ConstantIndex::VTABLE_CLASS_INDEX,
factory->NewSEcmaReadOnlyHClass(hClass, 0, JSType::VTABLE));
SetConstant(ConstantIndex::COW_MUTANT_TAGGED_ARRAY_CLASS_INDEX,
@ -277,6 +283,7 @@ void GlobalEnvConstants::InitSharedMiscellanious(JSThread *thread, ObjectFactory
SetConstant(ConstantIndex::EMPTY_ARRAY_OBJECT_INDEX, factory->NewSEmptyArray());
SetConstant(ConstantIndex::EMPTY_MUTANT_ARRAY_OBJECT_INDEX, factory->NewSEmptyMutantArray());
SetConstant(ConstantIndex::EMPTY_SLAYOUT_INFO_OBJECT_INDEX, factory->CreateSLayoutInfo(0));
SetConstant(ConstantIndex::EMPTY_PROFILE_TYPE_INFO_CELL_INDEX, factory->NewSEmptyProfileTypeInfoCell());
}
void GlobalEnvConstants::InitRootsClassesPartOne(JSHClass *hClass, ObjectFactory *factory)

View File

@ -92,6 +92,9 @@ class ObjectFactory;
V(JSTaggedValue, LinkedNode, LINKED_NODE_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, RBTreeNode, RB_TREENODE_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ClassLiteralClass, CLASS_LITERAL_HCLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ProfileTypeInfoCell0Class, PROFILE_TYPE_INFO_CELL_0_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ProfileTypeInfoCell1Class, PROFILE_TYPE_INFO_CELL_1_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ProfileTypeInfoCellNClass, PROFILE_TYPE_INFO_CELL_N_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, VTableClass, VTABLE_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ResolvedRecordIndexBindingClass, RESOLVED_RECORD_INEDX_BINDING_CLASS_INDEX, ecma_roots_class) \
V(JSTaggedValue, ResolvedRecordBindingClass, RESOLVED_RECORD_BINDING_CLASS_INDEX, ecma_roots_class) \
@ -606,7 +609,8 @@ class ObjectFactory;
V(JSTaggedValue, SingleCharTable, SINGLE_CHAR_TABLE_INDEX, ecma_roots_special) \
V(JSTaggedValue, EmptySLayoutInfo, EMPTY_SLAYOUT_INFO_OBJECT_INDEX, ecma_roots_special) \
V(JSTaggedValue, EmptyArray, EMPTY_ARRAY_OBJECT_INDEX, ecma_roots_special) \
V(JSTaggedValue, EmptyMutantArray, EMPTY_MUTANT_ARRAY_OBJECT_INDEX, ecma_roots_special)
V(JSTaggedValue, EmptyMutantArray, EMPTY_MUTANT_ARRAY_OBJECT_INDEX, ecma_roots_special) \
V(JSTaggedValue, EmptyProfileTypeInfoCell, EMPTY_PROFILE_TYPE_INFO_CELL_INDEX, ecma_roots_special)
#define GLOBAL_ENV_CACHES(V) \
V(JSTaggedValue, CachedJSCollatorLocales, CACHED_JSCOLLATOR_LOCALES_INDEX, cachedCollatorLocales)
@ -637,7 +641,7 @@ enum class ConstantIndex : size_t {
CONSTANT_END = CONSTANT_COUNT,
SHARED_BEGIN = HCLASS_CLASS_INDEX,
SHARED_END = EMPTY_MUTANT_ARRAY_OBJECT_INDEX,
SHARED_END = EMPTY_PROFILE_TYPE_INFO_CELL_INDEX,
SHARED_HCLASS_BEGIN = HCLASS_CLASS_INDEX,
SHARED_HCLASS_END = VTABLE_CLASS_INDEX,

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2024 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.
*/
#ifndef ECMASCRIPT_PROFILE_TYPE_INFO_CELL_H
#define ECMASCRIPT_PROFILE_TYPE_INFO_CELL_H
#include "ecmascript/ecma_macros.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_tagged_value.h"
namespace panda {
namespace ecmascript {
class ProfileTypeInfoCell : public TaggedObject {
public:
CAST_CHECK(ProfileTypeInfoCell, IsProfileTypeInfoCell);
static constexpr size_t VALUE_OFFSET = TaggedObjectSize();
ACCESSORS(Value, VALUE_OFFSET, LAST_OFFSET);
DEFINE_ALIGN_SIZE(LAST_OFFSET);
DECL_VISIT_OBJECT(VALUE_OFFSET, LAST_OFFSET);
bool IsEmptyProfileTypeInfoCell(const JSThread *thread) const
{
return this == thread->GlobalConstants()->GetEmptyProfileTypeInfoCell().GetTaggedObject();
}
void UpdateProfileTypeInfoCellType(const JSThread *thread)
{
// ProfileTypeInfoCell0 -> Cell1 -> CellN
JSType jsType = GetClass()->GetObjectType();
if (jsType == JSType::PROFILE_TYPE_INFO_CELL_0) {
SetClassWithoutBarrier(
JSHClass::Cast(thread->GlobalConstants()->GetProfileTypeInfoCell1Class().GetTaggedObject()));
} else if (jsType == JSType::PROFILE_TYPE_INFO_CELL_1) {
SetClassWithoutBarrier(
JSHClass::Cast(thread->GlobalConstants()->GetProfileTypeInfoCellNClass().GetTaggedObject()));
} else {
ASSERT(jsType == JSType::PROFILE_TYPE_INFO_CELL_N);
}
}
DECL_DUMP()
};
} // namespace ecmascript
} // namespace panda
#endif // ECMASCRIPT_PROFILE_TYPE_INFO_CELL_H

View File

@ -1003,6 +1003,25 @@ std::pair<JSTaggedValue, JSTaggedValue> EcmaInterpreter::GetCurrentEntryPoint(JS
JSTaggedValue::Undefined()));
}
void EcmaInterpreter::UpdateProfileTypeInfoCellToFunction(JSThread *thread, JSHandle<JSFunction> &function,
JSTaggedValue profileTypeInfo, uint16_t slotId)
{
if (!profileTypeInfo.IsUndefined()) {
JSHandle<ProfileTypeInfo> profileTypeArray(thread, profileTypeInfo);
JSTaggedValue slotValue = profileTypeArray->Get(slotId);
if (slotValue.IsUndefined()) {
JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
JSHandle<ProfileTypeInfoCell> newProfileTypeInfoCell =
thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(handleUndefined);
profileTypeArray->Set(thread, slotId, newProfileTypeInfoCell);
function->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
} else {
ProfileTypeInfoCell::Cast(slotValue.GetTaggedObject())->UpdateProfileTypeInfoCellType(thread);
function->SetRawProfileTypeInfo(thread, slotValue);
}
}
}
#ifndef EXCLUDE_C_INTERPRETER
// NOLINTNEXTLINE(readability-function-size)
NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t *pc, JSTaggedType *sp)
@ -4985,9 +5004,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
auto res = SlowRuntimeStub::DefineFunc(thread, constpool, methodId, currentFunc->GetModule(),
length, envHandle, currentFunc->GetHomeObject());
JSFunction *jsFunc = JSFunction::Cast(res.GetTaggedObject());
SET_ACC(JSTaggedValue(jsFunc));
JSHandle<JSFunction> jsFunc(thread, res);
#if ECMASCRIPT_ENABLE_IC
auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
uint16_t slotId = READ_INST_8_0();
UpdateProfileTypeInfoCellToFunction(thread, jsFunc, profileTypeInfo, slotId);
#endif
SET_ACC(jsFunc.GetTaggedValue());
DISPATCH(DEFINEFUNC_IMM8_ID16_IMM8);
}
HANDLE_OPCODE(DEFINEFUNC_IMM16_ID16_IMM8) {
@ -5002,9 +5025,13 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
auto res = SlowRuntimeStub::DefineFunc(thread, constpool, methodId, currentFunc->GetModule(),
length, envHandle, currentFunc->GetHomeObject());
JSFunction *jsFunc = JSFunction::Cast(res.GetTaggedObject());
SET_ACC(JSTaggedValue(jsFunc));
JSHandle<JSFunction> jsFunc(thread, res);
#if ECMASCRIPT_ENABLE_IC
auto profileTypeInfo = GetRuntimeProfileTypeInfo(sp);
uint16_t slotId = READ_INST_16_0();
UpdateProfileTypeInfoCellToFunction(thread, jsFunc, profileTypeInfo, slotId);
#endif
SET_ACC(jsFunc.GetTaggedValue());
DISPATCH(DEFINEFUNC_IMM16_ID16_IMM8);
}
HANDLE_OPCODE(DEFINEMETHOD_IMM8_ID16_IMM8) {

View File

@ -78,6 +78,8 @@ public:
static bool IsFastNewFrameExit(JSTaggedType *sp);
static int16_t GetHotnessCounter(uint32_t codeSize, bool cancelThreshold);
static JSTaggedType *GetInterpreterFrameEnd(JSThread *thread, JSTaggedType *sp);
static void UpdateProfileTypeInfoCellToFunction(JSThread *thread, JSHandle<JSFunction> &function,
JSTaggedValue profileTypeInfo, uint16_t slotId);
private:
static void InitStackFrameForSP(JSTaggedType *prevSp);
static EcmaRuntimeCallInfo* NewRuntimeCallInfoBase(

View File

@ -101,7 +101,7 @@ void JSFunction::InitializeWithDefaultValue(JSThread *thread, const JSHandle<JSF
func->SetLexicalEnv(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
func->SetMachineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
func->SetBaselineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
func->SetProfileTypeInfo(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
func->SetRawProfileTypeInfo(thread, thread->GlobalConstants()->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER);
func->SetMethod(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
func->SetModule(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
func->SetCodeEntry(reinterpret_cast<uintptr_t>(nullptr));
@ -885,6 +885,12 @@ JSTaggedValue JSFunction::GetRecordName() const
return JSTaggedValue::Hole();
}
JSTaggedValue JSFunction::GetProfileTypeInfo() const
{
JSTaggedValue raw = GetRawProfileTypeInfo();
return ProfileTypeInfoCell::Cast(raw.GetTaggedObject())->GetValue();
}
// Those interface below is discarded
void JSFunction::InitializeJSFunction(JSThread *thread, [[maybe_unused]] const JSHandle<GlobalEnv> &env,
const JSHandle<JSFunction> &func, FunctionKind kind)
@ -989,6 +995,19 @@ void JSFunction::SetSFunctionExtraInfo(
}
}
void JSFunction::SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFunction> &func,
const JSHandle<JSTaggedValue> &value, BarrierMode mode)
{
JSHandle<ProfileTypeInfoCell> handleRaw(thread, func->GetRawProfileTypeInfo());
if (handleRaw->IsEmptyProfileTypeInfoCell(thread)) {
JSHandle<ProfileTypeInfoCell> handleProfileTypeInfoCell =
thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(value);
func->SetRawProfileTypeInfo(thread, handleProfileTypeInfoCell, WRITE_BARRIER);
return;
}
handleRaw->SetValue(thread, value, mode);
}
JSTaggedValue JSFunction::GetFunctionExtraInfo() const
{
JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);

View File

@ -18,6 +18,7 @@
#include "ecmascript/accessor_data.h"
#include "ecmascript/ecma_macros.h"
#include "ecmascript/ic/profile_type_info_cell.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/lexical_env.h"
#include "ecmascript/js_proxy.h"
@ -230,10 +231,13 @@ public:
void *data, size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO);
void SetSFunctionExtraInfo(JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter,
void *data, size_t nativeBindingsize = 0);
static void SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFunction> &func,
const JSHandle<JSTaggedValue> &value, BarrierMode mode = WRITE_BARRIER);
JSTaggedValue GetFunctionExtraInfo() const;
JSTaggedValue GetNativeFunctionExtraInfo() const;
JSTaggedValue GetRecordName() const;
JSTaggedValue GetProfileTypeInfo() const;
void InitializeForConcurrentFunction(JSThread *thread);
@ -251,8 +255,8 @@ public:
// For runtime native function, the LexicalEnv field is used to store GlobalEnv, such as RegExp's native function
ACCESSORS(LexicalEnv, LEXICAL_ENV_OFFSET, MACHINECODE_OFFSET)
ACCESSORS(MachineCode, MACHINECODE_OFFSET, BASELINECODE_OFFSET)
ACCESSORS(BaselineCode, BASELINECODE_OFFSET, PROFILE_TYPE_INFO_OFFSET)
ACCESSORS(ProfileTypeInfo, PROFILE_TYPE_INFO_OFFSET, HOME_OBJECT_OFFSET)
ACCESSORS(BaselineCode, BASELINECODE_OFFSET, RAW_PROFILE_TYPE_INFO_OFFSET)
ACCESSORS(RawProfileTypeInfo, RAW_PROFILE_TYPE_INFO_OFFSET, HOME_OBJECT_OFFSET)
ACCESSORS(HomeObject, HOME_OBJECT_OFFSET, ECMA_MODULE_OFFSET)
ACCESSORS(Module, ECMA_MODULE_OFFSET, WORK_NODE_POINTER_OFFSET)
ACCESSORS_PRIMITIVE_FIELD(WorkNodePointer, uintptr_t, WORK_NODE_POINTER_OFFSET, LAST_OFFSET)

View File

@ -289,6 +289,10 @@ struct Reference;
MACHINE_CODE_OBJECT, \
CLASS_INFO_EXTRACTOR, /* //////////////////////////////////////////////////////////////////////////-PADDING */ \
\
PROFILE_TYPE_INFO_CELL_0, /* PROFILE_TYPE_INFO_CELL_FIRST ////////////////////////////////////////-PADDING */ \
PROFILE_TYPE_INFO_CELL_1, /* /////////////////////////////////////////////////////////////////////-PADDING */ \
PROFILE_TYPE_INFO_CELL_N, /* PROFILE_TYPE_INFO_CELL_LAST /////////////////////////////////////////-PADDING */ \
\
VTABLE, /* //////////////////////////////////////////////////////////////////-PADDING */ \
AOT_LITERAL_INFO, /* //////////////////////////////////////////////////////////////////////////////-PADDING */ \
TYPE_LAST = AOT_LITERAL_INFO, /* //////////////////////////////////////////////////////////////////-PADDING */ \
@ -321,7 +325,10 @@ struct Reference;
MODULE_RECORD_LAST = SOURCE_TEXT_MODULE_RECORD, /* ////////////////////////////////////////////////-PADDING */ \
\
STRING_FIRST = LINE_STRING, /* ////////////////////////////////////////////////////////////////////-PADDING */ \
STRING_LAST = TREE_STRING /* /////////////////////////////////////////////////////////////////////-PADDING */
STRING_LAST = TREE_STRING, /* ////////////////////////////////////////////////////////////////////-PADDING */ \
\
PROFILE_TYPE_INFO_CELL_FIRST = PROFILE_TYPE_INFO_CELL_0, /* //////////////////////////////////////-PADDING */ \
PROFILE_TYPE_INFO_CELL_LAST = PROFILE_TYPE_INFO_CELL_N /* //////////////////////////////////////-PADDING */
enum class JSType : uint8_t {
JSTYPE_DECL,
@ -1613,6 +1620,12 @@ public:
return GetObjectType() == JSType::AOT_LITERAL_INFO;
}
inline bool IsProfileTypeInfoCell() const
{
JSType jsType = GetObjectType();
return jsType >= JSType::PROFILE_TYPE_INFO_CELL_FIRST && jsType <= JSType::PROFILE_TYPE_INFO_CELL_LAST;
}
inline bool IsVTable() const
{
return GetObjectType() == JSType::VTABLE;

View File

@ -525,6 +525,11 @@ inline bool JSTaggedValue::IsAOTLiteralInfo() const
return IsHeapObject() && GetTaggedObject()->GetClass()->IsAOTLiteralInfo();
}
inline bool JSTaggedValue::IsProfileTypeInfoCell() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsProfileTypeInfoCell();
}
inline bool JSTaggedValue::IsVTable() const
{
return IsHeapObject() && GetTaggedObject()->GetClass()->IsVTable();

View File

@ -481,6 +481,7 @@ public:
bool IsByteArray() const;
bool IsConstantPool() const;
bool IsAOTLiteralInfo() const;
bool IsProfileTypeInfoCell() const;
bool IsVTable() const;
bool IsLinkedNode() const;
bool IsRBTreeNode() const;

View File

@ -424,6 +424,11 @@ public:
JSNativePointer::Cast(object)->VisitRangeSlot<visitType>(visitor);
}
break;
case JSType::PROFILE_TYPE_INFO_CELL_0:
case JSType::PROFILE_TYPE_INFO_CELL_1:
case JSType::PROFILE_TYPE_INFO_CELL_N:
ProfileTypeInfoCell::Cast(object)->VisitRangeSlot<visitType>(visitor);
break;
case JSType::TAGGED_ARRAY:
case JSType::TAGGED_DICTIONARY:
case JSType::TEMPLATE_MAP:

View File

@ -4812,6 +4812,16 @@ JSHandle<AOTLiteralInfo> ObjectFactory::NewAOTLiteralInfo(uint32_t length, JSTag
return aotLiteralInfo;
}
JSHandle<ProfileTypeInfoCell> ObjectFactory::NewProfileTypeInfoCell(const JSHandle<JSTaggedValue> &value)
{
NewObjectHook();
TaggedObject *header = heap_->AllocateYoungOrHugeObject(
JSHClass::Cast(thread_->GlobalConstants()->GetProfileTypeInfoCell0Class().GetTaggedObject()));
JSHandle<ProfileTypeInfoCell> profileTypeInfoCell(thread_, header);
profileTypeInfoCell->SetValue(thread_, value.GetTaggedValue());
return profileTypeInfoCell;
}
JSHandle<VTable> ObjectFactory::NewVTable(uint32_t length, JSTaggedValue initVal)
{
NewObjectHook();

View File

@ -172,6 +172,7 @@ class ProfileTypeInfo;
class MachineCode;
class ClassInfoExtractor;
class AOTLiteralInfo;
class ProfileTypeInfoCell;
class VTable;
namespace kungfu {
class TSHClassGenerator;
@ -693,6 +694,7 @@ public:
// ---------------------------------------Used by AOT------------------------------------------------
JSHandle<AOTLiteralInfo> NewAOTLiteralInfo(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
JSHandle<ProfileTypeInfoCell> NewProfileTypeInfoCell(const JSHandle<JSTaggedValue> &value);
JSHandle<VTable> NewVTable(uint32_t length, JSTaggedValue initVal = JSTaggedValue::Hole());
JSHandle<JSHClass> NewEcmaHClass(JSHClass *hclass, uint32_t size, JSType type,
uint32_t inlinedProps = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS);
@ -828,6 +830,8 @@ public:
JSHandle<LayoutInfo> PUBLIC_API CreateSLayoutInfo(uint32_t properties);
JSHandle<ProfileTypeInfoCell> NewSEmptyProfileTypeInfoCell();
JSHandle<TaggedArray> NewSEmptyArray(); // only used for EcmaVM.
JSHandle<MutantTaggedArray> NewSEmptyMutantArray();

View File

@ -273,7 +273,8 @@ void PatchLoader::UpdateJSFunction(JSThread *thread, PatchInfo &patchInfo)
JSHandle<JSTaggedValue> moduleRecord =
thread->GetCurrentEcmaContext()->FindPatchModule(replacedPatchMethods[methodId]);
function->SetModule(thread, moduleRecord.GetTaggedValue());
function->SetProfileTypeInfo(thread, JSTaggedValue::Undefined());
function->SetRawProfileTypeInfo(thread, thread->GlobalConstants()->GetEmptyProfileTypeInfoCell(),
SKIP_BARRIER);
}
}
});

View File

@ -177,6 +177,7 @@ void BaseDeserializer::HandleNewObjectEncodeFlag(SerializedObjectSpace space, u
// defer initialize concurrent function
concurrentFunctions_.push_back(reinterpret_cast<JSFunction *>(object));
}
func->SetRawProfileTypeInfo(thread_, thread_->GlobalConstants()->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER);
}
UpdateMaybeWeak(ObjectSlot(objAddr + fieldOffset), addr, isWeak);
if (!isRoot) {

View File

@ -190,7 +190,7 @@ void BaseSerializer::SerializeSFunctionFieldIndividually(TaggedObject *root, Obj
switch (fieldOffset) {
case JSFunction::MACHINECODE_OFFSET:
case JSFunction::BASELINECODE_OFFSET:
case JSFunction::PROFILE_TYPE_INFO_OFFSET: {
case JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET: {
data_->WriteEncodeFlag(EncodeFlag::PRIMITIVE);
data_->WriteJSTaggedValue(JSTaggedValue::Undefined());
slot++;
@ -294,7 +294,7 @@ void BaseSerializer::SerializeAsyncFunctionFieldIndividually(TaggedObject *root,
case JSFunction::LEXICAL_ENV_OFFSET:
case JSFunction::MACHINECODE_OFFSET:
case JSFunction::BASELINECODE_OFFSET:
case JSFunction::PROFILE_TYPE_INFO_OFFSET:
case JSFunction::RAW_PROFILE_TYPE_INFO_OFFSET:
case JSFunction::HOME_OBJECT_OFFSET:
case JSFunction::ECMA_MODULE_OFFSET: {
data_->WriteEncodeFlag(EncodeFlag::PRIMITIVE);

View File

@ -435,6 +435,16 @@ JSHandle<TaggedArray> ObjectFactory::NewSDictionaryArray(uint32_t length)
return array;
}
JSHandle<ProfileTypeInfoCell> ObjectFactory::NewSEmptyProfileTypeInfoCell()
{
NewSObjectHook();
auto header = sHeap_->AllocateReadOnlyOrHugeObject(thread_,
JSHClass::Cast(thread_->GlobalConstants()->GetProfileTypeInfoCell0Class().GetTaggedObject()));
JSHandle<ProfileTypeInfoCell> profileTypeInfoCell(thread_, header);
profileTypeInfoCell->SetValue(thread_, JSTaggedValue::Undefined());
return profileTypeInfoCell;
}
JSHandle<TaggedArray> ObjectFactory::NewSEmptyArray()
{
NewSObjectHook();

View File

@ -1108,7 +1108,7 @@ JSTaggedValue RuntimeStubs::RuntimeNotifyInlineCache(JSThread *thread, const JSH
profileTypeInfo->Set(thread, ProfileTypeInfo::INVALID_SLOT_INDEX, JSTaggedValue::Hole());
ASSERT(icSlotSize <= ProfileTypeInfo::MAX_SLOT_INDEX + 1);
}
function->SetProfileTypeInfo(thread, profileTypeInfo.GetTaggedValue());
JSFunction::SetProfileTypeInfo(thread, function, JSHandle<JSTaggedValue>::Cast(profileTypeInfo));
return profileTypeInfo.GetTaggedValue();
}

View File

@ -914,6 +914,14 @@ HWTEST_F_L0(EcmaDumpTest, HeapProfileDump)
DUMP_FOR_HANDLE(globalEnv->GetBigIntFunction());
break;
}
case JSType::PROFILE_TYPE_INFO_CELL_0:
case JSType::PROFILE_TYPE_INFO_CELL_1:
case JSType::PROFILE_TYPE_INFO_CELL_N: {
JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
JSHandle<ProfileTypeInfoCell> profileTypeInfoCell = factory->NewProfileTypeInfoCell(handleUndefined);
DUMP_FOR_HANDLE(profileTypeInfoCell);
break;
}
case JSType::TAGGED_ARRAY:
case JSType::VTABLE:
case JSType::LEXICAL_ENV:

View File

@ -19,3 +19,5 @@ get
undefined
0
1
1
1

View File

@ -113,4 +113,18 @@ let v2 = new c2();
for (let v5 = 0;v5 < 2; v5++) {
print(v5);
v2.y = 42;
}
}
function fun1(n) {
function fun2(o) {
return o.a;
}
let obj = {a: 1};
for (let i = 0; i < n; i++) {
fun2(obj);
}
return fun2(obj);
}
print(fun1(100));
print(fun1(1));