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