More refactoring of class Compiler's interface.
Change more functions used by the Compiler class to have a uniform interface: they get passed as argument an input/output pointer to a CompilationInfo that they mutate if they succeed, and they return a flag telling whether they succeeded. Also, remove some unnecessary timers. Review URL: http://codereview.chromium.org/3561012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5583 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2f54abf974
commit
ea910460bd
@ -3132,9 +3132,9 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
|
||||
|
||||
// Build the function info and instantiate it.
|
||||
Handle<SharedFunctionInfo> function_info =
|
||||
Compiler::BuildFunctionInfo(node, script(), this);
|
||||
// Check for stack-overflow exception.
|
||||
if (HasStackOverflow()) {
|
||||
Compiler::BuildFunctionInfo(node, script());
|
||||
if (function_info.is_null()) {
|
||||
SetStackOverflow();
|
||||
ASSERT(frame_->height() == original_height);
|
||||
return;
|
||||
}
|
||||
|
@ -207,9 +207,7 @@ enum NopMarkerTypes {
|
||||
|
||||
class CodeGenerator: public AstVisitor {
|
||||
public:
|
||||
// Takes a function literal, generates code for it. This function should only
|
||||
// be called by compiler.cc.
|
||||
static Handle<Code> MakeCode(CompilationInfo* info);
|
||||
static bool MakeCode(CompilationInfo* info);
|
||||
|
||||
// Printing of AST, etc. as requested by flags.
|
||||
static void MakeCodePrologue(CompilationInfo* info);
|
||||
|
@ -1436,6 +1436,11 @@ class FunctionLiteral: public Expression {
|
||||
|
||||
bool AllowsLazyCompilation();
|
||||
|
||||
Handle<String> debug_name() const {
|
||||
if (name_->length() > 0) return name_;
|
||||
return inferred_name();
|
||||
}
|
||||
|
||||
Handle<String> inferred_name() const { return inferred_name_; }
|
||||
void set_inferred_name(Handle<String> inferred_name) {
|
||||
inferred_name_ = inferred_name;
|
||||
|
@ -206,10 +206,9 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// Generate the code. Takes a function literal, generates code for it, assemble
|
||||
// all the pieces into a Code object. This function is only to be called by
|
||||
// the compiler.cc code.
|
||||
Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
// Generate the code. Compile the AST and assemble all the pieces into a
|
||||
// Code object.
|
||||
bool CodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
Handle<Script> script = info->script();
|
||||
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
|
||||
int len = String::cast(script->source())->length();
|
||||
@ -224,12 +223,14 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
cgen.Generate(info);
|
||||
if (cgen.HasStackOverflow()) {
|
||||
ASSERT(!Top::has_pending_exception());
|
||||
return Handle<Code>::null();
|
||||
return false;
|
||||
}
|
||||
|
||||
InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
|
||||
InLoopFlag in_loop = info->is_in_loop() ? IN_LOOP : NOT_IN_LOOP;
|
||||
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
|
||||
return MakeCodeEpilogue(cgen.masm(), flags, info);
|
||||
Handle<Code> code = MakeCodeEpilogue(cgen.masm(), flags, info);
|
||||
info->SetCode(code); // May be an empty handle.
|
||||
return !code.is_null();
|
||||
}
|
||||
|
||||
|
||||
@ -325,9 +326,12 @@ void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
|
||||
}
|
||||
} else {
|
||||
Handle<SharedFunctionInfo> function =
|
||||
Compiler::BuildFunctionInfo(node->fun(), script(), this);
|
||||
Compiler::BuildFunctionInfo(node->fun(), script());
|
||||
// Check for stack-overflow exception.
|
||||
if (HasStackOverflow()) return;
|
||||
if (function.is_null()) {
|
||||
SetStackOverflow();
|
||||
return;
|
||||
}
|
||||
array->set(j++, *function);
|
||||
}
|
||||
}
|
||||
|
307
src/compiler.cc
307
src/compiler.cc
@ -92,81 +92,57 @@ static bool AlwaysFullCompiler() {
|
||||
}
|
||||
|
||||
|
||||
static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
|
||||
FunctionLiteral* function = info->function();
|
||||
ASSERT(function != NULL);
|
||||
// Rewrite the AST by introducing .result assignments where needed.
|
||||
if (!Rewriter::Process(function)) {
|
||||
// Signal a stack overflow by returning a null handle. The stack
|
||||
// overflow exception will be thrown by the caller.
|
||||
return Handle<Code>::null();
|
||||
static bool MakeCode(CompilationInfo* info) {
|
||||
// Precondition: code has been parsed. Postcondition: the code field in
|
||||
// the compilation info is set if compilation succeeded.
|
||||
ASSERT(info->function() != NULL);
|
||||
|
||||
if (Rewriter::Rewrite(info) &&
|
||||
Scope::Analyze(info) &&
|
||||
Rewriter::Analyze(info)) {
|
||||
// Generate code and return it. Code generator selection is governed by
|
||||
// which backends are enabled and whether the function is considered
|
||||
// run-once code or not.
|
||||
//
|
||||
// --full-compiler enables the dedicated backend for code we expect to
|
||||
// be run once
|
||||
//
|
||||
// The normal choice of backend can be overridden with the flags
|
||||
// --always-full-compiler.
|
||||
Handle<SharedFunctionInfo> shared = info->shared_info();
|
||||
bool is_run_once = (shared.is_null())
|
||||
? info->scope()->is_global_scope()
|
||||
: (shared->is_toplevel() || shared->try_full_codegen());
|
||||
bool can_use_full =
|
||||
FLAG_full_compiler && !info->function()->contains_loops();
|
||||
if (AlwaysFullCompiler() || (is_run_once && can_use_full)) {
|
||||
return FullCodeGenerator::MakeCode(info);
|
||||
} else {
|
||||
AssignedVariablesAnalyzer ava;
|
||||
return ava.Analyze(info) && CodeGenerator::MakeCode(info);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Compute top scope and allocate variables. For lazy compilation
|
||||
// the top scope only contains the single lazily compiled function,
|
||||
// so this doesn't re-allocate variables repeatedly.
|
||||
HistogramTimerScope timer(&Counters::variable_allocation);
|
||||
Scope* top = info->scope();
|
||||
while (top->outer_scope() != NULL) top = top->outer_scope();
|
||||
top->AllocateVariables(context);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (Bootstrapper::IsActive() ?
|
||||
FLAG_print_builtin_scopes :
|
||||
FLAG_print_scopes) {
|
||||
info->scope()->Print();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Optimize the AST.
|
||||
if (!Rewriter::Optimize(function)) {
|
||||
// Signal a stack overflow by returning a null handle. The stack
|
||||
// overflow exception will be thrown by the caller.
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
// Generate code and return it. Code generator selection is governed by
|
||||
// which backends are enabled and whether the function is considered
|
||||
// run-once code or not:
|
||||
//
|
||||
// --full-compiler enables the dedicated backend for code we expect to be
|
||||
// run once
|
||||
//
|
||||
// The normal choice of backend can be overridden with the flags
|
||||
// --always-full-compiler.
|
||||
Handle<SharedFunctionInfo> shared = info->shared_info();
|
||||
bool is_run_once = (shared.is_null())
|
||||
? info->scope()->is_global_scope()
|
||||
: (shared->is_toplevel() || shared->try_full_codegen());
|
||||
bool use_full = FLAG_full_compiler && !function->contains_loops();
|
||||
if (AlwaysFullCompiler() || (use_full && is_run_once)) {
|
||||
return FullCodeGenerator::MakeCode(info);
|
||||
}
|
||||
|
||||
AssignedVariablesAnalyzer ava(function);
|
||||
if (!ava.Analyze()) return Handle<Code>::null();
|
||||
return CodeGenerator::MakeCode(info);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
|
||||
Handle<Context> context = Handle<Context>::null();
|
||||
Handle<Code> code = MakeCode(context, info);
|
||||
bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) {
|
||||
// Precondition: code has been parsed. Postcondition: the code field in
|
||||
// the compilation info is set if compilation succeeded.
|
||||
bool succeeded = MakeCode(info);
|
||||
if (!info->shared_info().is_null()) {
|
||||
Handle<SerializedScopeInfo> scope_info =
|
||||
SerializedScopeInfo::Create(info->scope());
|
||||
info->shared_info()->set_scope_info(*scope_info);
|
||||
}
|
||||
return code;
|
||||
return succeeded;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info,
|
||||
Handle<Context> context) {
|
||||
static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
|
||||
CompilationZoneScope zone_scope(DELETE_ON_EXIT);
|
||||
|
||||
PostponeInterruptsScope postpone;
|
||||
@ -215,34 +191,32 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info,
|
||||
// Compile the code.
|
||||
FunctionLiteral* lit = info->function();
|
||||
LiveEditFunctionTracker live_edit_tracker(lit);
|
||||
Handle<Code> code = MakeCode(context, info);
|
||||
|
||||
// Check for stack-overflow exceptions.
|
||||
if (code.is_null()) {
|
||||
if (!MakeCode(info)) {
|
||||
Top::StackOverflow();
|
||||
return Handle<SharedFunctionInfo>::null();
|
||||
}
|
||||
|
||||
ASSERT(!info->code().is_null());
|
||||
if (script->name()->IsString()) {
|
||||
PROFILE(CodeCreateEvent(
|
||||
info->is_eval()
|
||||
? Logger::EVAL_TAG
|
||||
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
|
||||
*code,
|
||||
*info->code(),
|
||||
String::cast(script->name())));
|
||||
OPROFILE(CreateNativeCodeRegion(String::cast(script->name()),
|
||||
code->instruction_start(),
|
||||
code->instruction_size()));
|
||||
info->code()->instruction_start(),
|
||||
info->code()->instruction_size()));
|
||||
} else {
|
||||
PROFILE(CodeCreateEvent(
|
||||
info->is_eval()
|
||||
? Logger::EVAL_TAG
|
||||
: Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
|
||||
*code,
|
||||
*info->code(),
|
||||
""));
|
||||
OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script",
|
||||
code->instruction_start(),
|
||||
code->instruction_size()));
|
||||
info->code()->instruction_start(),
|
||||
info->code()->instruction_size()));
|
||||
}
|
||||
|
||||
// Allocate function.
|
||||
@ -250,7 +224,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info,
|
||||
Factory::NewSharedFunctionInfo(
|
||||
lit->name(),
|
||||
lit->materialized_literal_count(),
|
||||
code,
|
||||
info->code(),
|
||||
SerializedScopeInfo::Create(info->scope()));
|
||||
|
||||
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
|
||||
@ -331,7 +305,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
|
||||
info.MarkAsGlobal();
|
||||
info.SetExtension(extension);
|
||||
info.SetPreParseData(pre_data);
|
||||
result = MakeFunctionInfo(&info, Handle<Context>::null());
|
||||
result = MakeFunctionInfo(&info);
|
||||
if (extension == NULL && !result.is_null()) {
|
||||
CompilationCache::PutScript(source, result);
|
||||
}
|
||||
@ -379,7 +353,8 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source,
|
||||
info.MarkAsEval();
|
||||
if (is_global) info.MarkAsGlobal();
|
||||
if (is_json) info.MarkAsJson();
|
||||
result = MakeFunctionInfo(&info, context);
|
||||
info.SetCallingContext(context);
|
||||
result = MakeFunctionInfo(&info);
|
||||
if (!result.is_null() && !is_json) {
|
||||
// For json it's unlikely that we'll ever see exactly the same string
|
||||
// again so we don't use the compilation cache.
|
||||
@ -399,126 +374,122 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
|
||||
|
||||
PostponeInterruptsScope postpone;
|
||||
|
||||
// Compute name, source code and script data.
|
||||
Handle<SharedFunctionInfo> shared = info->shared_info();
|
||||
int compiled_size = shared->end_position() - shared->start_position();
|
||||
Counters::total_compile_size.Increment(compiled_size);
|
||||
|
||||
// Generate the AST for the lazily compiled function.
|
||||
if (!Parser::Parse(info)) return false;
|
||||
if (Parser::Parse(info)) {
|
||||
// Measure how long it takes to do the lazy compilation; only take the
|
||||
// rest of the function into account to avoid overlap with the lazy
|
||||
// parsing statistics.
|
||||
HistogramTimerScope timer(&Counters::compile_lazy);
|
||||
|
||||
// Measure how long it takes to do the lazy compilation; only take
|
||||
// the rest of the function into account to avoid overlap with the
|
||||
// lazy parsing statistics.
|
||||
HistogramTimerScope timer(&Counters::compile_lazy);
|
||||
// Compile the code.
|
||||
if (!MakeCode(info)) {
|
||||
Top::StackOverflow();
|
||||
} else {
|
||||
ASSERT(!info->code().is_null());
|
||||
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
|
||||
Handle<String>(shared->DebugName()),
|
||||
shared->start_position(),
|
||||
info);
|
||||
|
||||
// Compile the code.
|
||||
Handle<Code> code = MakeCode(Handle<Context>::null(), info);
|
||||
// Update the shared function info with the compiled code and the
|
||||
// scope info. Please note, that the order of the sharedfunction
|
||||
// initialization is important since SerializedScopeInfo::Create might
|
||||
// trigger a GC, causing the ASSERT below to be invalid if the code
|
||||
// was flushed. By setting the code object last we avoid this.
|
||||
Handle<SerializedScopeInfo> scope_info =
|
||||
SerializedScopeInfo::Create(info->scope());
|
||||
shared->set_scope_info(*scope_info);
|
||||
shared->set_code(*info->code());
|
||||
if (!info->closure().is_null()) {
|
||||
info->closure()->set_code(*info->code());
|
||||
}
|
||||
|
||||
// Check for stack-overflow exception.
|
||||
if (code.is_null()) {
|
||||
Top::StackOverflow();
|
||||
return false;
|
||||
// Set the expected number of properties for instances.
|
||||
FunctionLiteral* lit = info->function();
|
||||
SetExpectedNofPropertiesFromEstimate(shared,
|
||||
lit->expected_property_count());
|
||||
|
||||
// Set the optimization hints after performing lazy compilation, as
|
||||
// these are not set when the function is set up as a lazily compiled
|
||||
// function.
|
||||
shared->SetThisPropertyAssignmentsInfo(
|
||||
lit->has_only_simple_this_property_assignments(),
|
||||
*lit->this_property_assignments());
|
||||
|
||||
// Check the function has compiled code.
|
||||
ASSERT(shared->is_compiled());
|
||||
shared->set_code_age(0);
|
||||
ASSERT(!info->code().is_null());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG,
|
||||
Handle<String>(String::cast(shared->name())),
|
||||
Handle<String>(shared->inferred_name()),
|
||||
shared->start_position(),
|
||||
info->script(),
|
||||
code);
|
||||
|
||||
// Update the shared function info with the compiled code and the scope info.
|
||||
// Please note, that the order of the sharedfunction initialization is
|
||||
// important since SerializedScopeInfo::Create might trigger a GC, causing
|
||||
// the ASSERT below to be invalid if the code was flushed. By setting the code
|
||||
// object last we avoid this.
|
||||
Handle<SerializedScopeInfo> scope_info =
|
||||
SerializedScopeInfo::Create(info->scope());
|
||||
shared->set_scope_info(*scope_info);
|
||||
shared->set_code(*code);
|
||||
if (!info->closure().is_null()) {
|
||||
info->closure()->set_code(*code);
|
||||
}
|
||||
|
||||
// Set the expected number of properties for instances.
|
||||
FunctionLiteral* lit = info->function();
|
||||
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
|
||||
|
||||
// Set the optimication hints after performing lazy compilation, as these are
|
||||
// not set when the function is set up as a lazily compiled function.
|
||||
shared->SetThisPropertyAssignmentsInfo(
|
||||
lit->has_only_simple_this_property_assignments(),
|
||||
*lit->this_property_assignments());
|
||||
|
||||
// Check the function has compiled code.
|
||||
ASSERT(shared->is_compiled());
|
||||
shared->set_code_age(0);
|
||||
return true;
|
||||
ASSERT(info->code().is_null());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
|
||||
Handle<Script> script,
|
||||
AstVisitor* caller) {
|
||||
LiveEditFunctionTracker live_edit_tracker(literal);
|
||||
Handle<Script> script) {
|
||||
#ifdef DEBUG
|
||||
// We should not try to compile the same function literal more than
|
||||
// once.
|
||||
literal->mark_as_compiled();
|
||||
#endif
|
||||
|
||||
// Determine if the function can be lazily compiled. This is
|
||||
// necessary to allow some of our builtin JS files to be lazily
|
||||
// compiled. These builtins cannot be handled lazily by the parser,
|
||||
// since we have to know if a function uses the special natives
|
||||
// syntax, which is something the parser records.
|
||||
// Precondition: code has been parsed and scopes have been analyzed.
|
||||
CompilationInfo info(script);
|
||||
info.SetFunction(literal);
|
||||
info.SetScope(literal->scope());
|
||||
|
||||
LiveEditFunctionTracker live_edit_tracker(literal);
|
||||
// Determine if the function can be lazily compiled. This is necessary to
|
||||
// allow some of our builtin JS files to be lazily compiled. These
|
||||
// builtins cannot be handled lazily by the parser, since we have to know
|
||||
// if a function uses the special natives syntax, which is something the
|
||||
// parser records.
|
||||
bool allow_lazy = literal->AllowsLazyCompilation() &&
|
||||
!LiveEditFunctionTracker::IsActive();
|
||||
|
||||
Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
|
||||
|
||||
// Generate code
|
||||
Handle<Code> code;
|
||||
if (FLAG_lazy && allow_lazy) {
|
||||
code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile));
|
||||
Handle<Code> code(Builtins::builtin(Builtins::LazyCompile));
|
||||
info.SetCode(code);
|
||||
} else {
|
||||
// The bodies of function literals have not yet been visited by
|
||||
// the AST optimizer/analyzer.
|
||||
if (!Rewriter::Optimize(literal)) {
|
||||
return Handle<SharedFunctionInfo>::null();
|
||||
}
|
||||
|
||||
// Generate code and return it. The way that the compilation mode
|
||||
// is controlled by the command-line flags is described in
|
||||
// the static helper function MakeCode.
|
||||
CompilationInfo info(script);
|
||||
info.SetFunction(literal);
|
||||
//
|
||||
// The bodies of function literals have not yet been visited by
|
||||
// the AST analyzer.
|
||||
if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null();
|
||||
|
||||
bool is_run_once = literal->try_full_codegen();
|
||||
bool use_full = FLAG_full_compiler && !literal->contains_loops();
|
||||
if (AlwaysFullCompiler() || (use_full && is_run_once)) {
|
||||
code = FullCodeGenerator::MakeCode(&info);
|
||||
if (!FullCodeGenerator::MakeCode(&info)) {
|
||||
return Handle<SharedFunctionInfo>::null();
|
||||
}
|
||||
} else {
|
||||
// We fall back to the classic V8 code generator.
|
||||
AssignedVariablesAnalyzer ava(literal);
|
||||
if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null();
|
||||
code = CodeGenerator::MakeCode(&info);
|
||||
}
|
||||
|
||||
// Check for stack-overflow exception.
|
||||
if (code.is_null()) {
|
||||
caller->SetStackOverflow();
|
||||
return Handle<SharedFunctionInfo>::null();
|
||||
AssignedVariablesAnalyzer ava;
|
||||
if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null();
|
||||
if (!CodeGenerator::MakeCode(&info)) {
|
||||
return Handle<SharedFunctionInfo>::null();
|
||||
}
|
||||
}
|
||||
|
||||
// Function compilation complete.
|
||||
RecordFunctionCompilation(Logger::FUNCTION_TAG,
|
||||
literal->name(),
|
||||
literal->inferred_name(),
|
||||
literal->debug_name(),
|
||||
literal->start_position(),
|
||||
script,
|
||||
code);
|
||||
&info);
|
||||
scope_info = SerializedScopeInfo::Create(info.scope());
|
||||
}
|
||||
|
||||
@ -526,7 +497,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
|
||||
Handle<SharedFunctionInfo> result =
|
||||
Factory::NewSharedFunctionInfo(literal->name(),
|
||||
literal->materialized_literal_count(),
|
||||
code,
|
||||
info.code(),
|
||||
scope_info);
|
||||
SetFunctionInfo(result, literal, false, script);
|
||||
|
||||
@ -566,32 +537,34 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
|
||||
|
||||
void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
|
||||
Handle<String> name,
|
||||
Handle<String> inferred_name,
|
||||
int start_position,
|
||||
Handle<Script> script,
|
||||
Handle<Code> code) {
|
||||
// Log the code generation. If source information is available
|
||||
// include script name and line number. Check explicitly whether
|
||||
// logging is enabled as finding the line number is not free.
|
||||
if (Logger::is_logging()
|
||||
|| OProfileAgent::is_enabled()
|
||||
|| CpuProfiler::is_profiling()) {
|
||||
Handle<String> func_name(name->length() > 0 ? *name : *inferred_name);
|
||||
CompilationInfo* info) {
|
||||
// Log the code generation. If source information is available include
|
||||
// script name and line number. Check explicitly whether logging is
|
||||
// enabled as finding the line number is not free.
|
||||
if (Logger::is_logging() ||
|
||||
OProfileAgent::is_enabled() ||
|
||||
CpuProfiler::is_profiling()) {
|
||||
Handle<Script> script = info->script();
|
||||
Handle<Code> code = info->code();
|
||||
if (script->name()->IsString()) {
|
||||
int line_num = GetScriptLineNumber(script, start_position) + 1;
|
||||
USE(line_num);
|
||||
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
|
||||
*code, *func_name,
|
||||
String::cast(script->name()), line_num));
|
||||
OPROFILE(CreateNativeCodeRegion(*func_name,
|
||||
*code,
|
||||
*name,
|
||||
String::cast(script->name()),
|
||||
line_num));
|
||||
OPROFILE(CreateNativeCodeRegion(*name,
|
||||
String::cast(script->name()),
|
||||
line_num,
|
||||
code->instruction_start(),
|
||||
code->instruction_size()));
|
||||
} else {
|
||||
PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
|
||||
*code, *func_name));
|
||||
OPROFILE(CreateNativeCodeRegion(*func_name,
|
||||
*code,
|
||||
*name));
|
||||
OPROFILE(CreateNativeCodeRegion(*name,
|
||||
code->instruction_start(),
|
||||
code->instruction_size()));
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -52,12 +52,14 @@ class CompilationInfo BASE_EMBEDDED {
|
||||
bool is_json() const { return (flags_ & IsJson::mask()) != 0; }
|
||||
bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; }
|
||||
FunctionLiteral* function() const { return function_; }
|
||||
Scope* scope() const { return function_->scope(); }
|
||||
Scope* scope() const { return scope_; }
|
||||
Handle<Code> code() const { return code_; }
|
||||
Handle<JSFunction> closure() const { return closure_; }
|
||||
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
|
||||
Handle<Script> script() const { return script_; }
|
||||
v8::Extension* extension() const { return extension_; }
|
||||
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
|
||||
Handle<Context> calling_context() const { return calling_context_; }
|
||||
|
||||
void MarkAsEval() {
|
||||
ASSERT(!is_lazy());
|
||||
@ -79,6 +81,11 @@ class CompilationInfo BASE_EMBEDDED {
|
||||
ASSERT(function_ == NULL);
|
||||
function_ = literal;
|
||||
}
|
||||
void SetScope(Scope* scope) {
|
||||
ASSERT(scope_ == NULL);
|
||||
scope_ = scope;
|
||||
}
|
||||
void SetCode(Handle<Code> code) { code_ = code; }
|
||||
void SetExtension(v8::Extension* extension) {
|
||||
ASSERT(!is_lazy());
|
||||
extension_ = extension;
|
||||
@ -87,6 +94,10 @@ class CompilationInfo BASE_EMBEDDED {
|
||||
ASSERT(!is_lazy());
|
||||
pre_parse_data_ = pre_parse_data;
|
||||
}
|
||||
void SetCallingContext(Handle<Context> context) {
|
||||
ASSERT(is_eval());
|
||||
calling_context_ = context;
|
||||
}
|
||||
|
||||
private:
|
||||
// Flags using template class BitField<type, start, length>. All are
|
||||
@ -104,8 +115,13 @@ class CompilationInfo BASE_EMBEDDED {
|
||||
unsigned flags_;
|
||||
|
||||
// Fields filled in by the compilation pipeline.
|
||||
// AST filled in by the parser.
|
||||
FunctionLiteral* function_;
|
||||
// The scope of the function literal as a convenience. Set to indidicate
|
||||
// that scopes have been analyzed.
|
||||
Scope* scope_;
|
||||
// The compiled code.
|
||||
Handle<Code> code_;
|
||||
|
||||
// Possible initial inputs to the compilation process.
|
||||
Handle<JSFunction> closure_;
|
||||
@ -116,6 +132,10 @@ class CompilationInfo BASE_EMBEDDED {
|
||||
v8::Extension* extension_;
|
||||
ScriptDataImpl* pre_parse_data_;
|
||||
|
||||
// The context of the caller is needed for eval code, and will be a null
|
||||
// handle otherwise.
|
||||
Handle<Context> calling_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
|
||||
};
|
||||
|
||||
@ -127,9 +147,9 @@ class CompilationInfo BASE_EMBEDDED {
|
||||
// functions, they will be compiled and allocated as part of the compilation
|
||||
// of the source code.
|
||||
|
||||
// Please note this interface returns shared function infos.
|
||||
// This means you need to call Factory::NewFunctionFromSharedFunctionInfo
|
||||
// before you have a real function with a context.
|
||||
// Please note this interface returns shared function infos. This means you
|
||||
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have a
|
||||
// real function with a context.
|
||||
|
||||
class Compiler : public AllStatic {
|
||||
public:
|
||||
@ -155,17 +175,14 @@ class Compiler : public AllStatic {
|
||||
bool is_global,
|
||||
ValidationState validation);
|
||||
|
||||
// Compile from function info (used for lazy compilation). Returns
|
||||
// true on success and false if the compilation resulted in a stack
|
||||
// overflow.
|
||||
// Compile from function info (used for lazy compilation). Returns true on
|
||||
// success and false if the compilation resulted in a stack overflow.
|
||||
static bool CompileLazy(CompilationInfo* info);
|
||||
|
||||
// Compile a shared function info object (the function is possibly
|
||||
// lazily compiled). Called recursively from a backend code
|
||||
// generator 'caller' to build the shared function info.
|
||||
// Compile a shared function info object (the function is possibly lazily
|
||||
// compiled).
|
||||
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node,
|
||||
Handle<Script> script,
|
||||
AstVisitor* caller);
|
||||
Handle<Script> script);
|
||||
|
||||
// Set the function info for a newly compiled function.
|
||||
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
|
||||
@ -173,23 +190,18 @@ class Compiler : public AllStatic {
|
||||
bool is_toplevel,
|
||||
Handle<Script> script);
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
static bool MakeCodeForLiveEdit(CompilationInfo* info);
|
||||
#endif
|
||||
|
||||
private:
|
||||
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
|
||||
Handle<String> name,
|
||||
Handle<String> inferred_name,
|
||||
int start_position,
|
||||
Handle<Script> script,
|
||||
Handle<Code> code);
|
||||
CompilationInfo* info);
|
||||
};
|
||||
|
||||
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
|
||||
Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// During compilation we need a global list of handles to constants
|
||||
// for frame elements. When the zone gets deleted, we make sure to
|
||||
// clear this list of handles as well.
|
||||
|
@ -50,12 +50,13 @@ void BitVector::Print() {
|
||||
#endif
|
||||
|
||||
|
||||
bool AssignedVariablesAnalyzer::Analyze() {
|
||||
Scope* scope = fun_->scope();
|
||||
bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) {
|
||||
info_ = info;
|
||||
Scope* scope = info->scope();
|
||||
int variables = scope->num_parameters() + scope->num_stack_slots();
|
||||
if (variables == 0) return true;
|
||||
av_.ExpandTo(variables);
|
||||
VisitStatements(fun_->body());
|
||||
VisitStatements(info->function()->body());
|
||||
return !HasStackOverflow();
|
||||
}
|
||||
|
||||
@ -129,7 +130,7 @@ int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
|
||||
if (slot->type() == Slot::PARAMETER) {
|
||||
return slot->index();
|
||||
} else {
|
||||
return fun_->scope()->num_parameters() + slot->index();
|
||||
return info_->scope()->num_parameters() + slot->index();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,8 +198,8 @@ class WorkList BASE_EMBEDDED {
|
||||
// is guaranteed to be a smi.
|
||||
class AssignedVariablesAnalyzer : public AstVisitor {
|
||||
public:
|
||||
explicit AssignedVariablesAnalyzer(FunctionLiteral* fun) : fun_(fun) { }
|
||||
bool Analyze();
|
||||
explicit AssignedVariablesAnalyzer() : info_(NULL) { }
|
||||
bool Analyze(CompilationInfo* info);
|
||||
|
||||
private:
|
||||
Variable* FindSmiLoopVariable(ForStatement* stmt);
|
||||
@ -219,7 +219,7 @@ class AssignedVariablesAnalyzer : public AstVisitor {
|
||||
AST_NODE_LIST(DECLARE_VISIT)
|
||||
#undef DECLARE_VISIT
|
||||
|
||||
FunctionLiteral* fun_;
|
||||
CompilationInfo* info_;
|
||||
|
||||
// Accumulator for assigned variables set.
|
||||
BitVector av_;
|
||||
|
@ -277,7 +277,7 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) {
|
||||
|
||||
#define __ ACCESS_MASM(masm())
|
||||
|
||||
Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
Handle<Script> script = info->script();
|
||||
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
|
||||
int len = String::cast(script->source())->length();
|
||||
@ -291,10 +291,13 @@ Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
cgen.Generate(info);
|
||||
if (cgen.HasStackOverflow()) {
|
||||
ASSERT(!Top::has_pending_exception());
|
||||
return Handle<Code>::null();
|
||||
return false;
|
||||
}
|
||||
|
||||
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
|
||||
return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
|
||||
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
|
||||
info->SetCode(code); // may be an empty handle.
|
||||
return !code.is_null();
|
||||
}
|
||||
|
||||
|
||||
@ -462,9 +465,12 @@ void FullCodeGenerator::VisitDeclarations(
|
||||
}
|
||||
} else {
|
||||
Handle<SharedFunctionInfo> function =
|
||||
Compiler::BuildFunctionInfo(decl->fun(), script(), this);
|
||||
Compiler::BuildFunctionInfo(decl->fun(), script());
|
||||
// Check for stack-overflow exception.
|
||||
if (HasStackOverflow()) return;
|
||||
if (function.is_null()) {
|
||||
SetStackOverflow();
|
||||
return;
|
||||
}
|
||||
array->set(j++, *function);
|
||||
}
|
||||
}
|
||||
@ -1156,8 +1162,11 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
|
||||
// Build the function boilerplate and instantiate it.
|
||||
Handle<SharedFunctionInfo> function_info =
|
||||
Compiler::BuildFunctionInfo(expr, script(), this);
|
||||
if (HasStackOverflow()) return;
|
||||
Compiler::BuildFunctionInfo(expr, script());
|
||||
if (function_info.is_null()) {
|
||||
SetStackOverflow();
|
||||
return;
|
||||
}
|
||||
EmitNewClosure(function_info);
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
context_(NULL) {
|
||||
}
|
||||
|
||||
static Handle<Code> MakeCode(CompilationInfo* info);
|
||||
static bool MakeCode(CompilationInfo* info);
|
||||
|
||||
void Generate(CompilationInfo* info);
|
||||
|
||||
|
@ -191,10 +191,8 @@ void CodeGenerator::Generate(CompilationInfo* info) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// New scope to get automatic timing calculation.
|
||||
{ HistogramTimerScope codegen_timer(&Counters::code_generation);
|
||||
{
|
||||
CodeGenState state(this);
|
||||
|
||||
// Entry:
|
||||
// Stack: receiver, arguments, return address.
|
||||
// ebp: caller's frame pointer
|
||||
@ -369,7 +367,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
|
||||
|
||||
// Process any deferred code using the register allocator.
|
||||
if (!HasStackOverflow()) {
|
||||
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
|
||||
JumpTarget::set_compiling_deferred_code(true);
|
||||
ProcessDeferred();
|
||||
JumpTarget::set_compiling_deferred_code(false);
|
||||
@ -4925,9 +4922,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
|
||||
ASSERT(!in_safe_int32_mode());
|
||||
// Build the function info and instantiate it.
|
||||
Handle<SharedFunctionInfo> function_info =
|
||||
Compiler::BuildFunctionInfo(node, script(), this);
|
||||
Compiler::BuildFunctionInfo(node, script());
|
||||
// Check for stack-overflow exception.
|
||||
if (HasStackOverflow()) return;
|
||||
if (function_info.is_null()) {
|
||||
SetStackOverflow();
|
||||
return;
|
||||
}
|
||||
Result result = InstantiateFunction(function_info);
|
||||
frame()->Push(&result);
|
||||
}
|
||||
|
@ -300,9 +300,7 @@ enum ArgumentsAllocationMode {
|
||||
|
||||
class CodeGenerator: public AstVisitor {
|
||||
public:
|
||||
// Takes a function literal, generates code for it. This function should only
|
||||
// be called by compiler.cc.
|
||||
static Handle<Code> MakeCode(CompilationInfo* info);
|
||||
static bool MakeCode(CompilationInfo* info);
|
||||
|
||||
// Printing of AST, etc. as requested by flags.
|
||||
static void MakeCodePrologue(CompilationInfo* info);
|
||||
|
@ -404,18 +404,16 @@ static void CompileScriptForTracker(Handle<Script> script) {
|
||||
// Build AST.
|
||||
CompilationInfo info(script);
|
||||
info.MarkAsGlobal();
|
||||
if (!Parser::Parse(&info)) return;
|
||||
|
||||
// Compile the code.
|
||||
LiveEditFunctionTracker tracker(info.function());
|
||||
Handle<Code> code = MakeCodeForLiveEdit(&info);
|
||||
|
||||
// Check for stack-overflow exceptions.
|
||||
if (code.is_null()) {
|
||||
Top::StackOverflow();
|
||||
return;
|
||||
if (Parser::Parse(&info)) {
|
||||
// Compile the code.
|
||||
LiveEditFunctionTracker tracker(info.function());
|
||||
if (Compiler::MakeCodeForLiveEdit(&info)) {
|
||||
ASSERT(!info.code().is_null());
|
||||
tracker.RecordRootFunctionInfo(info.code());
|
||||
} else {
|
||||
Top::StackOverflow();
|
||||
}
|
||||
}
|
||||
tracker.RecordRootFunctionInfo(code);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2009 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -5227,6 +5227,13 @@ Object* Oddball::Initialize(const char* to_string, Object* to_number) {
|
||||
}
|
||||
|
||||
|
||||
String* SharedFunctionInfo::DebugName() {
|
||||
Object* n = name();
|
||||
if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
|
||||
return String::cast(n);
|
||||
}
|
||||
|
||||
|
||||
bool SharedFunctionInfo::HasSourceCode() {
|
||||
return !script()->IsUndefined() &&
|
||||
!reinterpret_cast<Script*>(script())->source()->IsUndefined();
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2009 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -3621,6 +3621,9 @@ class SharedFunctionInfo: public HeapObject {
|
||||
// properties.
|
||||
DECL_ACCESSORS(inferred_name, String)
|
||||
|
||||
// The function's name if it is non-empty, otherwise the inferred name.
|
||||
String* DebugName();
|
||||
|
||||
// Position of the 'function' token in the script source.
|
||||
inline int function_token_position();
|
||||
inline void set_function_token_position(int function_token_position);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -27,10 +27,12 @@
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "ast.h"
|
||||
#include "scopes.h"
|
||||
#include "rewriter.h"
|
||||
|
||||
#include "ast.h"
|
||||
#include "compiler.h"
|
||||
#include "scopes.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
@ -986,34 +988,40 @@ void Processor::VisitThisFunction(ThisFunction* node) {
|
||||
}
|
||||
|
||||
|
||||
bool Rewriter::Process(FunctionLiteral* function) {
|
||||
HistogramTimerScope timer(&Counters::rewriting);
|
||||
// Assumes code has been parsed and scopes hve been analyzed. Mutates the
|
||||
// AST, so the AST should not continue to be used in the case of failure.
|
||||
bool Rewriter::Rewrite(CompilationInfo* info) {
|
||||
FunctionLiteral* function = info->function();
|
||||
ASSERT(function != NULL);
|
||||
Scope* scope = function->scope();
|
||||
ASSERT(scope != NULL);
|
||||
if (scope->is_function_scope()) return true;
|
||||
|
||||
ZoneList<Statement*>* body = function->body();
|
||||
if (body->is_empty()) return true;
|
||||
if (!body->is_empty()) {
|
||||
VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
|
||||
Processor processor(result);
|
||||
processor.Process(body);
|
||||
if (processor.HasStackOverflow()) return false;
|
||||
|
||||
VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
|
||||
Processor processor(result);
|
||||
processor.Process(body);
|
||||
if (processor.HasStackOverflow()) return false;
|
||||
if (processor.result_assigned()) body->Add(new ReturnStatement(result));
|
||||
}
|
||||
|
||||
if (processor.result_assigned()) body->Add(new ReturnStatement(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Rewriter::Optimize(FunctionLiteral* function) {
|
||||
ZoneList<Statement*>* body = function->body();
|
||||
// Assumes code has been parsed and scopes have been analyzed. Mutates the
|
||||
// AST, so the AST should not continue to be used in the case of failure.
|
||||
bool Rewriter::Analyze(CompilationInfo* info) {
|
||||
FunctionLiteral* function = info->function();
|
||||
ASSERT(function != NULL && function->scope() != NULL);
|
||||
|
||||
ZoneList<Statement*>* body = function->body();
|
||||
if (FLAG_optimize_ast && !body->is_empty()) {
|
||||
HistogramTimerScope timer(&Counters::ast_optimization);
|
||||
AstOptimizer optimizer;
|
||||
optimizer.Optimize(body);
|
||||
if (optimizer.HasStackOverflow()) {
|
||||
return false;
|
||||
}
|
||||
if (optimizer.HasStackOverflow()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -31,21 +31,26 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
// Currently, the rewriter takes function literals (only top-level)
|
||||
// and rewrites them to return the value of the last expression in
|
||||
// them.
|
||||
//
|
||||
// The rewriter adds a (hidden) variable, called .result, to the
|
||||
// activation, and tries to figure out where it needs to store into
|
||||
// this variable. If the variable is ever used, we conclude by adding
|
||||
// a return statement that returns the variable to the body of the
|
||||
// given function.
|
||||
class CompilationInfo;
|
||||
|
||||
class Rewriter {
|
||||
public:
|
||||
static bool Process(FunctionLiteral* function);
|
||||
static bool Optimize(FunctionLiteral* function);
|
||||
// Rewrite top-level code (ECMA 262 "programs") so as to conservatively
|
||||
// include an assignment of the value of the last statement in the code to
|
||||
// a compiler-generated temporary variable wherever needed.
|
||||
//
|
||||
// Assumes code has been parsed and scopes have been analyzed. Mutates the
|
||||
// AST, so the AST should not continue to be used in the case of failure.
|
||||
static bool Rewrite(CompilationInfo* info);
|
||||
|
||||
// Perform a suite of simple non-iterative analyses of the AST. Mark
|
||||
// expressions that are likely smis, expressions without side effects,
|
||||
// expressions whose value will be converted to Int32, and expressions in a
|
||||
// context where +0 and -0 are treated the same.
|
||||
//
|
||||
// Assumes code has been parsed and scopes have been analyzed. Mutates the
|
||||
// AST, so the AST should not continue to be used in the case of failure.
|
||||
static bool Analyze(CompilationInfo* info);
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -27,9 +27,12 @@
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "scopes.h"
|
||||
|
||||
#include "bootstrapper.h"
|
||||
#include "compiler.h"
|
||||
#include "prettyprinter.h"
|
||||
#include "scopeinfo.h"
|
||||
#include "scopes.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -168,6 +171,25 @@ Scope::Scope(Scope* outer_scope, Type type)
|
||||
}
|
||||
|
||||
|
||||
bool Scope::Analyze(CompilationInfo* info) {
|
||||
ASSERT(info->function() != NULL);
|
||||
Scope* top = info->function()->scope();
|
||||
while (top->outer_scope() != NULL) top = top->outer_scope();
|
||||
top->AllocateVariables(info->calling_context());
|
||||
|
||||
#ifdef DEBUG
|
||||
if (Bootstrapper::IsActive()
|
||||
? FLAG_print_builtin_scopes
|
||||
: FLAG_print_scopes) {
|
||||
info->function()->scope()->Print();
|
||||
}
|
||||
#endif
|
||||
|
||||
info->SetScope(info->function()->scope());
|
||||
return true; // Can not fail.
|
||||
}
|
||||
|
||||
|
||||
void Scope::Initialize(bool inside_with) {
|
||||
// Add this scope as a new inner scope of the outer scope.
|
||||
if (outer_scope_ != NULL) {
|
||||
|
10
src/scopes.h
10
src/scopes.h
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -34,6 +34,9 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class CompilationInfo;
|
||||
|
||||
|
||||
// A hash map to support fast variable declaration and lookup.
|
||||
class VariableMap: public HashMap {
|
||||
public:
|
||||
@ -96,6 +99,11 @@ class Scope: public ZoneObject {
|
||||
|
||||
virtual ~Scope() { }
|
||||
|
||||
// Compute top scope and allocate variables. For lazy compilation the top
|
||||
// scope only contains the single lazily compiled function, so this
|
||||
// doesn't re-allocate variables repeatedly.
|
||||
static bool Analyze(CompilationInfo* info);
|
||||
|
||||
// The scope name is only used for printing/debugging.
|
||||
void SetScopeName(Handle<String> scope_name) { scope_name_ = scope_name; }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2007-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2010 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -45,14 +45,7 @@ namespace internal {
|
||||
/* Total compilation times. */ \
|
||||
HT(compile, V8.Compile) \
|
||||
HT(compile_eval, V8.CompileEval) \
|
||||
HT(compile_lazy, V8.CompileLazy) \
|
||||
/* Individual compiler passes. */ \
|
||||
HT(rewriting, V8.Rewriting) \
|
||||
HT(usage_analysis, V8.UsageAnalysis) \
|
||||
HT(variable_allocation, V8.VariableAllocation) \
|
||||
HT(ast_optimization, V8.ASTOptimization) \
|
||||
HT(code_generation, V8.CodeGeneration) \
|
||||
HT(deferred_code_generation, V8.DeferredCodeGeneration)
|
||||
HT(compile_lazy, V8.CompileLazy)
|
||||
|
||||
|
||||
// WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
|
||||
|
@ -190,10 +190,8 @@ void CodeGenerator::Generate(CompilationInfo* info) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// New scope to get automatic timing calculation.
|
||||
{ HistogramTimerScope codegen_timer(&Counters::code_generation);
|
||||
{
|
||||
CodeGenState state(this);
|
||||
|
||||
// Entry:
|
||||
// Stack: receiver, arguments, return address.
|
||||
// rbp: caller's frame pointer
|
||||
@ -367,7 +365,6 @@ void CodeGenerator::Generate(CompilationInfo* info) {
|
||||
|
||||
// Process any deferred code using the register allocator.
|
||||
if (!HasStackOverflow()) {
|
||||
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
|
||||
JumpTarget::set_compiling_deferred_code(true);
|
||||
ProcessDeferred();
|
||||
JumpTarget::set_compiling_deferred_code(false);
|
||||
@ -4276,9 +4273,12 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
|
||||
|
||||
// Build the function info and instantiate it.
|
||||
Handle<SharedFunctionInfo> function_info =
|
||||
Compiler::BuildFunctionInfo(node, script(), this);
|
||||
Compiler::BuildFunctionInfo(node, script());
|
||||
// Check for stack-overflow exception.
|
||||
if (HasStackOverflow()) return;
|
||||
if (function_info.is_null()) {
|
||||
SetStackOverflow();
|
||||
return;
|
||||
}
|
||||
InstantiateFunction(function_info);
|
||||
}
|
||||
|
||||
|
@ -298,9 +298,7 @@ enum ArgumentsAllocationMode {
|
||||
|
||||
class CodeGenerator: public AstVisitor {
|
||||
public:
|
||||
// Takes a function literal, generates code for it. This function should only
|
||||
// be called by compiler.cc.
|
||||
static Handle<Code> MakeCode(CompilationInfo* info);
|
||||
static bool MakeCode(CompilationInfo* info);
|
||||
|
||||
// Printing of AST, etc. as requested by flags.
|
||||
static void MakeCodePrologue(CompilationInfo* info);
|
||||
|
Loading…
Reference in New Issue
Block a user