mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 01:59:58 +00:00
Opt TraceIC
Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/IB32C4 Signed-off-by: dov1s <maojunwei1@huawei.com> Change-Id: I2fd7b34302b2fb1444c8148857e5a521fcdef107
This commit is contained in:
parent
36a96121f4
commit
a5db84bf35
1
BUILD.gn
1
BUILD.gn
@ -722,6 +722,7 @@ ecma_source = [
|
||||
"ecmascript/async_generator_helper.cpp",
|
||||
"ecmascript/global_env.cpp",
|
||||
"ecmascript/global_env_constants.cpp",
|
||||
"ecmascript/ic/ic_handler.cpp",
|
||||
"ecmascript/ic/ic_runtime.cpp",
|
||||
"ecmascript/ic/profile_type_info.cpp",
|
||||
"ecmascript/ic/property_box.cpp",
|
||||
|
@ -34,6 +34,7 @@ namespace panda::ecmascript {
|
||||
#define ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER 0
|
||||
#define ECMASCRIPT_ENABLE_ELEMENTSKIND_ALWAY_GENERIC 0
|
||||
#define ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 0
|
||||
#define ECMASCRIPT_ENABLE_TRACE_IC 0
|
||||
|
||||
#define ENABLE_NEXT_OPTIMIZATION 1
|
||||
|
||||
|
333
ecmascript/ic/ic_handler.cpp
Normal file
333
ecmascript/ic/ic_handler.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (c) 2021-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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/ic/ic_handler.h"
|
||||
#include "ecmascript/global_env_constants-inl.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
|
||||
JSHandle<JSTaggedValue> LoadHandler::LoadProperty(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
uint64_t handler = 0;
|
||||
ASSERT(!op.IsElement());
|
||||
if (!op.IsFound()) {
|
||||
KindBit::Set<uint64_t>(HandlerKind::NON_EXIST, &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
ASSERT(op.IsFastMode());
|
||||
|
||||
JSTaggedValue val = op.GetValue();
|
||||
if (val.IsPropertyBox()) {
|
||||
return JSHandle<JSTaggedValue>(thread, val);
|
||||
}
|
||||
bool hasAccessor = op.IsAccessorDescriptor();
|
||||
AccessorBit::Set<uint64_t>(hasAccessor, &handler);
|
||||
|
||||
if (!hasAccessor) {
|
||||
JSHandle<JSTaggedValue> receiver = op.GetReceiver();
|
||||
if (receiver->IsString()) {
|
||||
JSTaggedValue lenKey = thread->GlobalConstants()->GetLengthString();
|
||||
JSHandle<JSTaggedValue> key = op.GetKey();
|
||||
EcmaString *proKey = key->IsString() ? EcmaString::Cast(key->GetTaggedObject()) : nullptr;
|
||||
if (EcmaStringAccessor::StringsAreEqual(proKey, EcmaString::Cast(lenKey.GetTaggedObject()))) {
|
||||
KindBit::Set<uint64_t>(HandlerKind::STRING_LENGTH, &handler);
|
||||
} else {
|
||||
KindBit::Set<uint64_t>(HandlerKind::STRING, &handler);
|
||||
}
|
||||
} else if (receiver->IsNumber()) {
|
||||
KindBit::Set<uint64_t>(HandlerKind::NUMBER, &handler);
|
||||
} else {
|
||||
KindBit::Set<uint64_t>(HandlerKind::FIELD, &handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (op.IsInlinedProps()) {
|
||||
InlinedPropsBit::Set<uint64_t>(true, &handler);
|
||||
JSHandle<JSObject> holder = JSHandle<JSObject>::Cast(op.GetHolder());
|
||||
auto index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex());
|
||||
OffsetBit::Set<uint64_t>(index, &handler);
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
RepresentationBit::Set<uint64_t>(op.GetRepresentation(), &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
if (op.IsFastMode()) {
|
||||
JSHandle<JSObject> holder = JSHandle<JSObject>::Cast(op.GetHolder());
|
||||
uint32_t inlinePropNum = holder->GetJSHClass()->GetInlinedProperties();
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex() + inlinePropNum, &handler);
|
||||
OffsetBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
RepresentationBit::Set<uint64_t>(Representation::TAGGED, &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> LoadHandler::LoadElement(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
uint64_t handler = 0;
|
||||
KindBit::Set<uint64_t>(HandlerKind::ELEMENT, &handler);
|
||||
// To avoid logical errors and Deopt, temporarily skipping PGO Profiling.
|
||||
// logical errors:
|
||||
// When accessing an element of an object, AOT does not have a chain-climbing operation,
|
||||
// so if the element is on a prototype, it will not be able to get the correct element.
|
||||
// deopt:
|
||||
// Currently there is no way to save the type of the key in pgo file, even if the type of the key
|
||||
// is string, it will be treated as a number type by the AOT, leading to deopt at runtime.
|
||||
if (op.GetReceiver() != op.GetHolder() || op.KeyFromStringType()) {
|
||||
NeedSkipInPGODumpBit::Set<uint64_t>(true, &handler);
|
||||
}
|
||||
if (op.GetReceiver()->IsJSArray()) {
|
||||
IsJSArrayBit::Set<uint64_t>(true, &handler);
|
||||
}
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> StoreHandler::StoreProperty(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
uint64_t handler = 0;
|
||||
JSHandle<JSObject> receiver = JSHandle<JSObject>::Cast(op.GetReceiver());
|
||||
SFieldTypeBitSet(op, receiver, &handler);
|
||||
if (op.IsElement()) {
|
||||
SOutOfBoundsBit::Set<uint64_t>(op.GetElementOutOfBounds(), &handler);
|
||||
return StoreElement(thread, op.GetReceiver(), handler);
|
||||
}
|
||||
JSTaggedValue val = op.GetValue();
|
||||
if (val.IsPropertyBox()) {
|
||||
return JSHandle<JSTaggedValue>(thread, val);
|
||||
}
|
||||
bool hasSetter = op.IsAccessorDescriptor();
|
||||
AccessorBit::Set<uint64_t>(hasSetter, &handler);
|
||||
if (!hasSetter) {
|
||||
SKindBit::Set<uint64_t>(StoreHandlerKind::S_FIELD, &handler);
|
||||
}
|
||||
if (op.IsInlinedProps()) {
|
||||
InlinedPropsBit::Set<uint64_t>(true, &handler);
|
||||
uint32_t index = 0;
|
||||
if (!hasSetter) {
|
||||
index = receiver->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex());
|
||||
} else {
|
||||
JSHandle<JSObject> holder = JSHandle<JSObject>::Cast(op.GetHolder());
|
||||
index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex());
|
||||
}
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
OffsetBit::Set<uint64_t>(index, &handler);
|
||||
RepresentationBit::Set(op.GetRepresentation(), &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
ASSERT(op.IsFastMode());
|
||||
uint32_t inlinePropNum = receiver->GetJSHClass()->GetInlinedProperties();
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex() + inlinePropNum, &handler);
|
||||
OffsetBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
RepresentationBit::Set(Representation::TAGGED, &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> TransitionHandler::StoreTransition(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TransitionHandler> handler = factory->NewTransitionHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
auto hclass = JSObject::Cast(op.GetReceiver()->GetTaggedObject())->GetJSHClass();
|
||||
handler->SetTransitionHClass(thread, JSTaggedValue(hclass));
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> PrototypeHandler::LoadPrototype(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> handlerInfo = LoadHandler::LoadProperty(thread, op);
|
||||
JSHandle<PrototypeHandler> handler = factory->NewPrototypeHandler();
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
if (op.IsFound()) {
|
||||
handler->SetHolder(thread, op.GetHolder());
|
||||
}
|
||||
if (op.IsAccessorDescriptor()) {
|
||||
JSTaggedValue result = op.GetValue();
|
||||
if (result.IsPropertyBox()) {
|
||||
result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
|
||||
}
|
||||
AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
|
||||
if (!accessor->IsInternal()) {
|
||||
JSTaggedValue getter = accessor->GetGetter();
|
||||
if (!getter.IsUndefined()) {
|
||||
JSHandle<JSFunction> func(thread, getter);
|
||||
uint32_t methodOffset = Method::Cast(func->GetMethod())->GetMethodId().GetOffset();
|
||||
handler->SetAccessorMethodId(methodOffset);
|
||||
handler->SetAccessorJSFunction(thread, getter);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ShareToLocal is prohibited
|
||||
if (!hclass->IsJSShared()) {
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
}
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> PrototypeHandler::StorePrototype(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<PrototypeHandler> handler = factory->NewPrototypeHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
handler->SetHolder(thread, op.GetHolder());
|
||||
if (op.IsAccessorDescriptor()) {
|
||||
JSTaggedValue result = op.GetValue();
|
||||
if (result.IsPropertyBox()) {
|
||||
result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
|
||||
}
|
||||
AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
|
||||
if (!accessor->IsInternal() && accessor->HasSetter()) {
|
||||
JSTaggedValue setter = accessor->GetSetter();
|
||||
JSHandle<JSFunction> func(thread, setter);
|
||||
handler->SetAccessorMethodId(
|
||||
Method::Cast(func->GetMethod())->GetMethodId().GetOffset());
|
||||
handler->SetAccessorJSFunction(thread, setter);
|
||||
}
|
||||
}
|
||||
// ShareToLocal is prohibited
|
||||
if (!hclass->IsJSShared()) {
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
}
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
|
||||
JSHandle<JSTaggedValue> TransWithProtoHandler::StoreTransition(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TransWithProtoHandler> handler = factory->NewTransWithProtoHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
handler->SetTransitionHClass(thread, hclass.GetTaggedValue());
|
||||
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
|
||||
void HandlerBase::PrintLoadHandler([[maybe_unused]] uint64_t handler, [[maybe_unused]] std::ostream& os)
|
||||
{
|
||||
#if ECMASCRIPT_ENABLE_TRACE_IC
|
||||
HandlerKind kind = GetKind(handler);
|
||||
os << "kind = ";
|
||||
switch (kind) {
|
||||
case HandlerKind::NONE:
|
||||
os << "NONE"
|
||||
<< ", is InlinedPropsBit = "
|
||||
<< InlinedPropsBit::Get(handler)
|
||||
<< ", is AccessorBit = "
|
||||
<< AccessorBit::Get(handler)
|
||||
<< ", OffsetBit = "
|
||||
<< OffsetBit::Get(handler)
|
||||
<< ", AttrIndexBit = "
|
||||
<< AttrIndexBit::Get(handler);
|
||||
break;
|
||||
case HandlerKind::FIELD:
|
||||
os << "FIELD"
|
||||
<< ", is InlinedPropsBit = "
|
||||
<< InlinedPropsBit::Get(handler)
|
||||
<< ", is AccessorBit = "
|
||||
<< AccessorBit::Get(handler)
|
||||
<< ", OffsetBit = "
|
||||
<< OffsetBit::Get(handler)
|
||||
<< ", AttrIndexBit = "
|
||||
<< AttrIndexBit::Get(handler);
|
||||
break;
|
||||
case HandlerKind::ELEMENT:
|
||||
os << "ELEMENT"
|
||||
<< ", is JSArray = "
|
||||
<< IsJSArrayBit::Get(handler);
|
||||
break;
|
||||
case HandlerKind::DICTIONARY:
|
||||
os << "DICTIONARY";
|
||||
break;
|
||||
case HandlerKind::STRING:
|
||||
os << "STRING";
|
||||
break;
|
||||
case HandlerKind::STRING_LENGTH:
|
||||
os << "STRING_LENGTH";
|
||||
break;
|
||||
case HandlerKind::TYPED_ARRAY:
|
||||
os << "TYPED_ARRAY,"
|
||||
<< "is OnHeap = "
|
||||
<< IsOnHeapBit::Get(handler);
|
||||
break;
|
||||
case HandlerKind::NUMBER:
|
||||
os << "NUMBER";
|
||||
break;
|
||||
case HandlerKind::NON_EXIST:
|
||||
os << "NON_EXIST";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
os << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void HandlerBase::PrintStoreHandler([[maybe_unused]] uint64_t handler, [[maybe_unused]] std::ostream& os)
|
||||
{
|
||||
#if ECMASCRIPT_ENABLE_TRACE_IC
|
||||
StoreHandlerKind kind = static_cast<StoreHandlerKind>(GetKind(handler));
|
||||
os << "kind = ";
|
||||
switch (kind) {
|
||||
case StoreHandlerKind::S_NONE:
|
||||
os << "NONE"
|
||||
<< ", is InlinedPropsBit = "
|
||||
<< InlinedPropsBit::Get(handler)
|
||||
<< ", is AccessorBit = "
|
||||
<< AccessorBit::Get(handler)
|
||||
<< ", OffsetBit = "
|
||||
<< OffsetBit::Get(handler)
|
||||
<< ", AttrIndexBit = "
|
||||
<< AttrIndexBit::Get(handler)
|
||||
<< ", SFieldTypeBit = "
|
||||
<< static_cast<uint32_t>(SFieldTypeBit::Get(handler));
|
||||
break;
|
||||
case StoreHandlerKind::S_FIELD:
|
||||
os << "S_FIELD"
|
||||
<< ", is InlinedPropsBit = "
|
||||
<< InlinedPropsBit::Get(handler)
|
||||
<< ", is AccessorBit = "
|
||||
<< AccessorBit::Get(handler)
|
||||
<< ", OffsetBit = "
|
||||
<< OffsetBit::Get(handler)
|
||||
<< ", AttrIndexBit = "
|
||||
<< AttrIndexBit::Get(handler)
|
||||
<< ", SFieldTypeBit = "
|
||||
<< static_cast<uint32_t>(SFieldTypeBit::Get(handler));
|
||||
break;
|
||||
case StoreHandlerKind::S_ELEMENT:
|
||||
os << "S_ELEMENT"
|
||||
<< ", is JSArray = "
|
||||
<< IsJSArrayBit::Get(handler)
|
||||
<< ", SOutOfBoundsBit = "
|
||||
<< SOutOfBoundsBit::Get(handler)
|
||||
<< ", SFieldTypeBit = "
|
||||
<< static_cast<uint32_t>(SFieldTypeBit::Get(handler));
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
os << std::endl;
|
||||
#endif
|
||||
}
|
||||
} // namespace panda::ecmascript
|
@ -194,85 +194,15 @@ public:
|
||||
{
|
||||
return IsOnHeapBit::Get(handler);
|
||||
}
|
||||
|
||||
static void PrintLoadHandler(uint64_t handler, std::ostream& os);
|
||||
static void PrintStoreHandler(uint64_t handler, std::ostream& os);
|
||||
};
|
||||
|
||||
class LoadHandler final : public HandlerBase {
|
||||
public:
|
||||
static inline JSHandle<JSTaggedValue> LoadProperty(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
uint64_t handler = 0;
|
||||
ASSERT(!op.IsElement());
|
||||
if (!op.IsFound()) {
|
||||
KindBit::Set<uint64_t>(HandlerKind::NON_EXIST, &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
ASSERT(op.IsFastMode());
|
||||
|
||||
JSTaggedValue val = op.GetValue();
|
||||
if (val.IsPropertyBox()) {
|
||||
return JSHandle<JSTaggedValue>(thread, val);
|
||||
}
|
||||
bool hasAccessor = op.IsAccessorDescriptor();
|
||||
AccessorBit::Set<uint64_t>(hasAccessor, &handler);
|
||||
|
||||
if (!hasAccessor) {
|
||||
JSHandle<JSTaggedValue> receiver = op.GetReceiver();
|
||||
if (receiver->IsString()) {
|
||||
JSTaggedValue lenKey = thread->GlobalConstants()->GetLengthString();
|
||||
JSHandle<JSTaggedValue> key = op.GetKey();
|
||||
EcmaString *proKey = key->IsString() ? EcmaString::Cast(key->GetTaggedObject()) : nullptr;
|
||||
if (EcmaStringAccessor::StringsAreEqual(proKey, EcmaString::Cast(lenKey.GetTaggedObject()))) {
|
||||
KindBit::Set<uint64_t>(HandlerKind::STRING_LENGTH, &handler);
|
||||
} else {
|
||||
KindBit::Set<uint64_t>(HandlerKind::STRING, &handler);
|
||||
}
|
||||
} else if (receiver->IsNumber()) {
|
||||
KindBit::Set<uint64_t>(HandlerKind::NUMBER, &handler);
|
||||
} else {
|
||||
KindBit::Set<uint64_t>(HandlerKind::FIELD, &handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (op.IsInlinedProps()) {
|
||||
InlinedPropsBit::Set<uint64_t>(true, &handler);
|
||||
JSHandle<JSObject> holder = JSHandle<JSObject>::Cast(op.GetHolder());
|
||||
auto index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex());
|
||||
OffsetBit::Set<uint64_t>(index, &handler);
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
RepresentationBit::Set<uint64_t>(op.GetRepresentation(), &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
if (op.IsFastMode()) {
|
||||
JSHandle<JSObject> holder = JSHandle<JSObject>::Cast(op.GetHolder());
|
||||
uint32_t inlinePropNum = holder->GetJSHClass()->GetInlinedProperties();
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex() + inlinePropNum, &handler);
|
||||
OffsetBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
RepresentationBit::Set<uint64_t>(Representation::TAGGED, &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static inline JSHandle<JSTaggedValue> LoadElement(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
uint64_t handler = 0;
|
||||
KindBit::Set<uint64_t>(HandlerKind::ELEMENT, &handler);
|
||||
// To avoid logical errors and Deopt, temporarily skipping PGO Profiling.
|
||||
// logical errors:
|
||||
// When accessing an element of an object, AOT does not have a chain-climbing operation,
|
||||
// so if the element is on a prototype, it will not be able to get the correct element.
|
||||
// deopt:
|
||||
// Currently there is no way to save the type of the key in pgo file, even if the type of the key
|
||||
// is string, it will be treated as a number type by the AOT, leading to deopt at runtime.
|
||||
if (op.GetReceiver() != op.GetHolder() || op.KeyFromStringType()) {
|
||||
NeedSkipInPGODumpBit::Set<uint64_t>(true, &handler);
|
||||
}
|
||||
if (op.GetReceiver()->IsJSArray()) {
|
||||
IsJSArrayBit::Set<uint64_t>(true, &handler);
|
||||
}
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
static JSHandle<JSTaggedValue> LoadProperty(const JSThread *thread, const ObjectOperator &op);
|
||||
static JSHandle<JSTaggedValue> LoadElement(const JSThread *thread, const ObjectOperator &op);
|
||||
|
||||
static inline JSHandle<JSTaggedValue> LoadStringElement(const JSThread *thread)
|
||||
{
|
||||
@ -293,45 +223,7 @@ public:
|
||||
|
||||
class StoreHandler final : public HandlerBase {
|
||||
public:
|
||||
static inline JSHandle<JSTaggedValue> StoreProperty(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
uint64_t handler = 0;
|
||||
JSHandle<JSObject> receiver = JSHandle<JSObject>::Cast(op.GetReceiver());
|
||||
SFieldTypeBitSet(op, receiver, &handler);
|
||||
if (op.IsElement()) {
|
||||
SOutOfBoundsBit::Set<uint64_t>(op.GetElementOutOfBounds(), &handler);
|
||||
return StoreElement(thread, op.GetReceiver(), handler);
|
||||
}
|
||||
JSTaggedValue val = op.GetValue();
|
||||
if (val.IsPropertyBox()) {
|
||||
return JSHandle<JSTaggedValue>(thread, val);
|
||||
}
|
||||
bool hasSetter = op.IsAccessorDescriptor();
|
||||
AccessorBit::Set<uint64_t>(hasSetter, &handler);
|
||||
if (!hasSetter) {
|
||||
SKindBit::Set<uint64_t>(StoreHandlerKind::S_FIELD, &handler);
|
||||
}
|
||||
if (op.IsInlinedProps()) {
|
||||
InlinedPropsBit::Set<uint64_t>(true, &handler);
|
||||
uint32_t index = 0;
|
||||
if (!hasSetter) {
|
||||
index = receiver->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex());
|
||||
} else {
|
||||
JSHandle<JSObject> holder = JSHandle<JSObject>::Cast(op.GetHolder());
|
||||
index = holder->GetJSHClass()->GetInlinedPropertiesIndex(op.GetIndex());
|
||||
}
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
OffsetBit::Set<uint64_t>(index, &handler);
|
||||
RepresentationBit::Set(op.GetRepresentation(), &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
ASSERT(op.IsFastMode());
|
||||
uint32_t inlinePropNum = receiver->GetJSHClass()->GetInlinedProperties();
|
||||
AttrIndexBit::Set<uint64_t>(op.GetIndex() + inlinePropNum, &handler);
|
||||
OffsetBit::Set<uint64_t>(op.GetIndex(), &handler);
|
||||
RepresentationBit::Set(Representation::TAGGED, &handler);
|
||||
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::WrapUint64(handler));
|
||||
}
|
||||
static JSHandle<JSTaggedValue> StoreProperty(const JSThread *thread, const ObjectOperator &op);
|
||||
|
||||
static inline JSHandle<JSTaggedValue> StoreElement(const JSThread *thread,
|
||||
JSHandle<JSTaggedValue> receiver, uint64_t handler)
|
||||
@ -364,16 +256,7 @@ public:
|
||||
return static_cast<TransitionHandler *>(object);
|
||||
}
|
||||
|
||||
static inline JSHandle<JSTaggedValue> StoreTransition(const JSThread *thread, const ObjectOperator &op)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TransitionHandler> handler = factory->NewTransitionHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
auto hclass = JSObject::Cast(op.GetReceiver()->GetTaggedObject())->GetJSHClass();
|
||||
handler->SetTransitionHClass(thread, JSTaggedValue(hclass));
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
static JSHandle<JSTaggedValue> StoreTransition(const JSThread *thread, const ObjectOperator &op);
|
||||
|
||||
static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, TRANSITION_HCLASS_OFFSET)
|
||||
@ -391,68 +274,10 @@ public:
|
||||
return static_cast<PrototypeHandler *>(object);
|
||||
}
|
||||
|
||||
static inline JSHandle<JSTaggedValue> LoadPrototype(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<JSTaggedValue> handlerInfo = LoadHandler::LoadProperty(thread, op);
|
||||
JSHandle<PrototypeHandler> handler = factory->NewPrototypeHandler();
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
if (op.IsFound()) {
|
||||
handler->SetHolder(thread, op.GetHolder());
|
||||
}
|
||||
if (op.IsAccessorDescriptor()) {
|
||||
JSTaggedValue result = op.GetValue();
|
||||
if (result.IsPropertyBox()) {
|
||||
result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
|
||||
}
|
||||
AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
|
||||
if (!accessor->IsInternal()) {
|
||||
JSTaggedValue getter = accessor->GetGetter();
|
||||
if (!getter.IsUndefined()) {
|
||||
JSHandle<JSFunction> func(thread, getter);
|
||||
uint32_t methodOffset = Method::Cast(func->GetMethod())->GetMethodId().GetOffset();
|
||||
handler->SetAccessorMethodId(methodOffset);
|
||||
handler->SetAccessorJSFunction(thread, getter);
|
||||
}
|
||||
}
|
||||
}
|
||||
// ShareToLocal is prohibited
|
||||
if (!hclass->IsJSShared()) {
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
}
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
static inline JSHandle<JSTaggedValue> StorePrototype(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<PrototypeHandler> handler = factory->NewPrototypeHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
handler->SetHolder(thread, op.GetHolder());
|
||||
if (op.IsAccessorDescriptor()) {
|
||||
JSTaggedValue result = op.GetValue();
|
||||
if (result.IsPropertyBox()) {
|
||||
result = PropertyBox::Cast(result.GetTaggedObject())->GetValue();
|
||||
}
|
||||
AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject());
|
||||
if (!accessor->IsInternal() && accessor->HasSetter()) {
|
||||
JSTaggedValue setter = accessor->GetSetter();
|
||||
JSHandle<JSFunction> func(thread, setter);
|
||||
handler->SetAccessorMethodId(
|
||||
Method::Cast(func->GetMethod())->GetMethodId().GetOffset());
|
||||
handler->SetAccessorJSFunction(thread, setter);
|
||||
}
|
||||
}
|
||||
// ShareToLocal is prohibited
|
||||
if (!hclass->IsJSShared()) {
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
}
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
static JSHandle<JSTaggedValue> LoadPrototype(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass);
|
||||
static JSHandle<JSTaggedValue> StorePrototype(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass);
|
||||
|
||||
static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, PROTO_CELL_OFFSET)
|
||||
@ -474,19 +299,8 @@ public:
|
||||
return static_cast<TransWithProtoHandler *>(object);
|
||||
}
|
||||
|
||||
static inline JSHandle<JSTaggedValue> StoreTransition(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<TransWithProtoHandler> handler = factory->NewTransWithProtoHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
handler->SetTransitionHClass(thread, hclass.GetTaggedValue());
|
||||
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
static JSHandle<JSTaggedValue> StoreTransition(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass);
|
||||
|
||||
static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, TRANSITION_HCLASS_OFFSET)
|
||||
@ -505,19 +319,6 @@ public:
|
||||
return static_cast<StoreAOTHandler *>(object);
|
||||
}
|
||||
|
||||
static inline JSHandle<JSTaggedValue> StoreAOT(const JSThread *thread, const ObjectOperator &op,
|
||||
const JSHandle<JSHClass> &hclass)
|
||||
{
|
||||
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
|
||||
JSHandle<StoreAOTHandler> handler = factory->NewStoreAOTHandler();
|
||||
JSHandle<JSTaggedValue> handlerInfo = StoreHandler::StoreProperty(thread, op);
|
||||
handler->SetHandlerInfo(thread, handlerInfo);
|
||||
handler->SetHolder(thread, op.GetHolder());
|
||||
auto result = JSHClass::EnableProtoChangeMarker(thread, hclass);
|
||||
handler->SetProtoCell(thread, result);
|
||||
return JSHandle<JSTaggedValue>::Cast(handler);
|
||||
}
|
||||
|
||||
static constexpr size_t HANDLER_INFO_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS(HandlerInfo, HANDLER_INFO_OFFSET, PROTO_CELL_OFFSET)
|
||||
ACCESSORS(ProtoCell, PROTO_CELL_OFFSET, HOLDER_OFFSET)
|
||||
|
@ -15,13 +15,13 @@
|
||||
|
||||
#include "ecmascript/ic/ic_runtime.h"
|
||||
#include "ecmascript/ic/ic_handler.h"
|
||||
#include "ecmascript/dfx/stackinfo/js_stackinfo.h"
|
||||
#include "ecmascript/interpreter/interpreter.h"
|
||||
#include "ecmascript/interpreter/slow_runtime_stub.h"
|
||||
#include "ecmascript/js_primitive_ref.h"
|
||||
#include "ecmascript/shared_objects/js_shared_array.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
#define TRACE_IC 0 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
|
||||
void ICRuntime::UpdateLoadHandler(const ObjectOperator &op, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> receiver)
|
||||
@ -152,25 +152,6 @@ void ICRuntime::UpdateStoreHandler(const ObjectOperator &op, JSHandle<JSTaggedVa
|
||||
}
|
||||
}
|
||||
|
||||
void ICRuntime::TraceIC([[maybe_unused]] JSHandle<JSTaggedValue> receiver,
|
||||
[[maybe_unused]] JSHandle<JSTaggedValue> key) const
|
||||
{
|
||||
#if TRACE_IC
|
||||
auto kind = ICKindToString(GetICKind());
|
||||
auto state = ProfileTypeAccessor::ICStateToString(icAccessor_.GetICState());
|
||||
if (key->IsString()) {
|
||||
auto keyStrHandle = JSHandle<EcmaString>::Cast(key);
|
||||
LOG_ECMA(ERROR) << kind << " miss key is: " << EcmaStringAccessor(keyStrHandle).ToCString()
|
||||
<< ", receiver is " << receiver->GetTaggedObject()->GetClass()->IsDictionaryMode()
|
||||
<< ", state is " << state;
|
||||
} else {
|
||||
LOG_ECMA(ERROR) << kind << " miss " << ", state is "
|
||||
<< ", receiver is " << receiver->GetTaggedObject()->GetClass()->IsDictionaryMode()
|
||||
<< state;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
JSTaggedValue LoadICRuntime::LoadValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key)
|
||||
{
|
||||
JSTaggedValue::RequireObjectCoercible(thread_, receiver, "Cannot load property of null or undefined");
|
||||
@ -210,7 +191,7 @@ JSTaggedValue LoadICRuntime::LoadValueMiss(JSHandle<JSTaggedValue> receiver, JSH
|
||||
icAccessor_.SetAsMega();
|
||||
return result.GetTaggedValue();
|
||||
}
|
||||
TraceIC(receiver, key);
|
||||
TraceIC(GetThread(), receiver, key);
|
||||
// do not cache element
|
||||
if (!op.IsFastMode()) {
|
||||
icAccessor_.SetAsMega();
|
||||
@ -261,7 +242,7 @@ JSTaggedValue LoadICRuntime::LoadMiss(JSHandle<JSTaggedValue> receiver, JSHandle
|
||||
icAccessor_.SetAsMega();
|
||||
return result.GetTaggedValue();
|
||||
}
|
||||
TraceIC(receiver, key);
|
||||
TraceIC(GetThread(), receiver, key);
|
||||
// do not cache element
|
||||
if (!op.IsFastMode()) {
|
||||
icAccessor_.SetAsMega();
|
||||
@ -320,7 +301,7 @@ JSTaggedValue LoadICRuntime::LoadTypedArrayValueMiss(JSHandle<JSTaggedValue> rec
|
||||
icAccessor_.SetAsMega();
|
||||
return result.GetTaggedValue();
|
||||
}
|
||||
TraceIC(receiver, key);
|
||||
TraceIC(GetThread(), receiver, key);
|
||||
// do not cache element
|
||||
if (!op.IsFastMode()) {
|
||||
icAccessor_.SetAsMega();
|
||||
@ -408,7 +389,7 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHand
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
TraceIC(receiver, key);
|
||||
TraceIC(GetThread(), receiver, key);
|
||||
if (success) {
|
||||
UpdateStoreHandler(op, key, receiver);
|
||||
}
|
||||
@ -474,7 +455,7 @@ JSTaggedValue StoreICRuntime::StoreTypedArrayValueMiss(JSHandle<JSTaggedValue> r
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
TraceIC(receiver, key);
|
||||
TraceIC(GetThread(), receiver, key);
|
||||
if (success) {
|
||||
UpdateStoreHandler(op, key, receiver);
|
||||
}
|
||||
@ -494,4 +475,56 @@ JSTaggedValue StoreICRuntime::HandleAccesor(ObjectOperator *op, const JSHandle<J
|
||||
}
|
||||
return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
|
||||
}
|
||||
|
||||
void ICRuntime::TraceIC([[maybe_unused]] JSThread *thread,
|
||||
[[maybe_unused]] JSHandle<JSTaggedValue> receiver,
|
||||
[[maybe_unused]] JSHandle<JSTaggedValue> key) const
|
||||
{
|
||||
#if ECMASCRIPT_ENABLE_TRACE_IC
|
||||
// If BackTrace affects IC, can choose not to execute it.
|
||||
std::string strTraceIC = "Miss Func BackTrace: ";
|
||||
std::vector<JsFrameInfo> jsStackInfo = JsStackInfo::BuildJsStackInfo(thread, true);
|
||||
if (jsStackInfo.empty()) {
|
||||
strTraceIC += "empty";
|
||||
} else {
|
||||
JsFrameInfo jsFrameInfo = jsStackInfo.front();
|
||||
size_t pos = jsFrameInfo.pos.find(':', 0);
|
||||
if (pos != CString::npos) {
|
||||
int lineNumber = std::stoi(jsFrameInfo.pos.substr(0, pos));
|
||||
int columnNumber = std::stoi(jsFrameInfo.pos.substr(pos + 1));
|
||||
auto sourceMapcb = thread->GetEcmaVM()->GetSourceMapTranslateCallback();
|
||||
if (sourceMapcb != nullptr && !jsFrameInfo.fileName.empty()) {
|
||||
sourceMapcb(jsFrameInfo.fileName, lineNumber, columnNumber);
|
||||
}
|
||||
}
|
||||
strTraceIC += "funcName: " + jsFrameInfo.functionName + ", url: " +
|
||||
jsFrameInfo.fileName + ":" + jsFrameInfo.pos;
|
||||
}
|
||||
LOG_ECMA(ERROR) << strTraceIC;
|
||||
|
||||
auto kind = ICKindToString(GetICKind());
|
||||
bool primitiveIc = false;
|
||||
if (receiver->IsNumber() || receiver->IsString()) {
|
||||
primitiveIc = true;
|
||||
}
|
||||
auto state = ProfileTypeAccessor::ICStateToString(icAccessor_.GetICState());
|
||||
if (key->IsString()) {
|
||||
auto keyStrHandle = JSHandle<EcmaString>::Cast(key);
|
||||
LOG_ECMA(ERROR) << kind << " miss, key is: " << EcmaStringAccessor(keyStrHandle).ToCString()
|
||||
<< ", icstate is: " << state
|
||||
<< ", slotid is: " << GetSlotId();
|
||||
} else {
|
||||
LOG_ECMA(ERROR) << kind << " miss, "
|
||||
<< ", icstate is " << state
|
||||
<< ", slotid is:" << GetSlotId();
|
||||
}
|
||||
if (primitiveIc) {
|
||||
LOG_ECMA(ERROR) << "primitiveIc ";
|
||||
} else {
|
||||
JSHClass *jshclass = receiver->GetTaggedObject()->GetClass();
|
||||
LOG_ECMA(ERROR) << "receiver DictionaryMode is: " << jshclass->IsDictionaryMode()
|
||||
<< ", hclass is: "<< std::hex << jshclass;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -57,7 +57,12 @@ public:
|
||||
return icAccessor_.GetKind();
|
||||
}
|
||||
|
||||
void TraceIC(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key) const;
|
||||
uint32_t GetSlotId() const
|
||||
{
|
||||
return icAccessor_.GetSlotId();
|
||||
}
|
||||
|
||||
void TraceIC(JSThread *thread, JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key) const;
|
||||
|
||||
protected:
|
||||
JSThread *thread_;
|
||||
|
@ -223,6 +223,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::StoreICWithHandler(JSThread *thread, JST
|
||||
INTERPRETER_TRACE(thread, StoreICWithHandler);
|
||||
if (handler.IsInt()) {
|
||||
auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler);
|
||||
HandlerBase::PrintStoreHandler(handlerInfo, std::cout);
|
||||
if (HandlerBase::IsNonSharedStoreField(handlerInfo)) {
|
||||
StoreField(thread, JSObject::Cast(receiver.GetTaggedObject()), value, handlerInfo);
|
||||
return JSTaggedValue::Undefined();
|
||||
@ -452,6 +453,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::LoadICWithHandler(JSThread *thread, JSTa
|
||||
INTERPRETER_TRACE(thread, LoadICWithHandler);
|
||||
if (LIKELY(handler.IsInt())) {
|
||||
auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler);
|
||||
HandlerBase::PrintLoadHandler(handlerInfo, std::cout);
|
||||
if (LIKELY(HandlerBase::IsField(handlerInfo))) {
|
||||
return LoadFromField(JSObject::Cast(holder.GetTaggedObject()), handlerInfo);
|
||||
}
|
||||
@ -481,6 +483,7 @@ ARK_INLINE JSTaggedValue ICRuntimeStub::LoadICWithElementHandler(JSThread *threa
|
||||
{
|
||||
if (LIKELY(handler.IsInt())) {
|
||||
auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler);
|
||||
HandlerBase::PrintLoadHandler(handlerInfo, std::cout);
|
||||
if (HandlerBase::IsNormalElement(handlerInfo)) {
|
||||
return LoadElement(JSObject::Cast(receiver.GetTaggedObject()), key);
|
||||
} else if (HandlerBase::IsTypedArrayElement(handlerInfo)) {
|
||||
@ -556,6 +559,7 @@ JSTaggedValue ICRuntimeStub::StoreElement(JSThread *thread, JSObject *receiver,
|
||||
uint32_t elementIndex = static_cast<uint32_t>(index);
|
||||
if (handler.IsInt()) {
|
||||
auto handlerInfo = JSTaggedValue::UnwrapToUint64(handler);
|
||||
HandlerBase::PrintStoreHandler(handlerInfo, std::cout);
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(thread);
|
||||
JSHandle<JSObject> receiverHandle(thread, receiver);
|
||||
JSHandle<JSTaggedValue> valueHandle(thread, value);
|
||||
|
@ -476,6 +476,11 @@ public:
|
||||
return kind_;
|
||||
}
|
||||
|
||||
uint32_t GetSlotId() const
|
||||
{
|
||||
return slotId_;
|
||||
}
|
||||
|
||||
private:
|
||||
JSThread* thread_;
|
||||
JSHandle<ProfileTypeInfo> profileTypeInfo_;
|
||||
|
@ -155,8 +155,8 @@ HWTEST_F_L0(ICRunTimeTest, TraceIC)
|
||||
JSHandle<ProfileTypeInfo> handleProfileTypeInfo = factory->NewProfileTypeInfo(arrayLength);
|
||||
|
||||
ICRuntime icRuntime(thread, handleProfileTypeInfo, 4, ICKind::NamedGlobalLoadIC); // 4: means the NamedGlobalLoadIC
|
||||
icRuntime.TraceIC(handleReceiver, handleKeyWithString);
|
||||
icRuntime.TraceIC(handleReceiver, handleKeyWithElement);
|
||||
icRuntime.TraceIC(thread, handleReceiver, handleKeyWithString);
|
||||
icRuntime.TraceIC(thread, handleReceiver, handleKeyWithElement);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(ICRunTimeTest, StoreMiss)
|
||||
|
Loading…
Reference in New Issue
Block a user