Begin using a list of bailouts instead of a singleton in the fast code generator.

A list of bailout descriptions is kept in the CompilationInfo
structure that is shared between the primary and secondary code
generators.  The primary adds a description to the list for each
bailout position.

Responsibility for binding labels is moved from the primary to the
secondary code generator. All the labels still target the start of the
secondary code and the compilation state of the primary is still
ignored.

Move the compilation mode flag to the CompilationInfo.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3920 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a47746d2
...@@ -142,7 +142,7 @@ Scope* CodeGenerator::scope() { return info_->function()->scope(); } ...@@ -142,7 +142,7 @@ Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// r1: called JS function // r1: called JS function
// cp: callee's context // cp: callee's context
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { void CodeGenerator::Generate(CompilationInfo* info) {
// Record the position for debugging purposes. // Record the position for debugging purposes.
CodeForFunctionPosition(info->function()); CodeForFunctionPosition(info->function());
...@@ -174,7 +174,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { ...@@ -174,7 +174,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
} }
#endif #endif
if (mode == PRIMARY) { if (info->mode() == CompilationInfo::PRIMARY) {
frame_->Enter(); frame_->Enter();
// tos: code slot // tos: code slot
...@@ -277,6 +277,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { ...@@ -277,6 +277,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
frame_->Adjust(4); frame_->Adjust(4);
allocator_->Unuse(r1); allocator_->Unuse(r1);
allocator_->Unuse(lr); allocator_->Unuse(lr);
// Bind all the bailout labels to the beginning of the function.
List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
for (int i = 0; i < bailouts->length(); i++) {
__ bind(bailouts->at(i)->label());
}
} }
// Initialize the function return target after the locals are set // Initialize the function return target after the locals are set
......
...@@ -150,15 +150,6 @@ class CodeGenState BASE_EMBEDDED { ...@@ -150,15 +150,6 @@ class CodeGenState BASE_EMBEDDED {
class CodeGenerator: public AstVisitor { class CodeGenerator: public AstVisitor {
public: 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 // Takes a function literal, generates code for it. This function should only
// be called by compiler.cc. // be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info); static Handle<Code> MakeCode(CompilationInfo* info);
...@@ -244,7 +235,7 @@ class CodeGenerator: public AstVisitor { ...@@ -244,7 +235,7 @@ class CodeGenerator: public AstVisitor {
inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements); inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function // Main code generation function
void Generate(CompilationInfo* info, Mode mode); void Generate(CompilationInfo* info);
// The following are used by class Reference. // The following are used by class Reference.
void LoadReference(Reference* ref); void LoadReference(Reference* ref);
......
...@@ -148,17 +148,25 @@ void FastCodeGenerator::EmitBitOr() { ...@@ -148,17 +148,25 @@ void FastCodeGenerator::EmitBitOr() {
if (!destination().is(no_reg)) { if (!destination().is(no_reg)) {
__ orr(destination(), accumulator1(), Operand(accumulator0())); __ orr(destination(), accumulator1(), Operand(accumulator0()));
} }
} else if (destination().is(no_reg)) {
// Result is not needed but do not clobber the operands in case of
// bailout.
__ orr(scratch0(), accumulator1(), Operand(accumulator0()));
__ BranchOnNotSmi(scratch0(), bailout());
} else { } else {
// Preserve the destination operand in a scratch register in case of // Left is in accumulator1, right in accumulator0.
// bailout. if (destination().is(accumulator0())) {
__ mov(scratch0(), destination()); __ mov(scratch0(), accumulator0());
__ orr(destination(), accumulator1(), Operand(accumulator1()));
Label* bailout =
info()->AddBailout(accumulator1(), scratch0()); // Left, right.
__ BranchOnNotSmi(destination(), bailout);
} else if (destination().is(accumulator1())) {
__ mov(scratch0(), accumulator1());
__ orr(destination(), accumulator1(), Operand(accumulator0())); __ orr(destination(), accumulator1(), Operand(accumulator0()));
__ BranchOnNotSmi(destination(), bailout()); Label* bailout = info()->AddBailout(scratch0(), accumulator0());
__ BranchOnNotSmi(destination(), bailout);
} else {
ASSERT(destination().is(no_reg));
__ orr(scratch0(), accumulator1(), Operand(accumulator0()));
Label* bailout = info()->AddBailout(accumulator1(), accumulator0());
__ BranchOnNotSmi(scratch0(), bailout);
}
} }
// If we didn't bailout, the result (in fact, both inputs too) is known to // If we didn't bailout, the result (in fact, both inputs too) is known to
...@@ -179,6 +187,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -179,6 +187,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
// Note that we keep a live register reference to cp (context) at // Note that we keep a live register reference to cp (context) at
// this point. // this point.
Label* bailout_to_beginning = info()->AddBailout();
// Receiver (this) is allocated to a fixed register. // Receiver (this) is allocated to a fixed register.
if (info()->has_this_properties()) { if (info()->has_this_properties()) {
Comment cmnt(masm(), ";; MapCheck(this)"); Comment cmnt(masm(), ";; MapCheck(this)");
...@@ -189,7 +198,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -189,7 +198,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
Handle<Map> map(object->map()); Handle<Map> map(object->map());
EmitLoadReceiver(); EmitLoadReceiver();
__ CheckMap(receiver_reg(), scratch0(), map, bailout(), false); __ CheckMap(receiver_reg(), scratch0(), map, bailout_to_beginning, false);
} }
// If there is a global variable access check if the global object is the // If there is a global variable access check if the global object is the
...@@ -202,7 +211,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -202,7 +211,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
ASSERT(info()->has_global_object()); ASSERT(info()->has_global_object());
Handle<Map> map(info()->global_object()->map()); Handle<Map> map(info()->global_object()->map());
__ ldr(scratch0(), CodeGenerator::GlobalObject()); __ ldr(scratch0(), CodeGenerator::GlobalObject());
__ CheckMap(scratch0(), scratch1(), map, bailout(), true); __ CheckMap(scratch0(), scratch1(), map, bailout_to_beginning, true);
} }
VisitStatements(function()->body()); VisitStatements(function()->body());
...@@ -217,8 +226,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -217,8 +226,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize; int32_t sp_delta = (scope()->num_parameters() + 1) * kPointerSize;
__ add(sp, sp, Operand(sp_delta)); __ add(sp, sp, Operand(sp_delta));
__ Jump(lr); __ Jump(lr);
__ bind(&bailout_);
} }
......
...@@ -248,7 +248,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -248,7 +248,7 @@ Handle<Code> CodeGenerator::MakeCode(CompilationInfo* info) {
CodeGenerator cgen(&masm); CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen); CodeGeneratorScope scope(&cgen);
live_edit_tracker.RecordFunctionScope(info->function()->scope()); live_edit_tracker.RecordFunctionScope(info->function()->scope());
cgen.Generate(info, PRIMARY); cgen.Generate(info);
if (cgen.HasStackOverflow()) { if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception()); ASSERT(!Top::has_pending_exception());
return Handle<Code>::null(); return Handle<Code>::null();
......
...@@ -41,6 +41,37 @@ namespace internal { ...@@ -41,6 +41,37 @@ namespace internal {
// is constructed based on the resources available at compile-time. // is constructed based on the resources available at compile-time.
class CompilationInfo BASE_EMBEDDED { class CompilationInfo BASE_EMBEDDED {
public: 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
};
// A description of the compilation state at a bailout to the secondary
// code generator.
//
// The state is currently simple: there are no parameters or local
// variables to worry about ('this' can be found in the stack frame).
// There are at most two live values.
//
// There is a label that should be bound to the beginning of the bailout
// stub code.
class Bailout : public ZoneObject {
public:
Bailout(Register left, Register right) : left_(left), right_(right) {}
Label* label() { return &label_; }
private:
Register left_;
Register right_;
Label label_;
};
// Lazy compilation of a JSFunction. // Lazy compilation of a JSFunction.
CompilationInfo(Handle<JSFunction> closure, CompilationInfo(Handle<JSFunction> closure,
int loop_nesting, int loop_nesting,
...@@ -117,9 +148,13 @@ class CompilationInfo BASE_EMBEDDED { ...@@ -117,9 +148,13 @@ class CompilationInfo BASE_EMBEDDED {
int loop_nesting() { return loop_nesting_; } int loop_nesting() { return loop_nesting_; }
bool has_receiver() { return !receiver_.is_null(); } bool has_receiver() { return !receiver_.is_null(); }
Handle<Object> receiver() { return receiver_; } Handle<Object> receiver() { return receiver_; }
List<Bailout*>* bailouts() { return &bailouts_; }
// Accessors for mutable fields, possibly set by analysis passes with // Accessors for mutable fields (possibly set by analysis passes) with
// default values given by Initialize. // default values given by Initialize.
Mode mode() { return mode_; }
void set_mode(Mode mode) { mode_ = mode; }
bool has_this_properties() { return has_this_properties_; } bool has_this_properties() { return has_this_properties_; }
void set_has_this_properties(bool flag) { has_this_properties_ = flag; } void set_has_this_properties(bool flag) { has_this_properties_ = flag; }
...@@ -137,8 +172,19 @@ class CompilationInfo BASE_EMBEDDED { ...@@ -137,8 +172,19 @@ class CompilationInfo BASE_EMBEDDED {
// Derived accessors. // Derived accessors.
Scope* scope() { return function()->scope(); } Scope* scope() { return function()->scope(); }
// Add a bailout with two live values.
Label* AddBailout(Register left, Register right) {
Bailout* bailout = new Bailout(left, right);
bailouts_.Add(bailout);
return bailout->label();
}
// Add a bailout with no live values.
Label* AddBailout() { return AddBailout(no_reg, no_reg); }
private: private:
void Initialize() { void Initialize() {
mode_ = PRIMARY;
has_this_properties_ = false; has_this_properties_ = false;
has_globals_ = false; has_globals_ = false;
} }
...@@ -148,6 +194,7 @@ class CompilationInfo BASE_EMBEDDED { ...@@ -148,6 +194,7 @@ class CompilationInfo BASE_EMBEDDED {
Handle<Script> script_; Handle<Script> script_;
FunctionLiteral* function_; FunctionLiteral* function_;
Mode mode_;
bool is_eval_; bool is_eval_;
int loop_nesting_; int loop_nesting_;
...@@ -157,6 +204,10 @@ class CompilationInfo BASE_EMBEDDED { ...@@ -157,6 +204,10 @@ class CompilationInfo BASE_EMBEDDED {
bool has_this_properties_; bool has_this_properties_;
bool has_globals_; bool has_globals_;
// An ordered list of bailout points encountered during fast-path
// compilation.
List<Bailout*> bailouts_;
DISALLOW_COPY_AND_ASSIGN(CompilationInfo); DISALLOW_COPY_AND_ASSIGN(CompilationInfo);
}; };
......
...@@ -456,7 +456,8 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -456,7 +456,8 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
// macro assembler. // macro assembler.
CodeGenerator cgen(&masm); CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen); CodeGeneratorScope scope(&cgen);
cgen.Generate(info, CodeGenerator::SECONDARY); info->set_mode(CompilationInfo::SECONDARY);
cgen.Generate(info);
if (cgen.HasStackOverflow()) { if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception()); ASSERT(!Top::has_pending_exception());
return Handle<Code>::null(); return Handle<Code>::null();
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "ast.h" #include "ast.h"
#include "compiler.h" #include "compiler.h"
#include "list.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -80,7 +81,6 @@ class FastCodeGenerator: public AstVisitor { ...@@ -80,7 +81,6 @@ class FastCodeGenerator: public AstVisitor {
private: private:
MacroAssembler* masm() { return masm_; } MacroAssembler* masm() { return masm_; }
CompilationInfo* info() { return info_; } CompilationInfo* info() { return info_; }
Label* bailout() { return &bailout_; }
Register destination() { return destination_; } Register destination() { return destination_; }
void set_destination(Register reg) { destination_ = reg; } void set_destination(Register reg) { destination_ = reg; }
...@@ -146,7 +146,6 @@ class FastCodeGenerator: public AstVisitor { ...@@ -146,7 +146,6 @@ class FastCodeGenerator: public AstVisitor {
MacroAssembler* masm_; MacroAssembler* masm_;
CompilationInfo* info_; CompilationInfo* info_;
Label bailout_;
Register destination_; Register destination_;
uint32_t smi_bits_; uint32_t smi_bits_;
......
...@@ -125,7 +125,7 @@ Scope* CodeGenerator::scope() { return info_->function()->scope(); } ...@@ -125,7 +125,7 @@ Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// edi: called JS function // edi: called JS function
// esi: callee's context // esi: callee's context
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { void CodeGenerator::Generate(CompilationInfo* info) {
// Record the position for debugging purposes. // Record the position for debugging purposes.
CodeForFunctionPosition(info->function()); CodeForFunctionPosition(info->function());
...@@ -164,7 +164,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { ...@@ -164,7 +164,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// esi: callee's context // esi: callee's context
allocator_->Initialize(); allocator_->Initialize();
if (mode == PRIMARY) { if (info->mode() == CompilationInfo::PRIMARY) {
frame_->Enter(); frame_->Enter();
// Allocate space for locals and initialize them. // Allocate space for locals and initialize them.
...@@ -255,6 +255,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { ...@@ -255,6 +255,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// frame to match this state. // frame to match this state.
frame_->Adjust(3); frame_->Adjust(3);
allocator_->Unuse(edi); allocator_->Unuse(edi);
// Bind all the bailout labels to the beginning of the function.
List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
for (int i = 0; i < bailouts->length(); i++) {
__ bind(bailouts->at(i)->label());
}
} }
// Initialize the function return target after the locals are set // Initialize the function return target after the locals are set
......
...@@ -294,15 +294,6 @@ enum ArgumentsAllocationMode { ...@@ -294,15 +294,6 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor { class CodeGenerator: public AstVisitor {
public: 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 // Takes a function literal, generates code for it. This function should only
// be called by compiler.cc. // be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info); static Handle<Code> MakeCode(CompilationInfo* info);
...@@ -384,7 +375,7 @@ class CodeGenerator: public AstVisitor { ...@@ -384,7 +375,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements); void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function // Main code generation function
void Generate(CompilationInfo* info, Mode mode); void Generate(CompilationInfo* info);
// Generate the return sequence code. Should be called no more than // Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return // once per compiled function, immediately after binding the return
......
...@@ -456,7 +456,8 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -456,7 +456,8 @@ Handle<Code> FastCodeGenerator::MakeCode(CompilationInfo* info) {
// macro assembler. // macro assembler.
CodeGenerator cgen(&masm); CodeGenerator cgen(&masm);
CodeGeneratorScope scope(&cgen); CodeGeneratorScope scope(&cgen);
cgen.Generate(info, CodeGenerator::SECONDARY); info->set_mode(CompilationInfo::SECONDARY);
cgen.Generate(info);
if (cgen.HasStackOverflow()) { if (cgen.HasStackOverflow()) {
ASSERT(!Top::has_pending_exception()); ASSERT(!Top::has_pending_exception());
return Handle<Code>::null(); return Handle<Code>::null();
...@@ -587,20 +588,27 @@ void FastCodeGenerator::EmitBitOr() { ...@@ -587,20 +588,27 @@ void FastCodeGenerator::EmitBitOr() {
// commutative. // commutative.
__ or_(destination(), Operand(other_accumulator(destination()))); __ or_(destination(), Operand(other_accumulator(destination())));
} }
} else if (destination().is(no_reg)) { } else {
// Result is not needed but do not clobber the operands in case of // Left is in accumulator1, right in accumulator0.
// bailout. Label* bailout = NULL;
if (destination().is(accumulator0())) {
__ mov(scratch0(), accumulator0());
__ or_(destination(), Operand(accumulator1())); // Or is commutative.
__ test(destination(), Immediate(kSmiTagMask));
bailout = info()->AddBailout(accumulator1(), scratch0()); // Left, right.
} else if (destination().is(accumulator1())) {
__ mov(scratch0(), accumulator1());
__ or_(destination(), Operand(accumulator0()));
__ test(destination(), Immediate(kSmiTagMask));
bailout = info()->AddBailout(scratch0(), accumulator0());
} else {
ASSERT(destination().is(no_reg));
__ mov(scratch0(), accumulator1()); __ mov(scratch0(), accumulator1());
__ or_(scratch0(), Operand(accumulator0())); __ or_(scratch0(), Operand(accumulator0()));
__ test(scratch0(), Immediate(kSmiTagMask)); __ test(scratch0(), Immediate(kSmiTagMask));
__ j(not_zero, bailout(), not_taken); bailout = info()->AddBailout(accumulator1(), accumulator0());
} else { }
// Preserve the destination operand in a scratch register in case of __ j(not_zero, bailout, not_taken);
// bailout.
__ mov(scratch0(), destination());
__ or_(destination(), Operand(other_accumulator(destination())));
__ test(destination(), Immediate(kSmiTagMask));
__ j(not_zero, bailout(), not_taken);
} }
// If we didn't bailout, the result (in fact, both inputs too) is known to // If we didn't bailout, the result (in fact, both inputs too) is known to
...@@ -623,6 +631,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -623,6 +631,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
// Note that we keep a live register reference to esi (context) at this // Note that we keep a live register reference to esi (context) at this
// point. // point.
Label* bailout_to_beginning = info()->AddBailout();
// Receiver (this) is allocated to a fixed register. // Receiver (this) is allocated to a fixed register.
if (info()->has_this_properties()) { if (info()->has_this_properties()) {
Comment cmnt(masm(), ";; MapCheck(this)"); Comment cmnt(masm(), ";; MapCheck(this)");
...@@ -633,7 +642,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -633,7 +642,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
Handle<Map> map(object->map()); Handle<Map> map(object->map());
EmitLoadReceiver(); EmitLoadReceiver();
__ CheckMap(receiver_reg(), map, bailout(), false); __ CheckMap(receiver_reg(), map, bailout_to_beginning, false);
} }
// If there is a global variable access check if the global object is the // If there is a global variable access check if the global object is the
...@@ -646,7 +655,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -646,7 +655,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
ASSERT(info()->has_global_object()); ASSERT(info()->has_global_object());
Handle<Map> map(info()->global_object()->map()); Handle<Map> map(info()->global_object()->map());
__ mov(scratch0(), CodeGenerator::GlobalObject()); __ mov(scratch0(), CodeGenerator::GlobalObject());
__ CheckMap(scratch0(), map, bailout(), true); __ CheckMap(scratch0(), map, bailout_to_beginning, true);
} }
VisitStatements(function()->body()); VisitStatements(function()->body());
...@@ -659,8 +668,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -659,8 +668,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
__ mov(esp, ebp); __ mov(esp, ebp);
__ pop(ebp); __ pop(ebp);
__ ret((scope()->num_parameters() + 1) * kPointerSize); __ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "ast.h" #include "ast.h"
#include "compiler.h" #include "compiler.h"
#include "list.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -76,7 +77,6 @@ class FastCodeGenerator: public AstVisitor { ...@@ -76,7 +77,6 @@ class FastCodeGenerator: public AstVisitor {
private: private:
MacroAssembler* masm() { return masm_; } MacroAssembler* masm() { return masm_; }
CompilationInfo* info() { return info_; } CompilationInfo* info() { return info_; }
Label* bailout() { return &bailout_; }
Register destination() { return destination_; } Register destination() { return destination_; }
void set_destination(Register reg) { destination_ = reg; } void set_destination(Register reg) { destination_ = reg; }
...@@ -142,7 +142,7 @@ class FastCodeGenerator: public AstVisitor { ...@@ -142,7 +142,7 @@ class FastCodeGenerator: public AstVisitor {
MacroAssembler* masm_; MacroAssembler* masm_;
CompilationInfo* info_; CompilationInfo* info_;
Label bailout_;
Register destination_; Register destination_;
uint32_t smi_bits_; uint32_t smi_bits_;
......
...@@ -277,7 +277,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { ...@@ -277,7 +277,7 @@ void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
} }
void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { void CodeGenerator::Generate(CompilationInfo* info) {
// Record the position for debugging purposes. // Record the position for debugging purposes.
CodeForFunctionPosition(info->function()); CodeForFunctionPosition(info->function());
...@@ -316,7 +316,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { ...@@ -316,7 +316,7 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// rsi: callee's context // rsi: callee's context
allocator_->Initialize(); allocator_->Initialize();
if (mode == PRIMARY) { if (info->mode() == CompilationInfo::PRIMARY) {
frame_->Enter(); frame_->Enter();
// Allocate space for locals and initialize them. // Allocate space for locals and initialize them.
...@@ -407,6 +407,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) { ...@@ -407,6 +407,12 @@ void CodeGenerator::Generate(CompilationInfo* info, Mode mode) {
// frame to match this state. // frame to match this state.
frame_->Adjust(3); frame_->Adjust(3);
allocator_->Unuse(rdi); allocator_->Unuse(rdi);
// Bind all the bailout labels to the beginning of the function.
List<CompilationInfo::Bailout*>* bailouts = info->bailouts();
for (int i = 0; i < bailouts->length(); i++) {
__ bind(bailouts->at(i)->label());
}
} }
// Initialize the function return target after the locals are set // Initialize the function return target after the locals are set
......
...@@ -294,15 +294,6 @@ enum ArgumentsAllocationMode { ...@@ -294,15 +294,6 @@ enum ArgumentsAllocationMode {
class CodeGenerator: public AstVisitor { class CodeGenerator: public AstVisitor {
public: 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 // Takes a function literal, generates code for it. This function should only
// be called by compiler.cc. // be called by compiler.cc.
static Handle<Code> MakeCode(CompilationInfo* info); static Handle<Code> MakeCode(CompilationInfo* info);
...@@ -385,7 +376,7 @@ class CodeGenerator: public AstVisitor { ...@@ -385,7 +376,7 @@ class CodeGenerator: public AstVisitor {
void VisitStatementsAndSpill(ZoneList<Statement*>* statements); void VisitStatementsAndSpill(ZoneList<Statement*>* statements);
// Main code generation function // Main code generation function
void Generate(CompilationInfo* info, Mode mode); void Generate(CompilationInfo* info);
// Generate the return sequence code. Should be called no more than // Generate the return sequence code. Should be called no more than
// once per compiled function, immediately after binding the return // once per compiled function, immediately after binding the return
......
...@@ -156,20 +156,27 @@ void FastCodeGenerator::EmitBitOr() { ...@@ -156,20 +156,27 @@ void FastCodeGenerator::EmitBitOr() {
// commutative. // commutative.
__ or_(destination(), other_accumulator(destination())); __ or_(destination(), other_accumulator(destination()));
} }
} else if (destination().is(no_reg)) { } else {
// Result is not needed but do not clobber the operands in case of // Left is in accumulator1, right in accumulator0.
// bailout. if (destination().is(accumulator0())) {
__ movq(scratch0(), accumulator0());
__ or_(destination(), accumulator1()); // Or is commutative.
Label* bailout =
info()->AddBailout(accumulator1(), scratch0()); // Left, right.
__ JumpIfNotSmi(destination(), bailout);
} else if (destination().is(accumulator1())) {
__ movq(scratch0(), accumulator1()); __ movq(scratch0(), accumulator1());
__ or_(scratch0(), accumulator0()); __ or_(destination(), accumulator0());
__ JumpIfNotSmi(scratch0(), bailout()); Label* bailout = info()->AddBailout(scratch0(), accumulator0());
__ JumpIfNotSmi(destination(), bailout);
} else { } else {
// Preserve the destination operand in a scratch register in case of ASSERT(destination().is(no_reg));
// bailout. __ movq(scratch0(), accumulator1());
__ movq(scratch0(), destination()); __ or_(scratch0(), accumulator0());
__ or_(destination(), other_accumulator(destination())); Label* bailout = info()->AddBailout(accumulator1(), accumulator0());
__ JumpIfNotSmi(destination(), bailout()); __ JumpIfNotSmi(scratch0(), bailout);
}
} }
// If we didn't bailout, the result (in fact, both inputs too) is known to // If we didn't bailout, the result (in fact, both inputs too) is known to
// be a smi. // be a smi.
...@@ -191,6 +198,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -191,6 +198,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
// Note that we keep a live register reference to esi (context) at this // Note that we keep a live register reference to esi (context) at this
// point. // point.
Label* bailout_to_beginning = info()->AddBailout();
// Receiver (this) is allocated to a fixed register. // Receiver (this) is allocated to a fixed register.
if (info()->has_this_properties()) { if (info()->has_this_properties()) {
Comment cmnt(masm(), ";; MapCheck(this)"); Comment cmnt(masm(), ";; MapCheck(this)");
...@@ -201,7 +209,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -201,7 +209,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver()); Handle<HeapObject> object = Handle<HeapObject>::cast(info()->receiver());
Handle<Map> map(object->map()); Handle<Map> map(object->map());
EmitLoadReceiver(); EmitLoadReceiver();
__ CheckMap(receiver_reg(), map, bailout(), false); __ CheckMap(receiver_reg(), map, bailout_to_beginning, false);
} }
// If there is a global variable access check if the global object is the // If there is a global variable access check if the global object is the
...@@ -214,7 +222,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -214,7 +222,7 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
ASSERT(info()->has_global_object()); ASSERT(info()->has_global_object());
Handle<Map> map(info()->global_object()->map()); Handle<Map> map(info()->global_object()->map());
__ movq(scratch0(), CodeGenerator::GlobalObject()); __ movq(scratch0(), CodeGenerator::GlobalObject());
__ CheckMap(scratch0(), map, bailout(), true); __ CheckMap(scratch0(), map, bailout_to_beginning, true);
} }
VisitStatements(info()->function()->body()); VisitStatements(info()->function()->body());
...@@ -227,8 +235,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) { ...@@ -227,8 +235,6 @@ void FastCodeGenerator::Generate(CompilationInfo* compilation_info) {
__ movq(rsp, rbp); __ movq(rsp, rbp);
__ pop(rbp); __ pop(rbp);
__ ret((scope()->num_parameters() + 1) * kPointerSize); __ ret((scope()->num_parameters() + 1) * kPointerSize);
__ bind(&bailout_);
} }
......
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