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_CONTEXTS_INL_H_
6 #define V8_CONTEXTS_INL_H_
7 
8 #include "src/contexts.h"
9 #include "src/heap/heap.h"
10 #include "src/objects-inl.h"
11 #include "src/objects/dictionary.h"
12 #include "src/objects/map-inl.h"
13 #include "src/objects/regexp-match-info.h"
14 #include "src/objects/shared-function-info-inl.h"
15 #include "src/objects/template-objects.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 
21 // static
cast(Object * context)22 ScriptContextTable* ScriptContextTable::cast(Object* context) {
23   DCHECK(context->IsScriptContextTable());
24   return reinterpret_cast<ScriptContextTable*>(context);
25 }
26 
used()27 int ScriptContextTable::used() const { return Smi::ToInt(get(kUsedSlotIndex)); }
28 
set_used(int used)29 void ScriptContextTable::set_used(int used) {
30   set(kUsedSlotIndex, Smi::FromInt(used));
31 }
32 
33 
34 // static
GetContext(Handle<ScriptContextTable> table,int i)35 Handle<Context> ScriptContextTable::GetContext(Handle<ScriptContextTable> table,
36                                                int i) {
37   DCHECK(i < table->used());
38   return Handle<Context>::cast(
39       FixedArray::get(*table, i + kFirstContextSlotIndex, table->GetIsolate()));
40 }
41 
42 
43 // static
cast(Object * context)44 Context* Context::cast(Object* context) {
45   DCHECK(context->IsContext());
46   return reinterpret_cast<Context*>(context);
47 }
48 
set_scope_info(ScopeInfo * scope_info)49 void Context::set_scope_info(ScopeInfo* scope_info) {
50   set(SCOPE_INFO_INDEX, scope_info);
51 }
52 
previous()53 Context* Context::previous() {
54   Object* result = get(PREVIOUS_INDEX);
55   DCHECK(IsBootstrappingOrValidParentContext(result, this));
56   return reinterpret_cast<Context*>(result);
57 }
set_previous(Context * context)58 void Context::set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
59 
next_context_link()60 Object* Context::next_context_link() { return get(Context::NEXT_CONTEXT_LINK); }
61 
has_extension()62 bool Context::has_extension() { return !extension()->IsTheHole(GetIsolate()); }
extension()63 HeapObject* Context::extension() {
64   return HeapObject::cast(get(EXTENSION_INDEX));
65 }
set_extension(HeapObject * object)66 void Context::set_extension(HeapObject* object) {
67   set(EXTENSION_INDEX, object);
68 }
69 
native_context()70 Context* Context::native_context() const {
71   Object* result = get(NATIVE_CONTEXT_INDEX);
72   DCHECK(IsBootstrappingOrNativeContext(this->GetIsolate(), result));
73   return reinterpret_cast<Context*>(result);
74 }
75 
76 
set_native_context(Context * context)77 void Context::set_native_context(Context* context) {
78   set(NATIVE_CONTEXT_INDEX, context);
79 }
80 
IsNativeContext()81 bool Context::IsNativeContext() const {
82   return map()->instance_type() == NATIVE_CONTEXT_TYPE;
83 }
84 
IsFunctionContext()85 bool Context::IsFunctionContext() const {
86   return map()->instance_type() == FUNCTION_CONTEXT_TYPE;
87 }
88 
IsCatchContext()89 bool Context::IsCatchContext() const {
90   return map()->instance_type() == CATCH_CONTEXT_TYPE;
91 }
92 
IsWithContext()93 bool Context::IsWithContext() const {
94   return map()->instance_type() == WITH_CONTEXT_TYPE;
95 }
96 
IsDebugEvaluateContext()97 bool Context::IsDebugEvaluateContext() const {
98   return map()->instance_type() == DEBUG_EVALUATE_CONTEXT_TYPE;
99 }
100 
IsBlockContext()101 bool Context::IsBlockContext() const {
102   return map()->instance_type() == BLOCK_CONTEXT_TYPE;
103 }
104 
IsModuleContext()105 bool Context::IsModuleContext() const {
106   return map()->instance_type() == MODULE_CONTEXT_TYPE;
107 }
108 
IsEvalContext()109 bool Context::IsEvalContext() const {
110   return map()->instance_type() == EVAL_CONTEXT_TYPE;
111 }
112 
IsScriptContext()113 bool Context::IsScriptContext() const {
114   return map()->instance_type() == SCRIPT_CONTEXT_TYPE;
115 }
116 
HasSameSecurityTokenAs(Context * that)117 bool Context::HasSameSecurityTokenAs(Context* that) const {
118   return this->native_context()->security_token() ==
119          that->native_context()->security_token();
120 }
121 
122 #define NATIVE_CONTEXT_FIELD_ACCESSORS(index, type, name) \
123   void Context::set_##name(type* value) {                 \
124     DCHECK(IsNativeContext());                            \
125     set(index, value);                                    \
126   }                                                       \
127   bool Context::is_##name(type* value) const {            \
128     DCHECK(IsNativeContext());                            \
129     return type::cast(get(index)) == value;               \
130   }                                                       \
131   type* Context::name() const {                           \
132     DCHECK(IsNativeContext());                            \
133     return type::cast(get(index));                        \
134   }
NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)135 NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSORS)
136 #undef NATIVE_CONTEXT_FIELD_ACCESSORS
137 
138 #define CHECK_FOLLOWS2(v1, v2) STATIC_ASSERT((v1 + 1) == (v2))
139 #define CHECK_FOLLOWS4(v1, v2, v3, v4) \
140   CHECK_FOLLOWS2(v1, v2);              \
141   CHECK_FOLLOWS2(v2, v3);              \
142   CHECK_FOLLOWS2(v3, v4)
143 
144 int Context::FunctionMapIndex(LanguageMode language_mode, FunctionKind kind,
145                               bool has_prototype_slot, bool has_shared_name,
146                               bool needs_home_object) {
147   if (IsClassConstructor(kind)) {
148     // Like the strict function map, but with no 'name' accessor. 'name'
149     // needs to be the last property and it is added during instantiation,
150     // in case a static property with the same name exists"
151     return CLASS_FUNCTION_MAP_INDEX;
152   }
153 
154   int base = 0;
155   if (IsGeneratorFunction(kind)) {
156     CHECK_FOLLOWS4(GENERATOR_FUNCTION_MAP_INDEX,
157                    GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
158                    GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
159                    GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
160     CHECK_FOLLOWS4(
161         ASYNC_GENERATOR_FUNCTION_MAP_INDEX,
162         ASYNC_GENERATOR_FUNCTION_WITH_NAME_MAP_INDEX,
163         ASYNC_GENERATOR_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
164         ASYNC_GENERATOR_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
165 
166     base = IsAsyncFunction(kind) ? ASYNC_GENERATOR_FUNCTION_MAP_INDEX
167                                  : GENERATOR_FUNCTION_MAP_INDEX;
168 
169   } else if (IsAsyncFunction(kind)) {
170     CHECK_FOLLOWS4(ASYNC_FUNCTION_MAP_INDEX, ASYNC_FUNCTION_WITH_NAME_MAP_INDEX,
171                    ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
172                    ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
173 
174     base = ASYNC_FUNCTION_MAP_INDEX;
175 
176   } else if (IsArrowFunction(kind) || IsConciseMethod(kind) ||
177              IsAccessorFunction(kind)) {
178     DCHECK_IMPLIES(IsArrowFunction(kind), !needs_home_object);
179     CHECK_FOLLOWS4(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
180                    METHOD_WITH_NAME_MAP_INDEX,
181                    METHOD_WITH_HOME_OBJECT_MAP_INDEX,
182                    METHOD_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
183 
184     base = STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
185 
186   } else {
187     DCHECK(!needs_home_object);
188     CHECK_FOLLOWS2(SLOPPY_FUNCTION_MAP_INDEX,
189                    SLOPPY_FUNCTION_WITH_NAME_MAP_INDEX);
190     CHECK_FOLLOWS2(STRICT_FUNCTION_MAP_INDEX,
191                    STRICT_FUNCTION_WITH_NAME_MAP_INDEX);
192 
193     base = is_strict(language_mode) ? STRICT_FUNCTION_MAP_INDEX
194                                     : SLOPPY_FUNCTION_MAP_INDEX;
195   }
196   int offset = static_cast<int>(!has_shared_name) |
197                (static_cast<int>(needs_home_object) << 1);
198   DCHECK_EQ(0, offset & ~3);
199 
200   return base + offset;
201 }
202 
203 #undef CHECK_FOLLOWS2
204 #undef CHECK_FOLLOWS4
205 
GetInitialJSArrayMap(ElementsKind kind)206 Map* Context::GetInitialJSArrayMap(ElementsKind kind) const {
207   DCHECK(IsNativeContext());
208   if (!IsFastElementsKind(kind)) return nullptr;
209   DisallowHeapAllocation no_gc;
210   Object* const initial_js_array_map = get(Context::ArrayMapIndex(kind));
211   DCHECK(!initial_js_array_map->IsUndefined(GetIsolate()));
212   return Map::cast(initial_js_array_map);
213 }
214 
215 }  // namespace internal
216 }  // namespace v8
217 
218 #endif  // V8_CONTEXTS_INL_H_
219