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