1 /* 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H 17 #define ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H 18 19 #include "ecmascript/js_tagged_value-inl.h" 20 #include "ecmascript/jspandafile/method_literal.h" 21 22 namespace panda::ecmascript { 23 // ClassInfoExtractor will analyze and extract the contents from class literal to keys, properties and elements(both 24 // non-static and static), later generate the complete hclass (both prototype and constructor) based on keys. 25 // Attention: keys accessor stores the property key and properties accessor stores the property value, but elements 26 // accessor stores the key-value pair abuttally. 27 using EntityId = panda_file::File::EntityId; 28 class ClassInfoExtractor : public TaggedObject { 29 public: 30 static constexpr uint8_t NON_STATIC_RESERVED_LENGTH = 1; 31 static constexpr uint8_t STATIC_RESERVED_LENGTH = 3; 32 33 static constexpr uint8_t CONSTRUCTOR_INDEX = 0; 34 static constexpr uint8_t LENGTH_INDEX = 0; 35 static constexpr uint8_t NAME_INDEX = 1; 36 static constexpr uint8_t PROTOTYPE_INDEX = 2; 37 38 struct ExtractContentsDetail { 39 uint32_t extractBegin; 40 uint32_t extractEnd; 41 uint8_t fillStartLoc; 42 MethodLiteral *methodLiteral; 43 }; 44 45 CAST_CHECK(ClassInfoExtractor, IsClassInfoExtractor); 46 47 static void BuildClassInfoExtractorFromLiteral(JSThread *thread, JSHandle<ClassInfoExtractor> &extractor, 48 const JSHandle<TaggedArray> &literal); 49 50 static JSHandle<JSHClass> CreatePrototypeHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base, 51 JSHandle<TaggedArray> &keys, 52 JSHandle<TaggedArray> &properties); 53 54 static JSHandle<JSHClass> CreateConstructorHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base, 55 JSHandle<TaggedArray> &keys, 56 JSHandle<TaggedArray> &properties); 57 58 static constexpr size_t PROTOTYPE_HCLASS_OFFSET = TaggedObjectSize(); 59 ACCESSORS(NonStaticKeys, PROTOTYPE_HCLASS_OFFSET, NON_STATIC_PROPERTIES_OFFSET) 60 ACCESSORS(NonStaticProperties, NON_STATIC_PROPERTIES_OFFSET, NON_STATIC_ELEMENTS_OFFSET) 61 ACCESSORS(NonStaticElements, NON_STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_HCLASS_OFFSET) 62 ACCESSORS(StaticKeys, CONSTRUCTOR_HCLASS_OFFSET, STATIC_PROPERTIES_OFFSET) 63 ACCESSORS(StaticProperties, STATIC_PROPERTIES_OFFSET, STATIC_ELEMENTS_OFFSET) 64 ACCESSORS(StaticElements, STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_METHOD_OFFSET) 65 ACCESSORS(ConstructorMethod, CONSTRUCTOR_METHOD_OFFSET, BIT_FIELD_OFFSET) 66 ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) 67 DEFINE_ALIGN_SIZE(LAST_OFFSET); 68 69 // define BitField 70 static constexpr size_t NON_STATIC_BITS = 1; 71 static constexpr size_t STATIC_BITS = 1; 72 FIRST_BIT_FIELD(BitField, NonStaticWithElements, bool, NON_STATIC_BITS) 73 NEXT_BIT_FIELD(BitField, StaticWithElements, bool, STATIC_BITS, NonStaticWithElements) 74 75 DECL_VISIT_OBJECT(PROTOTYPE_HCLASS_OFFSET, BIT_FIELD_OFFSET) 76 77 DECL_DUMP() 78 79 private: 80 static bool ExtractAndReturnWhetherWithElements(JSThread *thread, const JSHandle<TaggedArray> &literal, 81 const ExtractContentsDetail &detail, 82 JSHandle<TaggedArray> &keys, JSHandle<TaggedArray> &properties, 83 JSHandle<TaggedArray> &elements, 84 const JSPandaFile *jsPandaFile); 85 }; 86 87 enum class ClassPropertyType : uint8_t { NON_STATIC = 0, STATIC }; 88 89 class ClassHelper { 90 public: 91 static JSHandle<JSFunction> DefineClassFromExtractor(JSThread *thread, const JSHandle<JSTaggedValue> &base, 92 JSHandle<ClassInfoExtractor> &extractor, 93 const JSHandle<JSTaggedValue> &lexenv); 94 95 static JSHandle<JSFunction> DefineClassWithIHClass(JSThread *thread, const JSHandle<JSTaggedValue> &base, 96 JSHandle<ClassInfoExtractor> &extractor, 97 const JSHandle<JSTaggedValue> &lexenv, 98 const JSHandle<JSHClass> &ihclass); 99 100 private: 101 static JSHandle<NameDictionary> BuildDictionaryProperties(JSThread *thread, const JSHandle<JSObject> &object, 102 JSHandle<TaggedArray> &keys, 103 JSHandle<TaggedArray> &properties, ClassPropertyType type, 104 const JSHandle<JSTaggedValue> &lexenv); 105 106 static void HandleElementsProperties(JSThread *thread, const JSHandle<JSObject> &object, 107 JSHandle<TaggedArray> &elements); 108 }; 109 } // namespace panda::ecmascript 110 #endif // ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H 111