Obey the flag --lazy in the toplevel code generator.

There were two separate implementations of the function
'BuildBoilerplate' that is used to compile function declarations and
function literals.  The implementations did not do exactly the same
thing.  In particular, one ignored the flag --lazy.

Combine the two implementations.

Review URL: http://codereview.chromium.org/360011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3218 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f36c3228
......@@ -29,6 +29,7 @@
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
#include "parser.h"
#include "register-allocator-inl.h"
......@@ -575,8 +576,6 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) {
// load to make sure we do not get reference errors.
Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
Literal key(variable->name());
// TODO(1241834): Fetch the position from the variable instead of using
// no position.
Property property(&global, &key, RelocInfo::kNoPosition);
Reference ref(this, &property);
ref.GetValueAndSpill();
......@@ -2260,7 +2259,8 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(node);
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(node, script_, this);
// Check for stack-overflow exception.
if (HasStackOverflow()) {
ASSERT(frame_->height() == original_height);
......
......@@ -165,8 +165,8 @@ class CodeGenerator: public AstVisitor {
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
Handle<Script> script() { return script_; }
bool has_valid_frame() const { return frame_ != NULL; }
......@@ -319,7 +319,6 @@ class CodeGenerator: public AstVisitor {
InlineRuntimeLUT* old_entry);
static Handle<Code> ComputeLazyCompile(int argc);
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
#include "fast-codegen.h"
#include "parser.h"
......@@ -305,7 +306,8 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(expr, script_, this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
......
......@@ -29,6 +29,7 @@
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
#include "oprofile-agent.h"
#include "prettyprinter.h"
......@@ -250,99 +251,6 @@ bool CodeGenerator::ShouldGenerateLog(Expression* type) {
#endif
// Sets the function info on a function.
// The start_position points to the first '(' character after the function name
// in the full script source. When counting characters in the script source the
// the first character is number 0 (not 1).
void CodeGenerator::SetFunctionInfo(Handle<JSFunction> fun,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script) {
fun->shared()->set_length(lit->num_parameters());
fun->shared()->set_formal_parameter_count(lit->num_parameters());
fun->shared()->set_script(*script);
fun->shared()->set_function_token_position(lit->function_token_position());
fun->shared()->set_start_position(lit->start_position());
fun->shared()->set_end_position(lit->end_position());
fun->shared()->set_is_expression(lit->is_expression());
fun->shared()->set_is_toplevel(is_toplevel);
fun->shared()->set_inferred_name(*lit->inferred_name());
fun->shared()->SetThisPropertyAssignmentsInfo(
lit->has_only_this_property_assignments(),
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
fun->shared()->set_try_fast_codegen(lit->try_fast_codegen());
}
Handle<Code> CodeGenerator::ComputeLazyCompile(int argc) {
CALL_HEAP_FUNCTION(StubCache::ComputeLazyCompile(argc), Code);
}
Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
#ifdef DEBUG
// We should not try to compile the same function literal more than
// once.
node->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.
bool allow_lazy = node->AllowsLazyCompilation();
// Generate code
Handle<Code> code;
if (FLAG_lazy && allow_lazy) {
code = ComputeLazyCompile(node->num_parameters());
} else {
// The bodies of function literals have not yet been visited by
// the AST optimizer/analyzer.
if (!Rewriter::Optimize(node)) {
return Handle<JSFunction>::null();
}
code = MakeCode(node, script_, false);
// Check for stack-overflow exception.
if (code.is_null()) {
SetStackOverflow();
return Handle<JSFunction>::null();
}
// Function compilation complete.
LOG(CodeCreateEvent(Logger::FUNCTION_TAG, *code, *node->name()));
#ifdef ENABLE_OPROFILE_AGENT
OProfileAgent::CreateNativeCodeRegion(*node->name(),
code->instruction_start(),
code->instruction_size());
#endif
}
// Create a boilerplate function.
Handle<JSFunction> function =
Factory::NewFunctionBoilerplate(node->name(),
node->materialized_literal_count(),
code);
CodeGenerator::SetFunctionInfo(function, node, false, script_);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger that a new function has been added.
Debugger::OnNewFunction(function);
#endif
// Set the expected number of properties for instances and return
// the resulting function.
SetExpectedNofPropertiesFromEstimate(function,
node->expected_property_count());
return function;
}
Handle<Code> CodeGenerator::ComputeCallInitialize(
int argc,
InLoopFlag in_loop) {
......@@ -399,7 +307,8 @@ void CodeGenerator::ProcessDeclarations(ZoneList<Declaration*>* declarations) {
array->set_undefined(j++);
}
} else {
Handle<JSFunction> function = BuildBoilerplate(node->fun());
Handle<JSFunction> function =
Compiler::BuildBoilerplate(node->fun(), script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
array->set(j++, *function);
......
......@@ -38,9 +38,9 @@
// MakeCode
// MakeCodePrologue
// MakeCodeEpilogue
// SetFunctionInfo
// masm
// frame
// script
// has_valid_frame
// SetFrame
// DeleteFrame
......
......@@ -258,7 +258,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
code);
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
CodeGenerator::SetFunctionInfo(fun, lit, true, script);
Compiler::SetFunctionInfo(fun, lit, true, script);
// Hint to the runtime system used when allocating space for initial
// property space by setting the expected number of properties for
......@@ -475,6 +475,110 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
}
Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
Handle<Script> script,
AstVisitor* caller) {
#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.
bool allow_lazy = literal->AllowsLazyCompilation();
// Generate code
Handle<Code> code;
if (FLAG_lazy && allow_lazy) {
code = ComputeLazyCompile(literal->num_parameters());
} else {
// The bodies of function literals have not yet been visited by
// the AST optimizer/analyzer.
if (!Rewriter::Optimize(literal)) {
return Handle<JSFunction>::null();
}
// Generate code and return it.
if (FLAG_fast_compiler && literal->try_fast_codegen()) {
CodeGenSelector selector;
CodeGenSelector::CodeGenTag code_gen = selector.Select(literal);
if (code_gen == CodeGenSelector::FAST) {
code = FastCodeGenerator::MakeCode(literal,
script,
false); // Not eval.
}
ASSERT(code_gen == CodeGenSelector::NORMAL);
} else {
code = CodeGenerator::MakeCode(literal,
script,
false); // Not eval.
}
// Check for stack-overflow exception.
if (code.is_null()) {
caller->SetStackOverflow();
return Handle<JSFunction>::null();
}
// Function compilation complete.
LOG(CodeCreateEvent(Logger::FUNCTION_TAG, *code, *literal->name()));
#ifdef ENABLE_OPROFILE_AGENT
OProfileAgent::CreateNativeCodeRegion(*node->name(),
code->instruction_start(),
code->instruction_size());
#endif
}
// Create a boilerplate function.
Handle<JSFunction> function =
Factory::NewFunctionBoilerplate(literal->name(),
literal->materialized_literal_count(),
code);
SetFunctionInfo(function, literal, false, script);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger that a new function has been added.
Debugger::OnNewFunction(function);
#endif
// Set the expected number of properties for instances and return
// the resulting function.
SetExpectedNofPropertiesFromEstimate(function,
literal->expected_property_count());
return function;
}
// Sets the function info on a function.
// The start_position points to the first '(' character after the function name
// in the full script source. When counting characters in the script source the
// the first character is number 0 (not 1).
void Compiler::SetFunctionInfo(Handle<JSFunction> fun,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script) {
fun->shared()->set_length(lit->num_parameters());
fun->shared()->set_formal_parameter_count(lit->num_parameters());
fun->shared()->set_script(*script);
fun->shared()->set_function_token_position(lit->function_token_position());
fun->shared()->set_start_position(lit->start_position());
fun->shared()->set_end_position(lit->end_position());
fun->shared()->set_is_expression(lit->is_expression());
fun->shared()->set_is_toplevel(is_toplevel);
fun->shared()->set_inferred_name(*lit->inferred_name());
fun->shared()->SetThisPropertyAssignmentsInfo(
lit->has_only_this_property_assignments(),
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
fun->shared()->set_try_fast_codegen(lit->try_fast_codegen());
}
CodeGenSelector::CodeGenTag CodeGenSelector::Select(FunctionLiteral* fun) {
Scope* scope = fun->scope();
if (scope->num_heap_slots() != 0) {
......
......@@ -71,6 +71,19 @@ class Compiler : public AllStatic {
// true on success and false if the compilation resulted in a stack
// overflow.
static bool CompileLazy(Handle<SharedFunctionInfo> shared, int loop_nesting);
// Compile a function boilerplate object (the function is possibly
// lazily compiled). Called recursively from a backend code
// generator 'caller' to build the boilerplate.
static Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node,
Handle<Script> script,
AstVisitor* caller);
// Set the function info for a newly compiled function.
static void SetFunctionInfo(Handle<JSFunction> fun,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script);
};
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "fast-codegen.h"
#include "stub-cache.h"
#include "debug.h"
......@@ -79,8 +80,8 @@ void FastCodeGenerator::VisitDeclarations(
int length = declarations->length();
int globals = 0;
for (int i = 0; i < length; i++) {
Declaration* node = declarations->at(i);
Variable* var = node->proxy()->var();
Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var();
Slot* slot = var->slot();
// If it was not possible to allocate the variable at compile
......@@ -100,13 +101,13 @@ void FastCodeGenerator::VisitDeclarations(
// Compute array of global variable and function declarations.
Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED);
for (int j = 0, i = 0; i < length; i++) {
Declaration* node = declarations->at(i);
Variable* var = node->proxy()->var();
Declaration* decl = declarations->at(i);
Variable* var = decl->proxy()->var();
Slot* slot = var->slot();
if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) {
array->set(j++, *(var->name()));
if (node->fun() == NULL) {
if (decl->fun() == NULL) {
if (var->mode() == Variable::CONST) {
// In case this is const property use the hole.
array->set_the_hole(j++);
......@@ -114,7 +115,8 @@ void FastCodeGenerator::VisitDeclarations(
array->set_undefined(j++);
}
} else {
Handle<JSFunction> function = BuildBoilerplate(node->fun());
Handle<JSFunction> function =
Compiler::BuildBoilerplate(decl->fun(), script_, this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
array->set(j++, *function);
......@@ -127,40 +129,6 @@ void FastCodeGenerator::VisitDeclarations(
DeclareGlobals(array);
}
Handle<JSFunction> FastCodeGenerator::BuildBoilerplate(FunctionLiteral* fun) {
#ifdef DEBUG
// We should not try to compile the same function literal more than
// once.
fun->mark_as_compiled();
#endif
// Generate code
Handle<Code> code = CodeGenerator::ComputeLazyCompile(fun->num_parameters());
// Check for stack-overflow exception.
if (code.is_null()) {
SetStackOverflow();
return Handle<JSFunction>::null();
}
// Create a boilerplate function.
Handle<JSFunction> function =
Factory::NewFunctionBoilerplate(fun->name(),
fun->materialized_literal_count(),
code);
CodeGenerator::SetFunctionInfo(function, fun, false, script_);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger that a new function has been added.
Debugger::OnNewFunction(function);
#endif
// Set the expected number of properties for instances and return
// the resulting function.
SetExpectedNofPropertiesFromEstimate(function,
fun->expected_property_count());
return function;
}
void FastCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) {
if (FLAG_debug_info) {
......
......@@ -70,7 +70,6 @@ class FastCodeGenerator: public AstVisitor {
void TestAndBranch(Register source, Label* true_label, Label* false_label);
void VisitDeclarations(ZoneList<Declaration*>* declarations);
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* fun);
void DeclareGlobals(Handle<FixedArray> pairs);
// Platform-specific return sequence
......
......@@ -37,6 +37,7 @@
#include "global-handles.h"
#include "natives.h"
#include "runtime.h"
#include "stub-cache.h"
namespace v8 {
namespace internal {
......@@ -687,6 +688,11 @@ OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
}
Handle<Code> ComputeLazyCompile(int argc) {
CALL_HEAP_FUNCTION(StubCache::ComputeLazyCompile(argc), Code);
}
OptimizedObjectForAddingMultipleProperties::
~OptimizedObjectForAddingMultipleProperties() {
// Reoptimize the object to allow fast property access.
......
......@@ -308,8 +308,8 @@ Handle<Object> SetPrototype(Handle<JSFunction> function,
Handle<Object> prototype);
// Do lazy compilation of the given function. Returns true on success
// and false if the compilation resulted in a stack overflow.
// Does lazy compilation of the given function. Returns true on success and
// false if the compilation resulted in a stack overflow.
enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
......@@ -319,6 +319,9 @@ bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
bool CompileLazy(Handle<JSFunction> function, ClearExceptionFlag flag);
bool CompileLazyInLoop(Handle<JSFunction> function, ClearExceptionFlag flag);
// Returns the lazy compilation stub for argc arguments.
Handle<Code> ComputeLazyCompile(int argc);
// These deal with lazily loaded properties.
void SetupLazy(Handle<JSObject> obj,
int index,
......
......@@ -29,6 +29,7 @@
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
#include "ic-inl.h"
#include "parser.h"
......@@ -547,8 +548,6 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) {
// load to make sure we do not get reference errors.
Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
Literal key(variable->name());
// TODO(1241834): Fetch the position from the variable instead of using
// no position.
Property property(&global, &key, RelocInfo::kNoPosition);
Reference ref(this, &property);
ref.GetValue();
......@@ -3552,7 +3551,8 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(node);
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(node, script_, this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
InstantiateBoilerplate(boilerplate);
......
......@@ -299,17 +299,12 @@ class CodeGenerator: public AstVisitor {
static bool ShouldGenerateLog(Expression* type);
#endif
static void SetFunctionInfo(Handle<JSFunction> fun,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script);
static void RecordPositions(MacroAssembler* masm, int pos);
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
Handle<Script> script() { return script_; }
bool has_valid_frame() const { return frame_ != NULL; }
......@@ -500,8 +495,6 @@ class CodeGenerator: public AstVisitor {
const InlineRuntimeLUT& new_entry,
InlineRuntimeLUT* old_entry);
static Handle<Code> ComputeLazyCompile(int argc);
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "fast-codegen.h"
#include "parser.h"
#include "debug.h"
......@@ -299,7 +300,8 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(expr, script_, this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
......
......@@ -29,6 +29,7 @@
#include "bootstrapper.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
#include "ic-inl.h"
#include "parser.h"
......@@ -2164,7 +2165,8 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(node);
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(node, script_, this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
InstantiateBoilerplate(boilerplate);
......@@ -4812,8 +4814,6 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) {
// load to make sure we do not get reference errors.
Slot global(variable, Slot::CONTEXT, Context::GLOBAL_INDEX);
Literal key(variable->name());
// TODO(1241834): Fetch the position from the variable instead of using
// no position.
Property property(&global, &key, RelocInfo::kNoPosition);
Reference ref(this, &property);
ref.GetValue();
......
......@@ -299,17 +299,12 @@ class CodeGenerator: public AstVisitor {
static bool ShouldGenerateLog(Expression* type);
#endif
static void SetFunctionInfo(Handle<JSFunction> fun,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script);
static void RecordPositions(MacroAssembler* masm, int pos);
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
Handle<Script> script() { return script_; }
bool has_valid_frame() const { return frame_ != NULL; }
......@@ -500,8 +495,6 @@ class CodeGenerator: public AstVisitor {
static bool PatchInlineRuntimeEntry(Handle<String> name,
const InlineRuntimeLUT& new_entry,
InlineRuntimeLUT* old_entry);
static Handle<Code> ComputeLazyCompile(int argc);
Handle<JSFunction> BuildBoilerplate(FunctionLiteral* node);
void ProcessDeclarations(ZoneList<Declaration*>* declarations);
static Handle<Code> ComputeCallInitialize(int argc, InLoopFlag in_loop);
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "codegen-inl.h"
#include "compiler.h"
#include "debug.h"
#include "fast-codegen.h"
#include "parser.h"
......@@ -306,7 +307,8 @@ void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
Comment cmnt(masm_, "[ FunctionLiteral");
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate = BuildBoilerplate(expr);
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(expr, script_, this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment