1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef V8_OBJECTS_CONTEXTS_INL_H_ 6#define V8_OBJECTS_CONTEXTS_INL_H_ 7 8#include "src/common/globals.h" 9#include "src/heap/heap-write-barrier.h" 10#include "src/objects/contexts.h" 11#include "src/objects/dictionary-inl.h" 12#include "src/objects/fixed-array-inl.h" 13#include "src/objects/js-function-inl.h" 14#include "src/objects/js-objects-inl.h" 15#include "src/objects/map-inl.h" 16#include "src/objects/objects-inl.h" 17#include "src/objects/ordered-hash-table-inl.h" 18#include "src/objects/osr-optimized-code-cache-inl.h" 19#include "src/objects/regexp-match-info.h" 20#include "src/objects/scope-info.h" 21#include "src/objects/shared-function-info.h" 22 23// Has to be the last include (doesn't have include guards): 24#include "src/objects/object-macros.h" 25 26namespace v8 { 27namespace internal { 28 29#include "torque-generated/src/objects/contexts-tq-inl.inc" 30 31OBJECT_CONSTRUCTORS_IMPL(ScriptContextTable, FixedArray) 32CAST_ACCESSOR(ScriptContextTable) 33 34int ScriptContextTable::used(AcquireLoadTag tag) const { 35 return Smi::ToInt(get(kUsedSlotIndex, tag)); 36} 37 38void ScriptContextTable::set_used(int used, ReleaseStoreTag tag) { 39 set(kUsedSlotIndex, Smi::FromInt(used), tag); 40} 41 42ACCESSORS(ScriptContextTable, names_to_context_index, NameToIndexHashTable, 43 kHashTableOffset) 44 45// static 46Handle<Context> ScriptContextTable::GetContext(Isolate* isolate, 47 Handle<ScriptContextTable> table, 48 int i) { 49 return handle(table->get_context(i), isolate); 50} 51 52Context ScriptContextTable::get_context(int i) const { 53 DCHECK_LT(i, used(kAcquireLoad)); 54 return Context::cast(get(i + kFirstContextSlotIndex)); 55} 56 57Context ScriptContextTable::get_context(int i, AcquireLoadTag tag) const { 58 DCHECK_LT(i, used(kAcquireLoad)); 59 return Context::cast(get(i + kFirstContextSlotIndex, tag)); 60} 61 62TQ_OBJECT_CONSTRUCTORS_IMPL(Context) 63NEVER_READ_ONLY_SPACE_IMPL(Context) 64 65CAST_ACCESSOR(NativeContext) 66 67RELAXED_SMI_ACCESSORS(Context, length, kLengthOffset) 68 69Object Context::get(int index) const { 70 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); 71 return get(cage_base, index); 72} 73 74Object Context::get(PtrComprCageBase cage_base, int index) const { 75 DCHECK_LT(static_cast<unsigned int>(index), 76 static_cast<unsigned int>(length(kRelaxedLoad))); 77 return TaggedField<Object>::Relaxed_Load(cage_base, *this, 78 OffsetOfElementAt(index)); 79} 80 81void Context::set(int index, Object value, WriteBarrierMode mode) { 82 DCHECK_LT(static_cast<unsigned int>(index), 83 static_cast<unsigned int>(length(kRelaxedLoad))); 84 const int offset = OffsetOfElementAt(index); 85 RELAXED_WRITE_FIELD(*this, offset, value); 86 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); 87} 88 89Object Context::get(int index, AcquireLoadTag tag) const { 90 PtrComprCageBase cage_base = GetPtrComprCageBase(*this); 91 return get(cage_base, index, tag); 92} 93 94Object Context::get(PtrComprCageBase cage_base, int index, 95 AcquireLoadTag) const { 96 DCHECK_LT(static_cast<unsigned int>(index), 97 static_cast<unsigned int>(length(kRelaxedLoad))); 98 return ACQUIRE_READ_FIELD(*this, OffsetOfElementAt(index)); 99} 100 101void Context::set(int index, Object value, WriteBarrierMode mode, 102 ReleaseStoreTag) { 103 DCHECK_LT(static_cast<unsigned int>(index), 104 static_cast<unsigned int>(length(kRelaxedLoad))); 105 const int offset = OffsetOfElementAt(index); 106 RELEASE_WRITE_FIELD(*this, offset, value); 107 CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode); 108} 109 110void NativeContext::set(int index, Object value, WriteBarrierMode mode, 111 ReleaseStoreTag tag) { 112 Context::set(index, value, mode, tag); 113} 114 115ACCESSORS(Context, scope_info, ScopeInfo, kScopeInfoOffset) 116 117Object Context::unchecked_previous() const { return get(PREVIOUS_INDEX); } 118 119Context Context::previous() const { 120 Object result = get(PREVIOUS_INDEX); 121 DCHECK(IsBootstrappingOrValidParentContext(result, *this)); 122 return Context::unchecked_cast(result); 123} 124void Context::set_previous(Context context, WriteBarrierMode mode) { 125 set(PREVIOUS_INDEX, context, mode); 126} 127 128Object Context::next_context_link() const { 129 return get(Context::NEXT_CONTEXT_LINK); 130} 131 132bool Context::has_extension() const { 133 return scope_info().HasContextExtensionSlot() && !extension().IsUndefined(); 134} 135 136HeapObject Context::extension() const { 137 DCHECK(scope_info().HasContextExtensionSlot()); 138 return HeapObject::cast(get(EXTENSION_INDEX)); 139} 140 141NativeContext Context::native_context() const { 142 return this->map().native_context(); 143} 144 145bool Context::IsFunctionContext() const { 146 return map().instance_type() == FUNCTION_CONTEXT_TYPE; 147} 148 149bool Context::IsCatchContext() const { 150 return map().instance_type() == CATCH_CONTEXT_TYPE; 151} 152 153bool Context::IsWithContext() const { 154 return map().instance_type() == WITH_CONTEXT_TYPE; 155} 156 157bool Context::IsDebugEvaluateContext() const { 158 return map().instance_type() == DEBUG_EVALUATE_CONTEXT_TYPE; 159} 160 161bool Context::IsAwaitContext() const { 162 return map().instance_type() == AWAIT_CONTEXT_TYPE; 163} 164 165bool Context::IsBlockContext() const { 166 return map().instance_type() == BLOCK_CONTEXT_TYPE; 167} 168 169bool Context::IsModuleContext() const { 170 return map().instance_type() == MODULE_CONTEXT_TYPE; 171} 172 173bool Context::IsEvalContext() const { 174 return map().instance_type() == EVAL_CONTEXT_TYPE; 175} 176 177bool Context::IsScriptContext() const { 178 return map().instance_type() == SCRIPT_CONTEXT_TYPE; 179} 180 181bool Context::HasSameSecurityTokenAs(Context that) const { 182 return this->native_context().security_token() == 183 that.native_context().security_token(); 184} 185 186#define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \ 187 void Context::set_##name(type value) { \ 188 DCHECK(IsNativeContext()); \ 189 set(index, value, UPDATE_WRITE_BARRIER, kReleaseStore); \ 190 } \ 191 bool Context::is_##name(type value) const { \ 192 DCHECK(IsNativeContext()); \ 193 return type::cast(get(index)) == value; \ 194 } \ 195 type Context::name() const { \ 196 DCHECK(IsNativeContext()); \ 197 return type::cast(get(index)); \ 198 } \ 199 type Context::name(AcquireLoadTag tag) const { \ 200 DCHECK(IsNativeContext()); \ 201 return type::cast(get(index, tag)); \ 202 } 203NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS) 204#undef NATIVE_CONTEXT_FIELD_ACCESSORS 205 206#define CHECK_FOLLOWS2(v1, v2) STATIC_ASSERT((v1 + 1) == (v2)) 207#define CHECK_FOLLOWS4(v1, v2, v3, v4) \ 208 CHECK_FOLLOWS2(v1, v2); \ 209 CHECK_FOLLOWS2(v2, v3); \ 210 CHECK_FOLLOWS2(v3, v4) 211 212int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind, 213 bool has_shared_name) { 214 if (IsClassConstructor(kind)) { 215 // Like the strict function map, but with no 'name' accessor. 'name' 216 // needs to be the last property and it is added during instantiation, 217 // in case a static property with the same name exists" 218 return CLASS_FUNCTION_MAP_INDEX; 219 } 220 221 int base = 0; 222 if (IsGeneratorFunction(kind)) { 223 CHECK_FOLLOWS2(GENERATOR_FUNCTION_MAP_INDEX, 224 GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX); 225 CHECK_FOLLOWS2(ASYNC_GENERATOR_FUNCTION_MAP_INDEX, 226 ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX); 227 228 base = IsAsyncFunction(kind) ? ASYNC_GENERATOR_FUNCTION_MAP_INDEX 229 : GENERATOR_FUNCTION_MAP_INDEX; 230 231 } else if (IsAsyncFunction(kind) || IsAsyncModule(kind)) { 232 CHECK_FOLLOWS2(ASYNC_FUNCTION_MAP_INDEX, 233 ASYNC_FUNCTION_WITH_NAME_MAP_INDEX); 234 235 base = ASYNC_FUNCTION_MAP_INDEX; 236 237 } else if (IsStrictFunctionWithoutPrototype(kind)) { 238 CHECK_FOLLOWS2(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, 239 METHOD_WITH_NAME_MAP_INDEX); 240 241 base = STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX; 242 243 } else { 244 CHECK_FOLLOWS2(SLOPPY_FUNCTION_MAP_INDEX, 245 SLOPPY_FUNCTION_WITH_NAME_MAP_INDEX); 246 CHECK_FOLLOWS2(STRICT_FUNCTION_MAP_INDEX, 247 STRICT_FUNCTION_WITH_NAME_MAP_INDEX); 248 249 base = is_strict(language_mode) ? STRICT_FUNCTION_MAP_INDEX 250 : SLOPPY_FUNCTION_MAP_INDEX; 251 } 252 int offset = static_cast<int>(!has_shared_name); 253 DCHECK_EQ(0, offset & ~1); 254 255 return base + offset; 256} 257 258#undef CHECK_FOLLOWS2 259#undef CHECK_FOLLOWS4 260 261Map Context::GetInitialJSArrayMap(ElementsKind kind) const { 262 DCHECK(IsNativeContext()); 263 if (!IsFastElementsKind(kind)) return Map(); 264 DisallowGarbageCollection no_gc; 265 Object const initial_js_array_map = get(Context::ArrayMapIndex(kind)); 266 DCHECK(!initial_js_array_map.IsUndefined()); 267 return Map::cast(initial_js_array_map); 268} 269 270DEF_GETTER(NativeContext, microtask_queue, MicrotaskQueue*) { 271 Isolate* isolate = GetIsolateForSandbox(*this); 272 return reinterpret_cast<MicrotaskQueue*>(ReadExternalPointerField( 273 kMicrotaskQueueOffset, isolate, kNativeContextMicrotaskQueueTag)); 274} 275 276void NativeContext::AllocateExternalPointerEntries(Isolate* isolate) { 277 InitExternalPointerField(kMicrotaskQueueOffset, isolate, 278 kNativeContextMicrotaskQueueTag); 279} 280 281void NativeContext::set_microtask_queue(Isolate* isolate, 282 MicrotaskQueue* microtask_queue) { 283 WriteExternalPointerField(kMicrotaskQueueOffset, isolate, 284 reinterpret_cast<Address>(microtask_queue), 285 kNativeContextMicrotaskQueueTag); 286} 287 288void NativeContext::synchronized_set_script_context_table( 289 ScriptContextTable script_context_table) { 290 set(SCRIPT_CONTEXT_TABLE_INDEX, script_context_table, UPDATE_WRITE_BARRIER, 291 kReleaseStore); 292} 293 294ScriptContextTable NativeContext::synchronized_script_context_table() const { 295 return ScriptContextTable::cast( 296 get(SCRIPT_CONTEXT_TABLE_INDEX, kAcquireLoad)); 297} 298 299void NativeContext::SetOptimizedCodeListHead(Object head) { 300 set(OPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER, kReleaseStore); 301} 302 303Object NativeContext::OptimizedCodeListHead() { 304 return get(OPTIMIZED_CODE_LIST); 305} 306 307void NativeContext::SetDeoptimizedCodeListHead(Object head) { 308 set(DEOPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER, kReleaseStore); 309} 310 311Object NativeContext::DeoptimizedCodeListHead() { 312 return get(DEOPTIMIZED_CODE_LIST); 313} 314 315OBJECT_CONSTRUCTORS_IMPL(NativeContext, Context) 316 317} // namespace internal 318} // namespace v8 319 320#include "src/objects/object-macros-undef.h" 321 322#endif // V8_OBJECTS_CONTEXTS_INL_H_ 323