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