14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2022 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_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H
184514f5e3Sopenharmony_ci#include <vector>
194514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value-inl.h"
204514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value.h"
214514f5e3Sopenharmony_ci#include "ecmascript/js_tagged_value_internals.h"
224514f5e3Sopenharmony_ci#include "ecmascript/jspandafile/method_literal.h"
234514f5e3Sopenharmony_ci#include "ecmascript/property_attributes.h"
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_cinamespace panda::ecmascript {
264514f5e3Sopenharmony_ci// ClassInfoExtractor will analyze and extract the contents from class literal to keys, properties and elements(both
274514f5e3Sopenharmony_ci// non-static and static), later generate the complete hclass (both prototype and constructor) based on keys.
284514f5e3Sopenharmony_ci// Attention: keys accessor stores the property key and properties accessor stores the property value, but elements
294514f5e3Sopenharmony_ci// accessor stores the key-value pair abuttally.
304514f5e3Sopenharmony_ciusing EntityId = panda_file::File::EntityId;
314514f5e3Sopenharmony_cienum class FieldType {
324514f5e3Sopenharmony_ci    NONE = 0,
334514f5e3Sopenharmony_ci    NUMBER = (1 << 0),
344514f5e3Sopenharmony_ci    STRING = (1 << 1),
354514f5e3Sopenharmony_ci    BOOLEAN = (1 << 2),
364514f5e3Sopenharmony_ci    TS_TYPE_REF = (1 << 3),
374514f5e3Sopenharmony_ci    BIG_INT = (1 << 4),
384514f5e3Sopenharmony_ci    GENERIC = (1 << 5),
394514f5e3Sopenharmony_ci    NULL_TYPE = (1 << 6),
404514f5e3Sopenharmony_ci    UNDEFINED = (1 << 7),
414514f5e3Sopenharmony_ci};
424514f5e3Sopenharmony_ciclass ClassInfoExtractor : public TaggedObject {
434514f5e3Sopenharmony_cipublic:
444514f5e3Sopenharmony_ci    static constexpr uint8_t NON_STATIC_RESERVED_LENGTH = 1;
454514f5e3Sopenharmony_ci    static constexpr uint8_t STATIC_RESERVED_LENGTH = 3;
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_ci    static constexpr uint8_t CONSTRUCTOR_INDEX = 0;
484514f5e3Sopenharmony_ci    static constexpr uint8_t LENGTH_INDEX = 0;
494514f5e3Sopenharmony_ci    static constexpr uint8_t NAME_INDEX = 1;
504514f5e3Sopenharmony_ci    static constexpr uint8_t PROTOTYPE_INDEX = 2;
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    struct ExtractContentsDetail {
534514f5e3Sopenharmony_ci        uint32_t extractBegin;
544514f5e3Sopenharmony_ci        uint32_t extractEnd;
554514f5e3Sopenharmony_ci        uint8_t fillStartLoc;
564514f5e3Sopenharmony_ci        MethodLiteral *methodLiteral;
574514f5e3Sopenharmony_ci    };
584514f5e3Sopenharmony_ci
594514f5e3Sopenharmony_ci    CAST_CHECK(ClassInfoExtractor, IsClassInfoExtractor);
604514f5e3Sopenharmony_ci
614514f5e3Sopenharmony_ci    static void BuildClassInfoExtractorFromLiteral(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor,
624514f5e3Sopenharmony_ci                                                   const JSHandle<TaggedArray> &literal,
634514f5e3Sopenharmony_ci                                                   uint32_t length,
644514f5e3Sopenharmony_ci                                                   ClassKind kind = ClassKind::NON_SENDABLE);
654514f5e3Sopenharmony_ci
664514f5e3Sopenharmony_ci    static JSHandle<JSHClass> CreatePrototypeHClass(JSThread *thread,
674514f5e3Sopenharmony_ci                                                    JSHandle<TaggedArray> &keys,
684514f5e3Sopenharmony_ci                                                    JSHandle<TaggedArray> &properties);
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ci    static JSHandle<JSHClass> CreateConstructorHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base,
714514f5e3Sopenharmony_ci                                                      JSHandle<TaggedArray> &keys,
724514f5e3Sopenharmony_ci                                                      JSHandle<TaggedArray> &properties);
734514f5e3Sopenharmony_ci    static JSHandle<JSHClass> CreateSendableHClass(JSThread *thread, JSHandle<TaggedArray> &keys,
744514f5e3Sopenharmony_ci                                                   JSHandle<TaggedArray> &properties, bool isProtoClass,
754514f5e3Sopenharmony_ci                                                   uint32_t extraLength = 0);
764514f5e3Sopenharmony_ci    static void CorrectConstructorHClass(JSThread *thread,
774514f5e3Sopenharmony_ci                                         JSHandle<TaggedArray> &properties,
784514f5e3Sopenharmony_ci                                         JSHClass *constructorHClass);
794514f5e3Sopenharmony_ci
804514f5e3Sopenharmony_ci    static constexpr size_t PROTOTYPE_HCLASS_OFFSET = TaggedObjectSize();
814514f5e3Sopenharmony_ci    ACCESSORS(NonStaticKeys, PROTOTYPE_HCLASS_OFFSET, NON_STATIC_PROPERTIES_OFFSET)
824514f5e3Sopenharmony_ci    ACCESSORS(NonStaticProperties, NON_STATIC_PROPERTIES_OFFSET, NON_STATIC_ELEMENTS_OFFSET)
834514f5e3Sopenharmony_ci    ACCESSORS(NonStaticElements, NON_STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_HCLASS_OFFSET)
844514f5e3Sopenharmony_ci    ACCESSORS(StaticKeys, CONSTRUCTOR_HCLASS_OFFSET, STATIC_PROPERTIES_OFFSET)
854514f5e3Sopenharmony_ci    ACCESSORS(StaticProperties, STATIC_PROPERTIES_OFFSET, STATIC_ELEMENTS_OFFSET)
864514f5e3Sopenharmony_ci    ACCESSORS(StaticElements, STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_METHOD_OFFSET)
874514f5e3Sopenharmony_ci    ACCESSORS(ConstructorMethod, CONSTRUCTOR_METHOD_OFFSET, BIT_FIELD_OFFSET)
884514f5e3Sopenharmony_ci    ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET)
894514f5e3Sopenharmony_ci    DEFINE_ALIGN_SIZE(LAST_OFFSET);
904514f5e3Sopenharmony_ci
914514f5e3Sopenharmony_ci    // define BitField
924514f5e3Sopenharmony_ci    static constexpr size_t NON_STATIC_BITS = 1;
934514f5e3Sopenharmony_ci    static constexpr size_t STATIC_BITS = 1;
944514f5e3Sopenharmony_ci    FIRST_BIT_FIELD(BitField, NonStaticWithElements, bool, NON_STATIC_BITS)
954514f5e3Sopenharmony_ci    NEXT_BIT_FIELD(BitField, StaticWithElements, bool, STATIC_BITS, NonStaticWithElements)
964514f5e3Sopenharmony_ci
974514f5e3Sopenharmony_ci    DECL_VISIT_OBJECT(PROTOTYPE_HCLASS_OFFSET, BIT_FIELD_OFFSET)
984514f5e3Sopenharmony_ci
994514f5e3Sopenharmony_ci    DECL_DUMP()
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_ciprivate:
1024514f5e3Sopenharmony_ci    static bool ExtractAndReturnWhetherWithElements(JSThread *thread, const JSHandle<TaggedArray> &literal,
1034514f5e3Sopenharmony_ci                                                    const ExtractContentsDetail &detail,
1044514f5e3Sopenharmony_ci                                                    JSHandle<TaggedArray> &keys, JSHandle<TaggedArray> &properties,
1054514f5e3Sopenharmony_ci                                                    JSHandle<TaggedArray> &elements,
1064514f5e3Sopenharmony_ci                                                    const JSPandaFile *jsPandaFile);
1074514f5e3Sopenharmony_ci};
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_cienum class ClassPropertyType : uint8_t { NON_STATIC = 0, STATIC };
1104514f5e3Sopenharmony_ci
1114514f5e3Sopenharmony_ciclass ClassHelper {
1124514f5e3Sopenharmony_cipublic:
1134514f5e3Sopenharmony_ci    static JSHandle<JSFunction> DefineClassFromExtractor(JSThread *thread, const JSHandle<JSTaggedValue> &base,
1144514f5e3Sopenharmony_ci                                                         JSHandle<ClassInfoExtractor> &extractor,
1154514f5e3Sopenharmony_ci                                                         const JSHandle<JSTaggedValue> &lexenv);
1164514f5e3Sopenharmony_ci
1174514f5e3Sopenharmony_ci    static JSHandle<JSFunction> DefineClassWithIHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base,
1184514f5e3Sopenharmony_ci                                                       JSHandle<ClassInfoExtractor> &extractor,
1194514f5e3Sopenharmony_ci                                                       const JSHandle<JSTaggedValue> &lexenv,
1204514f5e3Sopenharmony_ci                                                       const JSHandle<JSTaggedValue> &prototypeOrHClassVal,
1214514f5e3Sopenharmony_ci                                                       const JSHandle<JSTaggedValue> &constructorHClassVal);
1224514f5e3Sopenharmony_ci
1234514f5e3Sopenharmony_ci    static bool PUBLIC_API MatchFieldType(SharedFieldType fieldType, JSTaggedValue value);
1244514f5e3Sopenharmony_ci    static CString StaticFieldTypeToString(uint32_t fieldType);
1254514f5e3Sopenharmony_ciprivate:
1264514f5e3Sopenharmony_ci    static JSHandle<NameDictionary> BuildDictionaryProperties(JSThread *thread, const JSHandle<JSObject> &object,
1274514f5e3Sopenharmony_ci                                                              JSHandle<TaggedArray> &keys,
1284514f5e3Sopenharmony_ci                                                              JSHandle<TaggedArray> &properties, ClassPropertyType type,
1294514f5e3Sopenharmony_ci                                                              const JSHandle<JSTaggedValue> &lexenv);
1304514f5e3Sopenharmony_ci
1314514f5e3Sopenharmony_ci    static JSHandle<JSFunction> CreateJSFunctionFromTemplate(JSThread *thread,
1324514f5e3Sopenharmony_ci                                                             const JSHandle<FunctionTemplate> &funcTemp,
1334514f5e3Sopenharmony_ci                                                             const JSHandle<JSObject> &homeObject,
1344514f5e3Sopenharmony_ci                                                             const JSHandle<JSTaggedValue> &lexenv);
1354514f5e3Sopenharmony_ci
1364514f5e3Sopenharmony_ci    static void HandleElementsProperties(JSThread *thread, const JSHandle<JSObject> &object,
1374514f5e3Sopenharmony_ci                                         const JSHandle<JSTaggedValue> &lexenv, JSHandle<TaggedArray> &elements);
1384514f5e3Sopenharmony_ci};
1394514f5e3Sopenharmony_ci
1404514f5e3Sopenharmony_ciclass SendableClassDefiner : public ClassHelper {
1414514f5e3Sopenharmony_cipublic:
1424514f5e3Sopenharmony_ci    static JSHandle<JSFunction> DefineSendableClassFromExtractor(JSThread *thread,
1434514f5e3Sopenharmony_ci                                                                 JSHandle<ClassInfoExtractor> &extractor,
1444514f5e3Sopenharmony_ci                                                                 const JSHandle<TaggedArray> &fieldTypeArray);
1454514f5e3Sopenharmony_ci
1464514f5e3Sopenharmony_ci    static void DefineSendableInstanceHClass(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray,
1474514f5e3Sopenharmony_ci                                             uint32_t length,
1484514f5e3Sopenharmony_ci                                             const JSHandle<JSFunction> &ctor, const JSHandle<JSTaggedValue> &base);
1494514f5e3Sopenharmony_ci
1504514f5e3Sopenharmony_ci    static JSHandle<TaggedArray> ExtractStaticFieldTypeArray(JSThread *thread,
1514514f5e3Sopenharmony_ci                                                             const JSHandle<TaggedArray> &fieldTypeArray);
1524514f5e3Sopenharmony_ci
1534514f5e3Sopenharmony_ci    static void FilterDuplicatedKeys(JSThread *thread, const JSHandle<TaggedArray> &keys,
1544514f5e3Sopenharmony_ci                                     const JSHandle<TaggedArray> &properties);
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ci    static SharedFieldType FromTaggedValue(JSTaggedValue value)
1574514f5e3Sopenharmony_ci    {
1584514f5e3Sopenharmony_ci        if (value.IsNull()) {
1594514f5e3Sopenharmony_ci            return SharedFieldType::NONE;
1604514f5e3Sopenharmony_ci        } else if (value.IsNumber()) {
1614514f5e3Sopenharmony_ci            return SharedFieldType::NUMBER;
1624514f5e3Sopenharmony_ci        } else if (value.IsString()) {
1634514f5e3Sopenharmony_ci            return SharedFieldType::STRING;
1644514f5e3Sopenharmony_ci        } else if (value.IsBoolean()) {
1654514f5e3Sopenharmony_ci            return SharedFieldType::BOOLEAN;
1664514f5e3Sopenharmony_ci        } else if (value.IsJSSharedObject()) {
1674514f5e3Sopenharmony_ci            return SharedFieldType::SENDABLE;
1684514f5e3Sopenharmony_ci        } else {
1694514f5e3Sopenharmony_ci            return SharedFieldType::NONE;
1704514f5e3Sopenharmony_ci        }
1714514f5e3Sopenharmony_ci    }
1724514f5e3Sopenharmony_ci
1734514f5e3Sopenharmony_ci    static void PUBLIC_API AddFieldTypeToHClass(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray,
1744514f5e3Sopenharmony_ci                                                uint32_t length, const JSHandle<NameDictionary> &nameDict,
1754514f5e3Sopenharmony_ci                                                const JSHandle<JSHClass> &hclass);
1764514f5e3Sopenharmony_ci
1774514f5e3Sopenharmony_ci    static void PUBLIC_API AddFieldTypeToHClass(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray,
1784514f5e3Sopenharmony_ci        uint32_t length, const JSHandle<LayoutInfo> &layout, const JSHandle<JSHClass> &hclass,
1794514f5e3Sopenharmony_ci        size_t start, const JSHandle<NumberDictionary> &elementsDic = JSHandle<NumberDictionary>(),
1804514f5e3Sopenharmony_ci        std::vector<JSHandle<JSTaggedValue>> &&propertyList = std::vector<JSHandle<JSTaggedValue>>());
1814514f5e3Sopenharmony_ciprivate:
1824514f5e3Sopenharmony_ci    static SharedFieldType FromFieldType(FieldType type)
1834514f5e3Sopenharmony_ci    {
1844514f5e3Sopenharmony_ci        return SharedFieldType(static_cast<uint32_t>(type));
1854514f5e3Sopenharmony_ci    }
1864514f5e3Sopenharmony_ci
1874514f5e3Sopenharmony_ci    static JSHandle<NameDictionary> BuildSendableDictionaryProperties(JSThread *thread,
1884514f5e3Sopenharmony_ci                                                                      const JSHandle<JSObject> &object,
1894514f5e3Sopenharmony_ci                                                                      JSHandle<TaggedArray> &keys,
1904514f5e3Sopenharmony_ci                                                                      JSHandle<TaggedArray> &properties,
1914514f5e3Sopenharmony_ci                                                                      ClassPropertyType type,
1924514f5e3Sopenharmony_ci                                                                      const JSHandle<JSFunction> &ctor);
1934514f5e3Sopenharmony_ci
1944514f5e3Sopenharmony_ci    static JSHandle<JSFunction> CreateSFunctionFromTemplate(JSThread *thread,
1954514f5e3Sopenharmony_ci                                                            const JSHandle<FunctionTemplate> &funcTemp,
1964514f5e3Sopenharmony_ci                                                            const JSHandle<JSObject> &homeObject,
1974514f5e3Sopenharmony_ci                                                            const JSHandle<JSTaggedValue> &lexenv);
1984514f5e3Sopenharmony_ci
1994514f5e3Sopenharmony_ci    static void UpdateAccessorFunction(JSThread *thread, const JSMutableHandle<JSTaggedValue> &value,
2004514f5e3Sopenharmony_ci                                       const JSHandle<JSTaggedValue> &homeObject, const JSHandle<JSFunction> &ctor);
2014514f5e3Sopenharmony_ci
2024514f5e3Sopenharmony_ci    static void AddFieldTypeToDict(JSThread *thread, const JSHandle<TaggedArray> &fieldTypeArray, uint32_t length,
2034514f5e3Sopenharmony_ci                                   JSMutableHandle<NameDictionary> &dict,
2044514f5e3Sopenharmony_ci                                   PropertyAttributes attributes = PropertyAttributes::Default(true, true, false));
2054514f5e3Sopenharmony_ci
2064514f5e3Sopenharmony_ci    static bool TryUpdateExistValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &existValue,
2074514f5e3Sopenharmony_ci                                    JSMutableHandle<JSTaggedValue> &value);
2084514f5e3Sopenharmony_ci
2094514f5e3Sopenharmony_ci    static void TryUpdateValue(JSThread *thread, JSMutableHandle<JSTaggedValue> &value);
2104514f5e3Sopenharmony_ci
2114514f5e3Sopenharmony_ci    static void UpdateValueToAccessor(JSThread *thread, JSMutableHandle<JSTaggedValue> &value,
2124514f5e3Sopenharmony_ci                                      JSHandle<AccessorData> &accessor);
2134514f5e3Sopenharmony_ci    static std::pair<uint32_t, uint32_t> GetSizeAndMaxInlineByType(JSType type);
2144514f5e3Sopenharmony_ci};
2154514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
2164514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H
217