1 /*
2  * Copyright (c) 2023-2024 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 #include "ecmascript/ecma_context.h"
17 #include "ecmascript/global_env.h"
18 #include "ecmascript/global_index_map.h"
19 
20 namespace panda::ecmascript {
Initialize(const JSThread *thread, JSMutableHandle<PointerToIndexDictionary> globalIndexMap)21 void GlobalIndexMap::Initialize(const JSThread *thread,
22                                 JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
23 {
24     // GlobalIndex map should be created when it is first used.
25     InitGlobalIndexMap(thread, globalIndexMap);
26 
27     // Init GlobalIndex map
28     InitGlobalConst(thread, globalIndexMap);
29     InitGlobalEnv(thread, globalIndexMap);
30     InitBuiltinEntries(thread, globalIndexMap);
31 }
32 
InitGlobalIndexMap(const JSThread *thread, JSMutableHandle<PointerToIndexDictionary> globalIndexMap)33 void GlobalIndexMap::InitGlobalIndexMap(const JSThread *thread,
34                                         JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
35 {
36     if (globalIndexMap.GetTaggedValue().IsHeapObject()) {
37         return;
38     }
39     globalIndexMap.Update(PointerToIndexDictionary::Create(thread));
40 }
41 
InitGlobalConst(const JSThread *thread, JSMutableHandle<PointerToIndexDictionary> globalIndexMap)42 void GlobalIndexMap::InitGlobalConst(const JSThread *thread,
43                                      JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
44 {
45     ASSERT_PRINT(globalIndexMap.GetTaggedValue().IsHeapObject(), "Global's IndexMap is not existed.");
46     auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
47     uint32_t constantCount = globalConst->GetConstantCount();
48     JSMutableHandle<PointerToIndexDictionary> globalIndexMapHandle(thread, globalIndexMap);
49     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
50     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
51     for (uint32_t index = 0; index < constantCount; index++) {
52         JSTaggedValue objectValue = globalConst->GetGlobalConstantObject(index);
53         if (objectValue.IsHeapObject() && !objectValue.IsString()) {
54             keyHandle.Update(objectValue);
55 
56             GlobalIndex globalIndex;
57             globalIndex.UpdateGlobalConstId(index);
58             valueHandle.Update(JSTaggedValue(globalIndex.GetGlobalIndex()));
59             JSHandle<PointerToIndexDictionary> newDict =
60                 PointerToIndexDictionary::PutIfAbsent(thread, globalIndexMapHandle, keyHandle, valueHandle);
61             globalIndexMapHandle.Update(newDict);
62         }
63     }
64     globalIndexMap.Update(globalIndexMapHandle);
65 }
66 
InitGlobalEnv(const JSThread *thread, JSMutableHandle<PointerToIndexDictionary> globalIndexMap)67 void GlobalIndexMap::InitGlobalEnv(const JSThread *thread,
68                                    JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
69 {
70     ASSERT_PRINT(globalIndexMap.GetTaggedValue().IsHeapObject(), "Global's IndexMap is not existed.");
71     auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
72     uint32_t globalEnvFieldSize = globalEnv->GetGlobalEnvFieldSize();
73     JSMutableHandle<PointerToIndexDictionary> globalIndexMapHandle(thread, globalIndexMap);
74     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
75     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
76     for (uint32_t index = 0; index < globalEnvFieldSize; index++) {
77         JSTaggedValue objectValue = globalEnv->GetGlobalEnvObjectByIndex(index).GetTaggedValue();
78         if (objectValue.IsHeapObject()) {
79             keyHandle.Update(objectValue);
80 
81             GlobalIndex globalIndex;
82             globalIndex.UpdateGlobalEnvId(index);
83             valueHandle.Update(JSTaggedValue(globalIndex.GetGlobalIndex()));
84             JSHandle<PointerToIndexDictionary> newDict =
85                 PointerToIndexDictionary::PutIfAbsent(thread, globalIndexMapHandle, keyHandle, valueHandle);
86             globalIndexMapHandle.Update(newDict);
87         }
88     }
89     globalIndexMap.Update(globalIndexMapHandle);
90 }
91 
InitBuiltinEntries(const JSThread *thread, JSMutableHandle<PointerToIndexDictionary> globalIndexMap)92 void GlobalIndexMap::InitBuiltinEntries(const JSThread *thread,
93                                         JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
94 {
95     ASSERT_PRINT(globalIndexMap.GetTaggedValue().IsHeapObject(), "Global's IndexMap is not existed.");
96     auto builtinEntries = thread->GetBuiltinEntries();
97     uint32_t builtinEntriesCount = BuiltinEntries::COUNT;
98     JSMutableHandle<PointerToIndexDictionary> globalIndexMapHandle(thread, globalIndexMap);
99     JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
100     JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
101     for (uint32_t index = 0; index < builtinEntriesCount; index++) {
102         JSTaggedValue objectValue = builtinEntries.builtin_[index].hClass_;
103         keyHandle.Update(objectValue);
104         if (objectValue.IsHeapObject()) {
105             GlobalIndex globalIndex;
106             globalIndex.UpdateBuiltinEntriesId(index);
107             valueHandle.Update(JSTaggedValue(globalIndex.GetGlobalIndex()));
108             JSHandle<PointerToIndexDictionary> newDict =
109                 PointerToIndexDictionary::PutIfAbsent(thread, globalIndexMapHandle, keyHandle, valueHandle);
110             globalIndexMapHandle.Update(newDict);
111         }
112     }
113     globalIndexMap.Update(globalIndexMapHandle);
114 }
115 
FindGlobalIndex(JSHandle<PointerToIndexDictionary> globalIndexMap, JSTaggedValue objAddress, GlobalIndex *globalIndex)116 void GlobalIndexMap::FindGlobalIndex(JSHandle<PointerToIndexDictionary> globalIndexMap,
117                                      JSTaggedValue objAddress, GlobalIndex *globalIndex)
118 {
119     int entry = globalIndexMap->FindEntry(objAddress);
120     if (entry != -1) {
121         *globalIndex = GlobalIndex(globalIndexMap->GetValue(entry).GetInt());
122     }
123 }
124 } // namespace panda::ecmascript
125