Commit dc49c566 authored by ager@chromium.org's avatar ager@chromium.org

Use the virtual-frame based optimizing compiler for split-compilation

bailouts.  For now the virtual-frame state at entry of a function is
hard-coded when using the virtual-frame based compiler as the
secondary compiler.

Setup frame pointer correctly on function entry on ARM in
fast-codegen-arm.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3776 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 0045327b
......@@ -143,7 +143,9 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm,
// r1: called JS function
// cp: callee's context
void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
void CodeGenerator::Generate(FunctionLiteral* fun,
Mode mode,
CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(fun);
......@@ -169,8 +171,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
// r1: called JS function
// cp: callee's context
allocator_->Initialize();
frame_->Enter();
// tos: code slot
#ifdef DEBUG
if (strlen(FLAG_stop_at) > 0 &&
fun->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
......@@ -179,13 +180,13 @@ void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
}
#endif
if (mode == PRIMARY) {
frame_->Enter();
// tos: code slot
// Allocate space for locals and initialize them. This also checks
// for stack overflow.
frame_->AllocateStackSlots();
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
VirtualFrame::SpilledScope spilled_scope;
int heap_slots = scope_->num_heap_slots();
......@@ -231,7 +232,8 @@ void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
Variable* par = scope_->parameter(i);
Slot* slot = par->slot();
if (slot != NULL && slot->type() == Slot::CONTEXT) {
ASSERT(!scope_->is_global_scope()); // no parameters in global scope
// No parameters in global scope.
ASSERT(!scope_->is_global_scope());
__ ldr(r1, frame_->ParameterAt(i));
// Loads r2 with context; used below in RecordWrite.
__ str(r1, SlotOperand(slot, r2));
......@@ -276,6 +278,19 @@ void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
frame_->EmitPush(ip);
StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, r1, cp,
// fp, and lr have been pushed on the stack. Adjust the virtual
// frame to match this state.
frame_->Adjust(4);
allocator_->Unuse(r1);
allocator_->Unuse(lr);
}
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
......
......@@ -150,6 +150,15 @@ class CodeGenState BASE_EMBEDDED {
class CodeGenerator: public AstVisitor {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
......@@ -240,7 +249,7 @@ class CodeGenerator: public AstVisitor {
inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void GenCode(FunctionLiteral* fun, CompilationInfo* info);
void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
// The following are used by class Reference.
void LoadReference(Reference* ref);
......
......@@ -111,6 +111,7 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun, CompilationInfo* info) {
// Save the caller's frame pointer and set up our own.
Comment prologue_cmnt(masm(), ";; Prologue");
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
__ add(fp, sp, Operand(2 * kPointerSize));
// Note that we keep a live register reference to cp (context) at
// this point.
......
......@@ -228,7 +228,7 @@ Handle<Code> CodeGenerator::MakeCode(FunctionLiteral* fun,
MacroAssembler masm(NULL, kInitialBufferSize);
CodeGenerator cgen(&masm, script, is_eval);
CodeGeneratorScope scope(&cgen);
cgen.GenCode(fun, info);
cgen.Generate(fun, PRIMARY, info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
......
......@@ -55,7 +55,7 @@
// CodeGenerator
// ~CodeGenerator
// ProcessDeferred
// GenCode
// Generate
// ComputeLazyCompile
// BuildBoilerplate
// ComputeCallInitialize
......
......@@ -30,7 +30,6 @@
#include "codegen-inl.h"
#include "data-flow.h"
#include "fast-codegen.h"
#include "full-codegen.h"
#include "scopes.h"
namespace v8 {
......@@ -358,9 +357,10 @@ Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
// Generate the full code for the function in bailout mode, using the same
// macro assembler.
FullCodeGenerator full_cgen(&masm, script, is_eval);
full_cgen.Generate(fun, FullCodeGenerator::SECONDARY);
if (full_cgen.HasStackOverflow()) {
CodeGenerator cgen(&masm, script, is_eval);
CodeGeneratorScope scope(&cgen);
cgen.Generate(fun, CodeGenerator::SECONDARY, info);
if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception());
return Handle<Code>::null();
}
......
......@@ -126,7 +126,9 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm,
// edi: called JS function
// esi: callee's context
void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
void CodeGenerator::Generate(FunctionLiteral* fun,
Mode mode,
CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(fun);
......@@ -167,14 +169,12 @@ void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
// edi: called JS function
// esi: callee's context
allocator_->Initialize();
if (mode == PRIMARY) {
frame_->Enter();
// Allocate space for locals and initialize them.
frame_->AllocateStackSlots();
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
// Allocate the local context if needed.
int heap_slots = scope_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
......@@ -256,6 +256,18 @@ void CodeGenerator::GenCode(FunctionLiteral* fun, CompilationInfo* info) {
frame_->Push(Factory::the_hole_value());
StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, ebp, esi,
// and edi have been pushed on the stack. Adjust the virtual
// frame to match this state.
frame_->Adjust(3);
allocator_->Unuse(edi);
}
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
......
......@@ -294,6 +294,15 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
......@@ -379,7 +388,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void GenCode(FunctionLiteral* fun, CompilationInfo* info);
void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
......
......@@ -278,7 +278,9 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
}
void CodeGenerator::GenCode(FunctionLiteral* function, CompilationInfo* info) {
void CodeGenerator::Generate(FunctionLiteral* function,
Mode mode,
CompilationInfo* info) {
// Record the position for debugging purposes.
CodeForFunctionPosition(function);
ZoneList<Statement*>* body = function->body();
......@@ -318,14 +320,12 @@ void CodeGenerator::GenCode(FunctionLiteral* function, CompilationInfo* info) {
// rdi: called JS function
// rsi: callee's context
allocator_->Initialize();
if (mode == PRIMARY) {
frame_->Enter();
// Allocate space for locals and initialize them.
frame_->AllocateStackSlots();
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
// Allocate the local context if needed.
int heap_slots = scope_->num_heap_slots();
......@@ -407,6 +407,18 @@ void CodeGenerator::GenCode(FunctionLiteral* function, CompilationInfo* info) {
frame_->Push(Factory::the_hole_value());
StoreToSlot(scope_->function()->slot(), NOT_CONST_INIT);
}
} else {
// When used as the secondary compiler for splitting, rbp, rsi,
// and rdi have been pushed on the stack. Adjust the virtual
// frame to match this state.
frame_->Adjust(3);
allocator_->Unuse(rdi);
}
// Initialize the function return target after the locals are set
// up, because it needs the expected frame height from the frame.
function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
function_return_is_shadowed_ = false;
// Generate code to 'execute' declarations and initialize functions
// (source elements). In case of an illegal redeclaration we need to
......
......@@ -294,6 +294,15 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor {
public:
// Compilation mode. Either the compiler is used as the primary
// compiler and needs to setup everything or the compiler is used as
// the secondary compiler for split compilation and has to handle
// bailouts.
enum Mode {
PRIMARY,
SECONDARY
};
// Takes a function literal, generates code for it. This function should only
// be called by compiler.cc.
static Handle<Code> MakeCode(FunctionLiteral* fun,
......@@ -381,7 +390,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function
void GenCode(FunctionLiteral* fun, CompilationInfo* info);
void Generate(FunctionLiteral* fun, Mode mode, CompilationInfo* info);
// Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return
......
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