Incorporate the arguments to the code generator constructors and their

MakeCode functions in the CompilationInfo structure.  This makes it
easier to add new arguments and makes all arguments uniformly
available to the various backends.
Review URL: http://codereview.chromium.org/566008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3789 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 62054f8b
......@@ -121,14 +121,10 @@ CodeGenState::~CodeGenState() {
// -------------------------------------------------------------------------
// CodeGenerator implementation
CodeGenerator::CodeGenerator(MacroAssembler* masm,
Handle<Script> script,
bool is_eval)
: is_eval_(is_eval),
script_(script),
deferred_(8),
CodeGenerator::CodeGenerator(MacroAssembler* masm)
: deferred_(8),
masm_(masm),
scope_(NULL),
info_(NULL),
frame_(NULL),
allocator_(NULL),
cc_reg_(al),
......@@ -137,23 +133,21 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm,
}
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// Calling conventions:
// fp: caller's frame pointer
// sp: stack pointer
// r1: called JS function
// cp: callee's context
void CodeGenerator::Generate(FunctionLiteral* fun,
Mode mode,
CompilationInfo* info) {
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// Record the position for debugging purposes.
CodeForFunctionPosition(fun);
ZoneList<Statement*>* body = fun->body();
CodeForFunctionPosition(info->function());
// Initialize state.
ASSERT(scope_ == NULL);
scope_ = fun->scope();
info_ = info;
ASSERT(allocator_ == NULL);
RegisterAllocator register_allocator(this);
allocator_ = &register_allocator;
......@@ -174,7 +168,7 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
frame_->SpillAll();
__ stop("stop-at");
}
......@@ -189,7 +183,7 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
frame_->AllocateStackSlots();
VirtualFrame::SpilledScope spilled_scope;
int heap_slots = scope_->num_heap_slots();
int heap_slots = scope()->num_heap_slots();
if (heap_slots > 0) {
// Allocate local context.
// Get outer context and create a new context based on it.
......@@ -219,7 +213,6 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// 3) don't copy parameter operand code from SlotOperand!
{
Comment cmnt2(masm_, "[ copy context parameters into .context");
// Note that iteration order is relevant here! If we have the same
// parameter twice (e.g., function (x, y, x)), and that parameter
// needs to be copied into the context, it must be the last argument
......@@ -228,12 +221,11 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// order: such a parameter is copied repeatedly into the same
// context location and thus the last value is what is seen inside
// the function.
for (int i = 0; i < scope_->num_parameters(); i++) {
Variable* par = scope_->parameter(i);
for (int i = 0; i < scope()->num_parameters(); i++) {
Variable* par = scope()->parameter(i);
Slot* slot = par->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
// No parameters in global scope.
ASSERT(!scope_->is_global_scope());
ASSERT(!scope()->is_global_scope()); // no parameters in global scope
__ ldr(r1, frame_->ParameterAt(i));
// Loads r2 with context; used below in RecordWrite.
__ str(r1, SlotOperand(slot, r2));
......@@ -249,20 +241,20 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// Store the arguments object. This must happen after context
// initialization because the arguments object may be stored in the
// context.
if (scope_->arguments() != NULL) {
if (scope()->arguments() != NULL) {
Comment cmnt(masm_, "[ allocate arguments object");
ASSERT(scope_->arguments_shadow() != NULL);
Variable* arguments = scope_->arguments()->var();
Variable* shadow = scope_->arguments_shadow()->var();
ASSERT(scope()->arguments_shadow() != NULL);
Variable* arguments = scope()->arguments()->var();
Variable* shadow = scope()->arguments_shadow()->var();
ASSERT(arguments != NULL && arguments->slot() != NULL);
ASSERT(shadow != NULL && shadow->slot() != NULL);
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
__ ldr(r2, frame_->Function());
// The receiver is below the arguments, the return address, and the
// frame pointer on the stack.
const int kReceiverDisplacement = 2 + scope_->num_parameters();
const int kReceiverDisplacement = 2 + scope()->num_parameters();
__ add(r1, fp, Operand(kReceiverDisplacement * kPointerSize));
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
frame_->Adjust(3);
__ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit());
frame_->CallStub(&stub, 3);
......@@ -273,10 +265,10 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
}
// Initialize ThisFunction reference if present.
if (scope_->is_function_scope() && scope_->function() != NULL) {
if (scope()->is_function_scope() && scope()->function() != NULL) {
__ mov(ip, Operand(Factory::the_hole_value()));
frame_->EmitPush(ip);
StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
StoreToSlot(scope()->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, r1, cp,
......@@ -295,12 +287,12 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
// handle that instead of processing the declarations.
if (scope_->HasIllegalRedeclaration()) {
if (scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ illegal redeclarations");
scope_->VisitIllegalRedeclaration(this);
scope()->VisitIllegalRedeclaration(this);
} else {
Comment cmnt(masm_, "[ declarations");
ProcessDeclarations(scope_->declarations());
ProcessDeclarations(scope()->declarations());
// Bail out if a stack-overflow exception occurred when processing
// declarations.
if (HasStackOverflow()) return;
......@@ -314,7 +306,7 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// Compile the body of the function in a vanilla state. Don't
// bother compiling all the code if the scope has an illegal
// redeclaration.
if (!scope_->HasIllegalRedeclaration()) {
if (!scope()->HasIllegalRedeclaration()) {
Comment cmnt(masm_, "[ function body");
#ifdef DEBUG
bool is_builtin = Bootstrapper::IsActive();
......@@ -325,14 +317,14 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// Ignore the return value.
}
#endif
VisitStatementsAndSpill(body);
VisitStatementsAndSpill(info->function()->body());
}
}
// Generate the return sequence if necessary.
if (has_valid_frame() || function_return_.is_linked()) {
if (!function_return_.is_linked()) {
CodeForReturnPosition(fun);
CodeForReturnPosition(info->function());
}
// exit
// r0: result
......@@ -355,7 +347,7 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
// Calculate the exact length of the return sequence and make sure that
// the constant pool is not emitted inside of the return sequence.
int32_t sp_delta = (scope_->num_parameters() + 1) * kPointerSize;
int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
int return_sequence_length = Assembler::kJSReturnSequenceLength;
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
// Additional mov instruction generated.
......@@ -395,7 +387,6 @@ void CodeGenerator::Generate(FunctionLiteral* fun,
}
allocator_ = NULL;
scope_ = NULL;
}
......@@ -2341,7 +2332,7 @@ void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(node, script_, this);
Compiler::BuildBoilerplate(node, script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) {
ASSERT(frame_->height() == original_height);
......@@ -3519,7 +3510,7 @@ void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
// Seed the result with the formal parameters count, which will be used
// in case no arguments adaptor frame is found below the current frame.
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to the arguments.length.
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH);
......@@ -3536,7 +3527,7 @@ void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) {
// Load the key into r1 and the formal parameters count into r0.
LoadAndSpill(args->at(0));
frame_->EmitPop(r1);
__ mov(r0, Operand(Smi::FromInt(scope_->num_parameters())));
__ mov(r0, Operand(Smi::FromInt(scope()->num_parameters())));
// Call the shared stub to get to arguments[key].
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
......
......@@ -161,19 +161,15 @@ class CodeGenerator: public AstVisitor {
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval,
CompilationInfo* info);
static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(FunctionLiteral* fun);
static void MakeCodePrologue(CompilationInfo* info);
// Allocate and install the code.
static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
MacroAssembler* masm,
static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
Handle<Script> script);
CompilationInfo* info);
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
......@@ -189,7 +185,7 @@ class CodeGenerator: public AstVisitor {
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
Handle<Script> script() { return script_; }
inline Handle<Script> script();
bool has_valid_frame() const { return frame_ != NULL; }
......@@ -212,16 +208,15 @@ class CodeGenerator: public AstVisitor {
private:
// Construction/Destruction
CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
CodeGenerator(MacroAssembler* masm);
// Accessors
Scope* scope() const { return scope_; }
inline bool is_eval();
Scope* scope();
// Generating deferred code.
void ProcessDeferred();
bool is_eval() { return is_eval_; }
// State
bool has_cc() const { return cc_reg_ != al; }
JumpTarget* true_target() const { return state_->true_target(); }
......@@ -249,7 +244,7 @@ class CodeGenerator: public AstVisitor {
inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
void Generate(CompilationInfo* info, Mode mode);
// The following are used by class Reference.
void LoadReference(Reference* ref);
......@@ -425,16 +420,14 @@ class CodeGenerator: public AstVisitor {
bool HasValidEntryRegisters();
#endif
bool is_eval_; // Tells whether code is generated for eval.
Handle<Script> script_;
List<DeferredCode*> deferred_;
// Assembler
MacroAssembler* masm_; // to generate code
CompilationInfo* info_;
// Code generation state
Scope* scope_;
VirtualFrame* frame_;
RegisterAllocator* allocator_;
Condition cc_reg_;
......
......@@ -37,7 +37,7 @@ namespace internal {
void FastCodeGenerator::EmitLoadReceiver(Register reg) {
// Offset 2 is due to return address and saved frame pointer.
int index = 2 + function()->scope()->num_parameters();
int index = 2 + scope()->num_parameters();
__ ldr(reg, MemOperand(sp, index * kPointerSize));
}
......@@ -102,10 +102,8 @@ void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
}
void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
ASSERT(function_ == NULL);
void FastCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
function_ = fun;
info_ = info;
// Save the caller's frame pointer and set up our own.
......@@ -118,7 +116,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
// Receiver (this) is allocated to r1 if there are this properties.
if (has_this_properties()) EmitReceiverMapCheck();
VisitStatements(fun->body());
VisitStatements(function()->body());
Comment return_cmnt(masm(), ";; Return(<undefined>)");
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
......@@ -126,7 +124,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
Comment epilogue_cmnt(masm(), ";; Epilogue");
__ mov(sp, fp);
__ ldm(ia_w, sp, fp.bit() | lr.bit());
int32_t sp_delta = (fun->scope()->num_parameters() + 1) * kPointerSize;
int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
__ add(sp, sp, Operand(sp_delta));
__ Jump(lr);
......
......@@ -52,12 +52,13 @@ namespace internal {
//
// The function builds a JS frame. Please see JavaScriptFrameConstants in
// frames-arm.h for its layout.
void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
function_ = fun;
SetFunctionPosition(fun);
void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
ASSERT(info_ == NULL);
info_ = info;
SetFunctionPosition(function());
if (mode == PRIMARY) {
int locals_count = fun->scope()->num_stack_slots();
int locals_count = scope()->num_stack_slots();
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
if (locals_count > 0) {
......@@ -77,7 +78,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
bool function_in_register = true;
// Possibly allocate a local context.
if (fun->scope()->num_heap_slots() > 0) {
if (scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is in r1.
__ push(r1);
......@@ -87,9 +88,9 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
// passed to us. It's saved in the stack and kept live in cp.
__ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
// Copy any necessary parameters into the context.
int num_parameters = fun->scope()->num_parameters();
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
Slot* slot = fun->scope()->parameter(i)->slot();
Slot* slot = scope()->parameter(i)->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
......@@ -107,7 +108,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
}
}
Variable* arguments = fun->scope()->arguments()->AsVariable();
Variable* arguments = scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
......@@ -118,9 +119,10 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ mov(r3, r1);
}
// Receiver is just before the parameters on the caller's stack.
__ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset +
fun->num_parameters() * kPointerSize));
__ mov(r1, Operand(Smi::FromInt(fun->num_parameters())));
int offset = scope()->num_parameters() * kPointerSize;
__ add(r2, fp,
Operand(StandardFrameConstants::kCallerSPOffset + offset));
__ mov(r1, Operand(Smi::FromInt(scope()->num_parameters())));
__ stm(db_w, sp, r3.bit() | r2.bit() | r1.bit());
// Arguments to ArgumentsAccessStub:
......@@ -133,7 +135,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ mov(r3, r0);
Move(arguments->slot(), r0, r1, r2);
Slot* dot_arguments_slot =
fun->scope()->arguments_shadow()->AsVariable()->slot();
scope()->arguments_shadow()->AsVariable()->slot();
Move(dot_arguments_slot, r3, r1, r2);
}
}
......@@ -155,7 +157,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
}
{ Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(fun->scope()->declarations());
VisitDeclarations(scope()->declarations());
}
if (FLAG_trace) {
......@@ -164,7 +166,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
{ Comment cmnt(masm_, "[ Body");
ASSERT(loop_depth() == 0);
VisitStatements(fun->body());
VisitStatements(function()->body());
ASSERT(loop_depth() == 0);
}
......@@ -173,7 +175,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
// body.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
}
EmitReturnSequence(function_->end_position());
EmitReturnSequence(function()->end_position());
}
......@@ -196,7 +198,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
// Calculate the exact length of the return sequence and make sure that
// the constant pool is not emitted inside of the return sequence.
int num_parameters = function_->scope()->num_parameters();
int num_parameters = scope()->num_parameters();
int32_t sp_delta = (num_parameters + 1) * kPointerSize;
int return_sequence_length = Assembler::kJSReturnSequenceLength;
if (!masm_->ImmediateFitsAddrMode1Instruction(sp_delta)) {
......@@ -512,7 +514,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
return MemOperand(fp, SlotOffset(slot));
case Slot::CONTEXT: {
int context_chain_length =
function_->scope()->ContextChainLength(slot->var()->scope());
scope()->ContextChainLength(slot->var()->scope());
__ LoadContext(scratch, context_chain_length);
return CodeGenerator::ContextOperand(scratch, slot->index());
}
......@@ -572,7 +574,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
// this specific context.
// The variable in the decl always resides in the current context.
ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ ldr(r1,
......@@ -652,7 +654,7 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
// The context is the first argument.
__ mov(r1, Operand(pairs));
__ mov(r0, Operand(Smi::FromInt(is_eval_ ? 1 : 0)));
__ mov(r0, Operand(Smi::FromInt(is_eval() ? 1 : 0)));
__ stm(db_w, sp, cp.bit() | r1.bit() | r0.bit());
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
......@@ -664,7 +666,7 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(expr, script_, this);
Compiler::BuildBoilerplate(expr, script(), this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
......
......@@ -30,6 +30,7 @@
#define V8_CODEGEN_INL_H_
#include "codegen.h"
#include "compiler.h"
#include "register-allocator-inl.h"
#if V8_TARGET_ARCH_IA32
......@@ -48,6 +49,10 @@ namespace internal {
#define __ ACCESS_MASM(masm_)
Handle<Script> CodeGenerator::script() { return info_->script(); }
bool CodeGenerator::is_eval() { return info_->is_eval(); }
// -----------------------------------------------------------------------------
// Support for "structured" code comments.
//
......
......@@ -126,7 +126,7 @@ void CodeGenerator::DeleteFrame() {
}
void CodeGenerator::MakeCodePrologue(FunctionLiteral* fun) {
void CodeGenerator::MakeCodePrologue(CompilationInfo* info) {
#ifdef DEBUG
bool print_source = false;
bool print_ast = false;
......@@ -147,34 +147,35 @@ void CodeGenerator::MakeCodePrologue(FunctionLiteral* fun) {
if (FLAG_trace_codegen || print_source || print_ast) {
PrintF("*** Generate code for %s function: ", ftype);
fun->name()->ShortPrint();
info->function()->name()->ShortPrint();
PrintF(" ***\n");
}
if (print_source) {
PrintF("--- Source from AST ---\n%s\n", PrettyPrinter().PrintProgram(fun));
PrintF("--- Source from AST ---\n%s\n",
PrettyPrinter().PrintProgram(info->function()));
}
if (print_ast) {
PrintF("--- AST ---\n%s\n", AstPrinter().PrintProgram(fun));
PrintF("--- AST ---\n%s\n",
AstPrinter().PrintProgram(info->function()));
}
if (print_json_ast) {
JsonAstBuilder builder;
PrintF("%s", builder.BuildProgram(fun));
PrintF("%s", builder.BuildProgram(info->function()));
}
#endif // DEBUG
}
Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
MacroAssembler* masm,
Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
Handle<Script> script) {
CompilationInfo* info) {
// Allocate and install the code.
CodeDesc desc;
masm->GetCode(&desc);
ZoneScopeInfo sinfo(fun->scope());
ZoneScopeInfo sinfo(info->scope());
Handle<Code> code =
Factory::NewCode(desc, &sinfo, flags, masm->CodeObject());
......@@ -187,20 +188,23 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
: FLAG_print_code;
if (print_code) {
// Print the source code if available.
Handle<Script> script = info->script();
FunctionLiteral* function = info->function();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
PrintF("--- Raw source ---\n");
StringInputBuffer stream(String::cast(script->source()));
stream.Seek(fun->start_position());
stream.Seek(function->start_position());
// fun->end_position() points to the last character in the stream. We
// need to compensate by adding one to calculate the length.
int source_len = fun->end_position() - fun->start_position() + 1;
int source_len =
function->end_position() - function->start_position() + 1;
for (int i = 0; i < source_len; i++) {
if (stream.has_more()) PrintF("%c", stream.GetNext());
}
PrintF("\n\n");
}
PrintF("--- Code ---\n");
code->Disassemble(*fun->name()->ToCString());
code->Disassemble(*function->name()->ToCString());
}
#endif // ENABLE_DISASSEMBLER
......@@ -214,21 +218,19 @@ Handle<Code> CodeGenerator::MakeCodeEpilogue(FunctionLiteral* fun,
// 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(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval,
CompilationInfo* info) {
Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
Counters::total_old_codegen_source_size.Increment(len);
}
MakeCodePrologue(fun);
MakeCodePrologue(info);
// Generate code.
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
CodeGenerator cgen(&masm, script, is_eval);
CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
cgen.Generate(fun, PRIMARY, info);
cgen.Generate(info, PRIMARY);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
......@@ -236,7 +238,7 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
InLoopFlag in_loop = (cgen.loop_nesting() != 0) ? IN_LOOP : NOT_IN_LOOP;
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
return MakeCodeEpilogue(fun, cgen.masm(), flags, script);
return MakeCodeEpilogue(cgen.masm(), flags, info);
}
......
......@@ -43,15 +43,11 @@ namespace v8 {
namespace internal {
static Handle<Code> MakeCode(FunctionLiteral* literal,
Handle<Script> script,
Handle<Context> context,
bool is_eval,
CompilationInfo* info) {
ASSERT(literal != NULL);
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(literal) || !AnalyzeVariableUsage(literal)) {
if (!Rewriter::Process(function) || !AnalyzeVariableUsage(function)) {
// Signal a stack overflow by returning a null handle. The stack
// overflow exception will be thrown by the caller.
return Handle<Code>::null();
......@@ -62,7 +58,7 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
// 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 = literal->scope();
Scope* top = info->scope();
while (top->outer_scope() != NULL) top = top->outer_scope();
top->AllocateVariables(context);
}
......@@ -71,12 +67,12 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
if (Bootstrapper::IsActive() ?
FLAG_print_builtin_scopes :
FLAG_print_scopes) {
literal->scope()->Print();
info->scope()->Print();
}
#endif
// Optimize the AST.
if (!Rewriter::Optimize(literal)) {
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();
......@@ -98,25 +94,25 @@ static Handle<Code> MakeCode(FunctionLiteral* literal,
Handle<SharedFunctionInfo> shared = info->shared_info();
bool is_run_once = (shared.is_null())
? literal->scope()->is_global_scope()
? info->scope()->is_global_scope()
: (shared->is_toplevel() || shared->try_full_codegen());
if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) {
FullCodeGenSyntaxChecker checker;
checker.Check(literal);
checker.Check(function);
if (checker.has_supported_syntax()) {
return FullCodeGenerator::MakeCode(literal, script, is_eval);
return FullCodeGenerator::MakeCode(info);
}
} else if (FLAG_always_fast_compiler ||
(FLAG_fast_compiler && !is_run_once)) {
FastCodeGenSyntaxChecker checker;
checker.Check(literal, info);
checker.Check(info);
if (checker.has_supported_syntax()) {
return FastCodeGenerator::MakeCode(literal, script, is_eval, info);
return FastCodeGenerator::MakeCode(info);
}
}
return CodeGenerator::MakeCode(literal, script, is_eval, info);
return CodeGenerator::MakeCode(info);
}
......@@ -180,10 +176,8 @@ static Handle<JSFunction> MakeFunction(bool is_global,
HistogramTimerScope timer(rate);
// Compile the code.
CompilationInfo info(Handle<SharedFunctionInfo>::null(),
Handle<Object>::null(), // No receiver.
0); // Not nested in a loop.
Handle<Code> code = MakeCode(lit, script, context, is_eval, &info);
CompilationInfo info(lit, script, is_eval);
Handle<Code> code = MakeCode(context, &info);
// Check for stack-overflow exceptions.
if (code.is_null()) {
......@@ -355,7 +349,6 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// Compute name, source code and script data.
Handle<SharedFunctionInfo> shared = info->shared_info();
Handle<String> name(String::cast(shared->name()));
Handle<Script> script(Script::cast(shared->script()));
int start_position = shared->start_position();
int end_position = shared->end_position();
......@@ -364,7 +357,8 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// Generate the AST for the lazily compiled function. The AST may be
// NULL in case of parser stack overflow.
FunctionLiteral* lit = MakeLazyAST(script, name,
FunctionLiteral* lit = MakeLazyAST(info->script(),
name,
start_position,
end_position,
is_expression);
......@@ -374,6 +368,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
ASSERT(Top::has_pending_exception());
return false;
}
info->set_function(lit);
// Measure how long it takes to do the lazy compilation; only take
// the rest of the function into account to avoid overlap with the
......@@ -381,11 +376,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
HistogramTimerScope timer(&Counters::compile_lazy);
// Compile the code.
Handle<Code> code = MakeCode(lit,
script,
Handle<Context>::null(),
false,
info);
Handle<Code> code = MakeCode(Handle<Context>::null(), info);
// Check for stack-overflow exception.
if (code.is_null()) {
......@@ -400,6 +391,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
if (Logger::is_logging() || OProfileAgent::is_enabled()) {
Handle<String> func_name(name->length() > 0 ?
*name : shared->inferred_name());
Handle<Script> script = info->script();
if (script->name()->IsString()) {
int line_num = GetScriptLineNumber(script, start_position) + 1;
LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG, *code, *func_name,
......@@ -466,9 +458,7 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
// 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(Handle<SharedFunctionInfo>::null(),
Handle<Object>::null(), // No receiver.
0); // Not nested in a loop.
CompilationInfo info(literal, script, false);
CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler);
bool is_run_once = literal->try_full_codegen();
......@@ -477,9 +467,7 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
FullCodeGenSyntaxChecker checker;
checker.Check(literal);
if (checker.has_supported_syntax()) {
code = FullCodeGenerator::MakeCode(literal,
script,
false); // Not eval.
code = FullCodeGenerator::MakeCode(&info);
is_compiled = true;
}
} else if (FLAG_always_fast_compiler ||
......@@ -487,19 +475,16 @@ Handle<JSFunction> Compiler::BuildBoilerplate(FunctionLiteral* literal,
// Since we are not lazily compiling we do not have a receiver to
// specialize for.
FastCodeGenSyntaxChecker checker;
checker.Check(literal, &info);
checker.Check(&info);
if (checker.has_supported_syntax()) {
code = FastCodeGenerator::MakeCode(literal, script, false, &info);
code = FastCodeGenerator::MakeCode(&info);
is_compiled = true;
}
}
if (!is_compiled) {
// We fall back to the classic V8 code generator.
code = CodeGenerator::MakeCode(literal,
script,
false, // Not eval.
&info);
code = CodeGenerator::MakeCode(&info);
}
// Check for stack-overflow exception.
......
......@@ -35,38 +35,119 @@
namespace v8 {
namespace internal {
// CompilationInfo encapsulates some information known at compile time.
// CompilationInfo encapsulates some information known at compile time. It
// is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED {
public:
CompilationInfo(Handle<SharedFunctionInfo> shared_info,
Handle<Object> receiver,
int loop_nesting)
: shared_info_(shared_info),
receiver_(receiver),
// Lazy compilation of a JSFunction.
CompilationInfo(Handle<JSFunction> closure,
int loop_nesting,
Handle<Object> receiver)
: closure_(closure),
function_(NULL),
is_eval_(false),
loop_nesting_(loop_nesting),
has_this_properties_(false),
has_globals_(false) {
receiver_(receiver) {
Initialize();
ASSERT(!closure_.is_null() &&
shared_info_.is_null() &&
script_.is_null());
}
Handle<SharedFunctionInfo> shared_info() { return shared_info_; }
// Lazy compilation based on SharedFunctionInfo.
explicit CompilationInfo(Handle<SharedFunctionInfo> shared_info)
: shared_info_(shared_info),
function_(NULL),
is_eval_(false),
loop_nesting_(0) {
Initialize();
ASSERT(closure_.is_null() &&
!shared_info_.is_null() &&
script_.is_null());
}
bool has_receiver() { return !receiver_.is_null(); }
Handle<Object> receiver() { return receiver_; }
// Eager compilation.
CompilationInfo(FunctionLiteral* literal, Handle<Script> script, bool is_eval)
: script_(script),
function_(literal),
is_eval_(is_eval),
loop_nesting_(0) {
Initialize();
ASSERT(closure_.is_null() &&
shared_info_.is_null() &&
!script_.is_null());
}
// We can only get a JSFunction if we actually have one.
Handle<JSFunction> closure() { return closure_; }
// We can get a SharedFunctionInfo from a JSFunction or if we actually
// have one.
Handle<SharedFunctionInfo> shared_info() {
if (!closure().is_null()) {
return Handle<SharedFunctionInfo>(closure()->shared());
} else {
return shared_info_;
}
}
// We can always get a script. Either we have one or we can get a shared
// function info.
Handle<Script> script() {
if (!script_.is_null()) {
return script_;
} else {
ASSERT(shared_info()->script()->IsScript());
return Handle<Script>(Script::cast(shared_info()->script()));
}
}
// There should always be a function literal, but it may be set after
// construction (for lazy compilation).
FunctionLiteral* function() { return function_; }
void set_function(FunctionLiteral* literal) {
ASSERT(function_ == NULL);
function_ = literal;
}
// Simple accessors.
bool is_eval() { return is_eval_; }
int loop_nesting() { return loop_nesting_; }
bool has_receiver() { return !receiver_.is_null(); }
Handle<Object> receiver() { return receiver_; }
// Accessors for mutable fields, possibly set by analysis passes with
// default values given by Initialize.
bool has_this_properties() { return has_this_properties_; }
void set_has_this_properties(bool flag) { has_this_properties_ = flag; }
bool has_globals() { return has_globals_; }
void set_has_globals(bool flag) { has_globals_ = flag; }
// Derived accessors.
Scope* scope() { return function()->scope(); }
private:
void Initialize() {
has_this_properties_ = false;
has_globals_ = false;
}
Handle<JSFunction> closure_;
Handle<SharedFunctionInfo> shared_info_;
Handle<Object> receiver_;
Handle<Script> script_;
FunctionLiteral* function_;
bool is_eval_;
int loop_nesting_;
Handle<Object> receiver_;
bool has_this_properties_;
bool has_globals_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
};
......
......@@ -33,8 +33,9 @@ namespace v8 {
namespace internal {
void AstLabeler::Label(FunctionLiteral* fun) {
VisitStatements(fun->body());
void AstLabeler::Label(CompilationInfo* info) {
info_ = info;
VisitStatements(info_->function()->body());
}
......@@ -198,7 +199,7 @@ void AstLabeler::VisitAssignment(Assignment* expr) {
ASSERT(prop->key()->IsPropertyName());
VariableProxy* proxy = prop->obj()->AsVariableProxy();
if (proxy != NULL && proxy->var()->is_this()) {
has_this_properties_ = true;
info()->set_has_this_properties(true);
} else {
Visit(prop->obj());
}
......
......@@ -29,7 +29,7 @@
#define V8_DATAFLOW_H_
#include "ast.h"
#include "scopes.h"
#include "compiler.h"
namespace v8 {
namespace internal {
......@@ -38,13 +38,13 @@ namespace internal {
// their evaluation order (post-order left-to-right traversal).
class AstLabeler: public AstVisitor {
public:
AstLabeler() : next_number_(0), has_this_properties_(false) {}
AstLabeler() : next_number_(0) {}
void Label(FunctionLiteral* fun);
bool has_this_properties() { return has_this_properties_; }
void Label(CompilationInfo* info);
private:
CompilationInfo* info() { return info_; }
void VisitDeclarations(ZoneList<Declaration*>* decls);
void VisitStatements(ZoneList<Statement*>* stmts);
......@@ -56,7 +56,7 @@ class AstLabeler: public AstVisitor {
// Traversal number for labelling AST nodes.
int next_number_;
bool has_this_properties_;
CompilationInfo* info_;
DISALLOW_COPY_AND_ASSIGN(AstLabeler);
};
......
......@@ -51,8 +51,7 @@ namespace internal {
} while (false)
void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun,
CompilationInfo* info) {
void FastCodeGenSyntaxChecker::Check(CompilationInfo* info) {
info_ = info;
// We do not specialize if we do not have a receiver or if it is not a
......@@ -64,7 +63,7 @@ void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun,
// We do not support stack or heap slots (both of which require
// allocation).
Scope* scope = fun->scope();
Scope* scope = info->scope();
if (scope->num_stack_slots() > 0) {
BAILOUT("Function has stack-allocated locals");
}
......@@ -76,8 +75,10 @@ void FastCodeGenSyntaxChecker::Check(FunctionLiteral* fun,
CHECK_BAILOUT;
// We do not support empty function bodies.
if (fun->body()->is_empty()) BAILOUT("Function has an empty body");
VisitStatements(fun->body());
if (info->function()->body()->is_empty()) {
BAILOUT("Function has an empty body");
}
VisitStatements(info->function()->body());
}
......@@ -332,24 +333,20 @@ void FastCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
#define __ ACCESS_MASM(masm())
Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval,
CompilationInfo* info) {
Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
// Label the AST before calling MakeCodePrologue, so AST node numbers are
// printed with the AST.
AstLabeler labeler;
labeler.Label(fun);
info->set_has_this_properties(labeler.has_this_properties());
labeler.Label(info);
CodeGenerator::MakeCodePrologue(fun);
CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
// Generate the fast-path code.
FastCodeGenerator fast_cgen(&masm, script, is_eval);
fast_cgen.Generate(fun, info);
FastCodeGenerator fast_cgen(&masm);
fast_cgen.Generate(info);
if (fast_cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
......@@ -357,16 +354,16 @@ Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
// Generate the full code for the function in bailout mode, using the same
// macro assembler.
CodeGenerator cgen(&masm, script, is_eval);
CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen);
cgen.Generate(fun, CodeGenerator::SECONDARY, info);
cgen.Generate(info, CodeGenerator::SECONDARY);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script);
return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
}
......
......@@ -42,7 +42,7 @@ class FastCodeGenSyntaxChecker: public AstVisitor {
: info_(NULL), has_supported_syntax_(true) {
}
void Check(FunctionLiteral* fun, CompilationInfo* info);
void Check(CompilationInfo* info);
CompilationInfo* info() { return info_; }
bool has_supported_syntax() { return has_supported_syntax_; }
......@@ -65,29 +65,21 @@ class FastCodeGenSyntaxChecker: public AstVisitor {
class FastCodeGenerator: public AstVisitor {
public:
FastCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
: masm_(masm),
script_(script),
is_eval_(is_eval),
function_(NULL),
info_(NULL) {
}
FastCodeGenerator(MacroAssembler* masm) : masm_(masm), info_(NULL) {}
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval,
CompilationInfo* info);
static Handle<Code> MakeCode(CompilationInfo* info);
void Generate(FunctionLiteral* fun, CompilationInfo* info);
void Generate(CompilationInfo* info);
private:
MacroAssembler* masm() { return masm_; }
FunctionLiteral* function() { return function_; }
Label* bailout() { return &bailout_; }
bool has_receiver() { return !info_->receiver().is_null(); }
Handle<Object> receiver() { return info_->receiver(); }
bool has_this_properties() { return info_->has_this_properties(); }
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return info_->scope(); }
// AST node visit functions.
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
......@@ -114,10 +106,7 @@ class FastCodeGenerator: public AstVisitor {
void EmitThisPropertyStore(Handle<String> name);
MacroAssembler* masm_;
Handle<Script> script_;
bool is_eval_;
FunctionLiteral* function_;
CompilationInfo* info_;
Label bailout_;
......
......@@ -439,24 +439,23 @@ void FullCodeGenSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
#define __ ACCESS_MASM(masm())
Handle<Code> FullCodeGenerator::MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval) {
Handle<Code> FullCodeGenerator::MakeCode(CompilationInfo* info) {
Handle<Script> script = info->script();
if (!script->IsUndefined() && !script->source()->IsUndefined()) {
int len = String::cast(script->source())->length();
Counters::total_full_codegen_source_size.Increment(len);
}
CodeGenerator::MakeCodePrologue(fun);
CodeGenerator::MakeCodePrologue(info);
const int kInitialBufferSize = 4 * KB;
MacroAssembler masm(NULL, kInitialBufferSize);
FullCodeGenerator cgen(&masm, script, is_eval);
cgen.Generate(fun, PRIMARY);
FullCodeGenerator cgen(&masm);
cgen.Generate(info, PRIMARY);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, NOT_IN_LOOP);
return CodeGenerator::MakeCodeEpilogue(fun, &masm, flags, script);
return CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
}
......@@ -467,7 +466,7 @@ int FullCodeGenerator::SlotOffset(Slot* slot) {
// Adjust by a (parameter or local) base offset.
switch (slot->type()) {
case Slot::PARAMETER:
offset += (function_->scope()->num_parameters() + 1) * kPointerSize;
offset += (scope()->num_parameters() + 1) * kPointerSize;
break;
case Slot::LOCAL:
offset += JavaScriptFrameConstants::kLocal0Offset;
......@@ -520,7 +519,7 @@ void FullCodeGenerator::VisitDeclarations(
}
} else {
Handle<JSFunction> function =
Compiler::BuildBoilerplate(decl->fun(), script_, this);
Compiler::BuildBoilerplate(decl->fun(), script(), this);
// Check for stack-overflow exception.
if (HasStackOverflow()) return;
array->set(j++, *function);
......
......@@ -68,11 +68,9 @@ class FullCodeGenerator: public AstVisitor {
SECONDARY
};
FullCodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval)
FullCodeGenerator(MacroAssembler* masm)
: masm_(masm),
script_(script),
is_eval_(is_eval),
function_(NULL),
info_(NULL),
nesting_stack_(NULL),
loop_depth_(0),
location_(kStack),
......@@ -80,11 +78,9 @@ class FullCodeGenerator: public AstVisitor {
false_label_(NULL) {
}
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval);
static Handle<Code> MakeCode(CompilationInfo* info);
void Generate(FunctionLiteral* fun, Mode mode);
void Generate(CompilationInfo* info, Mode mode);
private:
class Breakable;
......@@ -408,6 +404,12 @@ class FullCodeGenerator: public AstVisitor {
}
MacroAssembler* masm() { return masm_; }
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return info_->scope(); }
static Register result_register();
static Register context_register();
......@@ -427,10 +429,7 @@ class FullCodeGenerator: public AstVisitor {
void EmitLogicalOperation(BinaryOperation* expr);
MacroAssembler* masm_;
Handle<Script> script_;
bool is_eval_;
FunctionLiteral* function_;
CompilationInfo* info_;
Label return_label_;
NestedStatement* nesting_stack_;
......
......@@ -686,7 +686,7 @@ static bool CompileLazyHelper(CompilationInfo* info,
bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
ClearExceptionFlag flag) {
CompilationInfo info(shared, Handle<Object>::null(), 0);
CompilationInfo info(shared);
return CompileLazyHelper(&info, flag);
}
......@@ -694,8 +694,7 @@ bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
bool CompileLazy(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
Handle<SharedFunctionInfo> shared(function->shared());
CompilationInfo info(shared, receiver, 0);
CompilationInfo info(function, 0, receiver);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
return result;
......@@ -705,8 +704,7 @@ bool CompileLazy(Handle<JSFunction> function,
bool CompileLazyInLoop(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
Handle<SharedFunctionInfo> shared(function->shared());
CompilationInfo info(shared, receiver, 1);
CompilationInfo info(function, 1, receiver);
bool result = CompileLazyHelper(&info, flag);
LOG(FunctionCreateEvent(*function));
return result;
......
This diff is collapsed.
......@@ -305,19 +305,15 @@ class CodeGenerator: public AstVisitor {
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval,
CompilationInfo* info);
static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(FunctionLiteral* fun);
static void MakeCodePrologue(CompilationInfo* info);
// Allocate and install the code.
static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
MacroAssembler* masm,
static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
Handle<Script> script);
CompilationInfo* info);
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
......@@ -328,7 +324,7 @@ class CodeGenerator: public AstVisitor {
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
Handle<Script> script() { return script_; }
inline Handle<Script> script();
bool has_valid_frame() const { return frame_ != NULL; }
......@@ -352,11 +348,11 @@ class CodeGenerator: public AstVisitor {
private:
// Construction/Destruction
CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
CodeGenerator(MacroAssembler* masm);
// Accessors
Scope* scope() const { return scope_; }
bool is_eval() { return is_eval_; }
inline bool is_eval();
Scope* scope();
// Generating deferred code.
void ProcessDeferred();
......@@ -388,7 +384,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
void Generate(CompilationInfo* info, Mode mode);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
......@@ -396,7 +392,7 @@ class CodeGenerator: public AstVisitor {
void GenerateReturnSequence(Result* return_value);
// Returns the arguments allocation mode.
ArgumentsAllocationMode ArgumentsMode() const;
ArgumentsAllocationMode ArgumentsMode();
// Store the arguments object and allocate it if necessary.
Result StoreArgumentsObject(bool initial);
......@@ -607,15 +603,14 @@ class CodeGenerator: public AstVisitor {
bool HasValidEntryRegisters();
#endif
bool is_eval_; // Tells whether code is generated for eval.
Handle<Script> script_;
ZoneList<DeferredCode*> deferred_;
// Assembler
MacroAssembler* masm_; // to generate code
CompilationInfo* info_;
// Code generation state
Scope* scope_;
VirtualFrame* frame_;
RegisterAllocator* allocator_;
CodeGenState* state_;
......
......@@ -103,10 +103,8 @@ void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
}
void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
ASSERT(function_ == NULL);
void FastCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
function_ = fun;
info_ = info;
// Save the caller's frame pointer and set up our own.
......@@ -121,7 +119,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
// Receiver (this) is allocated to edx if there are this properties.
if (has_this_properties()) EmitReceiverMapCheck();
VisitStatements(fun->body());
VisitStatements(function()->body());
Comment return_cmnt(masm(), ";; Return(<undefined>)");
__ mov(eax, Factory::undefined_value());
......@@ -129,7 +127,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
Comment epilogue_cmnt(masm(), ";; Epilogue");
__ mov(esp, ebp);
__ pop(ebp);
__ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
__ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
}
......
......@@ -51,9 +51,10 @@ namespace internal {
//
// The function builds a JS frame. Please see JavaScriptFrameConstants in
// frames-ia32.h for its layout.
void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
function_ = fun;
SetFunctionPosition(fun);
void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
ASSERT(info_ == NULL);
info_ = info;
SetFunctionPosition(function());
if (mode == PRIMARY) {
__ push(ebp); // Caller's frame pointer.
......@@ -62,7 +63,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ push(edi); // Callee's JS Function.
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = fun->scope()->num_stack_slots();
int locals_count = scope()->num_stack_slots();
if (locals_count == 1) {
__ push(Immediate(Factory::undefined_value()));
} else if (locals_count > 1) {
......@@ -76,7 +77,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
bool function_in_register = true;
// Possibly allocate a local context.
if (fun->scope()->num_heap_slots() > 0) {
if (scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is still in edi.
__ push(edi);
......@@ -87,9 +88,9 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
// Copy parameters into context if necessary.
int num_parameters = fun->scope()->num_parameters();
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
Slot* slot = fun->scope()->parameter(i)->slot();
Slot* slot = scope()->parameter(i)->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
......@@ -107,7 +108,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
}
}
Variable* arguments = fun->scope()->arguments()->AsVariable();
Variable* arguments = scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Function uses arguments object.
Comment cmnt(masm_, "[ Allocate arguments object");
......@@ -117,10 +118,11 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
// Receiver is just before the parameters on the caller's stack.
__ lea(edx, Operand(ebp, StandardFrameConstants::kCallerSPOffset +
fun->num_parameters() * kPointerSize));
int offset = scope()->num_parameters() * kPointerSize;
__ lea(edx,
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx);
__ push(Immediate(Smi::FromInt(fun->num_parameters())));
__ push(Immediate(Smi::FromInt(scope()->num_parameters())));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
......@@ -130,13 +132,13 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ mov(ecx, eax); // Duplicate result.
Move(arguments->slot(), eax, ebx, edx);
Slot* dot_arguments_slot =
fun->scope()->arguments_shadow()->AsVariable()->slot();
scope()->arguments_shadow()->AsVariable()->slot();
Move(dot_arguments_slot, ecx, ebx, edx);
}
}
{ Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(fun->scope()->declarations());
VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
......@@ -156,14 +158,14 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
{ Comment cmnt(masm_, "[ Body");
ASSERT(loop_depth() == 0);
VisitStatements(fun->body());
VisitStatements(function()->body());
ASSERT(loop_depth() == 0);
}
{ Comment cmnt(masm_, "[ return <undefined>;");
// Emit a 'return undefined' in case control fell off the end of the body.
__ mov(eax, Factory::undefined_value());
EmitReturnSequence(function_->end_position());
EmitReturnSequence(function()->end_position());
}
}
......@@ -190,7 +192,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
// patch with the code required by the debugger.
__ mov(esp, ebp);
__ pop(ebp);
__ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
__ ret((scope()->num_parameters() + 1) * kPointerSize);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Check that the size of the code used for returning matches what is
// expected by the debugger.
......@@ -627,7 +629,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
return Operand(ebp, SlotOffset(slot));
case Slot::CONTEXT: {
int context_chain_length =
function_->scope()->ContextChainLength(slot->var()->scope());
scope()->ContextChainLength(slot->var()->scope());
__ LoadContext(scratch, context_chain_length);
return CodeGenerator::ContextOperand(scratch, slot->index());
}
......@@ -686,7 +688,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
// this specific context.
// The variable in the decl always resides in the current context.
ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ mov(ebx,
......@@ -764,7 +766,7 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(esi); // The context is the first argument.
__ push(Immediate(pairs));
__ push(Immediate(Smi::FromInt(is_eval_ ? 1 : 0)));
__ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
......@@ -775,7 +777,7 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(expr, script_, this);
Compiler::BuildBoilerplate(expr, script(), this);
if (HasStackOverflow()) return;
ASSERT(boilerplate->IsBoilerplate());
......
This diff is collapsed.
......@@ -305,19 +305,15 @@ class CodeGenerator: public AstVisitor {
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
Handle<Script> script,
bool is_eval,
CompilationInfo* info);
static Handle<Code> MakeCode(CompilationInfo* info);
// Printing of AST, etc. as requested by flags.
static void MakeCodePrologue(FunctionLiteral* fun);
static void MakeCodePrologue(CompilationInfo* info);
// Allocate and install the code.
static Handle<Code> MakeCodeEpilogue(FunctionLiteral* fun,
MacroAssembler* masm,
static Handle<Code> MakeCodeEpilogue(MacroAssembler* masm,
Code::Flags flags,
Handle<Script> script);
CompilationInfo* info);
#ifdef ENABLE_LOGGING_AND_PROFILING
static bool ShouldGenerateLog(Expression* type);
......@@ -328,7 +324,7 @@ class CodeGenerator: public AstVisitor {
// Accessors
MacroAssembler* masm() { return masm_; }
VirtualFrame* frame() const { return frame_; }
Handle<Script> script() { return script_; }
inline Handle<Script> script();
bool has_valid_frame() const { return frame_ != NULL; }
......@@ -352,16 +348,15 @@ class CodeGenerator: public AstVisitor {
private:
// Construction/Destruction
CodeGenerator(MacroAssembler* masm, Handle<Script> script, bool is_eval);
CodeGenerator(MacroAssembler* masm);
// Accessors
Scope* scope() const { return scope_; }
inline bool is_eval();
Scope* scope();
// Generating deferred code.
void ProcessDeferred();
bool is_eval() { return is_eval_; }
// State
ControlDestination* destination() const { return state_->destination(); }
......@@ -390,7 +385,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
void Generate(CompilationInfo* info, Mode mode);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
......@@ -398,7 +393,7 @@ class CodeGenerator: public AstVisitor {
void GenerateReturnSequence(Result* return_value);
// Returns the arguments allocation mode.
ArgumentsAllocationMode ArgumentsMode() const;
ArgumentsAllocationMode ArgumentsMode();
// Store the arguments object and allocate it if necessary.
Result StoreArgumentsObject(bool initial);
......@@ -604,15 +599,14 @@ class CodeGenerator: public AstVisitor {
bool HasValidEntryRegisters();
#endif
bool is_eval_; // Tells whether code is generated for eval.
Handle<Script> script_;
ZoneList<DeferredCode*> deferred_;
// Assembler
MacroAssembler* masm_; // to generate code
CompilationInfo* info_;
// Code generation state
Scope* scope_;
VirtualFrame* frame_;
RegisterAllocator* allocator_;
CodeGenState* state_;
......
......@@ -37,7 +37,7 @@ namespace internal {
void FastCodeGenerator::EmitLoadReceiver(Register reg) {
// Offset 2 is due to return address and saved frame pointer.
int index = 2 + function()->scope()->num_parameters();
int index = 2 + scope()->num_parameters();
__ movq(reg, Operand(rbp, index * kPointerSize));
}
......@@ -102,10 +102,8 @@ void FastCodeGenerator::EmitThisPropertyStore(Handle<String> name) {
}
void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
ASSERT(function_ == NULL);
void FastCodeGenerator::Generate(CompilationInfo* info) {
ASSERT(info_ == NULL);
function_ = fun;
info_ = info;
// Save the caller's frame pointer and set up our own.
......@@ -120,7 +118,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
// Receiver (this) is allocated to rdx if there are this properties.
if (has_this_properties()) EmitReceiverMapCheck();
VisitStatements(fun->body());
VisitStatements(info->function()->body());
Comment return_cmnt(masm(), ";; Return(<undefined>)");
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
......@@ -128,7 +126,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
Comment epilogue_cmnt(masm(), ";; Epilogue");
__ movq(rsp, rbp);
__ pop(rbp);
__ ret((fun->scope()->num_parameters() + 1) * kPointerSize);
__ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
}
......
......@@ -51,9 +51,10 @@ namespace internal {
//
// The function builds a JS frame. Please see JavaScriptFrameConstants in
// frames-x64.h for its layout.
void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
function_ = fun;
SetFunctionPosition(fun);
void FullCodeGenerator::Generate(CompilationInfo* info, Mode mode) {
ASSERT(info_ == NULL);
info_ = info;
SetFunctionPosition(function());
if (mode == PRIMARY) {
__ push(rbp); // Caller's frame pointer.
......@@ -62,7 +63,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ push(rdi); // Callee's JS Function.
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = fun->scope()->num_stack_slots();
int locals_count = scope()->num_stack_slots();
if (locals_count == 1) {
__ PushRoot(Heap::kUndefinedValueRootIndex);
} else if (locals_count > 1) {
......@@ -76,7 +77,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
bool function_in_register = true;
// Possibly allocate a local context.
if (fun->scope()->num_heap_slots() > 0) {
if (scope()->num_heap_slots() > 0) {
Comment cmnt(masm_, "[ Allocate local context");
// Argument to NewContext is the function, which is still in rdi.
__ push(rdi);
......@@ -87,9 +88,9 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ movq(Operand(rbp, StandardFrameConstants::kContextOffset), rsi);
// Copy any necessary parameters into the context.
int num_parameters = fun->scope()->num_parameters();
int num_parameters = scope()->num_parameters();
for (int i = 0; i < num_parameters; i++) {
Slot* slot = fun->scope()->parameter(i)->slot();
Slot* slot = scope()->parameter(i)->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
int parameter_offset = StandardFrameConstants::kCallerSPOffset +
(num_parameters - 1 - i) * kPointerSize;
......@@ -108,7 +109,7 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
}
// Possibly allocate an arguments object.
Variable* arguments = fun->scope()->arguments()->AsVariable();
Variable* arguments = scope()->arguments()->AsVariable();
if (arguments != NULL) {
// Arguments object must be allocated after the context object, in
// case the "arguments" or ".arguments" variables are in the context.
......@@ -119,10 +120,11 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
}
// The receiver is just before the parameters on the caller's stack.
__ lea(rdx, Operand(rbp, StandardFrameConstants::kCallerSPOffset +
fun->num_parameters() * kPointerSize));
int offset = scope()->num_parameters() * kPointerSize;
__ lea(rdx,
Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(rdx);
__ Push(Smi::FromInt(fun->num_parameters()));
__ Push(Smi::FromInt(scope()->num_parameters()));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
......@@ -133,13 +135,13 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
__ movq(rcx, rax);
Move(arguments->slot(), rax, rbx, rdx);
Slot* dot_arguments_slot =
fun->scope()->arguments_shadow()->AsVariable()->slot();
scope()->arguments_shadow()->AsVariable()->slot();
Move(dot_arguments_slot, rcx, rbx, rdx);
}
}
{ Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(fun->scope()->declarations());
VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Stack check");
......@@ -157,14 +159,14 @@ void FullCodeGenerator::Generate(FunctionLiteral* fun, Mode mode) {
{ Comment cmnt(masm_, "[ Body");
ASSERT(loop_depth() == 0);
VisitStatements(fun->body());
VisitStatements(function()->body());
ASSERT(loop_depth() == 0);
}
{ Comment cmnt(masm_, "[ return <undefined>;");
// Emit a 'return undefined' in case control fell off the end of the body.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
EmitReturnSequence(function_->end_position());
EmitReturnSequence(function()->end_position());
}
}
......@@ -190,7 +192,7 @@ void FullCodeGenerator::EmitReturnSequence(int position) {
// patch with the code required by the debugger.
__ movq(rsp, rbp);
__ pop(rbp);
__ ret((function_->scope()->num_parameters() + 1) * kPointerSize);
__ ret((scope()->num_parameters() + 1) * kPointerSize);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Add padding that will be overwritten by a debugger breakpoint. We
// have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
......@@ -629,7 +631,7 @@ MemOperand FullCodeGenerator::EmitSlotSearch(Slot* slot, Register scratch) {
return Operand(rbp, SlotOffset(slot));
case Slot::CONTEXT: {
int context_chain_length =
function_->scope()->ContextChainLength(slot->var()->scope());
scope()->ContextChainLength(slot->var()->scope());
__ LoadContext(scratch, context_chain_length);
return CodeGenerator::ContextOperand(scratch, slot->index());
}
......@@ -688,7 +690,7 @@ void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
// this specific context.
// The variable in the decl always resides in the current context.
ASSERT_EQ(0, function_->scope()->ContextChainLength(var->scope()));
ASSERT_EQ(0, scope()->ContextChainLength(var->scope()));
if (FLAG_debug_code) {
// Check if we have the correct context pointer.
__ movq(rbx,
......@@ -767,7 +769,7 @@ void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals.
__ push(rsi); // The context is the first argument.
__ Push(pairs);
__ Push(Smi::FromInt(is_eval_ ? 1 : 0));
__ Push(Smi::FromInt(is_eval() ? 1 : 0));
__ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
......@@ -778,7 +780,7 @@ void FullCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
// Build the function boilerplate and instantiate it.
Handle<JSFunction> boilerplate =
Compiler::BuildBoilerplate(expr, script_, this);
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