• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_fields.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,                                  // 0
41     HOLE = 0x01UL,                                  // 1
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,                          // 3
48     HOLE_NUMBER = HOLE | NUMBER,                    // 7
49     HOLE_STRING = HOLE | STRING,                    // 9
50     HOLE_OBJECT = HOLE | OBJECT,                    // 17
51     HOLE_TAGGED = HOLE | TAGGED,                    // 31
52     GENERIC = HOLE_TAGGED,
53     DICTIONARY = HOLE_TAGGED,
54 };
55 
56 class PUBLIC_API Elements {
57 public:
58     static constexpr int32_t KIND_COUNT = static_cast<uint8_t>(ElementsKind::HOLE_TAGGED) + 1;
59 
ToUint(ElementsKind kind)60     static constexpr uint32_t ToUint(ElementsKind kind)
61     {
62         return static_cast<uint32_t>(kind);
63     }
64     static std::string GetString(ElementsKind kind);
65     static bool IsInt(ElementsKind kind);
66     static bool IsNumber(ElementsKind kind);
67     static bool IsTagged(ElementsKind kind);
68     static bool IsObject(ElementsKind kind);
69     static bool IsHole(ElementsKind kind);
IsGeneric(ElementsKind kind)70     static bool IsGeneric(ElementsKind kind)
71     {
72         return kind == ElementsKind::GENERIC;
73     }
74 
IsNone(ElementsKind kind)75     static bool IsNone(ElementsKind kind)
76     {
77         return kind == ElementsKind::NONE;
78     }
79 
IsComplex(ElementsKind kind)80     static bool IsComplex(ElementsKind kind)
81     {
82         return IsNumber(kind) || IsTagged(kind);
83     }
84 
IsInNumbers(ElementsKind kind)85     static bool IsInNumbers(ElementsKind kind)
86     {
87         return (ToUint(kind) > ToUint(ElementsKind::HOLE) &&
88                 ToUint(kind) < ToUint(ElementsKind::STRING));
89     }
90 
IsIntOrHoleInt(ElementsKind kind)91     static bool IsIntOrHoleInt(ElementsKind kind)
92     {
93         return kind == ElementsKind::INT || kind == ElementsKind::HOLE_INT;
94     }
95 
IsNumberOrHoleNumber(ElementsKind kind)96     static bool IsNumberOrHoleNumber(ElementsKind kind)
97     {
98         return kind == ElementsKind::NUMBER || kind == ElementsKind::HOLE_NUMBER;
99     }
100 
IsStringOrHoleString(ElementsKind kind)101     static bool IsStringOrHoleString(ElementsKind kind)
102     {
103         return kind == ElementsKind::STRING || kind == ElementsKind::HOLE_STRING;
104     }
105 
106     static ElementsKind MergeElementsKind(ElementsKind curKind, ElementsKind newKind);
107     static ElementsKind FixElementsKind(ElementsKind oldKind);
ToElementsKind(JSTaggedValue value)108     static inline ElementsKind ToElementsKind(JSTaggedValue value)
109     {
110         ElementsKind valueKind = ElementsKind::NONE;
111         if (value.IsInt()) {
112             valueKind = ElementsKind::INT;
113         } else if (value.IsDouble()) {
114             valueKind = ElementsKind::NUMBER;
115         } else if (value.IsString()) {
116             valueKind = ElementsKind::STRING;
117         } else if (value.IsHeapObject()) {
118             valueKind = ElementsKind::OBJECT;
119         } else if (value.IsHole()) {
120             valueKind = ElementsKind::HOLE;
121         } else {
122             valueKind = ElementsKind::TAGGED;
123         }
124         return valueKind;
125     }
126     static ElementsKind ToElementsKind(JSTaggedValue value, ElementsKind kind);
127 
MergeElementsKindNoFix(JSTaggedValue value,ElementsKind curKind,ElementsKind newKind)128     static ElementsKind MergeElementsKindNoFix(JSTaggedValue value, ElementsKind curKind, ElementsKind newKind)
129     {
130         return static_cast<ElementsKind>(static_cast<uint8_t>(ToElementsKind(value)) | static_cast<uint8_t>(curKind) |
131             static_cast<uint8_t>(newKind));
132     }
133 
134     static void MigrateArrayWithKind(const JSThread *thread, const JSHandle<JSObject> &object,
135                                      const ElementsKind oldKind, const ElementsKind newKind);
136 private:
137     static JSTaggedValue MigrateFromRawValueToHeapValue(const JSThread *thread, const JSHandle<JSObject> object,
138                                                          bool needCOW, bool isIntKind);
139     static void HandleIntKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
140                                        const ElementsKind newKind, bool needCOW);
141     static bool IsNumberKind(const ElementsKind kind);
142     static bool IsStringOrNoneOrHole(const ElementsKind kind);
143     static void HandleNumberKindMigration(const JSThread *thread,
144                                           const JSHandle<JSObject> &object,
145                                           const ElementsKind newKind, bool needCOW);
146     static void HandleOtherKindMigration(const JSThread *thread, const JSHandle<JSObject> &object,
147                                          const ElementsKind newKind, bool needCOW);
148     static JSTaggedValue MigrateFromHeapValueToRawValue(const JSThread *thread, const JSHandle<JSObject> object,
149                                                         bool needCOW, bool isIntKind);
150     static void MigrateFromHoleIntToHoleNumber(const JSThread *thread, const JSHandle<JSObject> object);
151     static void MigrateFromHoleNumberToHoleInt(const JSThread *thread, const JSHandle<JSObject> object);
152 
153 };
154 }  // namespace panda::ecmascript
155 #endif // ECMASCRIPT_ELEMENTS_H
156