mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 10:09:54 +00:00
!7479 五大项整改::HeapSnapshot::GenerateNode();Elements::MigrateArrayWithKind();StoreICRuntime::StoreMiss();JITProfiler::ConvertICByNameWithHandler()
Merge pull request !7479 from 杨云飞/master
This commit is contained in:
commit
cd4448e45b
@ -658,6 +658,88 @@ void HeapSnapshot::FillNodes(bool isInFinish, bool isSimplify)
|
||||
}
|
||||
}
|
||||
|
||||
Node *HeapSnapshot::HandleStringNode(JSTaggedValue &entry, size_t &size, bool &isInFinish)
|
||||
{
|
||||
Node* node = nullptr;
|
||||
if (isPrivate_) {
|
||||
node = GeneratePrivateStringNode(size);
|
||||
} else {
|
||||
node = GenerateStringNode(entry, size, isInFinish);
|
||||
}
|
||||
if (node == nullptr) {
|
||||
LOG_ECMA(ERROR) << "string node nullptr";
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *HeapSnapshot::HandleFunctionNode(JSTaggedValue &entry, size_t &size, bool &isInFinish)
|
||||
{
|
||||
Node* node = GenerateFunctionNode(entry, size, isInFinish);
|
||||
if (node == nullptr) {
|
||||
LOG_ECMA(ERROR) << "function node nullptr";
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *HeapSnapshot::HandleObjectNode(JSTaggedValue &entry, size_t &size, bool &isInFinish)
|
||||
{
|
||||
Node* node = GenerateObjectNode(entry, size, isInFinish);
|
||||
if (node == nullptr) {
|
||||
LOG_ECMA(ERROR) << "object node nullptr";
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
Node *HeapSnapshot::HandleBaseClassNode(size_t size, bool idExist, unsigned int &sequenceId,
|
||||
TaggedObject* obj, JSTaggedType &addr)
|
||||
{
|
||||
size_t selfSize = (size != 0) ? size : obj->GetClass()->SizeFromJSHClass(obj);
|
||||
size_t nativeSize = 0;
|
||||
if (obj->GetClass()->IsJSNativePointer()) {
|
||||
nativeSize = JSNativePointer::Cast(obj)->GetBindingSize();
|
||||
}
|
||||
Node* node = Node::NewNode(chunk_, sequenceId, nodeCount_, GenerateNodeName(obj), GenerateNodeType(obj),
|
||||
selfSize, nativeSize, addr);
|
||||
entryMap_.InsertEntry(node);
|
||||
if (!idExist) {
|
||||
entryIdMap_->InsertId(addr, sequenceId);
|
||||
}
|
||||
InsertNodeUnique(node);
|
||||
ASSERT(entryMap_.FindEntry(node->GetAddress())->GetAddress() == node->GetAddress());
|
||||
return node;
|
||||
}
|
||||
|
||||
CString HeapSnapshot::GeneratePrimitiveNameString(JSTaggedValue &entry)
|
||||
{
|
||||
CString primitiveName;
|
||||
if (entry.IsInt()) {
|
||||
primitiveName.append("Int:");
|
||||
if (!isPrivate_) {
|
||||
primitiveName.append(ToCString(entry.GetInt()));
|
||||
}
|
||||
} else if (entry.IsDouble()) {
|
||||
primitiveName.append("Double:");
|
||||
if (!isPrivate_) {
|
||||
primitiveName.append(FloatToCString(entry.GetDouble()));
|
||||
}
|
||||
} else if (entry.IsHole()) {
|
||||
primitiveName.append("Hole");
|
||||
} else if (entry.IsNull()) {
|
||||
primitiveName.append("Null");
|
||||
} else if (entry.IsTrue()) {
|
||||
primitiveName.append("Boolean:true");
|
||||
} else if (entry.IsFalse()) {
|
||||
primitiveName.append("Boolean:false");
|
||||
} else if (entry.IsException()) {
|
||||
primitiveName.append("Exception");
|
||||
} else if (entry.IsUndefined()) {
|
||||
primitiveName.append("Undefined");
|
||||
} else {
|
||||
primitiveName.append("Illegal_Primitive");
|
||||
}
|
||||
return primitiveName;
|
||||
}
|
||||
|
||||
Node *HeapSnapshot::GenerateNode(JSTaggedValue entry, size_t size, bool isInFinish, bool isSimplify)
|
||||
{
|
||||
Node *node = nullptr;
|
||||
@ -666,29 +748,13 @@ Node *HeapSnapshot::GenerateNode(JSTaggedValue entry, size_t size, bool isInFini
|
||||
entry.RemoveWeakTag();
|
||||
}
|
||||
if (entry.IsString()) {
|
||||
if (isPrivate_) {
|
||||
node = GeneratePrivateStringNode(size);
|
||||
} else {
|
||||
node = GenerateStringNode(entry, size, isInFinish);
|
||||
}
|
||||
if (node == nullptr) {
|
||||
LOG_ECMA(ERROR) << "string node nullptr";
|
||||
}
|
||||
return node;
|
||||
return HandleStringNode(entry, size, isInFinish);
|
||||
}
|
||||
if (entry.IsJSFunction()) {
|
||||
node = GenerateFunctionNode(entry, size, isInFinish);
|
||||
if (node == nullptr) {
|
||||
LOG_ECMA(ERROR) << "function node nullptr";
|
||||
}
|
||||
return node;
|
||||
return HandleFunctionNode(entry, size, isInFinish);
|
||||
}
|
||||
if (entry.IsOnlyJSObject()) {
|
||||
node = GenerateObjectNode(entry, size, isInFinish);
|
||||
if (node == nullptr) {
|
||||
LOG_ECMA(ERROR) << "function node nullptr";
|
||||
}
|
||||
return node;
|
||||
return HandleObjectNode(entry, size, isInFinish);
|
||||
}
|
||||
TaggedObject *obj = entry.GetTaggedObject();
|
||||
auto *baseClass = obj->GetClass();
|
||||
@ -697,59 +763,17 @@ Node *HeapSnapshot::GenerateNode(JSTaggedValue entry, size_t size, bool isInFini
|
||||
Node *existNode = entryMap_.FindEntry(addr); // Fast Index
|
||||
auto [idExist, sequenceId] = entryIdMap_->FindId(addr);
|
||||
if (existNode == nullptr) {
|
||||
size_t selfSize = (size != 0) ? size : obj->GetClass()->SizeFromJSHClass(obj);
|
||||
size_t nativeSize = 0;
|
||||
if (obj->GetClass()->IsJSNativePointer()) {
|
||||
nativeSize = JSNativePointer::Cast(obj)->GetBindingSize();
|
||||
}
|
||||
node = Node::NewNode(chunk_, sequenceId, nodeCount_, GenerateNodeName(obj), GenerateNodeType(obj),
|
||||
selfSize, nativeSize, addr);
|
||||
entryMap_.InsertEntry(node);
|
||||
if (!idExist) {
|
||||
entryIdMap_->InsertId(addr, sequenceId);
|
||||
}
|
||||
InsertNodeUnique(node);
|
||||
ASSERT(entryMap_.FindEntry(node->GetAddress())->GetAddress() == node->GetAddress());
|
||||
return node;
|
||||
return HandleBaseClassNode(size, idExist, sequenceId, obj, addr);
|
||||
} else {
|
||||
existNode->SetLive(true);
|
||||
return existNode;
|
||||
}
|
||||
}
|
||||
} else if (!isSimplify) {
|
||||
CString primitiveName;
|
||||
if (entry.IsInt()) {
|
||||
if (!captureNumericValue_) {
|
||||
if ((entry.IsInt() || entry.IsDouble()) && !captureNumericValue_) {
|
||||
return nullptr;
|
||||
}
|
||||
primitiveName.append("Int:");
|
||||
if (!isPrivate_) {
|
||||
primitiveName.append(ToCString(entry.GetInt()));
|
||||
}
|
||||
} else if (entry.IsDouble()) {
|
||||
if (!captureNumericValue_) {
|
||||
return nullptr;
|
||||
}
|
||||
primitiveName.append("Double:");
|
||||
if (!isPrivate_) {
|
||||
primitiveName.append(FloatToCString(entry.GetDouble()));
|
||||
}
|
||||
} else if (entry.IsHole()) {
|
||||
primitiveName.append("Hole");
|
||||
} else if (entry.IsNull()) {
|
||||
primitiveName.append("Null");
|
||||
} else if (entry.IsTrue()) {
|
||||
primitiveName.append("Boolean:true");
|
||||
} else if (entry.IsFalse()) {
|
||||
primitiveName.append("Boolean:false");
|
||||
} else if (entry.IsException()) {
|
||||
primitiveName.append("Exception");
|
||||
} else if (entry.IsUndefined()) {
|
||||
primitiveName.append("Undefined");
|
||||
} else {
|
||||
primitiveName.append("Illegal_Primitive");
|
||||
}
|
||||
|
||||
CString primitiveName = GeneratePrimitiveNameString(entry);
|
||||
// A primitive value with tag will be regarded as a pointer
|
||||
JSTaggedType addr = entry.GetRawData();
|
||||
Node *existNode = entryMap_.FindEntry(addr);
|
||||
|
@ -500,6 +500,12 @@ private:
|
||||
void FillNodes(bool isInFinish = false, bool isSimplify = false);
|
||||
Node *GenerateNode(JSTaggedValue entry, size_t size = 0,
|
||||
bool isInFinish = false, bool isSimplify = false);
|
||||
Node *HandleStringNode(JSTaggedValue &entry, size_t &size, bool &isInFinish);
|
||||
Node *HandleFunctionNode(JSTaggedValue &entry, size_t &size, bool &isInFinish);
|
||||
Node *HandleObjectNode(JSTaggedValue &entry, size_t &size, bool &isInFinish);
|
||||
Node *HandleBaseClassNode(size_t size, bool idExist, unsigned int &sequenceId,
|
||||
TaggedObject* obj, JSTaggedType &addr);
|
||||
CString GeneratePrimitiveNameString(JSTaggedValue &entry);
|
||||
Node *GeneratePrivateStringNode(size_t size);
|
||||
Node *GenerateStringNode(JSTaggedValue entry, size_t size, bool isInFinish = false);
|
||||
Node *GenerateFunctionNode(JSTaggedValue entry, size_t size, bool isInFinish = false);
|
||||
|
@ -153,47 +153,73 @@ ElementsKind Elements::ToElementsKind(JSTaggedValue value, ElementsKind kind)
|
||||
return MergeElementsKind(valueKind, kind);
|
||||
}
|
||||
|
||||
void Elements::HandleIntKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||
const ElementsKind newKind, bool needCOW)
|
||||
{
|
||||
if (IsStringOrNoneOrHole(newKind)) {
|
||||
JSTaggedValue newElements = MigrateFromRawValueToHeapValue(thread, object, needCOW, true);
|
||||
object->SetElements(thread, newElements);
|
||||
} else if (newKind == ElementsKind::NUMBER || newKind == ElementsKind::HOLE_NUMBER) {
|
||||
MigrateFromHoleIntToHoleNumber(thread, object);
|
||||
}
|
||||
}
|
||||
|
||||
bool Elements::IsNumberKind(const ElementsKind kind)
|
||||
{
|
||||
return static_cast<uint32_t>(kind) >= static_cast<uint32_t>(ElementsKind::NUMBER) &&
|
||||
static_cast<uint32_t>(kind) <= static_cast<uint32_t>(ElementsKind::HOLE_NUMBER);
|
||||
}
|
||||
|
||||
bool Elements::IsStringOrNoneOrHole(const ElementsKind kind)
|
||||
{
|
||||
return static_cast<uint32_t>(kind) >= static_cast<uint32_t>(ElementsKind::STRING) ||
|
||||
kind == ElementsKind::NONE || kind == ElementsKind::HOLE;
|
||||
}
|
||||
|
||||
void Elements::HandleNumberKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||
const ElementsKind newKind, bool needCOW)
|
||||
{
|
||||
if (IsStringOrNoneOrHole(newKind)) {
|
||||
JSTaggedValue newElements = MigrateFromRawValueToHeapValue(thread, object, needCOW, false);
|
||||
object->SetElements(thread, newElements);
|
||||
} else if (newKind == ElementsKind::INT || newKind == ElementsKind::HOLE_INT) {
|
||||
MigrateFromHoleNumberToHoleInt(thread, object);
|
||||
}
|
||||
}
|
||||
|
||||
void Elements::HandleOtherKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||
const ElementsKind newKind, bool needCOW)
|
||||
{
|
||||
if (newKind == ElementsKind::INT || newKind == ElementsKind::HOLE_INT) {
|
||||
JSTaggedValue newElements = MigrateFromHeapValueToRawValue(thread, object, needCOW, true);
|
||||
object->SetElements(thread, newElements);
|
||||
} else if (IsNumberKind(newKind)) {
|
||||
JSTaggedValue newElements = MigrateFromHeapValueToRawValue(thread, object, needCOW, false);
|
||||
object->SetElements(thread, newElements);
|
||||
}
|
||||
}
|
||||
|
||||
void Elements::MigrateArrayWithKind(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||
const ElementsKind oldKind, const ElementsKind newKind)
|
||||
{
|
||||
if (!thread->GetEcmaVM()->IsEnableElementsKind()) {
|
||||
return;
|
||||
}
|
||||
if (oldKind == newKind) {
|
||||
return;
|
||||
}
|
||||
// When create ArrayLiteral from constantPool, we need to preserve the COW property if necessary.
|
||||
// When transition happens to Array, e.g. arr.x = 1, we need to preserve the COW property if necessary.
|
||||
bool needCOW = object->GetElements().IsCOWArray();
|
||||
if ((oldKind == ElementsKind::INT && newKind == ElementsKind::HOLE_INT) ||
|
||||
|
||||
if (oldKind == newKind ||
|
||||
(oldKind == ElementsKind::INT && newKind == ElementsKind::HOLE_INT) ||
|
||||
(oldKind == ElementsKind::NUMBER && newKind == ElementsKind::HOLE_NUMBER)) {
|
||||
return;
|
||||
} else if (oldKind == ElementsKind::INT || oldKind == ElementsKind::HOLE_INT) {
|
||||
if (static_cast<uint32_t>(newKind) >= static_cast<uint32_t>(ElementsKind::STRING) ||
|
||||
newKind == ElementsKind::NONE || newKind == ElementsKind::HOLE) {
|
||||
JSTaggedValue newElements = MigrateFromRawValueToHeapValue(thread, object, needCOW, true);
|
||||
object->SetElements(thread, newElements);
|
||||
} else if (newKind == ElementsKind::NUMBER || newKind == ElementsKind::HOLE_NUMBER) {
|
||||
MigrateFromHoleIntToHoleNumber(thread, object);
|
||||
}
|
||||
} else if (static_cast<uint32_t>(oldKind) >= static_cast<uint32_t>(ElementsKind::NUMBER) &&
|
||||
static_cast<uint32_t>(oldKind) <= static_cast<uint32_t>(ElementsKind::HOLE_NUMBER)) {
|
||||
if (static_cast<uint32_t>(newKind) >= static_cast<uint32_t>(ElementsKind::STRING) ||
|
||||
newKind == ElementsKind::NONE || newKind == ElementsKind::HOLE) {
|
||||
JSTaggedValue newElements = MigrateFromRawValueToHeapValue(thread, object, needCOW, false);
|
||||
object->SetElements(thread, newElements);
|
||||
} else if (newKind == ElementsKind::INT || newKind == ElementsKind::HOLE_INT) {
|
||||
MigrateFromHoleNumberToHoleInt(thread, object);
|
||||
}
|
||||
}
|
||||
|
||||
bool needCOW = object->GetElements().IsCOWArray();
|
||||
|
||||
if (oldKind == ElementsKind::INT || oldKind == ElementsKind::HOLE_INT) {
|
||||
HandleIntKindMigration(thread, object, newKind, needCOW);
|
||||
} else if ((IsNumberKind(oldKind))) {
|
||||
HandleNumberKindMigration(thread, object, newKind, needCOW);
|
||||
} else {
|
||||
if (newKind == ElementsKind::INT || newKind == ElementsKind::HOLE_INT) {
|
||||
JSTaggedValue newElements = MigrateFromHeapValueToRawValue(thread, object, needCOW, true);
|
||||
object->SetElements(thread, newElements);
|
||||
} else if (static_cast<uint32_t>(newKind) >= static_cast<uint32_t>(ElementsKind::NUMBER) &&
|
||||
static_cast<uint32_t>(newKind) <= static_cast<uint32_t>(ElementsKind::HOLE_NUMBER)) {
|
||||
JSTaggedValue newElements = MigrateFromHeapValueToRawValue(thread, object, needCOW, false);
|
||||
object->SetElements(thread, newElements);
|
||||
}
|
||||
HandleOtherKindMigration(thread, object, newKind, needCOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,15 @@ public:
|
||||
private:
|
||||
static JSTaggedValue MigrateFromRawValueToHeapValue(const JSThread *thread, const JSHandle<JSObject> object,
|
||||
bool needCOW, bool isIntKind);
|
||||
static void HandleIntKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||
const ElementsKind newKind, bool needCOW);
|
||||
static bool IsNumberKind(const ElementsKind kind);
|
||||
static bool IsStringOrNoneOrHole(const ElementsKind kind);
|
||||
static void HandleNumberKindMigration(const JSThread *thread,
|
||||
const JSHandle<JSObject> &object,
|
||||
const ElementsKind newKind, bool needCOW);
|
||||
static void HandleOtherKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
|
||||
const ElementsKind newKind, bool needCOW);
|
||||
static JSTaggedValue MigrateFromHeapValueToRawValue(const JSThread *thread, const JSHandle<JSObject> object,
|
||||
bool needCOW, bool isIntKind);
|
||||
static void MigrateFromHoleIntToHoleNumber(const JSThread *thread, const JSHandle<JSObject> object);
|
||||
|
@ -333,59 +333,55 @@ JSTaggedValue LoadICRuntime::LoadTypedArrayValueMiss(JSHandle<JSTaggedValue> rec
|
||||
}
|
||||
}
|
||||
|
||||
JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value, bool isOwn)
|
||||
JSTaggedValue StoreICRuntime::HandleOrdinarySet(JSHandle<JSTaggedValue> &receiver,
|
||||
JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
ICKind kind = GetICKind();
|
||||
if (IsValueIC(kind)) {
|
||||
key = JSTaggedValue::ToPropertyKey(GetThread(), key);
|
||||
}
|
||||
if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) {
|
||||
icAccessor_.SetAsMega();
|
||||
bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
|
||||
}
|
||||
if (receiver->IsTypedArray() || receiver->IsSharedTypedArray()) {
|
||||
return StoreTypedArrayValueMiss(receiver, key, value);
|
||||
}
|
||||
|
||||
// global variable find from global record firstly
|
||||
if (kind == ICKind::NamedGlobalStoreIC || kind == ICKind::NamedGlobalTryStoreIC) {
|
||||
JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue());
|
||||
if (!box.IsUndefined()) {
|
||||
ASSERT(box.IsPropertyBox());
|
||||
SlowRuntimeStub::TryUpdateGlobalRecord(thread_, key.GetTaggedValue(), value.GetTaggedValue());
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
if (icAccessor_.GetICState() != ProfileTypeAccessor::ICState::MEGA) {
|
||||
icAccessor_.AddGlobalRecordHandler(JSHandle<JSTaggedValue>(thread_, box));
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
}
|
||||
UpdateReceiverHClass(JSHandle<JSTaggedValue>(GetThread(), JSHandle<JSObject>::Cast(receiver)->GetClass()));
|
||||
icAccessor_.SetAsMega();
|
||||
bool success = JSTaggedValue::SetProperty(GetThread(), receiver, key, value, true);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
|
||||
}
|
||||
|
||||
// fixme(hzzhouzebin) Open IC for SharedArray later.
|
||||
if (receiver->IsJSSharedArray()) {
|
||||
bool success = JSSharedArray::SetProperty(thread_, receiver, key, value, true, SCheckMode::CHECK);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
if (success) {
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
return JSTaggedValue::Exception();
|
||||
JSTaggedValue StoreICRuntime::HandleGlobalStoreIC(JSTaggedValue &box, JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
ASSERT(box.IsPropertyBox());
|
||||
SlowRuntimeStub::TryUpdateGlobalRecord(thread_, key.GetTaggedValue(), value.GetTaggedValue());
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
if (icAccessor_.GetICState() != ProfileTypeAccessor::ICState::MEGA) {
|
||||
icAccessor_.AddGlobalRecordHandler(JSHandle<JSTaggedValue>(thread_, box));
|
||||
}
|
||||
return JSTaggedValue::Undefined();
|
||||
}
|
||||
|
||||
if (key->IsJSFunction()) { // key is a private setter
|
||||
JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo* info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread_, key, receiver, undefined, 1); // 1: setter has 1 argument
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
info->SetCallArg(value.GetTaggedValue());
|
||||
JSTaggedValue resSetter = JSFunction::Call(info);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
return resSetter;
|
||||
}
|
||||
JSTaggedValue StoreICRuntime::HandleSharedArraySet(JSHandle<JSTaggedValue> &receiver,
|
||||
JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
bool success = JSSharedArray::SetProperty(thread_, receiver, key, value, true, SCheckMode::CHECK);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
return success ? JSTaggedValue::Undefined() : JSTaggedValue::Exception();
|
||||
}
|
||||
|
||||
JSTaggedValue StoreICRuntime::HandlePrivateSetter(JSHandle<JSTaggedValue> &receiver,
|
||||
JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value)
|
||||
{
|
||||
JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
|
||||
EcmaRuntimeCallInfo* info =
|
||||
EcmaInterpreter::NewRuntimeCallInfo(thread_, key, receiver, undefined, 1); // 1: setter has 1 argument
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
info->SetCallArg(value.GetTaggedValue());
|
||||
JSTaggedValue resSetter = JSFunction::Call(info);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
return resSetter;
|
||||
}
|
||||
|
||||
JSTaggedValue StoreICRuntime::HandlePropertySet(JSHandle<JSTaggedValue> receiver,
|
||||
JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value, bool isOwn, ICKind kind)
|
||||
{
|
||||
ObjectOperator op = ConstructOp(receiver, key, value, isOwn);
|
||||
if (!op.IsFound()) {
|
||||
if (kind == ICKind::NamedGlobalStoreIC) {
|
||||
@ -395,6 +391,7 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHand
|
||||
return SlowRuntimeStub::ThrowReferenceError(GetThread(), key.GetTaggedValue(), " is not defined");
|
||||
}
|
||||
}
|
||||
|
||||
bool success = JSObject::SetProperty(&op, value, true);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_);
|
||||
// ic-switch
|
||||
@ -418,6 +415,39 @@ JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHand
|
||||
return JSTaggedValue::Exception();
|
||||
}
|
||||
|
||||
JSTaggedValue StoreICRuntime::StoreMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value, bool isOwn)
|
||||
{
|
||||
ICKind kind = GetICKind();
|
||||
if (IsValueIC(kind)) {
|
||||
key = JSTaggedValue::ToPropertyKey(GetThread(), key);
|
||||
}
|
||||
if (!receiver->IsJSObject() || receiver->HasOrdinaryGet()) {
|
||||
return HandleOrdinarySet(receiver, key, value);
|
||||
}
|
||||
if (receiver->IsTypedArray() || receiver->IsSharedTypedArray()) {
|
||||
return StoreTypedArrayValueMiss(receiver, key, value);
|
||||
}
|
||||
|
||||
// global variable find from global record firstly
|
||||
if (kind == ICKind::NamedGlobalStoreIC || kind == ICKind::NamedGlobalTryStoreIC) {
|
||||
JSTaggedValue box = SlowRuntimeStub::LdGlobalRecord(thread_, key.GetTaggedValue());
|
||||
if (!box.IsUndefined()) {
|
||||
return HandleGlobalStoreIC(box, key, value);
|
||||
}
|
||||
}
|
||||
UpdateReceiverHClass(JSHandle<JSTaggedValue>(GetThread(), JSHandle<JSObject>::Cast(receiver)->GetClass()));
|
||||
|
||||
// fixme(hzzhouzebin) Open IC for SharedArray later.
|
||||
if (receiver->IsJSSharedArray()) {
|
||||
return HandleSharedArraySet(receiver, key, value);
|
||||
}
|
||||
if (key->IsJSFunction()) { // key is a private setter
|
||||
return HandlePrivateSetter(receiver, key, value);
|
||||
}
|
||||
return HandlePropertySet(receiver, key, value, isOwn, kind);
|
||||
}
|
||||
|
||||
JSTaggedValue StoreICRuntime::StoreTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value)
|
||||
{
|
||||
|
@ -106,6 +106,21 @@ public:
|
||||
|
||||
JSTaggedValue StoreTypedArrayValueMiss(JSHandle<JSTaggedValue> receiver, JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value);
|
||||
private:
|
||||
JSTaggedValue HandleOrdinarySet(JSHandle<JSTaggedValue> &receiver,
|
||||
JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value);
|
||||
JSTaggedValue HandleGlobalStoreIC(JSTaggedValue &box, JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value);
|
||||
JSTaggedValue HandleSharedArraySet(JSHandle<JSTaggedValue> &receiver,
|
||||
JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value);
|
||||
JSTaggedValue HandlePrivateSetter(JSHandle<JSTaggedValue> &receiver,
|
||||
JSHandle<JSTaggedValue> &key,
|
||||
JSHandle<JSTaggedValue> &value);
|
||||
JSTaggedValue HandlePropertySet(JSHandle<JSTaggedValue> receiver,
|
||||
JSHandle<JSTaggedValue> key,
|
||||
JSHandle<JSTaggedValue> value, bool isOwn, ICKind kind);
|
||||
};
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -375,98 +375,147 @@ void JITProfiler::ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type
|
||||
}
|
||||
|
||||
void JITProfiler::ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue secondValue, BCType type)
|
||||
JSHClass *hclass,
|
||||
JSTaggedValue secondValue, BCType type)
|
||||
{
|
||||
if (type == BCType::LOAD) {
|
||||
if (secondValue.IsInt()) {
|
||||
auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
|
||||
if (HandlerBase::IsNonExist(handlerInfo)) {
|
||||
return;
|
||||
}
|
||||
if (HandlerBase::IsField(handlerInfo) || HandlerBase::IsAccessor(handlerInfo)) {
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
|
||||
}
|
||||
AddBuiltinsInfoByNameInInstance(abcId, bcOffset, hclass);
|
||||
} else if (secondValue.IsPrototypeHandler()) {
|
||||
auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = prototypeHandler->GetProtoCell();
|
||||
if (cellValue.IsUndefined()) {
|
||||
return;
|
||||
}
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto holder = prototypeHandler->GetHolder();
|
||||
auto holderHClass = holder.GetTaggedObject()->GetClass();
|
||||
JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo();
|
||||
if (!handlerInfoVal.IsInt()) {
|
||||
return;
|
||||
}
|
||||
auto handlerInfo = static_cast<uint32_t>(handlerInfoVal.GetInt());
|
||||
if (HandlerBase::IsNonExist(handlerInfo)) {
|
||||
return;
|
||||
}
|
||||
auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
|
||||
if (!AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId)) {
|
||||
return AddBuiltinsInfoByNameInProt(abcId, bcOffset, hclass, holderHClass);
|
||||
}
|
||||
}
|
||||
HandleLoadType(abcId, bcOffset, hclass, secondValue);
|
||||
// LoadGlobal
|
||||
return;
|
||||
}
|
||||
HandleOtherTypes(abcId, bcOffset, hclass, secondValue);
|
||||
}
|
||||
|
||||
void JITProfiler::HandleLoadType(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
if (secondValue.IsInt()) {
|
||||
HandleLoadTypeInt(abcId, bcOffset, hclass, secondValue);
|
||||
} else if (secondValue.IsPrototypeHandler()) {
|
||||
HandleLoadTypePrototypeHandler(abcId, bcOffset, hclass, secondValue);
|
||||
}
|
||||
}
|
||||
|
||||
void JITProfiler::HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
auto handlerInfo = static_cast<uint32_t>(secondValue.GetInt());
|
||||
if (HandlerBase::IsNonExist(handlerInfo)) {
|
||||
return;
|
||||
}
|
||||
if (HandlerBase::IsField(handlerInfo) || HandlerBase::IsAccessor(handlerInfo)) {
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
|
||||
}
|
||||
AddBuiltinsInfoByNameInInstance(abcId, bcOffset, hclass);
|
||||
}
|
||||
|
||||
void JITProfiler::HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = prototypeHandler->GetProtoCell();
|
||||
if (cellValue.IsUndefined()) {
|
||||
return;
|
||||
}
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto holder = prototypeHandler->GetHolder();
|
||||
auto holderHClass = holder.GetTaggedObject()->GetClass();
|
||||
JSTaggedValue handlerInfoVal = prototypeHandler->GetHandlerInfo();
|
||||
if (!handlerInfoVal.IsInt()) {
|
||||
return;
|
||||
}
|
||||
auto handlerInfo = static_cast<uint32_t>(handlerInfoVal.GetInt());
|
||||
if (HandlerBase::IsNonExist(handlerInfo)) {
|
||||
return;
|
||||
}
|
||||
auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
|
||||
if (!AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId)) {
|
||||
return AddBuiltinsInfoByNameInProt(abcId, bcOffset, hclass, holderHClass);
|
||||
}
|
||||
}
|
||||
|
||||
void JITProfiler::HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
if (secondValue.IsInt()) {
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, hclass);
|
||||
} else if (secondValue.IsTransitionHandler()) {
|
||||
auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto transitionHClassVal = transitionHandler->GetTransitionHClass();
|
||||
if (transitionHClassVal.IsJSHClass()) {
|
||||
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
|
||||
}
|
||||
HandleTransitionHandler(abcId, bcOffset, hclass, secondValue);
|
||||
} else if (secondValue.IsTransWithProtoHandler()) {
|
||||
auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = transWithProtoHandler->GetProtoCell();
|
||||
ASSERT(cellValue.IsProtoChangeMarker());
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass();
|
||||
if (transitionHClassVal.IsJSHClass()) {
|
||||
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
|
||||
}
|
||||
HandleTransWithProtoHandler(abcId, bcOffset, hclass, secondValue);
|
||||
} else if (secondValue.IsPrototypeHandler()) {
|
||||
auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = prototypeHandler->GetProtoCell();
|
||||
if (cellValue.IsUndefined()) {
|
||||
return;
|
||||
}
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto holder = prototypeHandler->GetHolder();
|
||||
auto holderHClass = holder.GetTaggedObject()->GetClass();
|
||||
auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
|
||||
AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId);
|
||||
HandleOtherTypesPrototypeHandler(abcId, bcOffset, hclass, secondValue);
|
||||
} else if (secondValue.IsPropertyBox()) {
|
||||
// StoreGlobal
|
||||
} else if (secondValue.IsStoreTSHandler()) {
|
||||
StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = storeTSHandler->GetProtoCell();
|
||||
ASSERT(cellValue.IsProtoChangeMarker());
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto holder = storeTSHandler->GetHolder();
|
||||
auto holderHClass = holder.GetTaggedObject()->GetClass();
|
||||
AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass);
|
||||
HandleStoreTSHandler(abcId, bcOffset, hclass, secondValue);
|
||||
}
|
||||
}
|
||||
|
||||
void JITProfiler::HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
auto transitionHandler = TransitionHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto transitionHClassVal = transitionHandler->GetTransitionHClass();
|
||||
if (transitionHClassVal.IsJSHClass()) {
|
||||
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
|
||||
}
|
||||
}
|
||||
|
||||
void JITProfiler::HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
auto transWithProtoHandler = TransWithProtoHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = transWithProtoHandler->GetProtoCell();
|
||||
ASSERT(cellValue.IsProtoChangeMarker());
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto transitionHClassVal = transWithProtoHandler->GetTransitionHClass();
|
||||
if (transitionHClassVal.IsJSHClass()) {
|
||||
auto transitionHClass = JSHClass::Cast(transitionHClassVal.GetTaggedObject());
|
||||
AddObjectInfo(abcId, bcOffset, hclass, hclass, transitionHClass);
|
||||
}
|
||||
}
|
||||
|
||||
void JITProfiler::HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
auto prototypeHandler = PrototypeHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = prototypeHandler->GetProtoCell();
|
||||
if (cellValue.IsUndefined()) {
|
||||
return;
|
||||
}
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto holder = prototypeHandler->GetHolder();
|
||||
auto holderHClass = holder.GetTaggedObject()->GetClass();
|
||||
auto accessorMethodId = prototypeHandler->GetAccessorMethodId();
|
||||
AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass, accessorMethodId);
|
||||
}
|
||||
|
||||
void JITProfiler::HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue)
|
||||
{
|
||||
StoreTSHandler *storeTSHandler = StoreTSHandler::Cast(secondValue.GetTaggedObject());
|
||||
auto cellValue = storeTSHandler->GetProtoCell();
|
||||
ASSERT(cellValue.IsProtoChangeMarker());
|
||||
ProtoChangeMarker *cell = ProtoChangeMarker::Cast(cellValue.GetTaggedObject());
|
||||
if (cell->GetHasChanged()) {
|
||||
return;
|
||||
}
|
||||
auto holder = storeTSHandler->GetHolder();
|
||||
auto holderHClass = holder.GetTaggedObject()->GetClass();
|
||||
AddObjectInfo(abcId, bcOffset, hclass, holderHClass, holderHClass);
|
||||
}
|
||||
|
||||
void JITProfiler::ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type)
|
||||
{
|
||||
if (cacheValue.IsWeak()) {
|
||||
|
@ -88,6 +88,22 @@ private:
|
||||
void ConvertICByName(int32_t bcOffset, uint32_t slotId, BCType type);
|
||||
void ConvertICByNameWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass,
|
||||
JSTaggedValue secondValue, BCType type);
|
||||
void HandleLoadType(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleLoadTypeInt(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleLoadTypePrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleOtherTypes(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleTransitionHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleTransWithProtoHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleOtherTypesPrototypeHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void HandleStoreTSHandler(ApEntityId &abcId, int32_t &bcOffset,
|
||||
JSHClass *hclass, JSTaggedValue &secondValue);
|
||||
void ConvertICByNameWithPoly(ApEntityId abcId, int32_t bcOffset, JSTaggedValue cacheValue, BCType type);
|
||||
void ConvertICByValue(int32_t bcOffset, uint32_t slotId, BCType type);
|
||||
void ConvertICByValueWithHandler(ApEntityId abcId, int32_t bcOffset, JSHClass *hclass,
|
||||
|
Loading…
Reference in New Issue
Block a user