1 /* 2 * Copyright (c) 2023 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_ELEMENTS_H 17 #define ECMASCRIPT_ELEMENTS_H 18 19 #include "ecmascript/global_env_constants.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/mem/c_containers.h" 22 23 namespace panda::ecmascript { 24 25 #define ELEMENTS_KIND_INIT_HCLASS_LIST(V) \ 26 V(NONE) \ 27 V(HOLE) \ 28 V(INT) \ 29 V(NUMBER) \ 30 V(STRING) \ 31 V(OBJECT) \ 32 V(TAGGED) \ 33 V(HOLE_INT) \ 34 V(HOLE_NUMBER) \ 35 V(HOLE_STRING) \ 36 V(HOLE_OBJECT) \ 37 V(HOLE_TAGGED) 38 39 enum class ElementsKind : uint8_t { 40 NONE = 0x00UL, 41 HOLE = 0x01UL, 42 INT = 0x1UL << 1, // 2 43 NUMBER = (0x1UL << 2) | INT, // 6 44 STRING = 0x1UL << 3, // 8 45 OBJECT = 0x1UL << 4, // 16 46 TAGGED = 0x1EUL, // 30 47 HOLE_INT = HOLE | INT, 48 HOLE_NUMBER = HOLE | NUMBER, 49 HOLE_STRING = HOLE | STRING, 50 HOLE_OBJECT = HOLE | OBJECT, 51 HOLE_TAGGED = HOLE | TAGGED, 52 GENERIC = HOLE_TAGGED, 53 DICTIONARY = HOLE_TAGGED, 54 }; 55 56 class PUBLIC_API Elements { 57 public: 58 static CMap<ElementsKind, std::pair<ConstantIndex, ConstantIndex>> InitializeHClassMap(); 59 60 static std::string GetString(ElementsKind kind); 61 static bool IsInt(ElementsKind kind); 62 static bool IsNumber(ElementsKind kind); 63 static bool IsTagged(ElementsKind kind); 64 static bool IsObject(ElementsKind kind); 65 static bool IsHole(ElementsKind kind); IsGeneric(ElementsKind kind)66 static bool IsGeneric(ElementsKind kind) 67 { 68 return kind == ElementsKind::GENERIC; 69 } 70 IsNone(ElementsKind kind)71 static bool IsNone(ElementsKind kind) 72 { 73 return kind == ElementsKind::NONE; 74 } 75 IsComplex(ElementsKind kind)76 static bool IsComplex(ElementsKind kind) 77 { 78 return IsNumber(kind) || IsTagged(kind); 79 } 80 IsInNumbers(ElementsKind kind)81 static bool IsInNumbers(ElementsKind kind) 82 { 83 return (static_cast<uint32_t>(kind) > static_cast<uint32_t>(ElementsKind::HOLE) && 84 static_cast<uint32_t>(kind) < static_cast<uint32_t>(ElementsKind::STRING)); 85 } 86 IsHoleInt(ElementsKind kind)87 static bool IsHoleInt(ElementsKind kind) 88 { 89 return kind == ElementsKind::HOLE_INT; 90 } 91 IsHoleNumber(ElementsKind kind)92 static bool IsHoleNumber(ElementsKind kind) 93 { 94 return kind == ElementsKind::HOLE_NUMBER; 95 } 96 97 static ConstantIndex GetGlobalContantIndexByKind(ElementsKind kind); 98 static ElementsKind MergeElementsKind(ElementsKind curKind, ElementsKind newKind); 99 static ElementsKind FixElementsKind(ElementsKind oldKind); 100 static ElementsKind ToElementsKind(JSTaggedValue value, ElementsKind kind); 101 static void MigrateArrayWithKind(const JSThread *thread, const JSHandle<JSObject> &object, 102 const ElementsKind oldKind, const ElementsKind newKind); 103 private: 104 static JSTaggedValue MigrateFromRawValueToHeapValue(const JSThread *thread, const JSHandle<JSObject> object, 105 bool needCOW, bool isIntKind); 106 static void HandleIntKindMigration(const JSThread *thread, const JSHandle<JSObject> &object, 107 const ElementsKind newKind, bool needCOW); 108 static bool IsNumberKind(const ElementsKind kind); 109 static bool IsStringOrNoneOrHole(const ElementsKind kind); 110 static void HandleNumberKindMigration(const JSThread *thread, 111 const JSHandle<JSObject> &object, 112 const ElementsKind newKind, bool needCOW); 113 static void HandleOtherKindMigration(const JSThread *thread, const JSHandle<JSObject> &object, 114 const ElementsKind newKind, bool needCOW); 115 static JSTaggedValue MigrateFromHeapValueToRawValue(const JSThread *thread, const JSHandle<JSObject> object, 116 bool needCOW, bool isIntKind); 117 static void MigrateFromHoleIntToHoleNumber(const JSThread *thread, const JSHandle<JSObject> object); 118 static void MigrateFromHoleNumberToHoleInt(const JSThread *thread, const JSHandle<JSObject> object); 119 120 }; 121 } // namespace panda::ecmascript 122 #endif // ECMASCRIPT_ELEMENTS_H 123