OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/contexts.h" | 5 #include "src/contexts.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
9 #include "src/scopeinfo.h" | 9 #include "src/scopeinfo.h" |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 result->set(used + 1, *script_context); | 34 result->set(used + 1, *script_context); |
35 return result; | 35 return result; |
36 } | 36 } |
37 | 37 |
38 | 38 |
39 bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table, | 39 bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table, |
40 Handle<String> name, LookupResult* result) { | 40 Handle<String> name, LookupResult* result) { |
41 for (int i = 0; i < table->used(); i++) { | 41 for (int i = 0; i < table->used(); i++) { |
42 Handle<Context> context = GetContext(table, i); | 42 Handle<Context> context = GetContext(table, i); |
43 DCHECK(context->IsScriptContext()); | 43 DCHECK(context->IsScriptContext()); |
44 Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); | 44 Handle<ScopeInfo> scope_info(context->scope_info()); |
45 int slot_index = ScopeInfo::ContextSlotIndex( | 45 int slot_index = ScopeInfo::ContextSlotIndex( |
46 scope_info, name, &result->mode, &result->location, &result->init_flag, | 46 scope_info, name, &result->mode, &result->location, &result->init_flag, |
47 &result->maybe_assigned_flag); | 47 &result->maybe_assigned_flag); |
48 | 48 |
49 if (slot_index >= 0 && result->location == VariableLocation::CONTEXT) { | 49 if (slot_index >= 0 && result->location == VariableLocation::CONTEXT) { |
50 result->context_index = i; | 50 result->context_index = i; |
51 result->slot_index = slot_index; | 51 result->slot_index = slot_index; |
52 return true; | 52 return true; |
53 } | 53 } |
54 } | 54 } |
55 return false; | 55 return false; |
56 } | 56 } |
57 | 57 |
58 | 58 |
| 59 bool Context::is_declaration_context() { |
| 60 if (IsFunctionContext() || IsNativeContext() || IsScriptContext()) { |
| 61 return true; |
| 62 } |
| 63 if (!IsBlockContext()) return false; |
| 64 Object* ext = extension(); |
| 65 // If we have the special extension, we immediately know it must be a |
| 66 // declaration scope. That's just a small performance shortcut. |
| 67 return ext->IsSloppyBlockWithEvalContextExtension() |
| 68 || ScopeInfo::cast(ext)->is_declaration_scope(); |
| 69 } |
| 70 |
| 71 |
59 Context* Context::declaration_context() { | 72 Context* Context::declaration_context() { |
60 Context* current = this; | 73 Context* current = this; |
61 while (!current->IsFunctionContext() && !current->IsNativeContext() && | 74 while (!current->is_declaration_context()) { |
62 !current->IsScriptContext()) { | |
63 current = current->previous(); | 75 current = current->previous(); |
64 DCHECK(current->closure() == closure()); | 76 DCHECK(current->closure() == closure()); |
65 } | 77 } |
66 return current; | 78 return current; |
67 } | 79 } |
68 | 80 |
69 | 81 |
| 82 JSObject* Context::extension_object() { |
| 83 DCHECK(IsNativeContext() || IsFunctionContext() || IsBlockContext()); |
| 84 Object* object = extension(); |
| 85 if (object == nullptr) return nullptr; |
| 86 if (IsBlockContext()) { |
| 87 if (!object->IsSloppyBlockWithEvalContextExtension()) return nullptr; |
| 88 object = SloppyBlockWithEvalContextExtension::cast(object)->extension(); |
| 89 } |
| 90 DCHECK(object->IsJSContextExtensionObject() || |
| 91 (IsNativeContext() && object->IsJSGlobalObject())); |
| 92 return JSObject::cast(object); |
| 93 } |
| 94 |
| 95 |
| 96 JSReceiver* Context::extension_receiver() { |
| 97 DCHECK(IsNativeContext() || IsWithContext() || |
| 98 IsFunctionContext() || IsBlockContext()); |
| 99 return IsWithContext() ? JSReceiver::cast(extension()) : extension_object(); |
| 100 } |
| 101 |
| 102 |
| 103 ScopeInfo* Context::scope_info() { |
| 104 DCHECK(IsModuleContext() || IsScriptContext() || IsBlockContext()); |
| 105 Object* object = extension(); |
| 106 if (object->IsSloppyBlockWithEvalContextExtension()) { |
| 107 DCHECK(IsBlockContext()); |
| 108 object = SloppyBlockWithEvalContextExtension::cast(object)->scope_info(); |
| 109 } |
| 110 return ScopeInfo::cast(object); |
| 111 } |
| 112 |
| 113 |
| 114 String* Context::catch_name() { |
| 115 DCHECK(IsCatchContext()); |
| 116 return String::cast(extension()); |
| 117 } |
| 118 |
| 119 |
70 JSBuiltinsObject* Context::builtins() { | 120 JSBuiltinsObject* Context::builtins() { |
71 GlobalObject* object = global_object(); | 121 GlobalObject* object = global_object(); |
72 if (object->IsJSGlobalObject()) { | 122 if (object->IsJSGlobalObject()) { |
73 return JSGlobalObject::cast(object)->builtins(); | 123 return JSGlobalObject::cast(object)->builtins(); |
74 } else { | 124 } else { |
75 DCHECK(object->IsJSBuiltinsObject()); | 125 DCHECK(object->IsJSBuiltinsObject()); |
76 return JSBuiltinsObject::cast(object); | 126 return JSBuiltinsObject::cast(object); |
77 } | 127 } |
78 } | 128 } |
79 | 129 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 } | 255 } |
206 | 256 |
207 do { | 257 do { |
208 if (FLAG_trace_contexts) { | 258 if (FLAG_trace_contexts) { |
209 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); | 259 PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); |
210 if (context->IsScriptContext()) PrintF(" (script context)"); | 260 if (context->IsScriptContext()) PrintF(" (script context)"); |
211 if (context->IsNativeContext()) PrintF(" (native context)"); | 261 if (context->IsNativeContext()) PrintF(" (native context)"); |
212 PrintF("\n"); | 262 PrintF("\n"); |
213 } | 263 } |
214 | 264 |
215 | |
216 // 1. Check global objects, subjects of with, and extension objects. | 265 // 1. Check global objects, subjects of with, and extension objects. |
217 if (context->IsNativeContext() || | 266 if ((context->IsNativeContext() || context->IsWithContext() || |
218 context->IsWithContext() || | 267 context->IsFunctionContext() || context->IsBlockContext()) && |
219 (context->IsFunctionContext() && context->has_extension())) { | 268 context->extension_receiver() != nullptr) { |
220 Handle<JSReceiver> object( | 269 Handle<JSReceiver> object(context->extension_receiver()); |
221 JSReceiver::cast(context->extension()), isolate); | |
222 | 270 |
223 if (context->IsNativeContext()) { | 271 if (context->IsNativeContext()) { |
224 if (FLAG_trace_contexts) { | 272 if (FLAG_trace_contexts) { |
225 PrintF(" - trying other script contexts\n"); | 273 PrintF(" - trying other script contexts\n"); |
226 } | 274 } |
227 // Try other script contexts. | 275 // Try other script contexts. |
228 Handle<ScriptContextTable> script_contexts( | 276 Handle<ScriptContextTable> script_contexts( |
229 context->global_object()->native_context()->script_context_table()); | 277 context->global_object()->native_context()->script_context_table()); |
230 ScriptContextTable::LookupResult r; | 278 ScriptContextTable::LookupResult r; |
231 if (ScriptContextTable::Lookup(script_contexts, name, &r)) { | 279 if (ScriptContextTable::Lookup(script_contexts, name, &r)) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 } | 321 } |
274 return object; | 322 return object; |
275 } | 323 } |
276 } | 324 } |
277 | 325 |
278 // 2. Check the context proper if it has slots. | 326 // 2. Check the context proper if it has slots. |
279 if (context->IsFunctionContext() || context->IsBlockContext() || | 327 if (context->IsFunctionContext() || context->IsBlockContext() || |
280 context->IsScriptContext()) { | 328 context->IsScriptContext()) { |
281 // Use serialized scope information of functions and blocks to search | 329 // Use serialized scope information of functions and blocks to search |
282 // for the context index. | 330 // for the context index. |
283 Handle<ScopeInfo> scope_info; | 331 Handle<ScopeInfo> scope_info(context->IsFunctionContext() |
284 if (context->IsFunctionContext()) { | 332 ? context->closure()->shared()->scope_info() |
285 scope_info = Handle<ScopeInfo>( | 333 : context->scope_info()); |
286 context->closure()->shared()->scope_info(), isolate); | |
287 } else { | |
288 scope_info = Handle<ScopeInfo>( | |
289 ScopeInfo::cast(context->extension()), isolate); | |
290 } | |
291 VariableMode mode; | 334 VariableMode mode; |
292 VariableLocation location; | 335 VariableLocation location; |
293 InitializationFlag init_flag; | 336 InitializationFlag init_flag; |
294 // TODO(sigurds) Figure out whether maybe_assigned_flag should | 337 // TODO(sigurds) Figure out whether maybe_assigned_flag should |
295 // be used to compute binding_flags. | 338 // be used to compute binding_flags. |
296 MaybeAssignedFlag maybe_assigned_flag; | 339 MaybeAssignedFlag maybe_assigned_flag; |
297 int slot_index = ScopeInfo::ContextSlotIndex( | 340 int slot_index = ScopeInfo::ContextSlotIndex( |
298 scope_info, name, &mode, &location, &init_flag, &maybe_assigned_flag); | 341 scope_info, name, &mode, &location, &init_flag, &maybe_assigned_flag); |
299 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS); | 342 DCHECK(slot_index < 0 || slot_index >= MIN_CONTEXT_SLOTS); |
300 if (slot_index >= 0 && location == VariableLocation::CONTEXT) { | 343 if (slot_index >= 0 && location == VariableLocation::CONTEXT) { |
(...skipping 21 matching lines...) Expand all Loading... |
322 *attributes = READ_ONLY; | 365 *attributes = READ_ONLY; |
323 DCHECK(mode == CONST_LEGACY || mode == CONST); | 366 DCHECK(mode == CONST_LEGACY || mode == CONST); |
324 *binding_flags = (mode == CONST_LEGACY) | 367 *binding_flags = (mode == CONST_LEGACY) |
325 ? IMMUTABLE_IS_INITIALIZED : IMMUTABLE_IS_INITIALIZED_HARMONY; | 368 ? IMMUTABLE_IS_INITIALIZED : IMMUTABLE_IS_INITIALIZED_HARMONY; |
326 return context; | 369 return context; |
327 } | 370 } |
328 } | 371 } |
329 | 372 |
330 } else if (context->IsCatchContext()) { | 373 } else if (context->IsCatchContext()) { |
331 // Catch contexts have the variable name in the extension slot. | 374 // Catch contexts have the variable name in the extension slot. |
332 if (String::Equals(name, handle(String::cast(context->extension())))) { | 375 if (String::Equals(name, handle(context->catch_name()))) { |
333 if (FLAG_trace_contexts) { | 376 if (FLAG_trace_contexts) { |
334 PrintF("=> found in catch context\n"); | 377 PrintF("=> found in catch context\n"); |
335 } | 378 } |
336 *index = Context::THROWN_OBJECT_INDEX; | 379 *index = Context::THROWN_OBJECT_INDEX; |
337 *attributes = NONE; | 380 *attributes = NONE; |
338 *binding_flags = MUTABLE_IS_INITIALIZED; | 381 *binding_flags = MUTABLE_IS_INITIALIZED; |
339 return context; | 382 return context; |
340 } | 383 } |
341 } | 384 } |
342 | 385 |
343 // 3. Prepare to continue with the previous (next outermost) context. | 386 // 3. Prepare to continue with the previous (next outermost) context. |
344 if (context->IsNativeContext()) { | 387 if (context->IsNativeContext()) { |
345 follow_context_chain = false; | 388 follow_context_chain = false; |
346 } else { | 389 } else { |
347 context = Handle<Context>(context->previous(), isolate); | 390 context = Handle<Context>(context->previous(), isolate); |
348 } | 391 } |
349 } while (follow_context_chain); | 392 } while (follow_context_chain); |
350 | 393 |
351 if (FLAG_trace_contexts) { | 394 if (FLAG_trace_contexts) { |
352 PrintF("=> no property/slot found\n"); | 395 PrintF("=> no property/slot found\n"); |
353 } | 396 } |
354 return Handle<Object>::null(); | 397 return Handle<Object>::null(); |
355 } | 398 } |
356 | 399 |
357 | 400 |
358 void Context::InitializeGlobalSlots() { | 401 void Context::InitializeGlobalSlots() { |
359 DCHECK(IsScriptContext()); | 402 DCHECK(IsScriptContext()); |
360 DisallowHeapAllocation no_gc; | 403 DisallowHeapAllocation no_gc; |
361 | 404 |
362 ScopeInfo* scope_info = ScopeInfo::cast(extension()); | 405 ScopeInfo* scope_info = this->scope_info(); |
363 | 406 |
364 int context_globals = scope_info->ContextGlobalCount(); | 407 int context_globals = scope_info->ContextGlobalCount(); |
365 if (context_globals > 0) { | 408 if (context_globals > 0) { |
366 PropertyCell* empty_cell = GetHeap()->empty_property_cell(); | 409 PropertyCell* empty_cell = GetHeap()->empty_property_cell(); |
367 | 410 |
368 int context_locals = scope_info->ContextLocalCount(); | 411 int context_locals = scope_info->ContextLocalCount(); |
369 int index = Context::MIN_CONTEXT_SLOTS + context_locals; | 412 int index = Context::MIN_CONTEXT_SLOTS + context_locals; |
370 for (int i = 0; i < context_globals; i++) { | 413 for (int i = 0; i < context_globals; i++) { |
371 set(index++, empty_cell); | 414 set(index++, empty_cell); |
372 } | 415 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 // During bootstrapping we allow all objects to pass as global | 554 // During bootstrapping we allow all objects to pass as global |
512 // objects. This is necessary to fix circular dependencies. | 555 // objects. This is necessary to fix circular dependencies. |
513 return isolate->heap()->gc_state() != Heap::NOT_IN_GC || | 556 return isolate->heap()->gc_state() != Heap::NOT_IN_GC || |
514 isolate->bootstrapper()->IsActive() || | 557 isolate->bootstrapper()->IsActive() || |
515 object->IsGlobalObject(); | 558 object->IsGlobalObject(); |
516 } | 559 } |
517 #endif | 560 #endif |
518 | 561 |
519 } // namespace internal | 562 } // namespace internal |
520 } // namespace v8 | 563 } // namespace v8 |
OLD | NEW |