Reviewers: rossberg,

Description:
Group lexical context variables for faster look up.

Currently, looking up a lexical context variable requires looking up
the variable name and then checking its mode. This can be a bottleneck
in Runtime_DeclareGlobals, even when no lexical context variables are
declared.

[email protected]
BUG=crbug:517778
LOG=N

Please review this at https://codereview.chromium.org/1281883002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+70, -7 lines):
  M src/contexts.h
  M src/contexts.cc
  M src/objects.h
  M src/runtime/runtime-scopes.cc
  M src/scopeinfo.cc
  M src/scopes.cc


Index: src/contexts.cc
diff --git a/src/contexts.cc b/src/contexts.cc
index 9f39aecd542ca24dbbad3bf7baf1109e853494ba..6bd4fcef11053c6285e02b1a98adda3e4afaf20a 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -56,6 +56,19 @@ bool ScriptContextTable::Lookup(Handle<ScriptContextTable> table,
 }


+bool ScriptContextTable::LookupLexical(Handle<ScriptContextTable> table,
+                                       Handle<String> name) {
+  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()));
+    int slot_index = ScopeInfo::LexicalContextSlotIndex(scope_info, name);
+    if (slot_index >= 0) return true;
+  }
+  return false;
+}
+
+
 Context* Context::declaration_context() {
   Context* current = this;
   while (!current->IsFunctionContext() && !current->IsNativeContext() &&
Index: src/contexts.h
diff --git a/src/contexts.h b/src/contexts.h
index 9c8dc8a860ab2e86cca55933a9aec93bc5e0f83a..d5b090618f13e06d92070518e743513352363673 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -244,6 +244,10 @@ class ScriptContextTable : public FixedArray {
                      LookupResult* result);

   MUST_USE_RESULT
+  static bool LookupLexical(Handle<ScriptContextTable> table,
+                            Handle<String> name);
+
+  MUST_USE_RESULT
static Handle<ScriptContextTable> Extend(Handle<ScriptContextTable> table,
                                            Handle<Context> script_context);

Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index 257f0e54c35d198f2c6ee16d605e961702edf4f7..19ca422bf7ce8b5e472d0669d0c2906996a7cc8e 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3941,6 +3941,9 @@ class ScopeInfo : public FixedArray {
                               InitializationFlag* init_flag,
                               MaybeAssignedFlag* maybe_assigned_flag);

+  static int LexicalContextSlotIndex(Handle<ScopeInfo> scope_info,
+                                     Handle<String> name);
+
   // Lookup the name of a certain context slot by its index.
   String* ContextSlotName(int slot_index);

@@ -3985,6 +3988,7 @@ class ScopeInfo : public FixedArray {
   V(ParameterCount)               \
   V(StackLocalCount)              \
   V(ContextLocalCount)            \
+  V(LexicalContextLocalCount)     \
   V(ContextGlobalCount)           \
   V(StrongModeFreeVariableCount)

Index: src/runtime/runtime-scopes.cc
diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc
index ff7e783393081cbe731a8d5f265a5b0fa852b773..06f84598438dc0e56761499823696dd8ee962269 100644
--- a/src/runtime/runtime-scopes.cc
+++ b/src/runtime/runtime-scopes.cc
@@ -36,9 +36,7 @@ static Object* DeclareGlobals(Isolate* isolate, Handle<GlobalObject> global,
                               bool is_const, bool is_function) {
   Handle<ScriptContextTable> script_contexts(
       global->native_context()->script_context_table());
-  ScriptContextTable::LookupResult lookup;
-  if (ScriptContextTable::Lookup(script_contexts, name, &lookup) &&
-      IsLexicalVariableMode(lookup.mode)) {
+  if (ScriptContextTable::LookupLexical(script_contexts, name)) {
     return ThrowRedeclarationError(isolate, name);
   }

@@ -624,9 +622,13 @@ static Object* FindNameClash(Handle<ScopeInfo> scope_info,
   for (int var = 0; var < scope_info->ContextLocalCount(); var++) {
     Handle<String> name(scope_info->ContextLocalName(var));
     VariableMode mode = scope_info->ContextLocalMode(var);
-    ScriptContextTable::LookupResult lookup;
-    if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
- if (IsLexicalVariableMode(mode) || IsLexicalVariableMode(lookup.mode)) {
+    if (IsLexicalVariableMode(mode)) {
+      ScriptContextTable::LookupResult lookup;
+      if (ScriptContextTable::Lookup(script_context, name, &lookup)) {
+        return ThrowRedeclarationError(isolate, name);
+      }
+    } else {
+      if (ScriptContextTable::LookupLexical(script_context, name)) {
         return ThrowRedeclarationError(isolate, name);
       }
     }
Index: src/scopeinfo.cc
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index e490fd9ce48f11eff84aa20f143f852dfea3d7ac..4c22b0aa17f295d76aca8bcfa0266abf271e9fbe 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -149,6 +149,8 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,

   // Add context locals' info.
   DCHECK(index == scope_info->ContextLocalInfoEntriesIndex());
+  bool encountered_lexical = false;
+  int lexical_context_local_count = 0;
   for (int i = 0; i < context_local_count; ++i) {
     Variable* var = context_locals[i];
     uint32_t value =
@@ -156,8 +158,16 @@ Handle<ScopeInfo> ScopeInfo::Create(Isolate* isolate, Zone* zone,
         ContextLocalInitFlag::encode(var->initialization_flag()) |
         ContextLocalMaybeAssignedFlag::encode(var->maybe_assigned());
     scope_info->set(index++, Smi::FromInt(value));
+    if (encountered_lexical) {
+ // Check that context locals are sorted so that lexicals are at the end.
+      DCHECK(IsLexicalVariableMode(var->mode()));
+    } else if (IsLexicalVariableMode(var->mode())) {
+      lexical_context_local_count = context_local_count - i;
+    }
   }

+  scope_info->SetLexicalContextLocalCount(lexical_context_local_count);
+
   // Add context globals' info.
   DCHECK(index == scope_info->ContextGlobalInfoEntriesIndex());
   for (int i = 0; i < context_global_count; ++i) {
@@ -222,6 +232,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {

   const int stack_local_count = 0;
   const int context_local_count = 1;
+  const int lexical_context_local_count = 1;
   const int context_global_count = 0;
   const int strong_mode_free_variable_count = 0;
   const bool simple_parameter_list = true;
@@ -254,6 +265,7 @@ Handle<ScopeInfo> ScopeInfo::CreateGlobalThisBinding(Isolate* isolate) {
   scope_info->SetParameterCount(parameter_count);
   scope_info->SetStackLocalCount(stack_local_count);
   scope_info->SetContextLocalCount(context_local_count);
+  scope_info->SetLexicalContextLocalCount(lexical_context_local_count);
   scope_info->SetContextGlobalCount(context_global_count);
scope_info->SetStrongModeFreeVariableCount(strong_mode_free_variable_count);

@@ -572,6 +584,30 @@ int ScopeInfo::ContextSlotIndex(Handle<ScopeInfo> scope_info,
 }


+int ScopeInfo::LexicalContextSlotIndex(Handle<ScopeInfo> scope_info,
+                                       Handle<String> name) {
+  DCHECK(name->IsInternalizedString());
+  if (scope_info->length() > 0) {
+    int total_count = scope_info->ContextLocalCount();
+    int lexical_count = scope_info->LexicalContextLocalCount();
+    int non_lexical_count = total_count - lexical_count;
+
+    int start = scope_info->ContextLocalNameEntriesIndex();
+    int end = start + total_count;
+    int lexical_start = start + non_lexical_count;
+
+    for (int i = lexical_start; i < end; ++i) {
+      if (*name == scope_info->get(i)) {
+        int var = i - start;
+        DCHECK(IsLexicalVariableMode(scope_info->ContextLocalMode(var)));
+        return Context::MIN_CONTEXT_SLOTS + var;
+      }
+    }
+  }
+  return -1;
+}
+
+
 String* ScopeInfo::ContextSlotName(int slot_index) {
   int const var = slot_index - Context::MIN_CONTEXT_SLOTS;
   DCHECK_LE(0, var);
Index: src/scopes.cc
diff --git a/src/scopes.cc b/src/scopes.cc
index 319aca518ed69187dc29cc817c58f9266b2a8700..ce06976c4c9d2369d208d41ccc53a9431f9cba8e 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -593,7 +593,11 @@ class VarAndOrder {
   Variable* var() const { return var_; }
   int order() const { return order_; }
   static int Compare(const VarAndOrder* a, const VarAndOrder* b) {
-    return a->order_ - b->order_;
+    // Sort lexical variables to the end of the list.
+    bool a_is_lexical = IsLexicalVariableMode(a->var()->mode());
+    bool b_is_lexical = IsLexicalVariableMode(b->var()->mode());
+    if (a_is_lexical == b_is_lexical) return a->order_ - b->order_;
+    return a_is_lexical ? 1 : -1;
   }

  private:


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to