5 #include "src/contexts.h" 7 #include "src/ast/modules.h" 8 #include "src/bootstrapper.h" 9 #include "src/debug/debug.h" 10 #include "src/isolate-inl.h" 11 #include "src/objects/module-inl.h" 17 Handle<ScriptContextTable> ScriptContextTable::Extend(
18 Handle<ScriptContextTable> table, Handle<Context> script_context) {
19 Handle<ScriptContextTable> result;
20 int used = table->used();
21 int length = table->length();
22 CHECK(used >= 0 && length > 0 && used < length);
23 if (used + kFirstContextSlotIndex == length) {
24 CHECK(length < Smi::kMaxValue / 2);
25 Isolate* isolate = script_context->GetIsolate();
26 Handle<FixedArray> copy =
27 isolate->factory()->CopyFixedArrayAndGrow(table, length);
28 copy->set_map(ReadOnlyRoots(isolate).script_context_table_map());
29 result = Handle<ScriptContextTable>::cast(copy);
33 result->set_used(used + 1);
35 DCHECK(script_context->IsScriptContext());
36 result->set(used + kFirstContextSlotIndex, *script_context);
40 bool ScriptContextTable::Lookup(Isolate* isolate,
41 Handle<ScriptContextTable> table,
42 Handle<String> name, LookupResult* result) {
43 for (
int i = 0;
i < table->used();
i++) {
44 Handle<Context> context = GetContext(isolate, table,
i);
45 DCHECK(context->IsScriptContext());
46 Handle<ScopeInfo> scope_info(context->scope_info(), context->GetIsolate());
47 int slot_index = ScopeInfo::ContextSlotIndex(
48 scope_info, name, &result->mode, &result->init_flag,
49 &result->maybe_assigned_flag);
51 if (slot_index >= 0) {
52 result->context_index =
i;
53 result->slot_index = slot_index;
61 bool Context::is_declaration_context() {
62 if (IsFunctionContext() || IsNativeContext() || IsScriptContext() ||
66 if (IsEvalContext()) {
67 return scope_info()->language_mode() == LanguageMode::kStrict;
69 if (!IsBlockContext())
return false;
70 return scope_info()->is_declaration_scope();
73 Context Context::declaration_context() {
74 Context current = *
this;
75 while (!current->is_declaration_context()) {
76 current = current->previous();
81 Context Context::closure_context() {
82 Context current = *
this;
83 while (!current->IsFunctionContext() && !current->IsScriptContext() &&
84 !current->IsModuleContext() && !current->IsNativeContext() &&
85 !current->IsEvalContext()) {
86 current = current->previous();
91 JSObject* Context::extension_object() {
92 DCHECK(IsNativeContext() || IsFunctionContext() || IsBlockContext() ||
93 IsEvalContext() || IsCatchContext());
94 HeapObject*
object = extension();
95 if (object->IsTheHole())
return nullptr;
96 DCHECK(object->IsJSContextExtensionObject() ||
97 (IsNativeContext() &&
object->IsJSGlobalObject()));
98 return JSObject::cast(
object);
101 JSReceiver* Context::extension_receiver() {
102 DCHECK(IsNativeContext() || IsWithContext() || IsEvalContext() ||
103 IsFunctionContext() || IsBlockContext());
104 return IsWithContext() ? JSReceiver::cast(extension()) : extension_object();
107 ScopeInfo Context::scope_info() {
108 return ScopeInfo::cast(
get(SCOPE_INFO_INDEX));
111 Module* Context::module() {
112 Context current = *
this;
113 while (!current->IsModuleContext()) {
114 current = current->previous();
116 return Module::cast(current->extension());
119 JSGlobalObject* Context::global_object() {
120 return JSGlobalObject::cast(native_context()->extension());
123 Context Context::script_context() {
124 Context current = *
this;
125 while (!current->IsScriptContext()) {
126 current = current->previous();
131 JSGlobalProxy* Context::global_proxy() {
132 return native_context()->global_proxy_object();
135 void Context::set_global_proxy(JSGlobalProxy*
object) {
136 native_context()->set_global_proxy_object(
object);
144 static Maybe<bool> UnscopableLookup(LookupIterator* it) {
145 Isolate* isolate = it->isolate();
147 Maybe<bool> found = JSReceiver::HasProperty(it);
148 if (found.IsNothing() || !found.FromJust())
return found;
150 Handle<Object> unscopables;
151 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
152 isolate, unscopables,
153 JSReceiver::GetProperty(isolate,
154 Handle<JSReceiver>::cast(it->GetReceiver()),
155 isolate->factory()->unscopables_symbol()),
157 if (!unscopables->IsJSReceiver())
return Just(
true);
158 Handle<Object> blacklist;
159 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
161 JSReceiver::GetProperty(isolate, Handle<JSReceiver>::cast(unscopables),
164 return Just(!blacklist->BooleanValue(isolate));
167 static PropertyAttributes GetAttributesForMode(VariableMode mode) {
168 DCHECK(IsDeclaredVariableMode(mode));
169 return mode == VariableMode::kConst ? READ_ONLY : NONE;
172 Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
173 int* index, PropertyAttributes* attributes,
174 InitializationFlag* init_flag,
175 VariableMode* variable_mode,
176 bool* is_sloppy_function_name) {
177 Isolate* isolate = GetIsolate();
178 Handle<Context> context(*
this, isolate);
180 bool follow_context_chain = (flags & FOLLOW_CONTEXT_CHAIN) != 0;
181 bool failed_whitelist =
false;
183 *attributes = ABSENT;
184 *init_flag = kCreatedInitialized;
185 *variable_mode = VariableMode::kVar;
186 if (is_sloppy_function_name !=
nullptr) {
187 *is_sloppy_function_name =
false;
190 if (FLAG_trace_contexts) {
191 PrintF(
"Context::Lookup(");
197 if (FLAG_trace_contexts) {
198 PrintF(
" - looking in context %p",
199 reinterpret_cast<void*>(context->ptr()));
200 if (context->IsScriptContext()) PrintF(
" (script context)");
201 if (context->IsNativeContext()) PrintF(
" (native context)");
206 DCHECK_IMPLIES(context->IsEvalContext(),
207 context->extension()->IsTheHole(isolate));
208 if ((context->IsNativeContext() ||
209 (context->IsWithContext() && ((flags & SKIP_WITH_CONTEXT) == 0)) ||
210 context->IsFunctionContext() || context->IsBlockContext()) &&
211 context->extension_receiver() !=
nullptr) {
212 Handle<JSReceiver> object(context->extension_receiver(), isolate);
214 if (context->IsNativeContext()) {
215 if (FLAG_trace_contexts) {
216 PrintF(
" - trying other script contexts\n");
219 Handle<ScriptContextTable> script_contexts(
220 context->global_object()->native_context()->script_context_table(),
222 ScriptContextTable::LookupResult r;
223 if (ScriptContextTable::Lookup(isolate, script_contexts, name, &r)) {
224 if (FLAG_trace_contexts) {
225 Handle<Context> c = ScriptContextTable::GetContext(
226 isolate, script_contexts, r.context_index);
227 PrintF(
"=> found property in script context %d: %p\n",
228 r.context_index, reinterpret_cast<void*>(c->ptr()));
230 *index = r.slot_index;
231 *variable_mode = r.mode;
232 *init_flag = r.init_flag;
233 *attributes = GetAttributesForMode(r.mode);
234 return ScriptContextTable::GetContext(isolate, script_contexts,
242 Maybe<PropertyAttributes> maybe = Nothing<PropertyAttributes>();
243 if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0 ||
244 object->IsJSContextExtensionObject()) {
245 maybe = JSReceiver::GetOwnPropertyAttributes(
object, name);
246 }
else if (context->IsWithContext()) {
254 if (ScopeInfo::VariableIsSynthetic(*name)) {
255 maybe = Just(ABSENT);
257 LookupIterator it(
object, name,
object);
258 Maybe<bool> found = UnscopableLookup(&it);
259 if (found.IsNothing()) {
260 maybe = Nothing<PropertyAttributes>();
265 maybe = Just(found.FromJust() ? NONE : ABSENT);
269 maybe = JSReceiver::GetPropertyAttributes(
object, name);
272 if (maybe.IsNothing())
return Handle<Object>();
273 DCHECK(!isolate->has_pending_exception());
274 *attributes = maybe.FromJust();
276 if (maybe.FromJust() != ABSENT) {
277 if (FLAG_trace_contexts) {
278 PrintF(
"=> found property in context object %p\n",
279 reinterpret_cast<void*>(*
object));
286 if (context->IsFunctionContext() || context->IsBlockContext() ||
287 context->IsScriptContext() || context->IsEvalContext() ||
288 context->IsModuleContext() || context->IsCatchContext()) {
291 Handle<ScopeInfo> scope_info(context->scope_info(), isolate);
293 InitializationFlag flag;
294 MaybeAssignedFlag maybe_assigned_flag;
295 int slot_index = ScopeInfo::ContextSlotIndex(scope_info, name, &mode,
296 &flag, &maybe_assigned_flag);
297 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS);
298 if (slot_index >= 0) {
299 if (FLAG_trace_contexts) {
300 PrintF(
"=> found local in context slot %d (mode = %hhu)\n",
301 slot_index, static_cast<uint8_t>(mode));
304 *variable_mode = mode;
306 *attributes = GetAttributesForMode(mode);
313 if (follow_context_chain && (flags & STOP_AT_DECLARATION_SCOPE) == 0 &&
314 context->IsFunctionContext()) {
315 int function_index = scope_info->FunctionContextSlotIndex(*name);
316 if (function_index >= 0) {
317 if (FLAG_trace_contexts) {
318 PrintF(
"=> found intermediate function in context slot %d\n",
321 *index = function_index;
322 *attributes = READ_ONLY;
323 *init_flag = kCreatedInitialized;
324 *variable_mode = VariableMode::kConst;
325 if (is_sloppy_function_name !=
nullptr &&
326 is_sloppy(scope_info->language_mode())) {
327 *is_sloppy_function_name =
true;
334 if (context->IsModuleContext()) {
336 InitializationFlag flag;
337 MaybeAssignedFlag maybe_assigned_flag;
339 scope_info->ModuleIndex(name, &mode, &flag, &maybe_assigned_flag);
340 if (cell_index != 0) {
341 if (FLAG_trace_contexts) {
342 PrintF(
"=> found in module imports or exports\n");
345 *variable_mode = mode;
347 *attributes = ModuleDescriptor::GetCellIndexKind(cell_index) ==
348 ModuleDescriptor::kExport
349 ? GetAttributesForMode(mode)
351 return handle(context->module(), isolate);
354 }
else if (context->IsDebugEvaluateContext()) {
356 Object* ext = context->get(EXTENSION_INDEX);
357 if (ext->IsJSReceiver()) {
358 Handle<JSReceiver> extension(JSReceiver::cast(ext), isolate);
359 LookupIterator it(extension, name, extension);
360 Maybe<bool> found = JSReceiver::HasProperty(&it);
361 if (found.FromMaybe(
false)) {
367 Object* obj = context->get(WRAPPED_CONTEXT_INDEX);
368 if (obj->IsContext()) {
369 Handle<Object> result =
370 Context::cast(obj)->Lookup(name, DONT_FOLLOW_CHAINS, index,
371 attributes, init_flag, variable_mode);
372 if (!result.is_null())
return result;
376 obj = context->get(WHITE_LIST_INDEX);
377 if (obj->IsStringSet()) {
379 failed_whitelist || !StringSet::cast(obj)->Has(isolate, name);
384 if (context->IsNativeContext() ||
385 ((flags & STOP_AT_DECLARATION_SCOPE) != 0 &&
386 context->is_declaration_context())) {
387 follow_context_chain =
false;
390 context = Handle<Context>(context->previous(), isolate);
394 }
while (failed_whitelist && !context->IsScriptContext() &&
395 !context->IsNativeContext() && !context->IsWithContext() &&
396 !context->IsModuleContext());
398 }
while (follow_context_chain);
400 if (FLAG_trace_contexts) {
401 PrintF(
"=> no property/slot found\n");
403 return Handle<Object>::null();
406 void Context::AddOptimizedCode(Code code) {
407 DCHECK(IsNativeContext());
408 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
409 DCHECK(code->next_code_link()->IsUndefined());
410 code->set_next_code_link(
get(OPTIMIZED_CODE_LIST));
411 set(OPTIMIZED_CODE_LIST, code, UPDATE_WEAK_WRITE_BARRIER);
415 void Context::SetOptimizedCodeListHead(Object* head) {
416 DCHECK(IsNativeContext());
417 set(OPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
421 Object* Context::OptimizedCodeListHead() {
422 DCHECK(IsNativeContext());
423 return get(OPTIMIZED_CODE_LIST);
427 void Context::SetDeoptimizedCodeListHead(Object* head) {
428 DCHECK(IsNativeContext());
429 set(DEOPTIMIZED_CODE_LIST, head, UPDATE_WEAK_WRITE_BARRIER);
433 Object* Context::DeoptimizedCodeListHead() {
434 DCHECK(IsNativeContext());
435 return get(DEOPTIMIZED_CODE_LIST);
439 Handle<Object> Context::ErrorMessageForCodeGenerationFromStrings() {
440 Isolate* isolate = GetIsolate();
441 Handle<Object> result(error_message_for_code_gen_from_strings(), isolate);
442 if (!result->IsUndefined(isolate))
return result;
443 return isolate->factory()->NewStringFromStaticChars(
444 "Code generation from strings disallowed for this context");
448 #define COMPARE_NAME(index, type, name) \ 449 if (string->IsOneByteEqualTo(STATIC_CHAR_VECTOR(#name))) return index; 451 int Context::ImportedFieldIndexForName(Handle<String>
string) {
452 NATIVE_CONTEXT_IMPORTED_FIELDS(COMPARE_NAME)
457 int Context::IntrinsicIndexForName(Handle<String>
string) {
458 NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(COMPARE_NAME);
464 #define COMPARE_NAME(index, type, name) \ 465 if (strncmp(string, #name, length) == 0) return index; 467 int Context::IntrinsicIndexForName(
const unsigned char* unsigned_string,
469 const char*
string =
reinterpret_cast<const char*
>(unsigned_string);
470 NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(COMPARE_NAME);
478 bool Context::IsBootstrappingOrNativeContext(Isolate* isolate, Object*
object) {
481 return isolate->heap()->gc_state() != Heap::NOT_IN_GC ||
482 isolate->bootstrapper()->IsActive() ||
object->IsNativeContext();
485 bool Context::IsBootstrappingOrValidParentContext(Object*
object,
489 if (child->GetIsolate()->bootstrapper()->IsActive())
return true;
490 if (!object->IsContext())
return false;
491 Context context = Context::cast(
object);
492 return context->IsNativeContext() || context->IsScriptContext() ||
493 context->IsModuleContext() || !child->IsModuleContext();
498 void Context::ResetErrorsThrown() {
499 DCHECK(IsNativeContext());
500 set_errors_thrown(Smi::FromInt(0));
503 void Context::IncrementErrorsThrown() {
504 DCHECK(IsNativeContext());
506 int previous_value = errors_thrown()->value();
507 set_errors_thrown(Smi::FromInt(previous_value + 1));
510 int Context::GetErrorsThrown() {
return errors_thrown()->value(); }
512 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4);
513 STATIC_ASSERT(NativeContext::kScopeInfoOffset ==
514 Context::OffsetOfElementAt(NativeContext::SCOPE_INFO_INDEX));
515 STATIC_ASSERT(NativeContext::kPreviousOffset ==
516 Context::OffsetOfElementAt(NativeContext::PREVIOUS_INDEX));
517 STATIC_ASSERT(NativeContext::kExtensionOffset ==
518 Context::OffsetOfElementAt(NativeContext::EXTENSION_INDEX));
519 STATIC_ASSERT(NativeContext::kNativeContextOffset ==
520 Context::OffsetOfElementAt(NativeContext::NATIVE_CONTEXT_INDEX));
522 STATIC_ASSERT(NativeContext::kStartOfStrongFieldsOffset ==
523 Context::OffsetOfElementAt(0));
524 STATIC_ASSERT(NativeContext::kStartOfWeakFieldsOffset ==
525 Context::OffsetOfElementAt(NativeContext::FIRST_WEAK_SLOT));
526 STATIC_ASSERT(NativeContext::kMicrotaskQueueOffset ==
527 Context::SizeFor(NativeContext::NATIVE_CONTEXT_SLOTS));
528 STATIC_ASSERT(NativeContext::kSize ==
529 (Context::SizeFor(NativeContext::NATIVE_CONTEXT_SLOTS) +
530 kSystemPointerSize));