Simplify deferred code by removing some unneeded or redundant stuff.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2065 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2009-05-27 15:13:00 +00:00
parent 2e37ebe1ed
commit 3d15415414
8 changed files with 231 additions and 257 deletions

View File

@ -289,9 +289,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
DeleteFrame();
// Process any deferred code using the register allocator.
if (HasStackOverflow()) {
ClearDeferred();
} else {
if (!HasStackOverflow()) {
ProcessDeferred();
}
@ -757,13 +755,11 @@ void CodeGenerator::GenericBinaryOperation(Token::Value op,
class DeferredInlineSmiOperation: public DeferredCode {
public:
DeferredInlineSmiOperation(CodeGenerator* generator,
Token::Value op,
DeferredInlineSmiOperation(Token::Value op,
int value,
bool reversed,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
op_(op),
: op_(op),
value_(value),
reversed_(reversed),
overwrite_mode_(overwrite_mode) {
@ -780,7 +776,12 @@ class DeferredInlineSmiOperation: public DeferredCode {
};
#undef __
#define __ ACCESS_MASM(masm)
void DeferredInlineSmiOperation::Generate() {
MacroAssembler* masm = cgen()->masm();
enter()->Bind();
VirtualFrame::SpilledScope spilled_scope;
@ -841,15 +842,19 @@ void DeferredInlineSmiOperation::Generate() {
}
GenericBinaryOpStub igostub(op_, overwrite_mode_);
Result arg0 = generator()->allocator()->Allocate(r1);
Result arg0 = cgen()->allocator()->Allocate(r1);
ASSERT(arg0.is_valid());
Result arg1 = generator()->allocator()->Allocate(r0);
Result arg1 = cgen()->allocator()->Allocate(r0);
ASSERT(arg1.is_valid());
generator()->frame()->CallStub(&igostub, &arg0, &arg1);
cgen()->frame()->CallStub(&igostub, &arg0, &arg1);
exit_.Jump();
}
#undef __
#define __ ACCESS_MASM(masm_)
void CodeGenerator::SmiOperation(Token::Value op,
Handle<Object> value,
bool reversed,
@ -872,7 +877,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
switch (op) {
case Token::ADD: {
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
new DeferredInlineSmiOperation(op, int_value, reversed, mode);
__ add(r0, r0, Operand(value), SetCC);
deferred->enter()->Branch(vs);
@ -884,7 +889,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
case Token::SUB: {
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
new DeferredInlineSmiOperation(op, int_value, reversed, mode);
if (!reversed) {
__ sub(r0, r0, Operand(value), SetCC);
@ -902,7 +907,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
case Token::BIT_XOR:
case Token::BIT_AND: {
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, op, int_value, reversed, mode);
new DeferredInlineSmiOperation(op, int_value, reversed, mode);
__ tst(r0, Operand(kSmiTagMask));
deferred->enter()->Branch(ne);
switch (op) {
@ -927,7 +932,7 @@ void CodeGenerator::SmiOperation(Token::Value op,
} else {
int shift_value = int_value & 0x1f; // least significant 5 bits
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, op, shift_value, false, mode);
new DeferredInlineSmiOperation(op, shift_value, false, mode);
__ tst(r0, Operand(kSmiTagMask));
deferred->enter()->Branch(ne);
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags
@ -2654,8 +2659,7 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
// therefore context dependent.
class DeferredObjectLiteral: public DeferredCode {
public:
DeferredObjectLiteral(CodeGenerator* generator, ObjectLiteral* node)
: DeferredCode(generator), node_(node) {
explicit DeferredObjectLiteral(ObjectLiteral* node) : node_(node) {
set_comment("[ DeferredObjectLiteral");
}
@ -2666,7 +2670,12 @@ class DeferredObjectLiteral: public DeferredCode {
};
#undef __
#define __ ACCESS_MASM(masm)
void DeferredObjectLiteral::Generate() {
MacroAssembler* masm = cgen()->masm();
// Argument is passed in r1.
enter()->Bind();
VirtualFrame::SpilledScope spilled_scope;
@ -2674,7 +2683,7 @@ void DeferredObjectLiteral::Generate() {
// If the entry is undefined we call the runtime system to compute
// the literal.
VirtualFrame* frame = generator()->frame();
VirtualFrame* frame = cgen()->frame();
// Literal array (0).
frame->EmitPush(r1);
// Literal index (1).
@ -2691,6 +2700,10 @@ void DeferredObjectLiteral::Generate() {
}
#undef __
#define __ ACCESS_MASM(masm_)
void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
#ifdef DEBUG
int original_height = frame_->height();
@ -2698,7 +2711,7 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ ObjectLiteral");
DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node);
DeferredObjectLiteral* deferred = new DeferredObjectLiteral(node);
// Retrieve the literal array and check the allocated entry.
@ -2783,8 +2796,7 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// therefore context dependent.
class DeferredArrayLiteral: public DeferredCode {
public:
DeferredArrayLiteral(CodeGenerator* generator, ArrayLiteral* node)
: DeferredCode(generator), node_(node) {
explicit DeferredArrayLiteral(ArrayLiteral* node) : node_(node) {
set_comment("[ DeferredArrayLiteral");
}
@ -2795,7 +2807,12 @@ class DeferredArrayLiteral: public DeferredCode {
};
#undef __
#define __ ACCESS_MASM(masm)
void DeferredArrayLiteral::Generate() {
MacroAssembler* masm = cgen()->masm();
// Argument is passed in r1.
enter()->Bind();
VirtualFrame::SpilledScope spilled_scope;
@ -2803,7 +2820,7 @@ void DeferredArrayLiteral::Generate() {
// If the entry is undefined we call the runtime system to computed
// the literal.
VirtualFrame* frame = generator()->frame();
VirtualFrame* frame = cgen()->frame();
// Literal array (0).
frame->EmitPush(r1);
// Literal index (1).
@ -2820,6 +2837,10 @@ void DeferredArrayLiteral::Generate() {
}
#undef __
#define __ ACCESS_MASM(masm_)
void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
#ifdef DEBUG
int original_height = frame_->height();
@ -2827,7 +2848,7 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
VirtualFrame::SpilledScope spilled_scope;
Comment cmnt(masm_, "[ ArrayLiteral");
DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
DeferredArrayLiteral* deferred = new DeferredArrayLiteral(node);
// Retrieve the literal array and check the allocated entry.

View File

@ -194,8 +194,7 @@ class CodeGenerator: public AstVisitor {
// Accessors
Scope* scope() const { return scope_; }
// Clearing and generating deferred code.
void ClearDeferred();
// Generating deferred code.
void ProcessDeferred();
bool is_eval() { return is_eval_; }

View File

@ -37,20 +37,20 @@ namespace internal {
void DeferredCode::SetEntryFrame(Result* arg) {
ASSERT(generator()->has_valid_frame());
generator()->frame()->Push(arg);
enter()->set_entry_frame(new VirtualFrame(generator()->frame()));
*arg = generator()->frame()->Pop();
ASSERT(cgen()->has_valid_frame());
cgen()->frame()->Push(arg);
enter()->set_entry_frame(new VirtualFrame(cgen()->frame()));
*arg = cgen()->frame()->Pop();
}
void DeferredCode::SetEntryFrame(Result* arg0, Result* arg1) {
ASSERT(generator()->has_valid_frame());
generator()->frame()->Push(arg0);
generator()->frame()->Push(arg1);
enter()->set_entry_frame(new VirtualFrame(generator()->frame()));
*arg1 = generator()->frame()->Pop();
*arg0 = generator()->frame()->Pop();
ASSERT(cgen()->has_valid_frame());
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
enter()->set_entry_frame(new VirtualFrame(cgen()->frame()));
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
}

View File

@ -45,32 +45,24 @@ namespace internal {
CodeGenerator* CodeGeneratorScope::top_ = NULL;
DeferredCode::DeferredCode(CodeGenerator* generator)
: generator_(generator),
masm_(generator->masm()),
exit_(JumpTarget::BIDIRECTIONAL),
statement_position_(masm_->current_statement_position()),
position_(masm_->current_position()) {
generator->AddDeferred(this);
DeferredCode::DeferredCode() : exit_(JumpTarget::BIDIRECTIONAL) {
MacroAssembler* masm = cgen()->masm();
statement_position_ = masm->current_statement_position();
position_ = masm->current_position();
ASSERT(statement_position_ != RelocInfo::kNoPosition);
ASSERT(position_ != RelocInfo::kNoPosition);
cgen()->AddDeferred(this);
#ifdef DEBUG
comment_ = "";
#endif
}
void CodeGenerator::ClearDeferred() {
for (int i = 0; i < deferred_.length(); i++) {
deferred_[i]->Clear();
}
}
void CodeGenerator::ProcessDeferred() {
while (!deferred_.is_empty()) {
DeferredCode* code = deferred_.RemoveLast();
MacroAssembler* masm = code->masm();
MacroAssembler* masm = code->cgen()->masm();
// Record position of deferred code stub.
masm->RecordStatementPosition(code->statement_position());
if (code->position() != RelocInfo::kNoPosition) {
@ -80,7 +72,6 @@ void CodeGenerator::ProcessDeferred() {
Comment cmnt(masm, code->comment());
code->Generate();
ASSERT(code->enter()->is_bound());
code->Clear();
}
}

View File

@ -52,7 +52,6 @@
// CodeGenerator
// ~CodeGenerator
// ProcessDeferred
// ClearDeferred
// GenCode
// BuildBoilerplate
// ComputeCallInitialize
@ -116,33 +115,17 @@ class CodeGeneratorScope BASE_EMBEDDED {
};
// Use lazy compilation; defaults to true.
// NOTE: Do not remove non-lazy compilation until we can properly
// install extensions with lazy compilation enabled. At the
// moment, this doesn't work for the extensions in Google3,
// and we can only run the tests with --nolazy.
// Deferred code objects are small pieces of code that are compiled
// out of line. They are used to defer the compilation of uncommon
// paths thereby avoiding expensive jumps around uncommon code parts.
class DeferredCode: public ZoneObject {
public:
explicit DeferredCode(CodeGenerator* generator);
DeferredCode();
virtual ~DeferredCode() { }
virtual void Generate() = 0;
// Unuse the entry and exit targets, deallocating all virtual frames
// held by them. It will be impossible to emit a (correct) jump
// into or out of the deferred code after clearing.
void Clear() {
enter_.Unuse();
exit_.Unuse();
}
MacroAssembler* masm() const { return masm_; }
CodeGenerator* generator() const { return generator_; }
CodeGenerator* cgen() const { return CodeGeneratorScope::Current(); }
// Set the virtual frame for entry to the deferred code as a
// snapshot of the code generator's current frame (plus additional
@ -169,13 +152,11 @@ class DeferredCode: public ZoneObject {
void set_comment(const char* comment) { comment_ = comment; }
const char* comment() const { return comment_; }
#else
inline void set_comment(const char* comment) { }
void set_comment(const char* comment) { }
const char* comment() const { return ""; }
#endif
protected:
CodeGenerator* const generator_;
MacroAssembler* const masm_;
JumpTarget enter_;
JumpTarget exit_;

View File

@ -318,9 +318,7 @@ void CodeGenerator::GenCode(FunctionLiteral* fun) {
DeleteFrame();
// Process any deferred code using the register allocator.
if (HasStackOverflow()) {
ClearDeferred();
} else {
if (!HasStackOverflow()) {
HistogramTimerScope deferred_timer(&Counters::deferred_code_generation);
JumpTarget::set_compiling_deferred_code(true);
ProcessDeferred();
@ -784,11 +782,10 @@ const char* GenericBinaryOpStub::GetName() {
// the GenericBinaryOpStub stub for slow cases.
class DeferredInlineBinaryOperation: public DeferredCode {
public:
DeferredInlineBinaryOperation(CodeGenerator* generator,
Token::Value op,
DeferredInlineBinaryOperation(Token::Value op,
OverwriteMode mode,
GenericBinaryFlags flags)
: DeferredCode(generator), stub_(op, mode, flags), op_(op) {
: stub_(op, mode, flags), op_(op) {
set_comment("[ DeferredInlineBinaryOperation");
}
@ -807,9 +804,9 @@ void DeferredInlineBinaryOperation::Generate() {
Result left;
Result right;
enter()->Bind(&left, &right);
generator()->frame()->Push(&left);
generator()->frame()->Push(&right);
Result answer = generator()->frame()->CallStub(&stub_, 2);
cgen()->frame()->Push(&left);
cgen()->frame()->Push(&right);
Result answer = cgen()->frame()->CallStub(&stub_, 2);
exit_.Jump(&answer);
}
@ -1013,8 +1010,7 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
// Implements a binary operation using a deferred code object
// and some inline code to operate on smis quickly.
DeferredInlineBinaryOperation* deferred =
new DeferredInlineBinaryOperation(this, op, overwrite_mode,
SMI_CODE_INLINED);
new DeferredInlineBinaryOperation(op, overwrite_mode, SMI_CODE_INLINED);
// Generate the inline code that handles some smi operations,
// and jumps to the deferred code for everything else.
Result answer = deferred->GenerateInlineCode(left, right);
@ -1025,12 +1021,10 @@ void CodeGenerator::LikelySmiBinaryOperation(Token::Value op,
class DeferredInlineSmiOperation: public DeferredCode {
public:
DeferredInlineSmiOperation(CodeGenerator* generator,
Token::Value op,
DeferredInlineSmiOperation(Token::Value op,
Smi* value,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
op_(op),
: op_(op),
value_(value),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiOperation");
@ -1048,22 +1042,20 @@ class DeferredInlineSmiOperation: public DeferredCode {
void DeferredInlineSmiOperation::Generate() {
Result left;
enter()->Bind(&left);
generator()->frame()->Push(&left);
generator()->frame()->Push(value_);
cgen()->frame()->Push(&left);
cgen()->frame()->Push(value_);
GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
Result answer = generator()->frame()->CallStub(&igostub, 2);
Result answer = cgen()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
class DeferredInlineSmiOperationReversed: public DeferredCode {
public:
DeferredInlineSmiOperationReversed(CodeGenerator* generator,
Token::Value op,
DeferredInlineSmiOperationReversed(Token::Value op,
Smi* value,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
op_(op),
: op_(op),
value_(value),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiOperationReversed");
@ -1081,21 +1073,19 @@ class DeferredInlineSmiOperationReversed: public DeferredCode {
void DeferredInlineSmiOperationReversed::Generate() {
Result right;
enter()->Bind(&right);
generator()->frame()->Push(value_);
generator()->frame()->Push(&right);
cgen()->frame()->Push(value_);
cgen()->frame()->Push(&right);
GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
Result answer = generator()->frame()->CallStub(&igostub, 2);
Result answer = cgen()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
class DeferredInlineSmiAdd: public DeferredCode {
public:
DeferredInlineSmiAdd(CodeGenerator* generator,
Smi* value,
DeferredInlineSmiAdd(Smi* value,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
value_(value),
: value_(value),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiAdd");
}
@ -1108,28 +1098,11 @@ class DeferredInlineSmiAdd: public DeferredCode {
};
void DeferredInlineSmiAdd::Generate() {
// Undo the optimistic add operation and call the shared stub.
Result left; // Initially left + value_.
enter()->Bind(&left);
left.ToRegister();
generator()->frame()->Spill(left.reg());
__ sub(Operand(left.reg()), Immediate(value_));
generator()->frame()->Push(&left);
generator()->frame()->Push(value_);
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
Result answer = generator()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
class DeferredInlineSmiAddReversed: public DeferredCode {
public:
DeferredInlineSmiAddReversed(CodeGenerator* generator,
Smi* value,
DeferredInlineSmiAddReversed(Smi* value,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
value_(value),
: value_(value),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiAddReversed");
}
@ -1142,28 +1115,11 @@ class DeferredInlineSmiAddReversed: public DeferredCode {
};
void DeferredInlineSmiAddReversed::Generate() {
// Undo the optimistic add operation and call the shared stub.
Result right; // Initially value_ + right.
enter()->Bind(&right);
right.ToRegister();
generator()->frame()->Spill(right.reg());
__ sub(Operand(right.reg()), Immediate(value_));
generator()->frame()->Push(value_);
generator()->frame()->Push(&right);
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
Result answer = generator()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
class DeferredInlineSmiSub: public DeferredCode {
public:
DeferredInlineSmiSub(CodeGenerator* generator,
Smi* value,
DeferredInlineSmiSub(Smi* value,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
value_(value),
: value_(value),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiSub");
}
@ -1176,28 +1132,64 @@ class DeferredInlineSmiSub: public DeferredCode {
};
#undef __
#define __ ACCESS_MASM(cgen()->masm())
void DeferredInlineSmiAdd::Generate() {
// Undo the optimistic add operation and call the shared stub.
Result left; // Initially left + value_.
enter()->Bind(&left);
left.ToRegister();
cgen()->frame()->Spill(left.reg());
__ sub(Operand(left.reg()), Immediate(value_));
cgen()->frame()->Push(&left);
cgen()->frame()->Push(value_);
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
Result answer = cgen()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
void DeferredInlineSmiAddReversed::Generate() {
// Undo the optimistic add operation and call the shared stub.
Result right; // Initially value_ + right.
enter()->Bind(&right);
right.ToRegister();
cgen()->frame()->Spill(right.reg());
__ sub(Operand(right.reg()), Immediate(value_));
cgen()->frame()->Push(value_);
cgen()->frame()->Push(&right);
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
Result answer = cgen()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
void DeferredInlineSmiSub::Generate() {
// Undo the optimistic sub operation and call the shared stub.
Result left; // Initially left - value_.
enter()->Bind(&left);
left.ToRegister();
generator()->frame()->Spill(left.reg());
cgen()->frame()->Spill(left.reg());
__ add(Operand(left.reg()), Immediate(value_));
generator()->frame()->Push(&left);
generator()->frame()->Push(value_);
cgen()->frame()->Push(&left);
cgen()->frame()->Push(value_);
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
Result answer = generator()->frame()->CallStub(&igostub, 2);
Result answer = cgen()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
#undef __
#define __ ACCESS_MASM(masm_)
class DeferredInlineSmiSubReversed: public DeferredCode {
public:
DeferredInlineSmiSubReversed(CodeGenerator* generator,
Smi* value,
DeferredInlineSmiSubReversed(Smi* value,
OverwriteMode overwrite_mode)
: DeferredCode(generator),
value_(value),
: value_(value),
overwrite_mode_(overwrite_mode) {
set_comment("[ DeferredInlineSmiSubReversed");
}
@ -1214,10 +1206,10 @@ void DeferredInlineSmiSubReversed::Generate() {
// Call the shared stub.
Result right;
enter()->Bind(&right);
generator()->frame()->Push(value_);
generator()->frame()->Push(&right);
cgen()->frame()->Push(value_);
cgen()->frame()->Push(&right);
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
Result answer = generator()->frame()->CallStub(&igostub, 2);
Result answer = cgen()->frame()->CallStub(&igostub, 2);
exit_.Jump(&answer);
}
@ -1260,10 +1252,9 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
DeferredCode* deferred = NULL;
if (reversed) {
deferred = new DeferredInlineSmiAddReversed(this, smi_value,
overwrite_mode);
deferred = new DeferredInlineSmiAddReversed(smi_value, overwrite_mode);
} else {
deferred = new DeferredInlineSmiAdd(this, smi_value, overwrite_mode);
deferred = new DeferredInlineSmiAdd(smi_value, overwrite_mode);
}
deferred->SetEntryFrame(operand);
deferred->enter()->Branch(overflow, operand, not_taken);
@ -1280,8 +1271,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
if (reversed) {
answer = allocator()->Allocate();
ASSERT(answer.is_valid());
deferred = new DeferredInlineSmiSubReversed(this, smi_value,
overwrite_mode);
deferred = new DeferredInlineSmiSubReversed(smi_value, overwrite_mode);
__ Set(answer.reg(), Immediate(value));
// We are in the reversed case so they can't both be Smi constants.
ASSERT(operand->is_register());
@ -1289,7 +1279,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
} else {
operand->ToRegister();
frame_->Spill(operand->reg());
deferred = new DeferredInlineSmiSub(this, smi_value, overwrite_mode);
deferred = new DeferredInlineSmiSub(smi_value, overwrite_mode);
__ sub(Operand(operand->reg()), Immediate(value));
answer = *operand;
}
@ -1313,8 +1303,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, Token::SAR, smi_value,
overwrite_mode);
new DeferredInlineSmiOperation(op, smi_value, overwrite_mode);
operand->ToRegister();
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->enter()->Branch(not_zero, operand, not_taken);
@ -1339,8 +1328,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, Token::SHR, smi_value,
overwrite_mode);
new DeferredInlineSmiOperation(op, smi_value, overwrite_mode);
operand->ToRegister();
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->enter()->Branch(not_zero, operand, not_taken);
@ -1374,8 +1362,7 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
// In the slow case, this masking is done inside the runtime call.
int shift_value = int_value & 0x1f;
DeferredCode* deferred =
new DeferredInlineSmiOperation(this, Token::SHL, smi_value,
overwrite_mode);
new DeferredInlineSmiOperation(op, smi_value, overwrite_mode);
operand->ToRegister();
__ test(operand->reg(), Immediate(kSmiTagMask));
deferred->enter()->Branch(not_zero, operand, not_taken);
@ -1408,10 +1395,10 @@ void CodeGenerator::ConstantSmiBinaryOperation(Token::Value op,
case Token::BIT_AND: {
DeferredCode* deferred = NULL;
if (reversed) {
deferred = new DeferredInlineSmiOperationReversed(this, op, smi_value,
deferred = new DeferredInlineSmiOperationReversed(op, smi_value,
overwrite_mode);
} else {
deferred = new DeferredInlineSmiOperation(this, op, smi_value,
deferred = new DeferredInlineSmiOperation(op, smi_value,
overwrite_mode);
}
operand->ToRegister();
@ -1697,8 +1684,7 @@ void CodeGenerator::CallWithArguments(ZoneList<Expression*>* args,
class DeferredStackCheck: public DeferredCode {
public:
explicit DeferredStackCheck(CodeGenerator* generator)
: DeferredCode(generator) {
explicit DeferredStackCheck() {
set_comment("[ DeferredStackCheck");
}
@ -1709,7 +1695,7 @@ class DeferredStackCheck: public DeferredCode {
void DeferredStackCheck::Generate() {
enter()->Bind();
StackCheckStub stub;
Result ignored = generator()->frame()->CallStub(&stub, 0);
Result ignored = cgen()->frame()->CallStub(&stub, 0);
ignored.Unuse();
exit_.Jump();
}
@ -1717,7 +1703,7 @@ void DeferredStackCheck::Generate() {
void CodeGenerator::CheckStack() {
if (FLAG_check_stack) {
DeferredStackCheck* deferred = new DeferredStackCheck(this);
DeferredStackCheck* deferred = new DeferredStackCheck;
ExternalReference stack_guard_limit =
ExternalReference::address_of_stack_guard_limit();
__ cmp(esp, Operand::StaticVariable(stack_guard_limit));
@ -3575,8 +3561,7 @@ bool CodeGenerator::IsUnsafeSmi(Handle<Object> value) {
class DeferredRegExpLiteral: public DeferredCode {
public:
DeferredRegExpLiteral(CodeGenerator* generator, RegExpLiteral* node)
: DeferredCode(generator), node_(node) {
explicit DeferredRegExpLiteral(RegExpLiteral* node) : node_(node) {
set_comment("[ DeferredRegExpLiteral");
}
@ -3593,7 +3578,7 @@ void DeferredRegExpLiteral::Generate() {
// Since the entry is undefined we call the runtime system to
// compute the literal.
VirtualFrame* frame = generator()->frame();
VirtualFrame* frame = cgen()->frame();
// Literal array (0).
frame->Push(&literals);
// Literal index (1).
@ -3610,7 +3595,7 @@ void DeferredRegExpLiteral::Generate() {
void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
Comment cmnt(masm_, "[ RegExp Literal");
DeferredRegExpLiteral* deferred = new DeferredRegExpLiteral(this, node);
DeferredRegExpLiteral* deferred = new DeferredRegExpLiteral(node);
// Retrieve the literals array and check the allocated entry. Begin
// with a writable copy of the function of this activation in a
@ -3651,9 +3636,7 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
// therefore context dependent.
class DeferredObjectLiteral: public DeferredCode {
public:
DeferredObjectLiteral(CodeGenerator* generator,
ObjectLiteral* node)
: DeferredCode(generator), node_(node) {
explicit DeferredObjectLiteral(ObjectLiteral* node) : node_(node) {
set_comment("[ DeferredObjectLiteral");
}
@ -3670,7 +3653,7 @@ void DeferredObjectLiteral::Generate() {
// Since the entry is undefined we call the runtime system to
// compute the literal.
VirtualFrame* frame = generator()->frame();
VirtualFrame* frame = cgen()->frame();
// Literal array (0).
frame->Push(&literals);
// Literal index (1).
@ -3685,7 +3668,7 @@ void DeferredObjectLiteral::Generate() {
void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
Comment cmnt(masm_, "[ ObjectLiteral");
DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node);
DeferredObjectLiteral* deferred = new DeferredObjectLiteral(node);
// Retrieve the literals array and check the allocated entry. Begin
// with a writable copy of the function of this activation in a
@ -3789,9 +3772,7 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// therefore context dependent.
class DeferredArrayLiteral: public DeferredCode {
public:
DeferredArrayLiteral(CodeGenerator* generator,
ArrayLiteral* node)
: DeferredCode(generator), node_(node) {
explicit DeferredArrayLiteral(ArrayLiteral* node) : node_(node) {
set_comment("[ DeferredArrayLiteral");
}
@ -3808,7 +3789,7 @@ void DeferredArrayLiteral::Generate() {
// Since the entry is undefined we call the runtime system to
// compute the literal.
VirtualFrame* frame = generator()->frame();
VirtualFrame* frame = cgen()->frame();
// Literal array (0).
frame->Push(&literals);
// Literal index (1).
@ -3823,7 +3804,7 @@ void DeferredArrayLiteral::Generate() {
void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
Comment cmnt(masm_, "[ ArrayLiteral");
DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
DeferredArrayLiteral* deferred = new DeferredArrayLiteral(node);
// Retrieve the literals array and check the allocated entry. Begin
// with a writable copy of the function of this activation in a
@ -4778,12 +4759,10 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
class DeferredCountOperation: public DeferredCode {
public:
DeferredCountOperation(CodeGenerator* generator,
bool is_postfix,
DeferredCountOperation(bool is_postfix,
bool is_increment,
int target_size)
: DeferredCode(generator),
is_postfix_(is_postfix),
: is_postfix_(is_postfix),
is_increment_(is_increment),
target_size_(target_size) {
set_comment("[ DeferredCountOperation");
@ -4798,11 +4777,14 @@ class DeferredCountOperation: public DeferredCode {
};
#undef __
#define __ ACCESS_MASM(cgen()->masm())
void DeferredCountOperation::Generate() {
CodeGenerator* cgen = generator();
Result value;
enter()->Bind(&value);
VirtualFrame* frame = cgen->frame();
VirtualFrame* frame = cgen()->frame();
// Undo the optimistic smi operation.
value.ToRegister();
frame->Spill(value.reg());
@ -4830,6 +4812,10 @@ void DeferredCountOperation::Generate() {
}
#undef __
#define __ ACCESS_MASM(masm_)
void CodeGenerator::VisitCountOperation(CountOperation* node) {
Comment cmnt(masm_, "[ CountOperation");
@ -4857,8 +4843,7 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
target.TakeValue(NOT_INSIDE_TYPEOF);
DeferredCountOperation* deferred =
new DeferredCountOperation(this, is_postfix,
is_increment, target.size());
new DeferredCountOperation(is_postfix, is_increment, target.size());
Result value = frame_->Pop();
value.ToRegister();
@ -5282,8 +5267,7 @@ bool CodeGenerator::HasValidEntryRegisters() {
class DeferredReferenceGetNamedValue: public DeferredCode {
public:
DeferredReferenceGetNamedValue(CodeGenerator* cgen, Handle<String> name)
: DeferredCode(cgen), name_(name) {
explicit DeferredReferenceGetNamedValue(Handle<String> name) : name_(name) {
set_comment("[ DeferredReferenceGetNamedValue");
}
@ -5297,35 +5281,10 @@ class DeferredReferenceGetNamedValue: public DeferredCode {
};
void DeferredReferenceGetNamedValue::Generate() {
CodeGenerator* cgen = generator();
Result receiver;
enter()->Bind(&receiver);
cgen->frame()->Push(&receiver);
cgen->frame()->Push(name_);
Result answer = cgen->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
// The call must be followed by a test eax instruction to indicate
// that the inobject property case was inlined.
ASSERT(answer.is_register() && answer.reg().is(eax));
// Store the delta to the map check instruction here in the test instruction.
// Use masm_-> instead of the double underscore macro since the latter can't
// return a value.
int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
// Here we use masm_-> instead of the double underscore macro because
// this is the instruction that gets patched and coverage code gets in
// the way.
masm_->test(answer.reg(), Immediate(-delta_to_patch_site));
__ IncrementCounter(&Counters::named_load_inline_miss, 1);
receiver = cgen->frame()->Pop();
exit_.Jump(&receiver, &answer);
}
class DeferredReferenceGetKeyedValue: public DeferredCode {
public:
DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global)
: DeferredCode(generator), is_global_(is_global) {
explicit DeferredReferenceGetKeyedValue(bool is_global)
: is_global_(is_global) {
set_comment("[ DeferredReferenceGetKeyedValue");
}
@ -5339,13 +5298,41 @@ class DeferredReferenceGetKeyedValue: public DeferredCode {
};
#undef __
#define __ ACCESS_MASM(cgen()->masm())
void DeferredReferenceGetNamedValue::Generate() {
Result receiver;
enter()->Bind(&receiver);
cgen()->frame()->Push(&receiver);
cgen()->frame()->Push(name_);
Result answer = cgen()->frame()->CallLoadIC(RelocInfo::CODE_TARGET);
// The call must be followed by a test eax instruction to indicate
// that the inobject property case was inlined.
ASSERT(answer.is_register() && answer.reg().is(eax));
// Store the delta to the map check instruction here in the test
// instruction. Use cgen()->masm()-> instead of the __ macro since
// the latter can't return a value.
int delta_to_patch_site =
cgen()->masm()->SizeOfCodeGeneratedSince(patch_site());
// Here we use cgen()->masm()-> instead of the __ macro because this
// is the instruction that gets patched and coverage code gets in the
// way.
cgen()->masm()->test(answer.reg(), Immediate(-delta_to_patch_site));
__ IncrementCounter(&Counters::named_load_inline_miss, 1);
receiver = cgen()->frame()->Pop();
exit_.Jump(&receiver, &answer);
}
void DeferredReferenceGetKeyedValue::Generate() {
CodeGenerator* cgen = generator();
Result receiver;
Result key;
enter()->Bind(&receiver, &key);
cgen->frame()->Push(&receiver); // First IC argument.
cgen->frame()->Push(&key); // Second IC argument.
cgen()->frame()->Push(&receiver); // First IC argument.
cgen()->frame()->Push(&key); // Second IC argument.
// Calculate the delta from the IC call instruction to the map check
// cmp instruction in the inlined version. This delta is stored in
@ -5356,28 +5343,30 @@ void DeferredReferenceGetKeyedValue::Generate() {
RelocInfo::Mode mode = is_global_
? RelocInfo::CODE_TARGET_CONTEXT
: RelocInfo::CODE_TARGET;
Result value = cgen->frame()->CallKeyedLoadIC(mode);
Result value = cgen()->frame()->CallKeyedLoadIC(mode);
// The result needs to be specifically the eax register because the
// offset to the patch site will be expected in a test eax
// instruction.
ASSERT(value.is_register() && value.reg().is(eax));
// The delta from the start of the map-compare instruction to the
// test instruction. We use masm_ directly here instead of the
// double underscore macro because the macro sometimes uses macro
// expansion to turn into something that can't return a value. This
// is encountered when doing generated code coverage tests.
int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
// Here we use masm_-> instead of the double underscore macro because this
// is the instruction that gets patched and coverage code gets in the way.
masm_->test(value.reg(), Immediate(-delta_to_patch_site));
// The delta from the start of the map-compare instruction to the test
// instruction. We use cgen()->masm() directly here instead of the __
// macro because the macro sometimes uses macro expansion to turn into
// something that can't return a value. This is encountered when
// doing generated code coverage tests.
int delta_to_patch_site =
cgen()->masm()->SizeOfCodeGeneratedSince(patch_site());
// Here we use cgen()->masm()-> instead of the __ macro because this
// is the instruction that gets patched and coverage code gets in the
// way.
cgen()->masm()->test(value.reg(), Immediate(-delta_to_patch_site));
__ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
// The receiver and key were spilled by the call, so their state as
// constants or copies has been changed. Thus, they need to be
// "mergable" in the block at the exit label and are therefore
// passed as return results here.
key = cgen->frame()->Pop();
receiver = cgen->frame()->Pop();
key = cgen()->frame()->Pop();
receiver = cgen()->frame()->Pop();
exit_.Jump(&receiver, &key, &value);
}
@ -5450,7 +5439,7 @@ void Reference::GetValue(TypeofState typeof_state) {
// Inline the inobject property case.
Comment cmnt(masm, "[ Inlined named property load");
DeferredReferenceGetNamedValue* deferred =
new DeferredReferenceGetNamedValue(cgen_, GetName());
new DeferredReferenceGetNamedValue(GetName());
Result receiver = cgen_->frame()->Pop();
receiver.ToRegister();
@ -5515,7 +5504,7 @@ void Reference::GetValue(TypeofState typeof_state) {
if (cgen_->loop_nesting() > 0) {
Comment cmnt(masm, "[ Inlined array index load");
DeferredReferenceGetKeyedValue* deferred =
new DeferredReferenceGetKeyedValue(cgen_, is_global);
new DeferredReferenceGetKeyedValue(is_global);
Result key = cgen_->frame()->Pop();
Result receiver = cgen_->frame()->Pop();
@ -5743,11 +5732,9 @@ void ToBooleanStub::Generate(MacroAssembler* masm) {
}
#undef __
#define __ ACCESS_MASM(masm_)
Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
Result* right) {
MacroAssembler* masm = cgen()->masm();
// Perform fast-case smi code for the operation (left <op> right) and
// returns the result in a Result.
// If any fast-case tests fail, it jumps to the slow-case deferred code,
@ -5761,7 +5748,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// A newly allocated register answer is used to hold the answer.
// The registers containing left and right are not modified in
// most cases, so they usually don't need to be spilled in the fast case.
Result answer = generator()->allocator()->Allocate();
Result answer = cgen()->allocator()->Allocate();
ASSERT(answer.is_valid());
// Perform the smi check.
@ -5832,8 +5819,8 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// from left and right, and is spilled.
// The value in left is copied to answer.
Result reg_eax = generator()->allocator()->Allocate(eax);
Result reg_edx = generator()->allocator()->Allocate(edx);
Result reg_eax = cgen()->allocator()->Allocate(eax);
Result reg_edx = cgen()->allocator()->Allocate(edx);
// These allocations may have failed, if one of left, right, or answer
// is in register eax or edx.
bool left_copied_to_eax = false; // We will make sure this becomes true.
@ -5847,7 +5834,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// We use answer if it is not edx, otherwise we allocate one.
if (answer.reg().is(edx)) {
reg_edx = answer;
answer = generator()->allocator()->Allocate();
answer = cgen()->allocator()->Allocate();
ASSERT(answer.is_valid());
}
@ -5878,7 +5865,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// Is answer used?
if (answer.reg().is(eax) || answer.reg().is(left->reg()) ||
answer.reg().is(right->reg())) {
answer = generator()->allocator()->Allocate();
answer = cgen()->allocator()->Allocate();
ASSERT(answer.is_valid()); // We cannot hit both Allocate() calls.
}
if (left->reg().is(edx)) {
@ -5897,12 +5884,12 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
ASSERT(!right->reg().is(eax));
answer = reg_eax; // May free answer, if it was never used.
generator()->frame()->Spill(eax);
cgen()->frame()->Spill(eax);
if (!left_copied_to_eax) {
__ mov(eax, left->reg());
left_copied_to_eax = true;
}
generator()->frame()->Spill(edx);
cgen()->frame()->Spill(edx);
// Postcondition:
// reg_eax, reg_edx are valid, correct, and spilled.
@ -5992,7 +5979,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// spilling left.
*left = answer;
} else if (left->reg().is(ecx)) {
generator()->frame()->Spill(left->reg());
cgen()->frame()->Spill(left->reg());
__ mov(left->reg(), right->reg());
*right = *left;
*left = answer; // Use copy of left in answer as left.
@ -6000,7 +5987,7 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
__ mov(answer.reg(), right->reg());
*right = answer;
} else {
Result reg_ecx = generator()->allocator()->Allocate(ecx);
Result reg_ecx = cgen()->allocator()->Allocate(ecx);
ASSERT(reg_ecx.is_valid());
__ mov(ecx, right->reg());
*right = reg_ecx;
@ -6018,8 +6005,8 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
// the same answer.
// We are modifying left and right. They must be spilled!
generator()->frame()->Spill(left->reg());
generator()->frame()->Spill(right->reg());
cgen()->frame()->Spill(left->reg());
cgen()->frame()->Spill(right->reg());
// Remove tags from operands (but keep sign).
__ sar(left->reg(), kSmiTagSize);
@ -6089,9 +6076,6 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left,
}
#undef __
#define __ ACCESS_MASM(masm)
void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
// Perform fast-case smi code for the operation (eax <op> ebx) and
// leave result in register eax.

View File

@ -333,8 +333,7 @@ class CodeGenerator: public AstVisitor {
// Accessors
Scope* scope() const { return scope_; }
// Clearing and generating deferred code.
void ClearDeferred();
// Generating deferred code.
void ProcessDeferred();
bool is_eval() { return is_eval_; }

View File

@ -333,8 +333,7 @@ class CodeGenerator: public AstVisitor {
// Accessors
Scope* scope() const { return scope_; }
// Clearing and generating deferred code.
void ClearDeferred();
// Generating deferred code.
void ProcessDeferred();
bool is_eval() { return is_eval_; }