14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_JS_HCLASS_INL_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_JS_HCLASS_INL_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/js_hclass.h" 204514f5e3Sopenharmony_ci 214514f5e3Sopenharmony_ci#include "ecmascript/js_bigint.h" 224514f5e3Sopenharmony_ci#include "ecmascript/layout_info.h" 234514f5e3Sopenharmony_ci#include "ecmascript/layout_info-inl.h" 244514f5e3Sopenharmony_ci#include "ecmascript/byte_array.h" 254514f5e3Sopenharmony_ci#include "ecmascript/mem/assert_scope.h" 264514f5e3Sopenharmony_ci#include "ecmascript/transitions_dictionary.h" 274514f5e3Sopenharmony_ci 284514f5e3Sopenharmony_cinamespace panda::ecmascript { 294514f5e3Sopenharmony_ci 304514f5e3Sopenharmony_cibool JSHClass::ProtoIsFastJSArray(const JSThread *thread, const JSHandle<JSTaggedValue> proto, 314514f5e3Sopenharmony_ci const JSHandle<JSHClass> hclass) 324514f5e3Sopenharmony_ci{ 334514f5e3Sopenharmony_ci // Since we currently only support ElementsKind for JSArray initial hclass, 344514f5e3Sopenharmony_ci // if an object's hclass has a non-generic ElementsKind, it must be one of the JSArray initial hclass. 354514f5e3Sopenharmony_ci // if an object's hclass has a Generic ElementsKind, it might be the JSArray initial generic elementskind hclass, 364514f5e3Sopenharmony_ci // which therefore needs further hclass comparison. 374514f5e3Sopenharmony_ci if (proto->IsJSArray()) { 384514f5e3Sopenharmony_ci JSTaggedValue genericArrayHClass = thread->GlobalConstants()->GetElementHoleTaggedClass(); 394514f5e3Sopenharmony_ci if (!Elements::IsGeneric(hclass->GetElementsKind()) || hclass.GetTaggedValue() == genericArrayHClass) { 404514f5e3Sopenharmony_ci return true; 414514f5e3Sopenharmony_ci } 424514f5e3Sopenharmony_ci } 434514f5e3Sopenharmony_ci return false; 444514f5e3Sopenharmony_ci} 454514f5e3Sopenharmony_ci 464514f5e3Sopenharmony_civoid JSHClass::AddTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, const JSHandle<JSHClass> &child, 474514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &key, PropertyAttributes attributes) 484514f5e3Sopenharmony_ci{ 494514f5e3Sopenharmony_ci UpdateRootHClass(thread, parent, child); 504514f5e3Sopenharmony_ci JSTaggedValue transitions = parent->GetTransitions(); 514514f5e3Sopenharmony_ci if (transitions.IsUndefined()) { 524514f5e3Sopenharmony_ci JSTaggedValue weakChild = JSTaggedValue(child.GetTaggedValue().CreateAndGetWeakRef()); 534514f5e3Sopenharmony_ci parent->SetTransitions(thread, weakChild); 544514f5e3Sopenharmony_ci return; 554514f5e3Sopenharmony_ci } 564514f5e3Sopenharmony_ci JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined()); 574514f5e3Sopenharmony_ci if (transitions.IsWeak()) { 584514f5e3Sopenharmony_ci auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef()); 594514f5e3Sopenharmony_ci if (cachedHClass->HasProps()) { 604514f5e3Sopenharmony_ci uint32_t last = cachedHClass->LastPropIndex(); 614514f5e3Sopenharmony_ci LayoutInfo* layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject()); 624514f5e3Sopenharmony_ci auto metaData = JSHandle<JSTaggedValue>(thread, 634514f5e3Sopenharmony_ci JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData())); 644514f5e3Sopenharmony_ci auto lastKey = JSHandle<JSTaggedValue>(thread, layoutInfo->GetKey(last)); 654514f5e3Sopenharmony_ci auto lastHClass = JSHandle<JSTaggedValue>(thread, cachedHClass); 664514f5e3Sopenharmony_ci dict.Update(TransitionsDictionary::Create(thread)); 674514f5e3Sopenharmony_ci transitions = TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, 684514f5e3Sopenharmony_ci metaData).GetTaggedValue(); 694514f5e3Sopenharmony_ci } 704514f5e3Sopenharmony_ci } 714514f5e3Sopenharmony_ci auto metaData = JSHandle<JSTaggedValue>(thread, JSTaggedValue(attributes.GetPropertyMetaData())); 724514f5e3Sopenharmony_ci dict.Update(transitions); 734514f5e3Sopenharmony_ci transitions = TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), 744514f5e3Sopenharmony_ci metaData).GetTaggedValue(); 754514f5e3Sopenharmony_ci parent->SetTransitions(thread, transitions); 764514f5e3Sopenharmony_ci} 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_civoid JSHClass::AddExtensionTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, 794514f5e3Sopenharmony_ci const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key) 804514f5e3Sopenharmony_ci{ 814514f5e3Sopenharmony_ci auto attr = JSHandle<JSTaggedValue>(thread, PropertyAttributes(0).GetTaggedValue()); 824514f5e3Sopenharmony_ci AddProtoTransitions(thread, parent, child, key, attr); 834514f5e3Sopenharmony_ci} 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_civoid JSHClass::AddProtoTransitions(const JSThread *thread, const JSHandle<JSHClass> &parent, 864514f5e3Sopenharmony_ci const JSHandle<JSHClass> &child, const JSHandle<JSTaggedValue> &key, 874514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &proto) 884514f5e3Sopenharmony_ci{ 894514f5e3Sopenharmony_ci ALLOW_LOCAL_TO_SHARE_WEAK_REF_HANDLE; 904514f5e3Sopenharmony_ci UpdateRootHClass(thread, parent, child); 914514f5e3Sopenharmony_ci JSTaggedValue transitions = parent->GetTransitions(); 924514f5e3Sopenharmony_ci JSMutableHandle<TransitionsDictionary> dict(thread, JSTaggedValue::Undefined()); 934514f5e3Sopenharmony_ci if (transitions.IsUndefined()) { 944514f5e3Sopenharmony_ci transitions = TransitionsDictionary::Create(thread).GetTaggedValue(); 954514f5e3Sopenharmony_ci } else if (transitions.IsWeak()) { 964514f5e3Sopenharmony_ci auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef()); 974514f5e3Sopenharmony_ci if (cachedHClass->HasProps()) { 984514f5e3Sopenharmony_ci uint32_t last = cachedHClass->LastPropIndex(); 994514f5e3Sopenharmony_ci LayoutInfo* layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject()); 1004514f5e3Sopenharmony_ci auto metaData = JSHandle<JSTaggedValue>(thread, 1014514f5e3Sopenharmony_ci JSTaggedValue(layoutInfo->GetAttr(last).GetPropertyMetaData())); 1024514f5e3Sopenharmony_ci auto lastKey = JSHandle<JSTaggedValue>(thread, layoutInfo->GetKey(last)); 1034514f5e3Sopenharmony_ci auto lastHClass = JSHandle<JSTaggedValue>(thread, cachedHClass); 1044514f5e3Sopenharmony_ci dict.Update(TransitionsDictionary::Create(thread)); 1054514f5e3Sopenharmony_ci transitions = TransitionsDictionary::PutIfAbsent(thread, dict, lastKey, lastHClass, 1064514f5e3Sopenharmony_ci metaData).GetTaggedValue(); 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci } 1094514f5e3Sopenharmony_ci dict.Update(transitions); 1104514f5e3Sopenharmony_ci transitions = 1114514f5e3Sopenharmony_ci TransitionsDictionary::PutIfAbsent(thread, dict, key, JSHandle<JSTaggedValue>(child), proto).GetTaggedValue(); 1124514f5e3Sopenharmony_ci parent->SetTransitions(thread, transitions); 1134514f5e3Sopenharmony_ci} 1144514f5e3Sopenharmony_ci 1154514f5e3Sopenharmony_ciinline JSHClass *JSHClass::FindTransitions(const JSTaggedValue &key, const JSTaggedValue &metaData, 1164514f5e3Sopenharmony_ci const Representation &rep) 1174514f5e3Sopenharmony_ci{ 1184514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 1194514f5e3Sopenharmony_ci JSTaggedValue transitions = GetTransitions(); 1204514f5e3Sopenharmony_ci if (transitions.IsUndefined()) { 1214514f5e3Sopenharmony_ci return nullptr; 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci if (transitions.IsWeak()) { 1244514f5e3Sopenharmony_ci auto cachedHClass = JSHClass::Cast(transitions.GetTaggedWeakRef()); 1254514f5e3Sopenharmony_ci if (cachedHClass->PropsIsEmpty()) { 1264514f5e3Sopenharmony_ci return nullptr; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci int last = static_cast<int>(cachedHClass->LastPropIndex()); 1294514f5e3Sopenharmony_ci LayoutInfo *layoutInfo = LayoutInfo::Cast(cachedHClass->GetLayout().GetTaggedObject()); 1304514f5e3Sopenharmony_ci auto lastMetaData = layoutInfo->GetAttr(last).GetPropertyMetaData(); 1314514f5e3Sopenharmony_ci auto lastKey = layoutInfo->GetKey(last); 1324514f5e3Sopenharmony_ci if (lastMetaData == metaData.GetInt() && key == lastKey) { 1334514f5e3Sopenharmony_ci return CheckHClassForRep(cachedHClass, rep); 1344514f5e3Sopenharmony_ci } 1354514f5e3Sopenharmony_ci return nullptr; 1364514f5e3Sopenharmony_ci } 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_ci ASSERT(transitions.IsTaggedArray()); 1394514f5e3Sopenharmony_ci TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject()); 1404514f5e3Sopenharmony_ci auto entry = dict->FindEntry(key, metaData); 1414514f5e3Sopenharmony_ci if (entry == -1) { 1424514f5e3Sopenharmony_ci return nullptr; 1434514f5e3Sopenharmony_ci } 1444514f5e3Sopenharmony_ci 1454514f5e3Sopenharmony_ci JSTaggedValue ret = dict->GetValue(entry); 1464514f5e3Sopenharmony_ci if (ret.IsUndefined()) { 1474514f5e3Sopenharmony_ci return nullptr; 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ci return CheckHClassForRep(JSHClass::Cast(ret.GetTaggedWeakRef()), rep); 1514514f5e3Sopenharmony_ci} 1524514f5e3Sopenharmony_ci 1534514f5e3Sopenharmony_ciinline JSHClass *JSHClass::FindProtoTransitions(const JSTaggedValue &key, const JSTaggedValue &proto) 1544514f5e3Sopenharmony_ci{ 1554514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 1564514f5e3Sopenharmony_ci JSTaggedValue transitions = GetTransitions(); 1574514f5e3Sopenharmony_ci if (transitions.IsWeak() || !transitions.IsTaggedArray()) { 1584514f5e3Sopenharmony_ci ASSERT(transitions.IsUndefined() || transitions.IsWeak()); 1594514f5e3Sopenharmony_ci return nullptr; 1604514f5e3Sopenharmony_ci } 1614514f5e3Sopenharmony_ci ASSERT(transitions.IsTaggedArray()); 1624514f5e3Sopenharmony_ci TransitionsDictionary *dict = TransitionsDictionary::Cast(transitions.GetTaggedObject()); 1634514f5e3Sopenharmony_ci auto entry = dict->FindEntry(key, proto); 1644514f5e3Sopenharmony_ci if (entry == -1) { 1654514f5e3Sopenharmony_ci return nullptr; 1664514f5e3Sopenharmony_ci } 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ci JSTaggedValue ret = dict->GetValue(entry); 1694514f5e3Sopenharmony_ci if (ret.IsUndefined()) { 1704514f5e3Sopenharmony_ci return nullptr; 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ci return JSHClass::Cast(ret.GetTaggedWeakRef()); 1744514f5e3Sopenharmony_ci} 1754514f5e3Sopenharmony_ci 1764514f5e3Sopenharmony_ciinline void JSHClass::RestoreElementsKindToGeneric(JSHClass *newJsHClass) 1774514f5e3Sopenharmony_ci{ 1784514f5e3Sopenharmony_ci newJsHClass->SetElementsKind(ElementsKind::GENERIC); 1794514f5e3Sopenharmony_ci} 1804514f5e3Sopenharmony_ci 1814514f5e3Sopenharmony_ciinline JSHClass *JSHClass::CheckHClassForRep(JSHClass *hclass, const Representation &rep) 1824514f5e3Sopenharmony_ci{ 1834514f5e3Sopenharmony_ci if (!hclass->IsTS()) { 1844514f5e3Sopenharmony_ci return hclass; 1854514f5e3Sopenharmony_ci } 1864514f5e3Sopenharmony_ci if (rep == Representation::NONE) { 1874514f5e3Sopenharmony_ci return hclass; 1884514f5e3Sopenharmony_ci } 1894514f5e3Sopenharmony_ci 1904514f5e3Sopenharmony_ci int last = static_cast<int>(hclass->LastPropIndex()); 1914514f5e3Sopenharmony_ci LayoutInfo *layoutInfo = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 1924514f5e3Sopenharmony_ci auto lastRep = layoutInfo->GetAttr(last).GetRepresentation(); 1934514f5e3Sopenharmony_ci auto result = hclass; 1944514f5e3Sopenharmony_ci if (lastRep == Representation::INT) { 1954514f5e3Sopenharmony_ci if (rep != Representation::INT) { 1964514f5e3Sopenharmony_ci result = nullptr; 1974514f5e3Sopenharmony_ci } 1984514f5e3Sopenharmony_ci } else if (lastRep == Representation::DOUBLE) { 1994514f5e3Sopenharmony_ci if (rep != Representation::INT && rep != Representation::DOUBLE) { 2004514f5e3Sopenharmony_ci result = nullptr; 2014514f5e3Sopenharmony_ci } 2024514f5e3Sopenharmony_ci } 2034514f5e3Sopenharmony_ci return result; 2044514f5e3Sopenharmony_ci} 2054514f5e3Sopenharmony_ci 2064514f5e3Sopenharmony_ciinline void JSHClass::UpdatePropertyMetaData(const JSThread *thread, [[maybe_unused]] const JSTaggedValue &key, 2074514f5e3Sopenharmony_ci const PropertyAttributes &metaData) 2084514f5e3Sopenharmony_ci{ 2094514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 2104514f5e3Sopenharmony_ci ASSERT(!GetLayout().IsNull()); 2114514f5e3Sopenharmony_ci LayoutInfo *layoutInfo = LayoutInfo::Cast(GetLayout().GetTaggedObject()); 2124514f5e3Sopenharmony_ci ASSERT(layoutInfo->GetLength() != 0); 2134514f5e3Sopenharmony_ci uint32_t entry = metaData.GetOffset(); 2144514f5e3Sopenharmony_ci 2154514f5e3Sopenharmony_ci layoutInfo->SetNormalAttr(thread, entry, metaData); 2164514f5e3Sopenharmony_ci} 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ciinline bool JSHClass::HasReferenceField() 2194514f5e3Sopenharmony_ci{ 2204514f5e3Sopenharmony_ci auto type = GetObjectType(); 2214514f5e3Sopenharmony_ci switch (type) { 2224514f5e3Sopenharmony_ci case JSType::LINE_STRING: 2234514f5e3Sopenharmony_ci case JSType::CONSTANT_STRING: 2244514f5e3Sopenharmony_ci case JSType::JS_NATIVE_POINTER: 2254514f5e3Sopenharmony_ci return false; 2264514f5e3Sopenharmony_ci default: 2274514f5e3Sopenharmony_ci return true; 2284514f5e3Sopenharmony_ci } 2294514f5e3Sopenharmony_ci} 2304514f5e3Sopenharmony_ci 2314514f5e3Sopenharmony_ciinline size_t JSHClass::SizeFromJSHClass(TaggedObject *header) 2324514f5e3Sopenharmony_ci{ 2334514f5e3Sopenharmony_ci // CAUTION! Never use T::Cast(header) in this function 2344514f5e3Sopenharmony_ci // it would cause issue during GC because hclass may forward to a new addres 2354514f5e3Sopenharmony_ci // and the casting method would still use the old address. 2364514f5e3Sopenharmony_ci auto type = GetObjectType(); 2374514f5e3Sopenharmony_ci size_t size = 0; 2384514f5e3Sopenharmony_ci switch (type) { 2394514f5e3Sopenharmony_ci case JSType::TAGGED_ARRAY: 2404514f5e3Sopenharmony_ci case JSType::TAGGED_DICTIONARY: 2414514f5e3Sopenharmony_ci case JSType::LEXICAL_ENV: 2424514f5e3Sopenharmony_ci case JSType::SENDABLE_ENV: 2434514f5e3Sopenharmony_ci case JSType::CONSTANT_POOL: 2444514f5e3Sopenharmony_ci case JSType::AOT_LITERAL_INFO: 2454514f5e3Sopenharmony_ci case JSType::VTABLE: 2464514f5e3Sopenharmony_ci case JSType::COW_TAGGED_ARRAY: 2474514f5e3Sopenharmony_ci case JSType::MUTANT_TAGGED_ARRAY: 2484514f5e3Sopenharmony_ci case JSType::COW_MUTANT_TAGGED_ARRAY: 2494514f5e3Sopenharmony_ci case JSType::PROFILE_TYPE_INFO: 2504514f5e3Sopenharmony_ci size = TaggedArray::ComputeSize(JSTaggedValue::TaggedTypeSize(), 2514514f5e3Sopenharmony_ci reinterpret_cast<TaggedArray *>(header)->GetLength()); 2524514f5e3Sopenharmony_ci break; 2534514f5e3Sopenharmony_ci case JSType::BYTE_ARRAY: 2544514f5e3Sopenharmony_ci size = ByteArray::ComputeSize(reinterpret_cast<ByteArray *>(header)->GetByteLength(), 2554514f5e3Sopenharmony_ci reinterpret_cast<ByteArray *>(header)->GetArrayLength()); 2564514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2574514f5e3Sopenharmony_ci break; 2584514f5e3Sopenharmony_ci case JSType::LINE_STRING: 2594514f5e3Sopenharmony_ci size = LineEcmaString::ObjectSize(reinterpret_cast<EcmaString* >(header)); 2604514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2614514f5e3Sopenharmony_ci break; 2624514f5e3Sopenharmony_ci case JSType::CONSTANT_STRING: 2634514f5e3Sopenharmony_ci size = ConstantString::SIZE; 2644514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2654514f5e3Sopenharmony_ci break; 2664514f5e3Sopenharmony_ci case JSType::TREE_STRING: 2674514f5e3Sopenharmony_ci size = TreeEcmaString::SIZE; 2684514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2694514f5e3Sopenharmony_ci break; 2704514f5e3Sopenharmony_ci case JSType::SLICED_STRING: 2714514f5e3Sopenharmony_ci size = SlicedString::SIZE; 2724514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2734514f5e3Sopenharmony_ci break; 2744514f5e3Sopenharmony_ci case JSType::MACHINE_CODE_OBJECT: 2754514f5e3Sopenharmony_ci size = reinterpret_cast<MachineCode *>(header)->GetMachineCodeObjectSize(); 2764514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2774514f5e3Sopenharmony_ci break; 2784514f5e3Sopenharmony_ci case JSType::BIGINT: 2794514f5e3Sopenharmony_ci size = BigInt::ComputeSize(reinterpret_cast<BigInt *>(header)->GetLength()); 2804514f5e3Sopenharmony_ci size = AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)); 2814514f5e3Sopenharmony_ci break; 2824514f5e3Sopenharmony_ci default: 2834514f5e3Sopenharmony_ci ASSERT(GetObjectSize() != 0); 2844514f5e3Sopenharmony_ci size = GetObjectSize(); 2854514f5e3Sopenharmony_ci break; 2864514f5e3Sopenharmony_ci } 2874514f5e3Sopenharmony_ci ASSERT(AlignUp(size, static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT)) == size); 2884514f5e3Sopenharmony_ci return size; 2894514f5e3Sopenharmony_ci} 2904514f5e3Sopenharmony_ci 2914514f5e3Sopenharmony_ciinline void JSHClass::Copy(const JSThread *thread, const JSHClass *jshclass) 2924514f5e3Sopenharmony_ci{ 2934514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 2944514f5e3Sopenharmony_ci 2954514f5e3Sopenharmony_ci // copy jshclass 2964514f5e3Sopenharmony_ci SetPrototype(thread, jshclass->GetPrototype()); 2974514f5e3Sopenharmony_ci SetBitField(jshclass->GetBitField()); 2984514f5e3Sopenharmony_ci SetIsAllTaggedProp(jshclass->IsAllTaggedProp()); 2994514f5e3Sopenharmony_ci SetNumberOfProps(jshclass->NumberOfProps()); 3004514f5e3Sopenharmony_ci} 3014514f5e3Sopenharmony_ci 3024514f5e3Sopenharmony_ciinline JSHClass *JSHClass::FindRootHClass(JSHClass *hclass) 3034514f5e3Sopenharmony_ci{ 3044514f5e3Sopenharmony_ci auto root = hclass; 3054514f5e3Sopenharmony_ci while (!ProfileType(root->GetProfileType()).IsRootType()) { 3064514f5e3Sopenharmony_ci auto parent = root->GetParent(); 3074514f5e3Sopenharmony_ci if (!parent.IsJSHClass()) { 3084514f5e3Sopenharmony_ci break; 3094514f5e3Sopenharmony_ci } 3104514f5e3Sopenharmony_ci root = JSHClass::Cast(parent.GetTaggedObject()); 3114514f5e3Sopenharmony_ci } 3124514f5e3Sopenharmony_ci return root; 3134514f5e3Sopenharmony_ci} 3144514f5e3Sopenharmony_ci 3154514f5e3Sopenharmony_ciinline JSTaggedValue JSHClass::FindProtoHClass(JSHClass *hclass) 3164514f5e3Sopenharmony_ci{ 3174514f5e3Sopenharmony_ci auto proto = hclass->GetProto(); 3184514f5e3Sopenharmony_ci if (proto.IsJSObject()) { 3194514f5e3Sopenharmony_ci auto prototypeObj = JSObject::Cast(proto); 3204514f5e3Sopenharmony_ci return JSTaggedValue(prototypeObj->GetClass()); 3214514f5e3Sopenharmony_ci } 3224514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 3234514f5e3Sopenharmony_ci} 3244514f5e3Sopenharmony_ci 3254514f5e3Sopenharmony_ciinline JSTaggedValue JSHClass::FindProtoRootHClass(JSHClass *hclass) 3264514f5e3Sopenharmony_ci{ 3274514f5e3Sopenharmony_ci auto proto = hclass->GetProto(); 3284514f5e3Sopenharmony_ci if (proto.IsJSObject()) { 3294514f5e3Sopenharmony_ci auto prototypeObj = JSObject::Cast(proto); 3304514f5e3Sopenharmony_ci auto prototypeHClass = prototypeObj->GetClass(); 3314514f5e3Sopenharmony_ci return JSTaggedValue(JSHClass::FindRootHClass(prototypeHClass)); 3324514f5e3Sopenharmony_ci } 3334514f5e3Sopenharmony_ci return JSTaggedValue::Undefined(); 3344514f5e3Sopenharmony_ci} 3354514f5e3Sopenharmony_ci 3364514f5e3Sopenharmony_ciinline void JSHClass::UpdateRootHClass(const JSThread *thread, const JSHandle<JSHClass> &parent, 3374514f5e3Sopenharmony_ci const JSHandle<JSHClass> &child) 3384514f5e3Sopenharmony_ci{ 3394514f5e3Sopenharmony_ci if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { 3404514f5e3Sopenharmony_ci child->SetParent(thread, parent); 3414514f5e3Sopenharmony_ci } 3424514f5e3Sopenharmony_ci} 3434514f5e3Sopenharmony_ci 3444514f5e3Sopenharmony_ciinline int JSHClass::FindPropertyEntry(const JSThread *thread, JSHClass *hclass, JSTaggedValue key) 3454514f5e3Sopenharmony_ci{ 3464514f5e3Sopenharmony_ci DISALLOW_GARBAGE_COLLECTION; 3474514f5e3Sopenharmony_ci LayoutInfo *layout = LayoutInfo::Cast(hclass->GetLayout().GetTaggedObject()); 3484514f5e3Sopenharmony_ci uint32_t propsNumber = hclass->NumberOfProps(); 3494514f5e3Sopenharmony_ci int entry = layout->FindElementWithCache(thread, hclass, key, propsNumber); 3504514f5e3Sopenharmony_ci return entry; 3514514f5e3Sopenharmony_ci} 3524514f5e3Sopenharmony_ci 3534514f5e3Sopenharmony_citemplate<bool checkDuplicateKeys /* = false*/> 3544514f5e3Sopenharmony_civoid JSHClass::AddPropertyToNewHClass(const JSThread *thread, JSHandle<JSHClass> &jshclass, 3554514f5e3Sopenharmony_ci JSHandle<JSHClass> &newJsHClass, 3564514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &key, 3574514f5e3Sopenharmony_ci const PropertyAttributes &attr) 3584514f5e3Sopenharmony_ci{ 3594514f5e3Sopenharmony_ci ASSERT(!jshclass->IsDictionaryMode()); 3604514f5e3Sopenharmony_ci ASSERT(!newJsHClass->IsDictionaryMode()); 3614514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 3624514f5e3Sopenharmony_ci // Add Property and metaData 3634514f5e3Sopenharmony_ci uint32_t offset = attr.GetOffset(); 3644514f5e3Sopenharmony_ci newJsHClass->IncNumberOfProps(); 3654514f5e3Sopenharmony_ci 3664514f5e3Sopenharmony_ci { 3674514f5e3Sopenharmony_ci JSMutableHandle<LayoutInfo> layoutInfoHandle(thread, newJsHClass->GetLayout()); 3684514f5e3Sopenharmony_ci 3694514f5e3Sopenharmony_ci if (layoutInfoHandle->NumberOfElements() != static_cast<int>(offset)) { 3704514f5e3Sopenharmony_ci layoutInfoHandle.Update(factory->CopyAndReSort(layoutInfoHandle, offset, offset + 1)); 3714514f5e3Sopenharmony_ci } else if (layoutInfoHandle->GetPropertiesCapacity() <= static_cast<int>(offset)) { // need to Grow 3724514f5e3Sopenharmony_ci layoutInfoHandle.Update( 3734514f5e3Sopenharmony_ci factory->ExtendLayoutInfo(layoutInfoHandle, offset)); 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci newJsHClass->SetLayout(thread, layoutInfoHandle); 3764514f5e3Sopenharmony_ci layoutInfoHandle->AddKey<checkDuplicateKeys>(thread, offset, key.GetTaggedValue(), attr); 3774514f5e3Sopenharmony_ci } 3784514f5e3Sopenharmony_ci 3794514f5e3Sopenharmony_ci // Add newClass to old hclass's transitions. 3804514f5e3Sopenharmony_ci AddTransitions(thread, jshclass, newJsHClass, key, attr); 3814514f5e3Sopenharmony_ci} 3824514f5e3Sopenharmony_ci 3834514f5e3Sopenharmony_citemplate<bool checkDuplicateKeys /* = false*/> 3844514f5e3Sopenharmony_ciJSHandle<JSHClass> JSHClass::SetPropertyOfObjHClass(const JSThread *thread, JSHandle<JSHClass> &jshclass, 3854514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &key, 3864514f5e3Sopenharmony_ci const PropertyAttributes &attr, const Representation &rep) 3874514f5e3Sopenharmony_ci{ 3884514f5e3Sopenharmony_ci JSHClass *newClass = jshclass->FindTransitions( 3894514f5e3Sopenharmony_ci key.GetTaggedValue(), JSTaggedValue(attr.GetPropertyMetaData()), rep); 3904514f5e3Sopenharmony_ci if (newClass != nullptr) { 3914514f5e3Sopenharmony_ci newClass->SetPrototype(thread, jshclass->GetPrototype()); 3924514f5e3Sopenharmony_ci return JSHandle<JSHClass>(thread, newClass); 3934514f5e3Sopenharmony_ci } 3944514f5e3Sopenharmony_ci 3954514f5e3Sopenharmony_ci JSHandle<JSHClass> newJsHClass = JSHClass::Clone(thread, jshclass); 3964514f5e3Sopenharmony_ci AddPropertyToNewHClass<checkDuplicateKeys>(thread, jshclass, newJsHClass, key, attr); 3974514f5e3Sopenharmony_ci return newJsHClass; 3984514f5e3Sopenharmony_ci} 3994514f5e3Sopenharmony_ci} // namespace panda::ecmascript 4004514f5e3Sopenharmony_ci 4014514f5e3Sopenharmony_ci#endif // ECMASCRIPT_JS_HCLASS_INL_H 402