Index: src/contexts.cc |
diff --git a/src/contexts.cc b/src/contexts.cc |
index ef850452ceefce3ae4551887d7def030b982145d..e3ace3c8c1e967a87d049578b6dc082e1bf8c6cf 100644 |
--- a/src/contexts.cc |
+++ b/src/contexts.cc |
@@ -41,7 +41,7 @@ bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table, |
for (int i = 0; i < table->used(); i++) { |
Handle<Context> context = GetContext(table, i); |
DCHECK(context->IsScriptContext()); |
- Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension())); |
+ Handle<ScopeInfo> scope_info(context->scope_info()); |
int slot_index = ScopeInfo::ContextSlotIndex( |
scope_info, name, &result->mode, &result->location, &result->init_flag, |
&result->maybe_assigned_flag); |
@@ -56,10 +56,22 @@ bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table, |
} |
+bool Context::is_declaration_context() { |
+ if (IsFunctionContext() || IsNativeContext() || IsScriptContext()) { |
+ return true; |
+ } |
+ if (!IsBlockContext()) return false; |
+ Object* ext = extension(); |
+ // If we have the special extension, we immediately know it must be a |
+ // declaration scope. That's just a small performance shortcut. |
+ return ext->IsSloppyBlockWithEvalContextExtension() |
+ || ScopeInfo::cast(ext)->is_declaration_scope(); |
+} |
+ |
+ |
Context* Context::declaration_context() { |
Context* current = this; |
- while (!current->IsFunctionContext() && !current->IsNativeContext() && |
- !current->IsScriptContext()) { |
+ while (!current->is_declaration_context()) { |
current = current->previous(); |
DCHECK(current->closure() == closure()); |
} |
@@ -67,6 +79,44 @@ Context* Context::declaration_context() { |
} |
+JSObject* Context::extension_object() { |
+ DCHECK(IsNativeContext() || IsFunctionContext() || IsBlockContext()); |
+ Object* object = extension(); |
+ if (object == nullptr) return nullptr; |
+ if (IsBlockContext()) { |
+ if (!object->IsSloppyBlockWithEvalContextExtension()) return nullptr; |
+ object = SloppyBlockWithEvalContextExtension::cast(object)->extension(); |
+ } |
+ DCHECK(object->IsJSContextExtensionObject() || |
+ (IsNativeContext() && object->IsJSGlobalObject())); |
+ return JSObject::cast(object); |
+} |
+ |
+ |
+JSReceiver* Context::extension_receiver() { |
+ DCHECK(IsNativeContext() || IsWithContext() || |
+ IsFunctionContext() || IsBlockContext()); |
+ return IsWithContext() ? JSReceiver::cast(extension()) : extension_object(); |
+} |
+ |
+ |
+ScopeInfo* Context::scope_info() { |
+ DCHECK(IsModuleContext() || IsScriptContext() || IsBlockContext()); |
+ Object* object = extension(); |
+ if (object->IsSloppyBlockWithEvalContextExtension()) { |
+ DCHECK(IsBlockContext()); |
+ object = SloppyBlockWithEvalContextExtension::cast(object)->scope_info(); |
+ } |
+ return ScopeInfo::cast(object); |
+} |
+ |
+ |
+String* Context::catch_name() { |
+ DCHECK(IsCatchContext()); |
+ return String::cast(extension()); |
+} |
+ |
+ |
JSBuiltinsObject* Context::builtins() { |
GlobalObject* object = global_object(); |
if (object->IsJSGlobalObject()) { |
@@ -212,13 +262,11 @@ Handle<Object> Context::Lookup(Handle<String> name, |
PrintF("\n"); |
} |
- |
// 1. Check global objects, subjects of with, and extension objects. |
- if (context->IsNativeContext() || |
- context->IsWithContext() || |
- (context->IsFunctionContext() && context->has_extension())) { |
- Handle<JSReceiver> object( |
- JSReceiver::cast(context->extension()), isolate); |
+ if ((context->IsNativeContext() || context->IsWithContext() || |
+ context->IsFunctionContext() || context->IsBlockContext()) && |
+ context->extension_receiver() != nullptr) { |
+ Handle<JSReceiver> object(context->extension_receiver()); |
if (context->IsNativeContext()) { |
if (FLAG_trace_contexts) { |
@@ -280,14 +328,9 @@ Handle<Object> Context::Lookup(Handle<String> name, |
context->IsScriptContext()) { |
// Use serialized scope information of functions and blocks to search |
// for the context index. |
- Handle<ScopeInfo> scope_info; |
- if (context->IsFunctionContext()) { |
- scope_info = Handle<ScopeInfo>( |
- context->closure()->shared()->scope_info(), isolate); |
- } else { |
- scope_info = Handle<ScopeInfo>( |
- ScopeInfo::cast(context->extension()), isolate); |
- } |
+ Handle<ScopeInfo> scope_info(context->IsFunctionContext() |
+ ? context->closure()->shared()->scope_info() |
+ : context->scope_info()); |
VariableMode mode; |
VariableLocation location; |
InitializationFlag init_flag; |
@@ -329,7 +372,7 @@ Handle<Object> Context::Lookup(Handle<String> name, |
} else if (context->IsCatchContext()) { |
// Catch contexts have the variable name in the extension slot. |
- if (String::Equals(name, handle(String::cast(context->extension())))) { |
+ if (String::Equals(name, handle(context->catch_name()))) { |
if (FLAG_trace_contexts) { |
PrintF("=> found in catch context\n"); |
} |
@@ -359,7 +402,7 @@ void Context::InitializeGlobalSlots() { |
DCHECK(IsScriptContext()); |
DisallowHeapAllocation no_gc; |
- ScopeInfo* scope_info = ScopeInfo::cast(extension()); |
+ ScopeInfo* scope_info = this->scope_info(); |
int context_globals = scope_info->ContextGlobalCount(); |
if (context_globals > 0) { |