From: yangguo Date: Fri, 7 Aug 2015 22:22:36 +0000 (-0700) Subject: Group lexical context variables for faster look up. X-Git-Tag: upstream/4.7.83~965 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a45ed17bb6aca02e940f13bbf456d660cccc86ae;p=platform%2Fupstream%2Fv8.git 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. R=rossberg@chromium.org BUG=crbug:517778 LOG=N Review URL: https://codereview.chromium.org/1281883002 Cr-Commit-Position: refs/heads/master@{#30075} --- diff --git a/src/contexts.cc b/src/contexts.cc index 9f39aecd5..6bd4fcef1 100644 --- a/src/contexts.cc +++ b/src/contexts.cc @@ -56,6 +56,19 @@ bool ScriptContextTable::Lookup(Handle table, } +bool ScriptContextTable::LookupLexical(Handle table, + Handle name) { + for (int i = 0; i < table->used(); i++) { + Handle context = GetContext(table, i); + DCHECK(context->IsScriptContext()); + Handle 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() && diff --git a/src/contexts.h b/src/contexts.h index 9c8dc8a86..d5b090618 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -243,6 +243,10 @@ class ScriptContextTable : public FixedArray { static bool Lookup(Handle table, Handle name, LookupResult* result); + MUST_USE_RESULT + static bool LookupLexical(Handle table, + Handle name); + MUST_USE_RESULT static Handle Extend(Handle table, Handle script_context); diff --git a/src/objects.h b/src/objects.h index 8e64fe38d..be539ef7f 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 scope_info, + Handle 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) diff --git a/src/runtime/runtime-scopes.cc b/src/runtime/runtime-scopes.cc index be13a14d4..3e2383772 100644 --- a/src/runtime/runtime-scopes.cc +++ b/src/runtime/runtime-scopes.cc @@ -36,9 +36,10 @@ static Object* DeclareGlobals(Isolate* isolate, Handle global, bool is_const, bool is_function) { Handle script_contexts( global->native_context()->script_context_table()); - ScriptContextTable::LookupResult lookup; - if (ScriptContextTable::Lookup(script_contexts, name, &lookup) && - IsLexicalVariableMode(lookup.mode)) { + // We use LookupLexical to limit lookup to lexical variables. As long as + // lexical variables are not used extensively, this is a performance win. + // TODO(yangguo): reconsider this shortcut. + if (ScriptContextTable::LookupLexical(script_contexts, name)) { return ThrowRedeclarationError(isolate, name); } @@ -624,9 +625,13 @@ static Object* FindNameClash(Handle scope_info, for (int var = 0; var < scope_info->ContextLocalCount(); var++) { Handle 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); } } diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc index e53f36d27..63c6ce108 100644 --- a/src/scopeinfo.cc +++ b/src/scopeinfo.cc @@ -149,6 +149,8 @@ Handle 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::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::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 has_simple_parameters = true; @@ -254,6 +265,7 @@ Handle 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,31 @@ int ScopeInfo::ContextSlotIndex(Handle scope_info, } +int ScopeInfo::LexicalContextSlotIndex(Handle scope_info, + Handle name) { + DCHECK(name->IsInternalizedString()); + if (scope_info->length() > 0) { + // TODO(yangguo): consider using the context slot cache here. + 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); diff --git a/src/scopes.cc b/src/scopes.cc index 8ce28bd6a..dfb9d70ba 100644 --- a/src/scopes.cc +++ b/src/scopes.cc @@ -596,7 +596,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: