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_GLOBAL_ENV_H 17 #define ECMASCRIPT_GLOBAL_ENV_H 18 19 #include "ecmascript/js_global_object.h" 20 #include "ecmascript/js_function.h" 21 #include "ecmascript/lexical_env.h" 22 #include "ecmascript/js_handle.h" 23 #include "ecmascript/global_env_constants-inl.h" 24 #include "ecmascript/global_env_fields.h" 25 26 namespace panda::ecmascript { 27 class JSThread; 28 class GlobalEnv : public TaggedObject { 29 public: 30 using Field = GlobalEnvField; 31 32 #define GLOBAL_ENV_SLOT(type, name, index) \ 33 static constexpr uint8_t index = static_cast<uint8_t>(GlobalEnvField::index); 34 35 GLOBAL_ENV_FIELDS(GLOBAL_ENV_SLOT) 36 static constexpr uint8_t FIRST_DETECTOR_SYMBOL_INDEX = static_cast<uint8_t>(Field::REPLACE_SYMBOL_INDEX); 37 static constexpr uint8_t LAST_DETECTOR_SYMBOL_INDEX = static_cast<uint8_t>(Field::SPECIES_SYMBOL_INDEX); 38 static constexpr uint8_t FINAL_INDEX = static_cast<uint8_t>(GlobalEnvField::FINAL_INDEX); 39 static constexpr uint8_t RESERVED_LENGTH = 1; // divide the gc area 40 static constexpr uint8_t JSTHREAD_INDEX = FINAL_INDEX; // not need gc 41 #undef GLOBAL_ENV_SLOT 42 GetGlobalObject()43 JSTaggedValue GetGlobalObject() const 44 { 45 return GetJSGlobalObject().GetTaggedValue(); 46 } 47 ComputeObjectAddress(size_t index)48 uintptr_t ComputeObjectAddress(size_t index) const 49 { 50 return reinterpret_cast<uintptr_t>(this) + HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); 51 } 52 GetGlobalEnvObjectByIndex(size_t index)53 JSHandle<JSTaggedValue> GetGlobalEnvObjectByIndex(size_t index) const 54 { 55 ASSERT(index < FINAL_INDEX); 56 uintptr_t address = ComputeObjectAddress(index); 57 JSHandle<JSTaggedValue> result(address); 58 return result; 59 } 60 GetNoLazyEnvObjectByIndex(size_t index)61 JSHandle<JSTaggedValue> GetNoLazyEnvObjectByIndex(size_t index) const 62 { 63 JSHandle<JSTaggedValue> result = GetGlobalEnvObjectByIndex(index); 64 if (result->IsInternalAccessor()) { 65 JSThread *thread = GetJSThread(); 66 AccessorData *accessor = AccessorData::Cast(result->GetTaggedObject()); 67 accessor->CallInternalGet(thread, JSHandle<JSObject>::Cast(GetJSGlobalObject())); 68 } 69 return result; 70 } 71 GetGlobalEnvFieldSize()72 size_t GetGlobalEnvFieldSize() const 73 { 74 return FINAL_INDEX; 75 } 76 77 void Init(JSThread *thread); 78 Cast(TaggedObject * object)79 static GlobalEnv *Cast(TaggedObject *object) 80 { 81 ASSERT(JSTaggedValue(object).IsJSGlobalEnv()); 82 return reinterpret_cast<GlobalEnv *>(object); 83 } 84 GetJSThread()85 JSThread* GetJSThread() const 86 { 87 uintptr_t address = ComputeObjectAddress(JSTHREAD_INDEX); 88 return *reinterpret_cast<JSThread**>(address); 89 } 90 SetJSThread(JSThread * thread)91 void SetJSThread(JSThread *thread) 92 { 93 uintptr_t address = ComputeObjectAddress(JSTHREAD_INDEX); 94 *reinterpret_cast<JSThread**>(address) = thread; 95 } 96 97 JSHandle<JSTaggedValue> GetSymbol(JSThread *thread, const JSHandle<JSTaggedValue> &string); 98 JSHandle<JSTaggedValue> GetStringFunctionByName(JSThread *thread, const char *name); 99 JSHandle<JSTaggedValue> GetStringPrototypeFunctionByName(JSThread *thread, const char *name); 100 GetFirstDetectorSymbolAddr(const GlobalEnv * env)101 static inline uintptr_t GetFirstDetectorSymbolAddr(const GlobalEnv *env) 102 { 103 constexpr size_t offset = HEADER_SIZE + FIRST_DETECTOR_SYMBOL_INDEX * JSTaggedValue::TaggedTypeSize(); 104 uintptr_t addr = reinterpret_cast<uintptr_t>(env) + offset; 105 return *reinterpret_cast<uintptr_t *>(addr); 106 } 107 GetLastDetectorSymbolAddr(const GlobalEnv * env)108 static uintptr_t GetLastDetectorSymbolAddr(const GlobalEnv *env) 109 { 110 constexpr size_t offset = HEADER_SIZE + LAST_DETECTOR_SYMBOL_INDEX * JSTaggedValue::TaggedTypeSize(); 111 uintptr_t addr = reinterpret_cast<uintptr_t>(env) + offset; 112 return *reinterpret_cast<uintptr_t *>(addr); 113 } 114 115 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 116 #define GLOBAL_ENV_FIELD_ACCESSORS(type, name, index) \ 117 inline JSHandle<type> Get##name() const \ 118 { \ 119 const uintptr_t address = \ 120 reinterpret_cast<uintptr_t>(this) + HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); \ 121 JSHandle<type> result(address); \ 122 if (result.GetTaggedValue().IsInternalAccessor()) { \ 123 JSThread *thread = GetJSThread(); \ 124 AccessorData *accessor = AccessorData::Cast(result.GetTaggedValue().GetTaggedObject()); \ 125 accessor->CallInternalGet(thread, JSHandle<JSObject>::Cast(GetJSGlobalObject())); \ 126 } \ 127 return result; \ 128 } \ 129 inline JSTaggedValue GetTagged##name() const \ 130 { \ 131 uint32_t offset = HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); \ 132 JSTaggedValue result(Barriers::GetValue<JSTaggedType>(this, offset)); \ 133 if (result.IsInternalAccessor()) { \ 134 JSThread *thread = GetJSThread(); \ 135 AccessorData *accessor = AccessorData::Cast(result.GetTaggedObject()); \ 136 accessor->CallInternalGet(thread, JSHandle<JSObject>::Cast(GetJSGlobalObject())); \ 137 } \ 138 return result; \ 139 } \ 140 template<typename T> \ 141 inline void Set##name(const JSThread *thread, JSHandle<T> value, BarrierMode mode = WRITE_BARRIER) \ 142 { \ 143 uint32_t offset = HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); \ 144 if (mode == WRITE_BARRIER && value.GetTaggedValue().IsHeapObject()) { \ 145 Barriers::SetObject<true>(thread, this, offset, value.GetTaggedValue().GetRawData()); \ 146 } else { \ 147 Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetTaggedValue().GetRawData()); \ 148 } \ 149 } \ 150 inline void Set##name(const JSThread *thread, type value, BarrierMode mode = WRITE_BARRIER) \ 151 { \ 152 uint32_t offset = HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); \ 153 if (mode == WRITE_BARRIER && value.IsHeapObject()) { \ 154 Barriers::SetObject<true>(thread, this, offset, value.GetRawData()); \ 155 } else { \ 156 Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetRawData()); \ 157 } \ 158 } 159 GLOBAL_ENV_FIELDS(GLOBAL_ENV_FIELD_ACCESSORS) 160 #undef GLOBAL_ENV_FIELD_ACCESSORS 161 162 static constexpr size_t HEADER_SIZE = TaggedObjectSize(); 163 static constexpr size_t DATA_SIZE = HEADER_SIZE + FINAL_INDEX * JSTaggedValue::TaggedTypeSize(); 164 static constexpr size_t SIZE = DATA_SIZE + RESERVED_LENGTH * JSTaggedValue::TaggedTypeSize(); 165 166 DECL_VISIT_OBJECT(HEADER_SIZE, DATA_SIZE); 167 168 DECL_DUMP() 169 }; 170 } // namespace panda::ecmascript 171 172 #endif // ECMASCRIPT_GLOBAL_ENV_H 173