Chromium Code Reviews| 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 |