14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/ecma_context.h"
174514f5e3Sopenharmony_ci#include "ecmascript/global_env.h"
184514f5e3Sopenharmony_ci#include "ecmascript/global_index_map.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_cinamespace panda::ecmascript {
214514f5e3Sopenharmony_civoid GlobalIndexMap::Initialize(const JSThread *thread,
224514f5e3Sopenharmony_ci                                JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
234514f5e3Sopenharmony_ci{
244514f5e3Sopenharmony_ci    // GlobalIndex map should be created when it is first used.
254514f5e3Sopenharmony_ci    InitGlobalIndexMap(thread, globalIndexMap);
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_ci    // Init GlobalIndex map
284514f5e3Sopenharmony_ci    InitGlobalConst(thread, globalIndexMap);
294514f5e3Sopenharmony_ci    InitGlobalEnv(thread, globalIndexMap);
304514f5e3Sopenharmony_ci    InitBuiltinEntries(thread, globalIndexMap);
314514f5e3Sopenharmony_ci}
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_civoid GlobalIndexMap::InitGlobalIndexMap(const JSThread *thread,
344514f5e3Sopenharmony_ci                                        JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
354514f5e3Sopenharmony_ci{
364514f5e3Sopenharmony_ci    if (globalIndexMap.GetTaggedValue().IsHeapObject()) {
374514f5e3Sopenharmony_ci        return;
384514f5e3Sopenharmony_ci    }
394514f5e3Sopenharmony_ci    globalIndexMap.Update(PointerToIndexDictionary::Create(thread));
404514f5e3Sopenharmony_ci}
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_civoid GlobalIndexMap::InitGlobalConst(const JSThread *thread,
434514f5e3Sopenharmony_ci                                     JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
444514f5e3Sopenharmony_ci{
454514f5e3Sopenharmony_ci    ASSERT_PRINT(globalIndexMap.GetTaggedValue().IsHeapObject(), "Global's IndexMap is not existed.");
464514f5e3Sopenharmony_ci    auto globalConst = const_cast<GlobalEnvConstants *>(thread->GlobalConstants());
474514f5e3Sopenharmony_ci    uint32_t constantCount = globalConst->GetConstantCount();
484514f5e3Sopenharmony_ci    JSMutableHandle<PointerToIndexDictionary> globalIndexMapHandle(thread, globalIndexMap);
494514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
504514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
514514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < constantCount; index++) {
524514f5e3Sopenharmony_ci        JSTaggedValue objectValue = globalConst->GetGlobalConstantObject(index);
534514f5e3Sopenharmony_ci        if (objectValue.IsHeapObject() && !objectValue.IsString()) {
544514f5e3Sopenharmony_ci            keyHandle.Update(objectValue);
554514f5e3Sopenharmony_ci
564514f5e3Sopenharmony_ci            GlobalIndex globalIndex;
574514f5e3Sopenharmony_ci            globalIndex.UpdateGlobalConstId(index);
584514f5e3Sopenharmony_ci            valueHandle.Update(JSTaggedValue(globalIndex.GetGlobalIndex()));
594514f5e3Sopenharmony_ci            JSHandle<PointerToIndexDictionary> newDict =
604514f5e3Sopenharmony_ci                PointerToIndexDictionary::PutIfAbsent(thread, globalIndexMapHandle, keyHandle, valueHandle);
614514f5e3Sopenharmony_ci            globalIndexMapHandle.Update(newDict);
624514f5e3Sopenharmony_ci        }
634514f5e3Sopenharmony_ci    }
644514f5e3Sopenharmony_ci    globalIndexMap.Update(globalIndexMapHandle);
654514f5e3Sopenharmony_ci}
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_civoid GlobalIndexMap::InitGlobalEnv(const JSThread *thread,
684514f5e3Sopenharmony_ci                                   JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
694514f5e3Sopenharmony_ci{
704514f5e3Sopenharmony_ci    ASSERT_PRINT(globalIndexMap.GetTaggedValue().IsHeapObject(), "Global's IndexMap is not existed.");
714514f5e3Sopenharmony_ci    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
724514f5e3Sopenharmony_ci    uint32_t globalEnvFieldSize = globalEnv->GetGlobalEnvFieldSize();
734514f5e3Sopenharmony_ci    JSMutableHandle<PointerToIndexDictionary> globalIndexMapHandle(thread, globalIndexMap);
744514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
754514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
764514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < globalEnvFieldSize; index++) {
774514f5e3Sopenharmony_ci        JSTaggedValue objectValue = globalEnv->GetGlobalEnvObjectByIndex(index).GetTaggedValue();
784514f5e3Sopenharmony_ci        if (objectValue.IsHeapObject()) {
794514f5e3Sopenharmony_ci            keyHandle.Update(objectValue);
804514f5e3Sopenharmony_ci
814514f5e3Sopenharmony_ci            GlobalIndex globalIndex;
824514f5e3Sopenharmony_ci            globalIndex.UpdateGlobalEnvId(index);
834514f5e3Sopenharmony_ci            valueHandle.Update(JSTaggedValue(globalIndex.GetGlobalIndex()));
844514f5e3Sopenharmony_ci            JSHandle<PointerToIndexDictionary> newDict =
854514f5e3Sopenharmony_ci                PointerToIndexDictionary::PutIfAbsent(thread, globalIndexMapHandle, keyHandle, valueHandle);
864514f5e3Sopenharmony_ci            globalIndexMapHandle.Update(newDict);
874514f5e3Sopenharmony_ci        }
884514f5e3Sopenharmony_ci    }
894514f5e3Sopenharmony_ci    globalIndexMap.Update(globalIndexMapHandle);
904514f5e3Sopenharmony_ci}
914514f5e3Sopenharmony_ci
924514f5e3Sopenharmony_civoid GlobalIndexMap::InitBuiltinEntries(const JSThread *thread,
934514f5e3Sopenharmony_ci                                        JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
944514f5e3Sopenharmony_ci{
954514f5e3Sopenharmony_ci    ASSERT_PRINT(globalIndexMap.GetTaggedValue().IsHeapObject(), "Global's IndexMap is not existed.");
964514f5e3Sopenharmony_ci    auto builtinEntries = thread->GetBuiltinEntries();
974514f5e3Sopenharmony_ci    uint32_t builtinEntriesCount = BuiltinEntries::COUNT;
984514f5e3Sopenharmony_ci    JSMutableHandle<PointerToIndexDictionary> globalIndexMapHandle(thread, globalIndexMap);
994514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> keyHandle(thread, JSTaggedValue::Undefined());
1004514f5e3Sopenharmony_ci    JSMutableHandle<JSTaggedValue> valueHandle(thread, JSTaggedValue::Undefined());
1014514f5e3Sopenharmony_ci    for (uint32_t index = 0; index < builtinEntriesCount; index++) {
1024514f5e3Sopenharmony_ci        JSTaggedValue objectValue = builtinEntries.builtin_[index].hClass_;
1034514f5e3Sopenharmony_ci        keyHandle.Update(objectValue);
1044514f5e3Sopenharmony_ci        if (objectValue.IsHeapObject()) {
1054514f5e3Sopenharmony_ci            GlobalIndex globalIndex;
1064514f5e3Sopenharmony_ci            globalIndex.UpdateBuiltinEntriesId(index);
1074514f5e3Sopenharmony_ci            valueHandle.Update(JSTaggedValue(globalIndex.GetGlobalIndex()));
1084514f5e3Sopenharmony_ci            JSHandle<PointerToIndexDictionary> newDict =
1094514f5e3Sopenharmony_ci                PointerToIndexDictionary::PutIfAbsent(thread, globalIndexMapHandle, keyHandle, valueHandle);
1104514f5e3Sopenharmony_ci            globalIndexMapHandle.Update(newDict);
1114514f5e3Sopenharmony_ci        }
1124514f5e3Sopenharmony_ci    }
1134514f5e3Sopenharmony_ci    globalIndexMap.Update(globalIndexMapHandle);
1144514f5e3Sopenharmony_ci}
1154514f5e3Sopenharmony_ci
1164514f5e3Sopenharmony_civoid GlobalIndexMap::FindGlobalIndex(JSHandle<PointerToIndexDictionary> globalIndexMap,
1174514f5e3Sopenharmony_ci                                     JSTaggedValue objAddress, GlobalIndex *globalIndex)
1184514f5e3Sopenharmony_ci{
1194514f5e3Sopenharmony_ci    int entry = globalIndexMap->FindEntry(objAddress);
1204514f5e3Sopenharmony_ci    if (entry != -1) {
1214514f5e3Sopenharmony_ci        *globalIndex = GlobalIndex(globalIndexMap->GetValue(entry).GetInt());
1224514f5e3Sopenharmony_ci    }
1234514f5e3Sopenharmony_ci}
1244514f5e3Sopenharmony_ci} // namespace panda::ecmascript
125