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 JSHandle<Method> &method); 58 59 static void CorrectConstructorHClass(JSThread *thread, 60 JSHandle<TaggedArray> &properties, 61 JSHClass *constructorHClass); 62 63 static constexpr size_t PROTOTYPE_HCLASS_OFFSET = TaggedObjectSize(); 64 ACCESSORS(NonStaticKeys, PROTOTYPE_HCLASS_OFFSET, NON_STATIC_PROPERTIES_OFFSET) 65 ACCESSORS(NonStaticProperties, NON_STATIC_PROPERTIES_OFFSET, NON_STATIC_ELEMENTS_OFFSET) 66 ACCESSORS(NonStaticElements, NON_STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_HCLASS_OFFSET) 67 ACCESSORS(StaticKeys, CONSTRUCTOR_HCLASS_OFFSET, STATIC_PROPERTIES_OFFSET) 68 ACCESSORS(StaticProperties, STATIC_PROPERTIES_OFFSET, STATIC_ELEMENTS_OFFSET) 69 ACCESSORS(StaticElements, STATIC_ELEMENTS_OFFSET, CONSTRUCTOR_METHOD_OFFSET) 70 ACCESSORS(ConstructorMethod, CONSTRUCTOR_METHOD_OFFSET, BIT_FIELD_OFFSET) 71 ACCESSORS_BIT_FIELD(BitField, BIT_FIELD_OFFSET, LAST_OFFSET) 72 DEFINE_ALIGN_SIZE(LAST_OFFSET); 73 74 // define BitField 75 static constexpr size_t NON_STATIC_BITS = 1; 76 static constexpr size_t STATIC_BITS = 1; 77 FIRST_BIT_FIELD(BitField, NonStaticWithElements, bool, NON_STATIC_BITS) 78 NEXT_BIT_FIELD(BitField, StaticWithElements, bool, STATIC_BITS, NonStaticWithElements) 79 80 DECL_VISIT_OBJECT(PROTOTYPE_HCLASS_OFFSET, BIT_FIELD_OFFSET) 81 82 DECL_DUMP() 83 84 private: 85 static bool ExtractAndReturnWhetherWithElements(JSThread *thread, const JSHandle<TaggedArray> &literal, 86 const ExtractContentsDetail &detail, 87 JSHandle<TaggedArray> &keys, JSHandle<TaggedArray> &properties, 88 JSHandle<TaggedArray> &elements, 89 const JSPandaFile *jsPandaFile); 90 }; 91 92 enum class ClassPropertyType : uint8_t { NON_STATIC = 0, STATIC }; 93 94 class ClassHelper { 95 public: 96 static JSHandle<JSFunction> DefineClassFromExtractor(JSThread *thread, const JSHandle<JSTaggedValue> &base, 97 JSHandle<ClassInfoExtractor> &extractor, 98 const JSHandle<JSTaggedValue> &lexenv); 99 100 static JSHandle<JSFunction> DefineClassWithIHClass(JSThread *thread, 101 JSHandle<ClassInfoExtractor> &extractor, 102 const JSHandle<JSTaggedValue> &lexenv, 103 const JSHandle<JSHClass> &ihclass, 104 const JSHandle<JSHClass> &constructorHClass); 105 106 private: 107 static JSHandle<NameDictionary> BuildDictionaryProperties(JSThread *thread, const JSHandle<JSObject> &object, 108 JSHandle<TaggedArray> &keys, 109 JSHandle<TaggedArray> &properties, ClassPropertyType type, 110 const JSHandle<JSTaggedValue> &lexenv); 111 112 static void HandleElementsProperties(JSThread *thread, const JSHandle<JSObject> &object, 113 JSHandle<TaggedArray> &elements); 114 }; 115 } // namespace panda::ecmascript 116 #endif // ECMASCRIPT_JSPANDAFILE_CLASS_INFO_EXTRACTOR_H 117