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#include "ecmascript/jspandafile/class_info_extractor.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/js_object-inl.h" 194514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/program_object.h" 204514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_sendable_arraybuffer.h" 214514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_shared_array.h" 224514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_shared_map.h" 234514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_shared_set.h" 244514f5e3Sopenharmony_ci#include "ecmascript/shared_objects/js_shared_typed_array.h" 254514f5e3Sopenharmony_ci#include "ecmascript/object_fast_operator-inl.h" 264514f5e3Sopenharmony_ci 274514f5e3Sopenharmony_cinamespace panda::ecmascript { 284514f5e3Sopenharmony_civoid ClassInfoExtractor::BuildClassInfoExtractorFromLiteral(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor, 294514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &literal, 304514f5e3Sopenharmony_ci uint32_t length, 314514f5e3Sopenharmony_ci ClassKind kind) 324514f5e3Sopenharmony_ci{ 334514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 344514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 354514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_ci ASSERT(length <= literal->GetLength()); 384514f5e3Sopenharmony_ci // non static properties number is hidden in the last index of Literal buffer 394514f5e3Sopenharmony_ci uint32_t nonStaticNum = 0; 404514f5e3Sopenharmony_ci if (length != 0) { 414514f5e3Sopenharmony_ci nonStaticNum = static_cast<uint32_t>(literal->Get(thread, length - 1).GetInt()); 424514f5e3Sopenharmony_ci } 434514f5e3Sopenharmony_ci 444514f5e3Sopenharmony_ci // Reserve sufficient length to prevent frequent creation. 454514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticKeys; 464514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticProperties; 474514f5e3Sopenharmony_ci factory->NewOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH); 484514f5e3Sopenharmony_ci if (kind == ClassKind::SENDABLE) { 494514f5e3Sopenharmony_ci nonStaticKeys = factory->NewSOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH); 504514f5e3Sopenharmony_ci nonStaticProperties = 514514f5e3Sopenharmony_ci factory->NewSOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH); 524514f5e3Sopenharmony_ci } else { 534514f5e3Sopenharmony_ci nonStaticKeys = factory->NewOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH); 544514f5e3Sopenharmony_ci nonStaticProperties = 554514f5e3Sopenharmony_ci factory->NewOldSpaceTaggedArray(nonStaticNum + NON_STATIC_RESERVED_LENGTH); 564514f5e3Sopenharmony_ci } 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_ci nonStaticKeys->Set(thread, CONSTRUCTOR_INDEX, globalConst->GetConstructorString()); 594514f5e3Sopenharmony_ci Method *method = Method::Cast(extractor->GetConstructorMethod().GetTaggedObject()); 604514f5e3Sopenharmony_ci MethodLiteral *methodLiteral = method->GetMethodLiteral(); 614514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); 624514f5e3Sopenharmony_ci EntityId methodId = method->GetMethodId(); 634514f5e3Sopenharmony_ci if (nonStaticNum) { 644514f5e3Sopenharmony_ci ExtractContentsDetail nonStaticDetail {0, nonStaticNum * 2, NON_STATIC_RESERVED_LENGTH, nullptr}; 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticElements = factory->EmptyArray(); 674514f5e3Sopenharmony_ci if (UNLIKELY(ExtractAndReturnWhetherWithElements(thread, literal, nonStaticDetail, nonStaticKeys, 684514f5e3Sopenharmony_ci nonStaticProperties, nonStaticElements, jsPandaFile))) { 694514f5e3Sopenharmony_ci extractor->SetNonStaticWithElements(true); 704514f5e3Sopenharmony_ci extractor->SetNonStaticElements(thread, nonStaticElements); 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_ci extractor->SetNonStaticKeys(thread, nonStaticKeys); 754514f5e3Sopenharmony_ci extractor->SetNonStaticProperties(thread, nonStaticProperties); 764514f5e3Sopenharmony_ci 774514f5e3Sopenharmony_ci uint32_t staticNum = length == 0 ? 0 : (length - 1) / 2 - nonStaticNum; 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_ci // Reserve sufficient length to prevent frequent creation. 804514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticKeys; 814514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticProperties; 824514f5e3Sopenharmony_ci if (kind == ClassKind::SENDABLE) { 834514f5e3Sopenharmony_ci staticKeys = factory->NewSOldSpaceTaggedArray(staticNum + STATIC_RESERVED_LENGTH); 844514f5e3Sopenharmony_ci staticProperties = factory->NewSOldSpaceTaggedArray(staticNum + STATIC_RESERVED_LENGTH); 854514f5e3Sopenharmony_ci } else { 864514f5e3Sopenharmony_ci staticKeys = factory->NewOldSpaceTaggedArray(staticNum + STATIC_RESERVED_LENGTH); 874514f5e3Sopenharmony_ci staticProperties = factory->NewOldSpaceTaggedArray(staticNum + STATIC_RESERVED_LENGTH); 884514f5e3Sopenharmony_ci } 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci staticKeys->Set(thread, LENGTH_INDEX, globalConst->GetLengthString()); 914514f5e3Sopenharmony_ci staticKeys->Set(thread, NAME_INDEX, globalConst->GetNameString()); 924514f5e3Sopenharmony_ci staticKeys->Set(thread, PROTOTYPE_INDEX, globalConst->GetPrototypeString()); 934514f5e3Sopenharmony_ci 944514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticElements = factory->EmptyArray(); 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ci if (staticNum) { 974514f5e3Sopenharmony_ci ExtractContentsDetail staticDetail { 984514f5e3Sopenharmony_ci nonStaticNum * 2, 994514f5e3Sopenharmony_ci length - 1, 1004514f5e3Sopenharmony_ci STATIC_RESERVED_LENGTH, 1014514f5e3Sopenharmony_ci methodLiteral 1024514f5e3Sopenharmony_ci }; 1034514f5e3Sopenharmony_ci if (UNLIKELY(ExtractAndReturnWhetherWithElements(thread, literal, staticDetail, staticKeys, 1044514f5e3Sopenharmony_ci staticProperties, staticElements, jsPandaFile))) { 1054514f5e3Sopenharmony_ci extractor->SetStaticWithElements(true); 1064514f5e3Sopenharmony_ci extractor->SetStaticElements(thread, staticElements); 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci } else { 1094514f5e3Sopenharmony_ci // without static properties, set class name 1104514f5e3Sopenharmony_ci std::string clsName = MethodLiteral::ParseFunctionName(jsPandaFile, methodId); 1114514f5e3Sopenharmony_ci JSHandle<EcmaString> clsNameHandle = factory->NewFromStdString(clsName); 1124514f5e3Sopenharmony_ci staticProperties->Set(thread, NAME_INDEX, clsNameHandle); 1134514f5e3Sopenharmony_ci } 1144514f5e3Sopenharmony_ci 1154514f5e3Sopenharmony_ci // set prototype internal accessor 1164514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> prototypeAccessor = globalConst->GetHandledFunctionPrototypeAccessor(); 1174514f5e3Sopenharmony_ci staticProperties->Set(thread, PROTOTYPE_INDEX, prototypeAccessor); 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ci extractor->SetStaticKeys(thread, staticKeys); 1204514f5e3Sopenharmony_ci extractor->SetStaticProperties(thread, staticProperties); 1214514f5e3Sopenharmony_ci} 1224514f5e3Sopenharmony_ci 1234514f5e3Sopenharmony_cibool ClassInfoExtractor::ExtractAndReturnWhetherWithElements(JSThread *thread, const JSHandle<TaggedArray> &literal, 1244514f5e3Sopenharmony_ci const ExtractContentsDetail &detail, 1254514f5e3Sopenharmony_ci JSHandle<TaggedArray> &keys, 1264514f5e3Sopenharmony_ci JSHandle<TaggedArray> &properties, 1274514f5e3Sopenharmony_ci JSHandle<TaggedArray> &elements, 1284514f5e3Sopenharmony_ci const JSPandaFile *jsPandaFile) 1294514f5e3Sopenharmony_ci{ 1304514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 1314514f5e3Sopenharmony_ci 1324514f5e3Sopenharmony_ci ASSERT(keys->GetLength() == properties->GetLength() && elements->GetLength() == 0); 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ci uint32_t pos = detail.fillStartLoc; 1354514f5e3Sopenharmony_ci bool withElementsFlag = false; 1364514f5e3Sopenharmony_ci bool isStaticFlag = (detail.methodLiteral != nullptr); 1374514f5e3Sopenharmony_ci bool keysHasNameFlag = false; 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> nameString = globalConst->GetHandledNameString(); 1404514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> firstValue(thread, JSTaggedValue::Undefined()); 1414514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> secondValue(thread, JSTaggedValue::Undefined()); 1424514f5e3Sopenharmony_ci for (uint32_t index = detail.extractBegin; index < detail.extractEnd; index += 2) { // 2: key-value pair 1434514f5e3Sopenharmony_ci firstValue.Update(literal->Get(index)); 1444514f5e3Sopenharmony_ci secondValue.Update(literal->Get(index + 1)); 1454514f5e3Sopenharmony_ci ASSERT_PRINT(JSTaggedValue::IsPropertyKey(firstValue), "Key is not a property key"); 1464514f5e3Sopenharmony_ci 1474514f5e3Sopenharmony_ci if (LIKELY(firstValue->IsString())) { 1484514f5e3Sopenharmony_ci if (isStaticFlag && !keysHasNameFlag && JSTaggedValue::SameValue(firstValue, nameString)) { 1494514f5e3Sopenharmony_ci properties->Set(thread, NAME_INDEX, secondValue); 1504514f5e3Sopenharmony_ci keysHasNameFlag = true; 1514514f5e3Sopenharmony_ci continue; 1524514f5e3Sopenharmony_ci } 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_ci // front-end can do better: write index in class literal directly. 1554514f5e3Sopenharmony_ci uint32_t elementIndex = 0; 1564514f5e3Sopenharmony_ci if (JSTaggedValue::StringToElementIndex(firstValue.GetTaggedValue(), &elementIndex)) { 1574514f5e3Sopenharmony_ci ASSERT(elementIndex < JSObject::MAX_ELEMENT_INDEX); 1584514f5e3Sopenharmony_ci uint32_t elementsLength = elements->GetLength(); 1594514f5e3Sopenharmony_ci elements = 1604514f5e3Sopenharmony_ci TaggedArray::SetCapacityInOldSpace(thread, elements, elementsLength + 2); // 2: key-value pair 1614514f5e3Sopenharmony_ci elements->Set(thread, elementsLength, firstValue); 1624514f5e3Sopenharmony_ci elements->Set(thread, elementsLength + 1, secondValue); 1634514f5e3Sopenharmony_ci withElementsFlag = true; 1644514f5e3Sopenharmony_ci continue; 1654514f5e3Sopenharmony_ci } 1664514f5e3Sopenharmony_ci } 1674514f5e3Sopenharmony_ci 1684514f5e3Sopenharmony_ci keys->Set(thread, pos, firstValue); 1694514f5e3Sopenharmony_ci properties->Set(thread, pos, secondValue); 1704514f5e3Sopenharmony_ci pos++; 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci 1734514f5e3Sopenharmony_ci if (isStaticFlag) { 1744514f5e3Sopenharmony_ci if (LIKELY(!keysHasNameFlag)) { 1754514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope handleScope(thread); 1764514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 1774514f5e3Sopenharmony_ci EntityId methodId = detail.methodLiteral->GetMethodId(); 1784514f5e3Sopenharmony_ci std::string clsName = MethodLiteral::ParseFunctionName(jsPandaFile, methodId); 1794514f5e3Sopenharmony_ci JSHandle<EcmaString> clsNameHandle = factory->NewFromStdString(clsName); 1804514f5e3Sopenharmony_ci properties->Set(thread, NAME_INDEX, clsNameHandle); 1814514f5e3Sopenharmony_ci } else { 1824514f5e3Sopenharmony_ci // class has static name property, reserved length bigger 1 than actual, need trim 1834514f5e3Sopenharmony_ci uint32_t trimOneLength = keys->GetLength() - 1; 1844514f5e3Sopenharmony_ci keys->Trim(thread, trimOneLength); 1854514f5e3Sopenharmony_ci properties->Trim(thread, trimOneLength); 1864514f5e3Sopenharmony_ci } 1874514f5e3Sopenharmony_ci } 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ci if (UNLIKELY(withElementsFlag)) { 1904514f5e3Sopenharmony_ci ASSERT(pos + elements->GetLength() / 2 == properties->GetLength()); // 2: half 1914514f5e3Sopenharmony_ci keys->Trim(thread, pos); 1924514f5e3Sopenharmony_ci properties->Trim(thread, pos); 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci 1954514f5e3Sopenharmony_ci return withElementsFlag; 1964514f5e3Sopenharmony_ci} 1974514f5e3Sopenharmony_ci 1984514f5e3Sopenharmony_ciJSHandle<JSHClass> ClassInfoExtractor::CreatePrototypeHClass(JSThread *thread, 1994514f5e3Sopenharmony_ci JSHandle<TaggedArray> &keys, 2004514f5e3Sopenharmony_ci JSHandle<TaggedArray> &properties) 2014514f5e3Sopenharmony_ci{ 2024514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 2034514f5e3Sopenharmony_ci 2044514f5e3Sopenharmony_ci uint32_t length = keys->GetLength(); 2054514f5e3Sopenharmony_ci JSHandle<JSHClass> hclass; 2064514f5e3Sopenharmony_ci if (LIKELY(length <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) { 2074514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 2084514f5e3Sopenharmony_ci JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length, MemSpaceType::OLD_SPACE, GrowMode::KEEP); 2094514f5e3Sopenharmony_ci for (uint32_t index = 0; index < length; ++index) { 2104514f5e3Sopenharmony_ci key.Update(keys->Get(index)); 2114514f5e3Sopenharmony_ci ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); 2124514f5e3Sopenharmony_ci PropertyAttributes attributes = PropertyAttributes::Default(true, false, true); // non-enumerable 2134514f5e3Sopenharmony_ci 2144514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(index).IsAccessor())) { 2154514f5e3Sopenharmony_ci attributes.SetIsAccessor(true); 2164514f5e3Sopenharmony_ci } 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ci attributes.SetIsInlinedProps(true); 2194514f5e3Sopenharmony_ci attributes.SetRepresentation(Representation::TAGGED); 2204514f5e3Sopenharmony_ci attributes.SetOffset(index); 2214514f5e3Sopenharmony_ci layout->AddKey(thread, index, key.GetTaggedValue(), attributes); 2224514f5e3Sopenharmony_ci } 2234514f5e3Sopenharmony_ci 2244514f5e3Sopenharmony_ci hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, length); 2254514f5e3Sopenharmony_ci // Not need set proto here 2264514f5e3Sopenharmony_ci hclass->SetLayout(thread, layout); 2274514f5e3Sopenharmony_ci hclass->SetNumberOfProps(length); 2284514f5e3Sopenharmony_ci } else { 2294514f5e3Sopenharmony_ci // dictionary mode 2304514f5e3Sopenharmony_ci hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, 0); // without in-obj 2314514f5e3Sopenharmony_ci hclass->SetIsDictionaryMode(true); 2324514f5e3Sopenharmony_ci hclass->SetNumberOfProps(0); 2334514f5e3Sopenharmony_ci } 2344514f5e3Sopenharmony_ci 2354514f5e3Sopenharmony_ci hclass->SetClassPrototype(true); 2364514f5e3Sopenharmony_ci hclass->SetIsPrototype(true); 2374514f5e3Sopenharmony_ci return hclass; 2384514f5e3Sopenharmony_ci} 2394514f5e3Sopenharmony_ci 2404514f5e3Sopenharmony_ciJSHandle<JSHClass> ClassInfoExtractor::CreateConstructorHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base, 2414514f5e3Sopenharmony_ci JSHandle<TaggedArray> &keys, 2424514f5e3Sopenharmony_ci JSHandle<TaggedArray> &properties) 2434514f5e3Sopenharmony_ci{ 2444514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 2454514f5e3Sopenharmony_ci 2464514f5e3Sopenharmony_ci uint32_t length = keys->GetLength(); 2474514f5e3Sopenharmony_ci if (!thread->GetEcmaVM()->IsEnablePGOProfiler()) { 2484514f5e3Sopenharmony_ci // The class constructor of AOT is not shared, and PGO collect cannot be shared. 2494514f5e3Sopenharmony_ci if (length == ClassInfoExtractor::STATIC_RESERVED_LENGTH && base->IsHole() && 2504514f5e3Sopenharmony_ci properties->Get(NAME_INDEX).IsString()) { 2514514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 2524514f5e3Sopenharmony_ci return JSHandle<JSHClass>(globalConst->GetHandledClassConstructorClass()); 2534514f5e3Sopenharmony_ci } 2544514f5e3Sopenharmony_ci } 2554514f5e3Sopenharmony_ci JSHandle<JSHClass> hclass; 2564514f5e3Sopenharmony_ci if (LIKELY(length <= PropertyAttributes::MAX_FAST_PROPS_CAPACITY)) { 2574514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 2584514f5e3Sopenharmony_ci JSHandle<LayoutInfo> layout = factory->CreateLayoutInfo(length, MemSpaceType::OLD_SPACE, GrowMode::KEEP); 2594514f5e3Sopenharmony_ci for (uint32_t index = 0; index < length; ++index) { 2604514f5e3Sopenharmony_ci key.Update(keys->Get(index)); 2614514f5e3Sopenharmony_ci ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); 2624514f5e3Sopenharmony_ci PropertyAttributes attributes; 2634514f5e3Sopenharmony_ci switch (index) { 2644514f5e3Sopenharmony_ci case LENGTH_INDEX: 2654514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(false, false, true); 2664514f5e3Sopenharmony_ci break; 2674514f5e3Sopenharmony_ci case NAME_INDEX: 2684514f5e3Sopenharmony_ci if (LIKELY(properties->Get(NAME_INDEX).IsString())) { 2694514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(false, false, true); 2704514f5e3Sopenharmony_ci } else { 2714514f5e3Sopenharmony_ci ASSERT(properties->Get(NAME_INDEX).IsFunctionTemplate()); 2724514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(true, false, true); 2734514f5e3Sopenharmony_ci } 2744514f5e3Sopenharmony_ci break; 2754514f5e3Sopenharmony_ci case PROTOTYPE_INDEX: 2764514f5e3Sopenharmony_ci attributes = PropertyAttributes::DefaultAccessor(false, false, false); 2774514f5e3Sopenharmony_ci break; 2784514f5e3Sopenharmony_ci default: 2794514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(true, false, true); 2804514f5e3Sopenharmony_ci break; 2814514f5e3Sopenharmony_ci } 2824514f5e3Sopenharmony_ci 2834514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(index).IsAccessor())) { 2844514f5e3Sopenharmony_ci attributes.SetIsAccessor(true); 2854514f5e3Sopenharmony_ci } 2864514f5e3Sopenharmony_ci 2874514f5e3Sopenharmony_ci attributes.SetIsInlinedProps(true); 2884514f5e3Sopenharmony_ci attributes.SetRepresentation(Representation::TAGGED); 2894514f5e3Sopenharmony_ci attributes.SetOffset(index); 2904514f5e3Sopenharmony_ci layout->AddKey(thread, index, key.GetTaggedValue(), attributes); 2914514f5e3Sopenharmony_ci } 2924514f5e3Sopenharmony_ci 2934514f5e3Sopenharmony_ci hclass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, length); 2944514f5e3Sopenharmony_ci // Not need set proto here 2954514f5e3Sopenharmony_ci hclass->SetLayout(thread, layout); 2964514f5e3Sopenharmony_ci hclass->SetNumberOfProps(length); 2974514f5e3Sopenharmony_ci } else { 2984514f5e3Sopenharmony_ci // dictionary mode 2994514f5e3Sopenharmony_ci hclass = factory->NewEcmaHClass(JSFunction::SIZE, JSType::JS_FUNCTION, 0); // without in-obj 3004514f5e3Sopenharmony_ci hclass->SetIsDictionaryMode(true); 3014514f5e3Sopenharmony_ci hclass->SetNumberOfProps(0); 3024514f5e3Sopenharmony_ci } 3034514f5e3Sopenharmony_ci 3044514f5e3Sopenharmony_ci hclass->SetClassConstructor(true); 3054514f5e3Sopenharmony_ci hclass->SetConstructor(true); 3064514f5e3Sopenharmony_ci 3074514f5e3Sopenharmony_ci return hclass; 3084514f5e3Sopenharmony_ci} 3094514f5e3Sopenharmony_ci 3104514f5e3Sopenharmony_civoid ClassInfoExtractor::CorrectConstructorHClass(JSThread *thread, 3114514f5e3Sopenharmony_ci JSHandle<TaggedArray> &properties, 3124514f5e3Sopenharmony_ci JSHClass *constructorHClass) 3134514f5e3Sopenharmony_ci{ 3144514f5e3Sopenharmony_ci if (constructorHClass->IsDictionaryMode()) { 3154514f5e3Sopenharmony_ci return; 3164514f5e3Sopenharmony_ci } 3174514f5e3Sopenharmony_ci JSHandle<LayoutInfo> layout(thread, constructorHClass->GetLayout()); 3184514f5e3Sopenharmony_ci for (uint32_t index = 0; index < ClassInfoExtractor::STATIC_RESERVED_LENGTH; ++index) { 3194514f5e3Sopenharmony_ci if (index == NAME_INDEX) { 3204514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(NAME_INDEX).IsFunctionTemplate())) { 3214514f5e3Sopenharmony_ci PropertyAttributes attr = layout->GetAttr(index); 3224514f5e3Sopenharmony_ci attr.SetWritable(true); 3234514f5e3Sopenharmony_ci layout->SetNormalAttr(thread, index, attr); 3244514f5e3Sopenharmony_ci } 3254514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(index).IsAccessor())) { 3264514f5e3Sopenharmony_ci PropertyAttributes attr = layout->GetAttr(index); 3274514f5e3Sopenharmony_ci attr.SetIsAccessor(true); 3284514f5e3Sopenharmony_ci layout->SetNormalAttr(thread, index, attr); 3294514f5e3Sopenharmony_ci } 3304514f5e3Sopenharmony_ci } else { 3314514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(index).IsAccessor())) { 3324514f5e3Sopenharmony_ci PropertyAttributes attr = layout->GetAttr(index); 3334514f5e3Sopenharmony_ci attr.SetIsAccessor(true); 3344514f5e3Sopenharmony_ci layout->SetNormalAttr(thread, index, attr); 3354514f5e3Sopenharmony_ci } 3364514f5e3Sopenharmony_ci } 3374514f5e3Sopenharmony_ci } 3384514f5e3Sopenharmony_ci} 3394514f5e3Sopenharmony_ci 3404514f5e3Sopenharmony_ciJSHandle<JSHClass> ClassInfoExtractor::CreateSendableHClass(JSThread *thread, JSHandle<TaggedArray> &keys, 3414514f5e3Sopenharmony_ci JSHandle<TaggedArray> &properties, bool isProtoClass, 3424514f5e3Sopenharmony_ci uint32_t extraLength) 3434514f5e3Sopenharmony_ci{ 3444514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 3454514f5e3Sopenharmony_ci uint32_t length = keys->GetLength(); 3464514f5e3Sopenharmony_ci JSHandle<JSHClass> hclass; 3474514f5e3Sopenharmony_ci uint32_t maxInline = isProtoClass ? JSSharedObject::MAX_INLINE : JSSharedFunction::MAX_INLINE; 3484514f5e3Sopenharmony_ci if (LIKELY(length + extraLength <= maxInline)) { 3494514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 3504514f5e3Sopenharmony_ci JSHandle<LayoutInfo> layout = factory->CreateSLayoutInfo(length + extraLength); 3514514f5e3Sopenharmony_ci for (uint32_t index = 0; index < length; ++index) { 3524514f5e3Sopenharmony_ci key.Update(keys->Get(index)); 3534514f5e3Sopenharmony_ci ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key"); 3544514f5e3Sopenharmony_ci PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); 3554514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(index).IsAccessor())) { 3564514f5e3Sopenharmony_ci attributes.SetIsAccessor(true); 3574514f5e3Sopenharmony_ci } 3584514f5e3Sopenharmony_ci attributes.SetIsInlinedProps(true); 3594514f5e3Sopenharmony_ci attributes.SetRepresentation(Representation::TAGGED); 3604514f5e3Sopenharmony_ci attributes.SetOffset(index); 3614514f5e3Sopenharmony_ci layout->AddKey(thread, index, key.GetTaggedValue(), attributes); 3624514f5e3Sopenharmony_ci } 3634514f5e3Sopenharmony_ci hclass = isProtoClass ? factory->NewSEcmaHClass(JSSharedObject::SIZE, JSType::JS_SHARED_OBJECT, length) : 3644514f5e3Sopenharmony_ci factory->NewSEcmaHClass(JSSharedFunction::SIZE, JSType::JS_SHARED_FUNCTION, length + extraLength); 3654514f5e3Sopenharmony_ci hclass->SetLayout(thread, layout); 3664514f5e3Sopenharmony_ci hclass->SetNumberOfProps(length); 3674514f5e3Sopenharmony_ci } else { 3684514f5e3Sopenharmony_ci // dictionary mode 3694514f5e3Sopenharmony_ci hclass = isProtoClass ? factory->NewSEcmaHClass(JSSharedObject::SIZE, JSType::JS_SHARED_OBJECT, 0) : 3704514f5e3Sopenharmony_ci factory->NewSEcmaHClass(JSSharedFunction::SIZE, JSType::JS_SHARED_FUNCTION, 0); 3714514f5e3Sopenharmony_ci hclass->SetIsDictionaryMode(true); 3724514f5e3Sopenharmony_ci hclass->SetNumberOfProps(0); 3734514f5e3Sopenharmony_ci } 3744514f5e3Sopenharmony_ci if (isProtoClass) { 3754514f5e3Sopenharmony_ci hclass->SetClassPrototype(true); 3764514f5e3Sopenharmony_ci hclass->SetIsPrototype(true); 3774514f5e3Sopenharmony_ci } else { 3784514f5e3Sopenharmony_ci hclass->SetClassConstructor(true); 3794514f5e3Sopenharmony_ci hclass->SetConstructor(true); 3804514f5e3Sopenharmony_ci } 3814514f5e3Sopenharmony_ci return hclass; 3824514f5e3Sopenharmony_ci} 3834514f5e3Sopenharmony_ci 3844514f5e3Sopenharmony_ciJSHandle<JSFunction> ClassHelper::DefineClassFromExtractor(JSThread *thread, const JSHandle<JSTaggedValue> &base, 3854514f5e3Sopenharmony_ci JSHandle<ClassInfoExtractor> &extractor, 3864514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &lexenv) 3874514f5e3Sopenharmony_ci{ 3884514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 3894514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys()); 3904514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties()); 3914514f5e3Sopenharmony_ci 3924514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys()); 3934514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties()); 3944514f5e3Sopenharmony_ci JSHandle<JSHClass> prototypeHClass = ClassInfoExtractor::CreatePrototypeHClass(thread, nonStaticKeys, 3954514f5e3Sopenharmony_ci nonStaticProperties); 3964514f5e3Sopenharmony_ci 3974514f5e3Sopenharmony_ci JSHandle<JSObject> prototype = factory->NewOldSpaceJSObject(prototypeHClass); 3984514f5e3Sopenharmony_ci JSHandle<Method> method(thread, Method::Cast(extractor->GetConstructorMethod().GetTaggedObject())); 3994514f5e3Sopenharmony_ci JSHandle<JSHClass> constructorHClass = ClassInfoExtractor::CreateConstructorHClass(thread, base, staticKeys, 4004514f5e3Sopenharmony_ci staticProperties); 4014514f5e3Sopenharmony_ci // Allocate to non-movable space for PGO 4024514f5e3Sopenharmony_ci JSHandle<JSFunction> constructor = factory->NewJSFunctionByHClass(method, constructorHClass, 4034514f5e3Sopenharmony_ci MemSpaceType::NON_MOVABLE); 4044514f5e3Sopenharmony_ci 4054514f5e3Sopenharmony_ci // non-static 4064514f5e3Sopenharmony_ci nonStaticProperties->Set(thread, 0, constructor); 4074514f5e3Sopenharmony_ci 4084514f5e3Sopenharmony_ci uint32_t nonStaticLength = nonStaticProperties->GetLength(); 4094514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined()); 4104514f5e3Sopenharmony_ci 4114514f5e3Sopenharmony_ci if (LIKELY(!prototypeHClass->IsDictionaryMode())) { 4124514f5e3Sopenharmony_ci for (uint32_t index = 0; index < nonStaticLength; ++index) { 4134514f5e3Sopenharmony_ci propValue.Update(nonStaticProperties->Get(index)); 4144514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 4154514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 4164514f5e3Sopenharmony_ci propValue.Update(CreateJSFunctionFromTemplate(thread, literalFunc, prototype, lexenv)); 4174514f5e3Sopenharmony_ci } 4184514f5e3Sopenharmony_ci prototype->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue()); 4194514f5e3Sopenharmony_ci } 4204514f5e3Sopenharmony_ci } else { 4214514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = BuildDictionaryProperties(thread, prototype, nonStaticKeys, nonStaticProperties, 4224514f5e3Sopenharmony_ci ClassPropertyType::NON_STATIC, lexenv); 4234514f5e3Sopenharmony_ci prototype->SetProperties(thread, dict); 4244514f5e3Sopenharmony_ci } 4254514f5e3Sopenharmony_ci 4264514f5e3Sopenharmony_ci // non-static elements 4274514f5e3Sopenharmony_ci if (UNLIKELY(extractor->GetNonStaticWithElements())) { 4284514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticElements(thread, extractor->GetNonStaticElements()); 4294514f5e3Sopenharmony_ci ClassHelper::HandleElementsProperties(thread, prototype, lexenv, nonStaticElements); 4304514f5e3Sopenharmony_ci } 4314514f5e3Sopenharmony_ci 4324514f5e3Sopenharmony_ci // static 4334514f5e3Sopenharmony_ci uint32_t staticLength = staticProperties->GetLength(); 4344514f5e3Sopenharmony_ci 4354514f5e3Sopenharmony_ci if (LIKELY(!constructorHClass->IsDictionaryMode())) { 4364514f5e3Sopenharmony_ci for (uint32_t index = 0; index < staticLength; ++index) { 4374514f5e3Sopenharmony_ci propValue.Update(staticProperties->Get(index)); 4384514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 4394514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 4404514f5e3Sopenharmony_ci propValue.Update( 4414514f5e3Sopenharmony_ci CreateJSFunctionFromTemplate(thread, literalFunc, JSHandle<JSObject>(constructor), lexenv)); 4424514f5e3Sopenharmony_ci } 4434514f5e3Sopenharmony_ci JSHandle<JSObject>::Cast(constructor)->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue()); 4444514f5e3Sopenharmony_ci } 4454514f5e3Sopenharmony_ci } else { 4464514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = BuildDictionaryProperties(thread, JSHandle<JSObject>(constructor), staticKeys, 4474514f5e3Sopenharmony_ci staticProperties, ClassPropertyType::STATIC, lexenv); 4484514f5e3Sopenharmony_ci constructor->SetProperties(thread, dict); 4494514f5e3Sopenharmony_ci } 4504514f5e3Sopenharmony_ci 4514514f5e3Sopenharmony_ci // static elements 4524514f5e3Sopenharmony_ci if (UNLIKELY(extractor->GetStaticWithElements())) { 4534514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticElements(thread, extractor->GetStaticElements()); 4544514f5e3Sopenharmony_ci ClassHelper::HandleElementsProperties(thread, JSHandle<JSObject>(constructor), lexenv, staticElements); 4554514f5e3Sopenharmony_ci } 4564514f5e3Sopenharmony_ci 4574514f5e3Sopenharmony_ci PropertyDescriptor ctorDesc(thread, JSHandle<JSTaggedValue>(constructor), true, false, true); 4584514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 4594514f5e3Sopenharmony_ci JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(prototype), 4604514f5e3Sopenharmony_ci globalConst->GetHandledConstructorString(), ctorDesc); 4614514f5e3Sopenharmony_ci RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSFunction, thread); 4624514f5e3Sopenharmony_ci constructor->SetHomeObject(thread, prototype); 4634514f5e3Sopenharmony_ci constructor->SetProtoOrHClass(thread, prototype); 4644514f5e3Sopenharmony_ci if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { 4654514f5e3Sopenharmony_ci thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineClass(constructor.GetTaggedType()); 4664514f5e3Sopenharmony_ci } 4674514f5e3Sopenharmony_ci return constructor; 4684514f5e3Sopenharmony_ci} 4694514f5e3Sopenharmony_ci 4704514f5e3Sopenharmony_ciJSHandle<JSFunction> ClassHelper::DefineClassWithIHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base, 4714514f5e3Sopenharmony_ci JSHandle<ClassInfoExtractor> &extractor, 4724514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &lexenv, 4734514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &prototypeOrHClassVal, 4744514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &constructorHClassVal) 4754514f5e3Sopenharmony_ci{ 4764514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 4774514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys()); 4784514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties()); 4794514f5e3Sopenharmony_ci JSHandle<JSHClass> constructorHClass; 4804514f5e3Sopenharmony_ci // When constructorHClassVal is undefined, it means that AOT has not generated the corresponding hclass (chc), 4814514f5e3Sopenharmony_ci // then chc will be created through the interpreter. 4824514f5e3Sopenharmony_ci if (constructorHClassVal->IsUndefined()) { 4834514f5e3Sopenharmony_ci constructorHClass = ClassInfoExtractor::CreateConstructorHClass(thread, base, staticKeys, staticProperties); 4844514f5e3Sopenharmony_ci } else { 4854514f5e3Sopenharmony_ci constructorHClass = JSHandle<JSHClass>(constructorHClassVal); 4864514f5e3Sopenharmony_ci ClassInfoExtractor::CorrectConstructorHClass(thread, staticProperties, *constructorHClass); 4874514f5e3Sopenharmony_ci } 4884514f5e3Sopenharmony_ci 4894514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys()); 4904514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties()); 4914514f5e3Sopenharmony_ci JSHandle<JSObject> prototype; 4924514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> prototypeOrHClass = prototypeOrHClassVal; 4934514f5e3Sopenharmony_ci // When prototypeOrHClassVal is undefined, it means that AOT has not generated the corresponding hclass or 4944514f5e3Sopenharmony_ci // prototype, then prototype will be created through the interpreter. 4954514f5e3Sopenharmony_ci if (prototypeOrHClassVal->IsUndefined()) { 4964514f5e3Sopenharmony_ci JSHandle<JSHClass> prototypeHClass = ClassInfoExtractor::CreatePrototypeHClass(thread, nonStaticKeys, 4974514f5e3Sopenharmony_ci nonStaticProperties); 4984514f5e3Sopenharmony_ci prototype = factory->NewOldSpaceJSObject(prototypeHClass); 4994514f5e3Sopenharmony_ci prototypeOrHClass = JSHandle<JSTaggedValue>(prototype); 5004514f5e3Sopenharmony_ci } else if (prototypeOrHClassVal->IsJSHClass()) { 5014514f5e3Sopenharmony_ci JSHandle<JSHClass> ihclass(prototypeOrHClassVal); 5024514f5e3Sopenharmony_ci prototype = JSHandle<JSObject>(thread, ihclass->GetProto()); 5034514f5e3Sopenharmony_ci } else { 5044514f5e3Sopenharmony_ci prototype = JSHandle<JSObject>(prototypeOrHClassVal); 5054514f5e3Sopenharmony_ci } 5064514f5e3Sopenharmony_ci 5074514f5e3Sopenharmony_ci JSHandle<Method> method(thread, Method::Cast(extractor->GetConstructorMethod().GetTaggedObject())); 5084514f5e3Sopenharmony_ci JSHandle<JSFunction> constructor = factory->NewJSFunctionByHClass(method, constructorHClass, 5094514f5e3Sopenharmony_ci MemSpaceType::NON_MOVABLE); 5104514f5e3Sopenharmony_ci 5114514f5e3Sopenharmony_ci // non-static 5124514f5e3Sopenharmony_ci nonStaticProperties->Set(thread, 0, constructor); 5134514f5e3Sopenharmony_ci 5144514f5e3Sopenharmony_ci uint32_t nonStaticLength = nonStaticProperties->GetLength(); 5154514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined()); 5164514f5e3Sopenharmony_ci 5174514f5e3Sopenharmony_ci if (LIKELY(!prototype->GetJSHClass()->IsDictionaryMode())) { 5184514f5e3Sopenharmony_ci for (uint32_t index = 0; index < nonStaticLength; ++index) { 5194514f5e3Sopenharmony_ci propValue.Update(nonStaticProperties->Get(index)); 5204514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 5214514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 5224514f5e3Sopenharmony_ci propValue.Update(CreateJSFunctionFromTemplate(thread, literalFunc, prototype, lexenv)); 5234514f5e3Sopenharmony_ci } 5244514f5e3Sopenharmony_ci prototype->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue()); 5254514f5e3Sopenharmony_ci } 5264514f5e3Sopenharmony_ci } else { 5274514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = BuildDictionaryProperties(thread, prototype, nonStaticKeys, nonStaticProperties, 5284514f5e3Sopenharmony_ci ClassPropertyType::NON_STATIC, lexenv); 5294514f5e3Sopenharmony_ci prototype->SetProperties(thread, dict); 5304514f5e3Sopenharmony_ci } 5314514f5e3Sopenharmony_ci 5324514f5e3Sopenharmony_ci // non-static elements 5334514f5e3Sopenharmony_ci if (UNLIKELY(extractor->GetNonStaticWithElements())) { 5344514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticElements(thread, extractor->GetNonStaticElements()); 5354514f5e3Sopenharmony_ci ClassHelper::HandleElementsProperties(thread, prototype, lexenv, nonStaticElements); 5364514f5e3Sopenharmony_ci } 5374514f5e3Sopenharmony_ci 5384514f5e3Sopenharmony_ci // static 5394514f5e3Sopenharmony_ci uint32_t staticLength = staticProperties->GetLength(); 5404514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 5414514f5e3Sopenharmony_ci int correntIndex = 0; 5424514f5e3Sopenharmony_ci if (LIKELY(!constructorHClass->IsDictionaryMode())) { 5434514f5e3Sopenharmony_ci for (uint32_t index = 0; index < staticLength; ++index) { 5444514f5e3Sopenharmony_ci propValue.Update(staticProperties->Get(index)); 5454514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 5464514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 5474514f5e3Sopenharmony_ci propValue.Update( 5484514f5e3Sopenharmony_ci CreateJSFunctionFromTemplate(thread, literalFunc, JSHandle<JSObject>(constructor), lexenv)); 5494514f5e3Sopenharmony_ci } 5504514f5e3Sopenharmony_ci bool needCorrentIndex = index >= ClassInfoExtractor::STATIC_RESERVED_LENGTH; 5514514f5e3Sopenharmony_ci if (needCorrentIndex) { 5524514f5e3Sopenharmony_ci key.Update(staticKeys->Get(index)); 5534514f5e3Sopenharmony_ci correntIndex = JSHClass::FindPropertyEntry(thread, *constructorHClass, key.GetTaggedValue()); 5544514f5e3Sopenharmony_ci } 5554514f5e3Sopenharmony_ci JSHandle<JSObject>::Cast(constructor)->SetPropertyInlinedProps(thread, 5564514f5e3Sopenharmony_ci needCorrentIndex ? static_cast<uint32_t>(correntIndex) : index, propValue.GetTaggedValue()); 5574514f5e3Sopenharmony_ci } 5584514f5e3Sopenharmony_ci } else { 5594514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = BuildDictionaryProperties(thread, JSHandle<JSObject>(constructor), staticKeys, 5604514f5e3Sopenharmony_ci staticProperties, ClassPropertyType::STATIC, lexenv); 5614514f5e3Sopenharmony_ci constructor->SetProperties(thread, dict); 5624514f5e3Sopenharmony_ci } 5634514f5e3Sopenharmony_ci 5644514f5e3Sopenharmony_ci // static elements 5654514f5e3Sopenharmony_ci if (UNLIKELY(extractor->GetStaticWithElements())) { 5664514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticElements(thread, extractor->GetStaticElements()); 5674514f5e3Sopenharmony_ci ClassHelper::HandleElementsProperties(thread, JSHandle<JSObject>(constructor), lexenv, staticElements); 5684514f5e3Sopenharmony_ci } 5694514f5e3Sopenharmony_ci 5704514f5e3Sopenharmony_ci PropertyDescriptor ctorDesc(thread, JSHandle<JSTaggedValue>(constructor), true, false, true); 5714514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 5724514f5e3Sopenharmony_ci JSTaggedValue::DefinePropertyOrThrow(thread, JSHandle<JSTaggedValue>(prototype), 5734514f5e3Sopenharmony_ci globalConst->GetHandledConstructorString(), ctorDesc); 5744514f5e3Sopenharmony_ci RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSFunction, thread); 5754514f5e3Sopenharmony_ci constructor->SetHomeObject(thread, prototype); 5764514f5e3Sopenharmony_ci constructor->SetProtoOrHClass(thread, prototypeOrHClass); 5774514f5e3Sopenharmony_ci 5784514f5e3Sopenharmony_ci if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { 5794514f5e3Sopenharmony_ci thread->GetEcmaVM()->GetPGOProfiler()->ProfileDefineClass(constructor.GetTaggedType()); 5804514f5e3Sopenharmony_ci } 5814514f5e3Sopenharmony_ci return constructor; 5824514f5e3Sopenharmony_ci} 5834514f5e3Sopenharmony_ci 5844514f5e3Sopenharmony_ciJSHandle<JSFunction> ClassHelper::CreateJSFunctionFromTemplate(JSThread *thread, 5854514f5e3Sopenharmony_ci const JSHandle<FunctionTemplate> &funcTemp, 5864514f5e3Sopenharmony_ci const JSHandle<JSObject> &homeObject, 5874514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &lexenv) 5884514f5e3Sopenharmony_ci{ 5894514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 5904514f5e3Sopenharmony_ci JSHandle<JSFunction> propFunc = factory->CreateJSFunctionFromTemplate(funcTemp); 5914514f5e3Sopenharmony_ci JSFunction::UpdateProfileTypeInfoCell(thread, funcTemp, propFunc); 5924514f5e3Sopenharmony_ci propFunc->SetHomeObject(thread, homeObject); 5934514f5e3Sopenharmony_ci propFunc->SetLexicalEnv(thread, lexenv); 5944514f5e3Sopenharmony_ci return propFunc; 5954514f5e3Sopenharmony_ci} 5964514f5e3Sopenharmony_ci 5974514f5e3Sopenharmony_ciJSHandle<NameDictionary> ClassHelper::BuildDictionaryProperties(JSThread *thread, const JSHandle<JSObject> &object, 5984514f5e3Sopenharmony_ci JSHandle<TaggedArray> &keys, 5994514f5e3Sopenharmony_ci JSHandle<TaggedArray> &properties, 6004514f5e3Sopenharmony_ci ClassPropertyType type, 6014514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &lexenv) 6024514f5e3Sopenharmony_ci{ 6034514f5e3Sopenharmony_ci uint32_t length = keys->GetLength(); 6044514f5e3Sopenharmony_ci ASSERT(length > PropertyAttributes::MAX_FAST_PROPS_CAPACITY); 6054514f5e3Sopenharmony_ci ASSERT(keys->GetLength() == properties->GetLength()); 6064514f5e3Sopenharmony_ci 6074514f5e3Sopenharmony_ci JSMutableHandle<NameDictionary> dict( 6084514f5e3Sopenharmony_ci thread, NameDictionary::Create(thread, NameDictionary::ComputeHashTableSize(length))); 6094514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propKey(thread, JSTaggedValue::Undefined()); 6104514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined()); 6114514f5e3Sopenharmony_ci for (uint32_t index = 0; index < length; index++) { 6124514f5e3Sopenharmony_ci PropertyAttributes attributes; 6134514f5e3Sopenharmony_ci if (type == ClassPropertyType::STATIC) { 6144514f5e3Sopenharmony_ci switch (index) { 6154514f5e3Sopenharmony_ci case ClassInfoExtractor::LENGTH_INDEX: 6164514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(false, false, true); 6174514f5e3Sopenharmony_ci break; 6184514f5e3Sopenharmony_ci case ClassInfoExtractor::NAME_INDEX: 6194514f5e3Sopenharmony_ci if (LIKELY(properties->Get(ClassInfoExtractor::NAME_INDEX).IsString())) { 6204514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(false, false, true); 6214514f5e3Sopenharmony_ci } else { 6224514f5e3Sopenharmony_ci ASSERT(properties->Get(ClassInfoExtractor::NAME_INDEX).IsFunctionTemplate()); 6234514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(true, false, true); 6244514f5e3Sopenharmony_ci } 6254514f5e3Sopenharmony_ci break; 6264514f5e3Sopenharmony_ci case ClassInfoExtractor::PROTOTYPE_INDEX: 6274514f5e3Sopenharmony_ci attributes = PropertyAttributes::DefaultAccessor(false, false, false); 6284514f5e3Sopenharmony_ci break; 6294514f5e3Sopenharmony_ci default: 6304514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(true, false, true); 6314514f5e3Sopenharmony_ci break; 6324514f5e3Sopenharmony_ci } 6334514f5e3Sopenharmony_ci } else { 6344514f5e3Sopenharmony_ci attributes = PropertyAttributes::Default(true, false, true); // non-enumerable 6354514f5e3Sopenharmony_ci } 6364514f5e3Sopenharmony_ci propKey.Update(keys->Get(index)); 6374514f5e3Sopenharmony_ci propValue.Update(properties->Get(index)); 6384514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 6394514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 6404514f5e3Sopenharmony_ci propValue.Update(CreateJSFunctionFromTemplate(thread, literalFunc, object, lexenv)); 6414514f5e3Sopenharmony_ci } 6424514f5e3Sopenharmony_ci JSHandle<NameDictionary> newDict = NameDictionary::PutIfAbsent(thread, dict, propKey, propValue, attributes); 6434514f5e3Sopenharmony_ci dict.Update(newDict); 6444514f5e3Sopenharmony_ci } 6454514f5e3Sopenharmony_ci return dict; 6464514f5e3Sopenharmony_ci} 6474514f5e3Sopenharmony_ci 6484514f5e3Sopenharmony_cibool ClassHelper::MatchFieldType(SharedFieldType fieldType, JSTaggedValue value) 6494514f5e3Sopenharmony_ci{ 6504514f5e3Sopenharmony_ci // all sendable types can be set to undefined 6514514f5e3Sopenharmony_ci if (value.IsUndefined()) { 6524514f5e3Sopenharmony_ci return true; 6534514f5e3Sopenharmony_ci } 6544514f5e3Sopenharmony_ci uint32_t sharedFieldType = static_cast<uint32_t>(fieldType); 6554514f5e3Sopenharmony_ci if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::NUMBER)) != 0 && value.IsNumber()) { 6564514f5e3Sopenharmony_ci return true; 6574514f5e3Sopenharmony_ci } else if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::BOOLEAN)) != 0 && value.IsBoolean()) { 6584514f5e3Sopenharmony_ci return true; 6594514f5e3Sopenharmony_ci } else if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::STRING)) != 0 && 6604514f5e3Sopenharmony_ci (value.IsString() || value.IsNull())) { 6614514f5e3Sopenharmony_ci return true; 6624514f5e3Sopenharmony_ci } else if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::BIG_INT)) != 0 && value.IsBigInt()) { 6634514f5e3Sopenharmony_ci return true; 6644514f5e3Sopenharmony_ci } else if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::SENDABLE)) != 0 && 6654514f5e3Sopenharmony_ci (value.IsJSShared() || value.IsNull())) { 6664514f5e3Sopenharmony_ci return true; 6674514f5e3Sopenharmony_ci } else if ((sharedFieldType == static_cast<uint32_t>(SharedFieldType::NONE) || 6684514f5e3Sopenharmony_ci (sharedFieldType & static_cast<uint32_t>(SharedFieldType::GENERIC)) != 0) && 6694514f5e3Sopenharmony_ci (value.IsJSShared() || !value.IsHeapObject())) { 6704514f5e3Sopenharmony_ci // (none || generic) && (jsShared || !heapObject) 6714514f5e3Sopenharmony_ci return true; 6724514f5e3Sopenharmony_ci } else if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::NULL_TYPE)) != 0 && value.IsNull()) { 6734514f5e3Sopenharmony_ci return true; 6744514f5e3Sopenharmony_ci } else if ((sharedFieldType & static_cast<uint32_t>(SharedFieldType::UNDEFINED)) != 0 && value.IsUndefined()) { 6754514f5e3Sopenharmony_ci return true; 6764514f5e3Sopenharmony_ci } 6774514f5e3Sopenharmony_ci std::stringstream oss; 6784514f5e3Sopenharmony_ci value.DumpTaggedValueType(oss); 6794514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "Sendable obj Match field type fail. expected type: " << 6804514f5e3Sopenharmony_ci StaticFieldTypeToString(sharedFieldType) << ", actual type: " << oss.str(); 6814514f5e3Sopenharmony_ci return false; 6824514f5e3Sopenharmony_ci} 6834514f5e3Sopenharmony_ci 6844514f5e3Sopenharmony_ciCString ClassHelper::StaticFieldTypeToString(uint32_t fieldType) 6854514f5e3Sopenharmony_ci{ 6864514f5e3Sopenharmony_ci switch (fieldType) { 6874514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::NONE): 6884514f5e3Sopenharmony_ci return "[None]"; 6894514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::NUMBER): 6904514f5e3Sopenharmony_ci return "[Number]"; 6914514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::STRING): 6924514f5e3Sopenharmony_ci return "[String]"; 6934514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::BOOLEAN): 6944514f5e3Sopenharmony_ci return "[Boolean]"; 6954514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::SENDABLE): 6964514f5e3Sopenharmony_ci return "[Sendable Object]"; 6974514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::BIG_INT): 6984514f5e3Sopenharmony_ci return "[BigInt]"; 6994514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::GENERIC): 7004514f5e3Sopenharmony_ci return "[Generic]"; 7014514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::NULL_TYPE): 7024514f5e3Sopenharmony_ci return "[Null]"; 7034514f5e3Sopenharmony_ci case static_cast<uint32_t>(SharedFieldType::UNDEFINED): 7044514f5e3Sopenharmony_ci return "[Undefined]"; 7054514f5e3Sopenharmony_ci default: { 7064514f5e3Sopenharmony_ci CString ret = "unknown type "; 7074514f5e3Sopenharmony_ci return ret.append(std::to_string(fieldType)); 7084514f5e3Sopenharmony_ci } 7094514f5e3Sopenharmony_ci } 7104514f5e3Sopenharmony_ci} 7114514f5e3Sopenharmony_ci 7124514f5e3Sopenharmony_civoid ClassHelper::HandleElementsProperties(JSThread *thread, const JSHandle<JSObject> &object, 7134514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &lexenv, JSHandle<TaggedArray> &elements) 7144514f5e3Sopenharmony_ci{ 7154514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> elementsKey(thread, JSTaggedValue::Undefined()); 7164514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> elementsValue(thread, JSTaggedValue::Undefined()); 7174514f5e3Sopenharmony_ci for (uint32_t index = 0; index < elements->GetLength(); index += 2) { // 2: key-value pair 7184514f5e3Sopenharmony_ci elementsKey.Update(elements->Get(index)); 7194514f5e3Sopenharmony_ci elementsValue.Update(elements->Get(index + 1)); 7204514f5e3Sopenharmony_ci if (elementsValue->IsFunctionTemplate()) { 7214514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(elementsValue); 7224514f5e3Sopenharmony_ci elementsValue.Update(CreateJSFunctionFromTemplate(thread, literalFunc, object, lexenv)); 7234514f5e3Sopenharmony_ci } 7244514f5e3Sopenharmony_ci 7254514f5e3Sopenharmony_ci // class property attribute is not default, will transition to dictionary directly. 7264514f5e3Sopenharmony_ci JSObject::DefinePropertyByLiteral(thread, object, elementsKey, elementsValue, true); 7274514f5e3Sopenharmony_ci } 7284514f5e3Sopenharmony_ci} 7294514f5e3Sopenharmony_ci 7304514f5e3Sopenharmony_ciJSHandle<JSFunction> SendableClassDefiner::DefineSendableClassFromExtractor(JSThread *thread, 7314514f5e3Sopenharmony_ci JSHandle<ClassInfoExtractor> &extractor, const JSHandle<TaggedArray> &staticFieldArray) 7324514f5e3Sopenharmony_ci{ 7334514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 7344514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticKeys(thread, extractor->GetStaticKeys()); 7354514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticProperties(thread, extractor->GetStaticProperties()); 7364514f5e3Sopenharmony_ci SendableClassDefiner::FilterDuplicatedKeys(thread, staticKeys, staticProperties); 7374514f5e3Sopenharmony_ci 7384514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticKeys(thread, extractor->GetNonStaticKeys()); 7394514f5e3Sopenharmony_ci JSHandle<TaggedArray> nonStaticProperties(thread, extractor->GetNonStaticProperties()); 7404514f5e3Sopenharmony_ci SendableClassDefiner::FilterDuplicatedKeys(thread, nonStaticKeys, nonStaticProperties); 7414514f5e3Sopenharmony_ci JSHandle<JSHClass> prototypeHClass = ClassInfoExtractor::CreateSendableHClass(thread, nonStaticKeys, 7424514f5e3Sopenharmony_ci nonStaticProperties, true); 7434514f5e3Sopenharmony_ci JSHandle<JSObject> prototype = factory->NewSharedOldSpaceJSObject(prototypeHClass); 7444514f5e3Sopenharmony_ci uint32_t length = staticFieldArray->GetLength(); 7454514f5e3Sopenharmony_ci uint32_t staticFields = length / 2; // 2: key-type 7464514f5e3Sopenharmony_ci JSHandle<JSHClass> constructorHClass = 7474514f5e3Sopenharmony_ci ClassInfoExtractor::CreateSendableHClass(thread, staticKeys, staticProperties, false, staticFields); 7484514f5e3Sopenharmony_ci JSHandle<Method> method(thread, Method::Cast(extractor->GetConstructorMethod().GetTaggedObject())); 7494514f5e3Sopenharmony_ci /* 7504514f5e3Sopenharmony_ci * Method::SetFunctionKind can't be called here, because method will set kind when set inheritance relationship, 7514514f5e3Sopenharmony_ci * so there is a multi-threading problem with multi-threads define sendable DERIVED class at the same time. 7524514f5e3Sopenharmony_ci * Scenario: 7534514f5e3Sopenharmony_ci * A thread: define DERIVED class X [X's kind = DEFAULT --> BASE CLASS --> DERIVED CLASS], new X() 7544514f5e3Sopenharmony_ci * B thread: define DERIVED class X [X's kind = DEFAULT --> BASE CLASS --> DERIVED CLASS], new X() 7554514f5e3Sopenharmony_ci * Issue: 7564514f5e3Sopenharmony_ci * When A thread new DERIVED class X, X's kind maybe set to BASE CLASS at B thread, 7574514f5e3Sopenharmony_ci * and A thread will throw error when call super(). 7584514f5e3Sopenharmony_ci */ 7594514f5e3Sopenharmony_ci if (!constructorHClass->IsDictionaryMode() && staticFields > 0) { 7604514f5e3Sopenharmony_ci auto layout = JSHandle<LayoutInfo>(thread, constructorHClass->GetLayout()); 7614514f5e3Sopenharmony_ci AddFieldTypeToHClass(thread, staticFieldArray, length, layout, constructorHClass, ~0U); 7624514f5e3Sopenharmony_ci } 7634514f5e3Sopenharmony_ci 7644514f5e3Sopenharmony_ci JSHandle<JSFunction> constructor = factory->NewSFunctionByHClass(method, constructorHClass); 7654514f5e3Sopenharmony_ci 7664514f5e3Sopenharmony_ci // non-static 7674514f5e3Sopenharmony_ci nonStaticProperties->Set(thread, 0, constructor); 7684514f5e3Sopenharmony_ci 7694514f5e3Sopenharmony_ci uint32_t nonStaticLength = nonStaticProperties->GetLength(); 7704514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined()); 7714514f5e3Sopenharmony_ci 7724514f5e3Sopenharmony_ci if (LIKELY(!prototypeHClass->IsDictionaryMode())) { 7734514f5e3Sopenharmony_ci for (uint32_t index = 0; index < nonStaticLength; ++index) { 7744514f5e3Sopenharmony_ci propValue.Update(nonStaticProperties->Get(index)); 7754514f5e3Sopenharmony_ci // constructor don't need to clone 7764514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate() && index != ClassInfoExtractor::CONSTRUCTOR_INDEX) { 7774514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 7784514f5e3Sopenharmony_ci propValue.Update( 7794514f5e3Sopenharmony_ci CreateSFunctionFromTemplate(thread, literalFunc, prototype, JSHandle<JSTaggedValue>(constructor))); 7804514f5e3Sopenharmony_ci } else if (propValue->IsAccessorData()) { 7814514f5e3Sopenharmony_ci UpdateAccessorFunction(thread, propValue, JSHandle<JSTaggedValue>(prototype), constructor); 7824514f5e3Sopenharmony_ci } 7834514f5e3Sopenharmony_ci prototype->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue()); 7844514f5e3Sopenharmony_ci } 7854514f5e3Sopenharmony_ci } else { 7864514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = BuildSendableDictionaryProperties(thread, prototype, nonStaticKeys, 7874514f5e3Sopenharmony_ci nonStaticProperties, ClassPropertyType::NON_STATIC, constructor); 7884514f5e3Sopenharmony_ci prototype->SetProperties(thread, dict); 7894514f5e3Sopenharmony_ci } 7904514f5e3Sopenharmony_ci 7914514f5e3Sopenharmony_ci // non-static elements 7924514f5e3Sopenharmony_ci if (UNLIKELY(extractor->GetNonStaticWithElements())) { 7934514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "Concurrent class don't support members with numerical key", 7944514f5e3Sopenharmony_ci JSHandle<JSFunction>(thread, JSTaggedValue::Exception())); 7954514f5e3Sopenharmony_ci } 7964514f5e3Sopenharmony_ci 7974514f5e3Sopenharmony_ci // static 7984514f5e3Sopenharmony_ci uint32_t staticLength = staticProperties->GetLength(); 7994514f5e3Sopenharmony_ci if (LIKELY(!constructorHClass->IsDictionaryMode())) { 8004514f5e3Sopenharmony_ci for (uint32_t index = 0; index < staticLength; ++index) { 8014514f5e3Sopenharmony_ci propValue.Update(staticProperties->Get(index)); 8024514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 8034514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 8044514f5e3Sopenharmony_ci propValue.Update(CreateSFunctionFromTemplate( 8054514f5e3Sopenharmony_ci thread, literalFunc, JSHandle<JSObject>(constructor), JSHandle<JSTaggedValue>(constructor))); 8064514f5e3Sopenharmony_ci } else if (propValue->IsAccessorData()) { 8074514f5e3Sopenharmony_ci UpdateAccessorFunction(thread, propValue, JSHandle<JSTaggedValue>(constructor), constructor); 8084514f5e3Sopenharmony_ci } 8094514f5e3Sopenharmony_ci JSHandle<JSObject>::Cast(constructor)->SetPropertyInlinedProps(thread, index, propValue.GetTaggedValue()); 8104514f5e3Sopenharmony_ci } 8114514f5e3Sopenharmony_ci } else { 8124514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = 8134514f5e3Sopenharmony_ci BuildSendableDictionaryProperties(thread, JSHandle<JSObject>(constructor), staticKeys, 8144514f5e3Sopenharmony_ci staticProperties, ClassPropertyType::STATIC, constructor); 8154514f5e3Sopenharmony_ci JSMutableHandle<NameDictionary> nameDict(thread, dict); 8164514f5e3Sopenharmony_ci if (staticFields > 0) { 8174514f5e3Sopenharmony_ci AddFieldTypeToDict(thread, staticFieldArray, length, nameDict, 8184514f5e3Sopenharmony_ci PropertyAttributes::Default(true, true, false)); 8194514f5e3Sopenharmony_ci } 8204514f5e3Sopenharmony_ci constructor->SetProperties(thread, nameDict); 8214514f5e3Sopenharmony_ci } 8224514f5e3Sopenharmony_ci 8234514f5e3Sopenharmony_ci // static elements 8244514f5e3Sopenharmony_ci if (UNLIKELY(extractor->GetStaticWithElements())) { 8254514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "Concurrent class don't support static members with numerical key", 8264514f5e3Sopenharmony_ci JSHandle<JSFunction>(thread, JSTaggedValue::Exception())); 8274514f5e3Sopenharmony_ci } 8284514f5e3Sopenharmony_ci prototype->GetJSHClass()->SetExtensible(false); 8294514f5e3Sopenharmony_ci constructor->SetHomeObject(thread, prototype); 8304514f5e3Sopenharmony_ci constructor->SetProtoOrHClass(thread, prototype); 8314514f5e3Sopenharmony_ci constructor->SetLexicalEnv(thread, constructor); 8324514f5e3Sopenharmony_ci return constructor; 8334514f5e3Sopenharmony_ci} 8344514f5e3Sopenharmony_ci 8354514f5e3Sopenharmony_ci// Process duplicated key due to getter/setter. 8364514f5e3Sopenharmony_civoid SendableClassDefiner::FilterDuplicatedKeys(JSThread *thread, const JSHandle<TaggedArray> &keys, 8374514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &properties) 8384514f5e3Sopenharmony_ci{ 8394514f5e3Sopenharmony_ci auto attr = PropertyAttributes::Default(); 8404514f5e3Sopenharmony_ci uint32_t length = keys->GetLength(); 8414514f5e3Sopenharmony_ci uint32_t left = 0; 8424514f5e3Sopenharmony_ci uint32_t right = 0; 8434514f5e3Sopenharmony_ci JSMutableHandle<NameDictionary> dict( 8444514f5e3Sopenharmony_ci thread, NameDictionary::Create(thread, NameDictionary::ComputeHashTableSize(length))); 8454514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 8464514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> value(thread, JSTaggedValue::Undefined()); 8474514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> existValue(thread, JSTaggedValue::Undefined()); 8484514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> index(thread, JSTaggedValue::Undefined()); 8494514f5e3Sopenharmony_ci for (; right < length; right++) { 8504514f5e3Sopenharmony_ci key.Update(keys->Get(right)); 8514514f5e3Sopenharmony_ci value.Update(properties->Get(right)); 8524514f5e3Sopenharmony_ci int entry = dict->FindEntry(key.GetTaggedValue()); 8534514f5e3Sopenharmony_ci if (entry == -1) { 8544514f5e3Sopenharmony_ci TryUpdateValue(thread, value); 8554514f5e3Sopenharmony_ci index.Update(JSTaggedValue(left)); 8564514f5e3Sopenharmony_ci JSHandle<NameDictionary> newDict = 8574514f5e3Sopenharmony_ci NameDictionary::PutIfAbsent(thread, dict, key, index, attr); 8584514f5e3Sopenharmony_ci dict.Update(newDict); 8594514f5e3Sopenharmony_ci if (left < right) { 8604514f5e3Sopenharmony_ci keys->Set(thread, left, key); 8614514f5e3Sopenharmony_ci } 8624514f5e3Sopenharmony_ci properties->Set(thread, left, value); 8634514f5e3Sopenharmony_ci left++; 8644514f5e3Sopenharmony_ci continue; 8654514f5e3Sopenharmony_ci } 8664514f5e3Sopenharmony_ci auto existIndex = static_cast<uint32_t>(dict->GetValue(entry).GetNumber()); 8674514f5e3Sopenharmony_ci existValue.Update(properties->Get(existIndex)); 8684514f5e3Sopenharmony_ci bool needUpdateValue = TryUpdateExistValue(thread, existValue, value); 8694514f5e3Sopenharmony_ci if (needUpdateValue) { 8704514f5e3Sopenharmony_ci properties->Set(thread, existIndex, value); 8714514f5e3Sopenharmony_ci } 8724514f5e3Sopenharmony_ci } 8734514f5e3Sopenharmony_ci if (left < right) { 8744514f5e3Sopenharmony_ci keys->Trim(thread, left); 8754514f5e3Sopenharmony_ci properties->Trim(thread, left); 8764514f5e3Sopenharmony_ci } 8774514f5e3Sopenharmony_ci} 8784514f5e3Sopenharmony_ci 8794514f5e3Sopenharmony_ciJSHandle<NameDictionary> SendableClassDefiner::BuildSendableDictionaryProperties(JSThread *thread, 8804514f5e3Sopenharmony_ci const JSHandle<JSObject> &object, JSHandle<TaggedArray> &keys, JSHandle<TaggedArray> &properties, 8814514f5e3Sopenharmony_ci ClassPropertyType type, const JSHandle<JSFunction> &ctor) 8824514f5e3Sopenharmony_ci{ 8834514f5e3Sopenharmony_ci uint32_t length = keys->GetLength(); 8844514f5e3Sopenharmony_ci ASSERT(keys->GetLength() == properties->GetLength()); 8854514f5e3Sopenharmony_ci 8864514f5e3Sopenharmony_ci JSMutableHandle<NameDictionary> dict( 8874514f5e3Sopenharmony_ci thread, NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(length))); 8884514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propKey(thread, JSTaggedValue::Undefined()); 8894514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> propValue(thread, JSTaggedValue::Undefined()); 8904514f5e3Sopenharmony_ci for (uint32_t index = 0; index < length; index++) { 8914514f5e3Sopenharmony_ci PropertyAttributes attributes = PropertyAttributes::Default(false, false, false); 8924514f5e3Sopenharmony_ci if (UNLIKELY(properties->Get(index).IsAccessor())) { 8934514f5e3Sopenharmony_ci attributes.SetIsAccessor(true); 8944514f5e3Sopenharmony_ci } 8954514f5e3Sopenharmony_ci propKey.Update(keys->Get(index)); 8964514f5e3Sopenharmony_ci propValue.Update(properties->Get(index)); 8974514f5e3Sopenharmony_ci // constructor don't need to clone 8984514f5e3Sopenharmony_ci if (index == ClassInfoExtractor::CONSTRUCTOR_INDEX && type == ClassPropertyType::NON_STATIC) { 8994514f5e3Sopenharmony_ci JSHandle<NameDictionary> newDict = 9004514f5e3Sopenharmony_ci NameDictionary::PutIfAbsent(thread, dict, propKey, propValue, attributes); 9014514f5e3Sopenharmony_ci dict.Update(newDict); 9024514f5e3Sopenharmony_ci continue; 9034514f5e3Sopenharmony_ci } 9044514f5e3Sopenharmony_ci if (propValue->IsFunctionTemplate()) { 9054514f5e3Sopenharmony_ci auto literalFunc = JSHandle<FunctionTemplate>::Cast(propValue); 9064514f5e3Sopenharmony_ci propValue.Update(CreateSFunctionFromTemplate(thread, literalFunc, object, JSHandle<JSTaggedValue>(ctor))); 9074514f5e3Sopenharmony_ci } else if (propValue->IsAccessorData()) { 9084514f5e3Sopenharmony_ci UpdateAccessorFunction(thread, propValue, JSHandle<JSTaggedValue>(object), ctor); 9094514f5e3Sopenharmony_ci } 9104514f5e3Sopenharmony_ci JSHandle<NameDictionary> newDict = NameDictionary::PutIfAbsent(thread, dict, propKey, propValue, attributes); 9114514f5e3Sopenharmony_ci dict.Update(newDict); 9124514f5e3Sopenharmony_ci } 9134514f5e3Sopenharmony_ci return dict; 9144514f5e3Sopenharmony_ci} 9154514f5e3Sopenharmony_ci 9164514f5e3Sopenharmony_ciJSHandle<JSFunction> SendableClassDefiner::CreateSFunctionFromTemplate(JSThread *thread, 9174514f5e3Sopenharmony_ci const JSHandle<FunctionTemplate> &funcTemp, 9184514f5e3Sopenharmony_ci const JSHandle<JSObject> &homeObject, 9194514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &lexenv) 9204514f5e3Sopenharmony_ci{ 9214514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 9224514f5e3Sopenharmony_ci JSHandle<JSFunction> propFunc = factory->CreateSFunctionFromTemplate(funcTemp); 9234514f5e3Sopenharmony_ci propFunc->SetHomeObject(thread, homeObject); 9244514f5e3Sopenharmony_ci propFunc->SetLexicalEnv(thread, lexenv); 9254514f5e3Sopenharmony_ci ASSERT(!propFunc->GetClass()->IsExtensible()); 9264514f5e3Sopenharmony_ci return propFunc; 9274514f5e3Sopenharmony_ci} 9284514f5e3Sopenharmony_ci 9294514f5e3Sopenharmony_civoid SendableClassDefiner::AddFieldTypeToDict(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray, 9304514f5e3Sopenharmony_ci uint32_t length, JSMutableHandle<NameDictionary> &dict, PropertyAttributes attributes) 9314514f5e3Sopenharmony_ci{ 9324514f5e3Sopenharmony_ci ASSERT(length <= fieldTypeArray->GetLength()); 9334514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 9344514f5e3Sopenharmony_ci auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants()); 9354514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = globalConst->GetHandledUndefined(); 9364514f5e3Sopenharmony_ci for (uint32_t i = 0; i < length; i += 2) { // 2: key-value pair; 9374514f5e3Sopenharmony_ci key.Update(fieldTypeArray->Get(i)); 9384514f5e3Sopenharmony_ci ASSERT(key->IsString()); 9394514f5e3Sopenharmony_ci SharedFieldType type = FromFieldType(FieldType(fieldTypeArray->Get(i + 1).GetInt())); 9404514f5e3Sopenharmony_ci attributes.SetSharedFieldType(type); 9414514f5e3Sopenharmony_ci attributes.SetBoxType(PropertyBoxType::UNDEFINED); 9424514f5e3Sopenharmony_ci JSHandle<NameDictionary> newDict = NameDictionary::Put(thread, dict, key, value, attributes); 9434514f5e3Sopenharmony_ci dict.Update(newDict); 9444514f5e3Sopenharmony_ci } 9454514f5e3Sopenharmony_ci} 9464514f5e3Sopenharmony_ci 9474514f5e3Sopenharmony_civoid SendableClassDefiner::AddFieldTypeToHClass(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray, 9484514f5e3Sopenharmony_ci uint32_t length, const JSHandle<LayoutInfo> &layout, 9494514f5e3Sopenharmony_ci const JSHandle<JSHClass> &hclass, size_t start, 9504514f5e3Sopenharmony_ci const JSHandle<NumberDictionary> &elementsDic, 9514514f5e3Sopenharmony_ci std::vector<JSHandle<JSTaggedValue>> &&propertyList) 9524514f5e3Sopenharmony_ci{ 9534514f5e3Sopenharmony_ci ASSERT(length <= fieldTypeArray->GetLength()); 9544514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 9554514f5e3Sopenharmony_ci uint32_t index = static_cast<uint32_t>(layout->NumberOfElements()); 9564514f5e3Sopenharmony_ci JSMutableHandle<NumberDictionary> elementsDicUpdate(thread, elementsDic); 9574514f5e3Sopenharmony_ci const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 9584514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> undefinedVal(thread, globalConst->GetUndefined()); 9594514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> eleIndexKey(thread, JSTaggedValue::Undefined()); 9604514f5e3Sopenharmony_ci for (uint32_t i = 0; i < length; i += 2) { // 2: key-value pair; 9614514f5e3Sopenharmony_ci PropertyAttributes attributes = PropertyAttributes::Default(true, true, false); 9624514f5e3Sopenharmony_ci key.Update(fieldTypeArray->Get(i)); 9634514f5e3Sopenharmony_ci ASSERT(key->IsString()); 9644514f5e3Sopenharmony_ci SharedFieldType type = FromFieldType(FieldType(fieldTypeArray->Get(i + 1).GetInt())); 9654514f5e3Sopenharmony_ci int entry = layout->FindElementWithCache(thread, *hclass, key.GetTaggedValue(), index); 9664514f5e3Sopenharmony_ci if (entry != -1) { 9674514f5e3Sopenharmony_ci attributes = layout->GetAttr(entry); 9684514f5e3Sopenharmony_ci attributes.SetSharedFieldType(type); 9694514f5e3Sopenharmony_ci layout->SetNormalAttr(thread, entry, attributes); 9704514f5e3Sopenharmony_ci if (start != ~0U && propertyList.size() > 0) { 9714514f5e3Sopenharmony_ci propertyList[start + (static_cast<uint32_t>(entry) << 1)] = propertyList[start + i]; 9724514f5e3Sopenharmony_ci propertyList[start + (static_cast<uint32_t>(entry) << 1) + 1] = propertyList[start + i + 1]; 9734514f5e3Sopenharmony_ci } 9744514f5e3Sopenharmony_ci } else { 9754514f5e3Sopenharmony_ci if (start != ~0U && propertyList.size() > 0) { 9764514f5e3Sopenharmony_ci propertyList[start + (index << 1)] = propertyList[start + i]; 9774514f5e3Sopenharmony_ci propertyList[start + (index << 1) + 1] = propertyList[start + i + 1]; 9784514f5e3Sopenharmony_ci } 9794514f5e3Sopenharmony_ci attributes.SetIsInlinedProps(true); 9804514f5e3Sopenharmony_ci attributes.SetRepresentation(Representation::TAGGED); 9814514f5e3Sopenharmony_ci attributes.SetSharedFieldType(type); 9824514f5e3Sopenharmony_ci attributes.SetOffset(index); 9834514f5e3Sopenharmony_ci layout->AddKey(thread, index++, key.GetTaggedValue(), attributes); 9844514f5e3Sopenharmony_ci int64_t eleIndex = ObjectFastOperator::TryToElementsIndex(key.GetTaggedValue()); 9854514f5e3Sopenharmony_ci if (eleIndex >= 0 && !elementsDic.IsEmpty()) { 9864514f5e3Sopenharmony_ci eleIndexKey.Update(JSTaggedValue(eleIndex)); 9874514f5e3Sopenharmony_ci JSHandle<NumberDictionary> newElementsDic = NumberDictionary::Put( 9884514f5e3Sopenharmony_ci thread, elementsDic, eleIndexKey, undefinedVal, attributes); 9894514f5e3Sopenharmony_ci elementsDicUpdate.Update(newElementsDic); 9904514f5e3Sopenharmony_ci } 9914514f5e3Sopenharmony_ci } 9924514f5e3Sopenharmony_ci } 9934514f5e3Sopenharmony_ci hclass->SetLayout(thread, layout); 9944514f5e3Sopenharmony_ci hclass->SetNumberOfProps(index); 9954514f5e3Sopenharmony_ci auto inlinedProps = hclass->GetInlinedProperties(); 9964514f5e3Sopenharmony_ci if (inlinedProps > index) { 9974514f5e3Sopenharmony_ci // resize hclass due to duplicated key. 9984514f5e3Sopenharmony_ci uint32_t duplicatedSize = (inlinedProps - index) * JSTaggedValue::TaggedTypeSize(); 9994514f5e3Sopenharmony_ci hclass->SetObjectSize(hclass->GetObjectSize() - duplicatedSize); 10004514f5e3Sopenharmony_ci } 10014514f5e3Sopenharmony_ci} 10024514f5e3Sopenharmony_ci 10034514f5e3Sopenharmony_civoid SendableClassDefiner::AddFieldTypeToHClass(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray, 10044514f5e3Sopenharmony_ci uint32_t length, const JSHandle<NameDictionary> &nameDict, const JSHandle<JSHClass> &hclass) 10054514f5e3Sopenharmony_ci{ 10064514f5e3Sopenharmony_ci JSMutableHandle<NameDictionary> dict(thread, nameDict); 10074514f5e3Sopenharmony_ci AddFieldTypeToDict(thread, fieldTypeArray, length, dict); 10084514f5e3Sopenharmony_ci hclass->SetLayout(thread, dict); 10094514f5e3Sopenharmony_ci hclass->SetNumberOfProps(0); 10104514f5e3Sopenharmony_ci hclass->SetIsDictionaryMode(true); 10114514f5e3Sopenharmony_ci} 10124514f5e3Sopenharmony_ci 10134514f5e3Sopenharmony_civoid SendableClassDefiner::DefineSendableInstanceHClass(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray, 10144514f5e3Sopenharmony_ci uint32_t length, const JSHandle<JSFunction> &ctor, const JSHandle<JSTaggedValue> &base) 10154514f5e3Sopenharmony_ci{ 10164514f5e3Sopenharmony_ci ASSERT(ctor->GetClass()->IsJSSharedFunction()); 10174514f5e3Sopenharmony_ci JSHandle<JSObject> clsPrototype(thread, JSHandle<JSFunction>(ctor)->GetFunctionPrototype()); 10184514f5e3Sopenharmony_ci ASSERT(clsPrototype->GetClass()->IsJSSharedObject()); 10194514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 10204514f5e3Sopenharmony_ci ASSERT(length <= fieldTypeArray->GetLength()); 10214514f5e3Sopenharmony_ci uint32_t fieldNum = length / 2; // 2: key-value pair; 10224514f5e3Sopenharmony_ci JSHandle<JSHClass> iHClass; 10234514f5e3Sopenharmony_ci if (base->IsHole() || base->IsNull()) { 10244514f5e3Sopenharmony_ci if (fieldNum == 0) { 10254514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(JSSharedObject::SIZE, JSType::JS_SHARED_OBJECT, fieldNum); 10264514f5e3Sopenharmony_ci } else if (LIKELY(fieldNum <= JSSharedObject::MAX_INLINE)) { 10274514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(JSSharedObject::SIZE, JSType::JS_SHARED_OBJECT, fieldNum); 10284514f5e3Sopenharmony_ci JSHandle<LayoutInfo> layout = factory->CreateSLayoutInfo(fieldNum); 10294514f5e3Sopenharmony_ci AddFieldTypeToHClass(thread, fieldTypeArray, length, layout, iHClass, ~0U); 10304514f5e3Sopenharmony_ci } else { 10314514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(JSSharedObject::SIZE, JSType::JS_SHARED_OBJECT, 0); 10324514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = 10334514f5e3Sopenharmony_ci NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(fieldNum)); 10344514f5e3Sopenharmony_ci AddFieldTypeToHClass(thread, fieldTypeArray, length, dict, iHClass); 10354514f5e3Sopenharmony_ci } 10364514f5e3Sopenharmony_ci } else { 10374514f5e3Sopenharmony_ci ASSERT(base->IsJSSharedFunction()); 10384514f5e3Sopenharmony_ci JSHandle<JSFunction> baseCtor = JSHandle<JSFunction>::Cast(base); 10394514f5e3Sopenharmony_ci JSHandle<JSHClass> baseIHClass(thread, baseCtor->GetProtoOrHClass()); 10404514f5e3Sopenharmony_ci ASSERT(baseIHClass->IsJSShared()); 10414514f5e3Sopenharmony_ci JSType baseType = baseIHClass->GetObjectType(); 10424514f5e3Sopenharmony_ci const auto [baseSize, baseMaxInlineSize] = GetSizeAndMaxInlineByType(baseType); 10434514f5e3Sopenharmony_ci if (LIKELY(!baseIHClass->IsDictionaryMode())) { 10444514f5e3Sopenharmony_ci auto baseLength = baseIHClass->NumberOfProps(); 10454514f5e3Sopenharmony_ci JSHandle<LayoutInfo> baseLayout(thread, baseIHClass->GetLayout()); 10464514f5e3Sopenharmony_ci auto newLength = baseLength + fieldNum; 10474514f5e3Sopenharmony_ci if (newLength == 0) { 10484514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(baseSize, baseType, 0); 10494514f5e3Sopenharmony_ci } else if (LIKELY(newLength <= baseMaxInlineSize)) { 10504514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(baseSize, baseType, newLength); 10514514f5e3Sopenharmony_ci JSHandle<LayoutInfo> layout = factory->CopyAndReSortSLayoutInfo(baseLayout, baseLength, newLength); 10524514f5e3Sopenharmony_ci AddFieldTypeToHClass(thread, fieldTypeArray, length, layout, iHClass, ~0U); 10534514f5e3Sopenharmony_ci } else { 10544514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(baseSize, baseType, 0); 10554514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = 10564514f5e3Sopenharmony_ci NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(newLength)); 10574514f5e3Sopenharmony_ci auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants()); 10584514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> value = globalConst->GetHandledUndefined(); 10594514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> key(thread, JSTaggedValue::Undefined()); 10604514f5e3Sopenharmony_ci for (uint32_t i = 0; i < baseLength; i++) { 10614514f5e3Sopenharmony_ci key.Update(baseLayout->GetKey(i)); 10624514f5e3Sopenharmony_ci PropertyAttributes attr = baseLayout->GetAttr(i); 10634514f5e3Sopenharmony_ci attr.SetIsInlinedProps(false); 10644514f5e3Sopenharmony_ci attr.SetBoxType(PropertyBoxType::UNDEFINED); 10654514f5e3Sopenharmony_ci dict = NameDictionary::Put(thread, dict, key, value, attr); 10664514f5e3Sopenharmony_ci } 10674514f5e3Sopenharmony_ci AddFieldTypeToHClass(thread, fieldTypeArray, length, dict, iHClass); 10684514f5e3Sopenharmony_ci } 10694514f5e3Sopenharmony_ci } else { 10704514f5e3Sopenharmony_ci JSHandle<NameDictionary> baseDict(thread, baseIHClass->GetLayout()); 10714514f5e3Sopenharmony_ci auto baseLength = baseDict->EntriesCount(); 10724514f5e3Sopenharmony_ci auto newLength = fieldNum + static_cast<uint32_t>(baseLength); 10734514f5e3Sopenharmony_ci JSHandle<NameDictionary> dict = 10744514f5e3Sopenharmony_ci NameDictionary::CreateInSharedHeap(thread, NameDictionary::ComputeHashTableSize(newLength)); 10754514f5e3Sopenharmony_ci baseDict->Rehash(thread, *dict); 10764514f5e3Sopenharmony_ci dict->SetNextEnumerationIndex(thread, baseDict->GetNextEnumerationIndex()); 10774514f5e3Sopenharmony_ci iHClass = factory->NewSEcmaHClass(baseSize, baseType, 0); 10784514f5e3Sopenharmony_ci AddFieldTypeToHClass(thread, fieldTypeArray, length, dict, iHClass); 10794514f5e3Sopenharmony_ci } 10804514f5e3Sopenharmony_ci } 10814514f5e3Sopenharmony_ci iHClass->SetPrototype(thread, JSHandle<JSTaggedValue>(clsPrototype)); 10824514f5e3Sopenharmony_ci iHClass->SetExtensible(false); 10834514f5e3Sopenharmony_ci ctor->SetProtoOrHClass(thread, iHClass); 10844514f5e3Sopenharmony_ci ctor->GetJSHClass()->SetExtensible(false); 10854514f5e3Sopenharmony_ci} 10864514f5e3Sopenharmony_ci 10874514f5e3Sopenharmony_ciJSHandle<TaggedArray> SendableClassDefiner::ExtractStaticFieldTypeArray(JSThread *thread, 10884514f5e3Sopenharmony_ci const JSHandle<TaggedArray> &fieldTypeArray) 10894514f5e3Sopenharmony_ci{ 10904514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 10914514f5e3Sopenharmony_ci uint32_t arrayLength = fieldTypeArray->GetLength(); 10924514f5e3Sopenharmony_ci ASSERT(arrayLength > 0); 10934514f5e3Sopenharmony_ci auto instanceFieldNums = static_cast<uint32_t>(fieldTypeArray->Get(arrayLength - 1).GetInt()); 10944514f5e3Sopenharmony_ci uint32_t staticFieldBegin = instanceFieldNums * 2; // 2: key-type 10954514f5e3Sopenharmony_ci if (staticFieldBegin >= arrayLength) { 10964514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "ExtractStaticFieldTypeArray Failed, staticFieldBegin:" << staticFieldBegin 10974514f5e3Sopenharmony_ci << " should be less than totalLength:" << arrayLength; 10984514f5e3Sopenharmony_ci return factory->EmptyArray(); 10994514f5e3Sopenharmony_ci } 11004514f5e3Sopenharmony_ci uint32_t staticFieldLength = arrayLength - staticFieldBegin - 1; 11014514f5e3Sopenharmony_ci JSHandle<TaggedArray> staticFieldArray = factory->NewTaggedArray(staticFieldLength); 11024514f5e3Sopenharmony_ci for (uint32_t i = 0; i < staticFieldLength; i += 2) { // 2: key-type 11034514f5e3Sopenharmony_ci staticFieldArray->Set(thread, i, fieldTypeArray->Get(staticFieldBegin + i)); 11044514f5e3Sopenharmony_ci staticFieldArray->Set(thread, i + 1, fieldTypeArray->Get(staticFieldBegin + i + 1)); 11054514f5e3Sopenharmony_ci } 11064514f5e3Sopenharmony_ci return staticFieldArray; 11074514f5e3Sopenharmony_ci} 11084514f5e3Sopenharmony_ci 11094514f5e3Sopenharmony_civoid SendableClassDefiner::UpdateAccessorFunction(JSThread *thread, const JSMutableHandle<JSTaggedValue> &value, 11104514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &homeObject, const JSHandle<JSFunction> &ctor) 11114514f5e3Sopenharmony_ci{ 11124514f5e3Sopenharmony_ci ASSERT(value->IsAccessorData()); 11134514f5e3Sopenharmony_ci JSHandle<AccessorData> accessor(value); 11144514f5e3Sopenharmony_ci auto getter = accessor->GetGetter(); 11154514f5e3Sopenharmony_ci if (getter.IsFunctionTemplate()) { 11164514f5e3Sopenharmony_ci auto funcTemp = JSHandle<FunctionTemplate>(thread, getter); 11174514f5e3Sopenharmony_ci auto propFunc = CreateSFunctionFromTemplate( 11184514f5e3Sopenharmony_ci thread, funcTemp, JSHandle<JSObject>(homeObject), JSHandle<JSTaggedValue>(ctor)); 11194514f5e3Sopenharmony_ci accessor->SetGetter(thread, propFunc); 11204514f5e3Sopenharmony_ci } 11214514f5e3Sopenharmony_ci auto setter = accessor->GetSetter(); 11224514f5e3Sopenharmony_ci if (setter.IsFunctionTemplate()) { 11234514f5e3Sopenharmony_ci auto funcTemp = JSHandle<FunctionTemplate>(thread, setter); 11244514f5e3Sopenharmony_ci auto propFunc = CreateSFunctionFromTemplate( 11254514f5e3Sopenharmony_ci thread, funcTemp, JSHandle<JSObject>(homeObject), JSHandle<JSTaggedValue>(ctor)); 11264514f5e3Sopenharmony_ci accessor->SetSetter(thread, propFunc); 11274514f5e3Sopenharmony_ci } 11284514f5e3Sopenharmony_ci} 11294514f5e3Sopenharmony_ci 11304514f5e3Sopenharmony_cibool SendableClassDefiner::TryUpdateExistValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &existValue, 11314514f5e3Sopenharmony_ci JSMutableHandle<JSTaggedValue> &value) 11324514f5e3Sopenharmony_ci{ 11334514f5e3Sopenharmony_ci bool needUpdateValue = true; 11344514f5e3Sopenharmony_ci if (existValue->IsAccessorData()) { 11354514f5e3Sopenharmony_ci if (value->IsFunctionTemplate() && JSHandle<FunctionTemplate>(value)->IsGetterOrSetter()) { 11364514f5e3Sopenharmony_ci JSHandle<AccessorData> accessor(existValue); 11374514f5e3Sopenharmony_ci UpdateValueToAccessor(thread, value, accessor); 11384514f5e3Sopenharmony_ci needUpdateValue = false; 11394514f5e3Sopenharmony_ci } 11404514f5e3Sopenharmony_ci } else { 11414514f5e3Sopenharmony_ci if (value->IsFunctionTemplate() && JSHandle<FunctionTemplate>(value)->IsGetterOrSetter()) { 11424514f5e3Sopenharmony_ci JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewSAccessorData(); 11434514f5e3Sopenharmony_ci UpdateValueToAccessor(thread, value, accessor); 11444514f5e3Sopenharmony_ci } 11454514f5e3Sopenharmony_ci } 11464514f5e3Sopenharmony_ci return needUpdateValue; 11474514f5e3Sopenharmony_ci} 11484514f5e3Sopenharmony_ci 11494514f5e3Sopenharmony_civoid SendableClassDefiner::TryUpdateValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &value) 11504514f5e3Sopenharmony_ci{ 11514514f5e3Sopenharmony_ci if (value->IsFunctionTemplate() && JSHandle<FunctionTemplate>(value)->IsGetterOrSetter()) { 11524514f5e3Sopenharmony_ci JSHandle<AccessorData> accessor = thread->GetEcmaVM()->GetFactory()->NewSAccessorData(); 11534514f5e3Sopenharmony_ci UpdateValueToAccessor(thread, value, accessor); 11544514f5e3Sopenharmony_ci } 11554514f5e3Sopenharmony_ci} 11564514f5e3Sopenharmony_ci 11574514f5e3Sopenharmony_civoid SendableClassDefiner::UpdateValueToAccessor(JSThread *thread, JSMutableHandle<JSTaggedValue> &value, 11584514f5e3Sopenharmony_ci JSHandle<AccessorData> &accessor) 11594514f5e3Sopenharmony_ci{ 11604514f5e3Sopenharmony_ci ASSERT(value->IsFunctionTemplate() && JSHandle<FunctionTemplate>(value)->IsGetterOrSetter()); 11614514f5e3Sopenharmony_ci if (JSHandle<FunctionTemplate>(value)->IsGetter()) { 11624514f5e3Sopenharmony_ci accessor->SetGetter(thread, value); 11634514f5e3Sopenharmony_ci } else { 11644514f5e3Sopenharmony_ci accessor->SetSetter(thread, value); 11654514f5e3Sopenharmony_ci } 11664514f5e3Sopenharmony_ci value.Update(accessor); 11674514f5e3Sopenharmony_ci} 11684514f5e3Sopenharmony_ci 11694514f5e3Sopenharmony_cistd::pair<uint32_t, uint32_t> SendableClassDefiner::GetSizeAndMaxInlineByType(JSType type) 11704514f5e3Sopenharmony_ci{ 11714514f5e3Sopenharmony_ci switch (type) { 11724514f5e3Sopenharmony_ci case JSType::JS_SHARED_OBJECT: 11734514f5e3Sopenharmony_ci return { JSSharedObject::SIZE, JSSharedObject::MAX_INLINE }; 11744514f5e3Sopenharmony_ci case JSType::JS_SHARED_ARRAY: 11754514f5e3Sopenharmony_ci return { JSSharedArray::SIZE, JSSharedArray::MAX_INLINE }; 11764514f5e3Sopenharmony_ci case JSType::JS_SHARED_MAP: 11774514f5e3Sopenharmony_ci return { JSSharedMap::SIZE, JSSharedMap::MAX_INLINE }; 11784514f5e3Sopenharmony_ci case JSType::JS_SHARED_SET: 11794514f5e3Sopenharmony_ci return { JSSharedSet::SIZE, JSSharedSet::MAX_INLINE }; 11804514f5e3Sopenharmony_ci case JSType::JS_SENDABLE_ARRAY_BUFFER: 11814514f5e3Sopenharmony_ci return { JSSendableArrayBuffer::SIZE, JSSendableArrayBuffer::MAX_INLINE }; 11824514f5e3Sopenharmony_ci default: 11834514f5e3Sopenharmony_ci if (JSType::JS_SHARED_TYPED_ARRAY_FIRST < type && type <= JSType::JS_SHARED_TYPED_ARRAY_LAST) { 11844514f5e3Sopenharmony_ci return { JSSharedTypedArray::SIZE, JSSharedTypedArray::MAX_INLINE }; 11854514f5e3Sopenharmony_ci } 11864514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable, cannot get size for type: " << static_cast<uint32_t>(type); 11874514f5e3Sopenharmony_ci UNREACHABLE(); 11884514f5e3Sopenharmony_ci return {}; 11894514f5e3Sopenharmony_ci } 11904514f5e3Sopenharmony_ci} 11914514f5e3Sopenharmony_ci} // namespace panda::ecmascript 1192