Index: src/compiler.cc |
diff --git a/src/compiler.cc b/src/compiler.cc |
index e4864e48015df3ef51186b5f814920b6d5364518..794df01f597b0e9df120cfddbf4d241c7c80511b 100755 |
--- a/src/compiler.cc |
+++ b/src/compiler.cc |
@@ -551,6 +551,60 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, |
} |
+class PrecompiledScope: public Scope { |
+ public: |
+ PrecompiledScope(Scope* inner_scope, SerializedScopeInfo* scope_info) |
+ : Scope(inner_scope->outer_scope(), Scope::FUNCTION_SCOPE), |
+ scope_info_(scope_info) { |
+ InsertAfterScope(inner_scope); |
+ if (scope_info->HasHeapAllocatedLocals()) { |
+ num_heap_slots_ = scope_info->NumberOfContextSlots(); |
+ } |
+ MarkAsResolved(); |
+ } |
+ |
+ virtual void Initialize(bool inside_with) { |
+ UNREACHABLE(); |
+ } |
+ |
+ virtual Variable* LocalLookup(Handle<String> name) { |
+ // Check arguments object lookup. |
+ if (*name == *Factory::arguments_symbol()) { |
+ return new Variable(this, name, Variable::VAR, true, Variable::ARGUMENTS); |
+ } |
+ |
+ // Check context slot lookup. |
+ Variable::Mode mode; |
+ int index = scope_info_->ContextSlotIndex(*name, &mode); |
+ if (index < 0) { |
+ return NULL; |
+ } |
+ |
+ Variable* var = new Variable(this, name, mode, true, Variable::NORMAL); |
+ var->set_rewrite(new Slot(var, Slot::CONTEXT, index)); |
+ return var; |
+ } |
+ |
+ virtual Variable* DeclareLocal(Handle<String> name, Variable::Mode mode) { |
+ UNREACHABLE(); |
+ return NULL; |
+ } |
+ |
+ virtual VariableProxy* NewUnresolved(Handle<String> name, bool inside_with) { |
+ UNREACHABLE(); |
+ return NULL; |
+ } |
+ |
+ virtual Variable* NewTemporary(Handle<String> name) { |
+ UNREACHABLE(); |
+ return NULL; |
+ } |
+ |
+ private: |
+ SerializedScopeInfo* scope_info_; |
+}; |
+ |
+ |
bool Compiler::CompileLazy(CompilationInfo* info) { |
CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
@@ -570,6 +624,25 @@ bool Compiler::CompileLazy(CompilationInfo* info) { |
// parsing statistics. |
HistogramTimerScope timer(&Counters::compile_lazy); |
+ // If we have scope info, reuse it to build scope for function literal |
+ // being compiled. |
+ if (!info->closure().is_null()) { |
+ SerializedScopeInfo* scope_info = info->closure()->shared()->scope_info(); |
+ if (scope_info != SerializedScopeInfo::Empty()) { |
+ Scope* scope = info->function()->scope(); |
+ JSFunction* current = *info->closure(); |
+ do { |
+ current = current->context()->closure(); |
+ SerializedScopeInfo* scope_info = current->shared()->scope_info(); |
+ if (scope_info != SerializedScopeInfo::Empty()) { |
+ scope = new PrecompiledScope(scope, scope_info); |
+ } else { |
+ ASSERT(current->context()->IsGlobalContext()); |
+ } |
+ } while (!current->context()->IsGlobalContext()); |
+ } |
+ } |
+ |
// Compile the code. |
if (!MakeCode(info)) { |
Top::StackOverflow(); |
@@ -665,6 +738,12 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
if (!MakeCrankshaftCode(&info)) { |
return Handle<SharedFunctionInfo>::null(); |
} |
+ if (!AlwaysFullCompiler() |
+ && !info.scope()->outer_scope_calls_eval() |
+ && !info.scope()->inside_with()) { |
+ ASSERT(info.code()->kind() == Code::FUNCTION); |
+ info.code()->set_optimizable(true); |
+ } |
} else { |
// The bodies of function literals have not yet been visited by the |
// AST optimizer/analyzer. |