Start using the overwrite mode from the full codegens to generate

slightly better code and allow passing arguments to binary op stubs
in registers on the platforms that support it.
Review URL: http://codereview.chromium.org/3203005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5339 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kasperl@chromium.org 2010-08-25 11:10:05 +00:00
parent 82309445ad
commit 3c26a55def
12 changed files with 151 additions and 134 deletions

View File

@ -3550,9 +3550,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) {
// Perform the binary operation.
Literal* literal = node->value()->AsLiteral();
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
if (literal != NULL && literal->handle()->IsSmi()) {
SmiOperation(node->binary_op(),
literal->handle(),
@ -3650,9 +3648,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
// Perform the binary operation.
Literal* literal = node->value()->AsLiteral();
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
if (literal != NULL && literal->handle()->IsSmi()) {
SmiOperation(node->binary_op(),
literal->handle(),
@ -3766,9 +3762,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
// Perform the binary operation.
Literal* literal = node->value()->AsLiteral();
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
if (literal != NULL && literal->handle()->IsSmi()) {
SmiOperation(node->binary_op(),
literal->handle(),
@ -5755,9 +5749,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
frame_->EmitPush(r0); // r0 has result
} else {
bool can_overwrite =
(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = node->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
@ -6081,12 +6073,8 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
Literal* rliteral = node->right()->AsLiteral();
// NOTE: The code below assumes that the slow cases (calls to runtime)
// never return a constant/immutable object.
bool overwrite_left =
(node->left()->AsBinaryOperation() != NULL &&
node->left()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_right =
(node->right()->AsBinaryOperation() != NULL &&
node->right()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_left = node->left()->ResultOverwriteAllowed();
bool overwrite_right = node->right()->ResultOverwriteAllowed();
if (rliteral != NULL && rliteral->handle()->IsSmi()) {
VirtualFrame::RegisterAllocationScope scope(this);

View File

@ -1207,7 +1207,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
if (expr->is_compound()) {
Location saved_location = location_;
location_ = kAccumulator;
EmitBinaryOp(expr->binary_op(), Expression::kValue);
OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
? OVERWRITE_RIGHT
: NO_OVERWRITE;
EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
location_ = saved_location;
}
@ -1250,9 +1253,10 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
Expression::Context context) {
Expression::Context context,
OverwriteMode mode) {
__ pop(r1);
GenericBinaryOpStub stub(op, NO_OVERWRITE, r1, r0);
GenericBinaryOpStub stub(op, mode, r1, r0);
__ CallStub(&stub);
Apply(context, r0);
}
@ -2654,9 +2658,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::SUB: {
Comment cmt(masm_, "[ UnaryOperation (SUB)");
bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite);
@ -2670,9 +2672,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
@ -2791,7 +2791,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Inline smi case if we are in a loop.
Label stub_call, done;
int count_value = expr->op() == Token::INC ? 1 : -1;
if (loop_depth() > 0) {
if (ShouldInlineSmiCase(expr->op())) {
__ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
__ b(vs, &stub_call);
// We could eliminate this smi check if we split the code at
@ -2998,7 +2998,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
VisitForValue(expr->left(), kStack);
switch (expr->op()) {
switch (op) {
case Token::IN:
VisitForValue(expr->right(), kStack);
__ InvokeBuiltin(Builtins::IN, CALL_JS);
@ -3021,7 +3021,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForValue(expr->right(), kAccumulator);
Condition cc = eq;
bool strict = false;
switch (expr->op()) {
switch (op) {
case Token::EQ_STRICT:
strict = true;
// Fall through

View File

@ -239,6 +239,42 @@ void Expression::CopyAnalysisResultsFrom(Expression* other) {
}
bool UnaryOperation::ResultOverwriteAllowed() {
switch (op_) {
case Token::BIT_NOT:
case Token::SUB:
return true;
default:
return false;
}
}
bool BinaryOperation::ResultOverwriteAllowed() {
switch (op_) {
case Token::COMMA:
case Token::OR:
case Token::AND:
return false;
case Token::BIT_OR:
case Token::BIT_XOR:
case Token::BIT_AND:
case Token::SHL:
case Token::SAR:
case Token::SHR:
case Token::ADD:
case Token::SUB:
case Token::MUL:
case Token::DIV:
case Token::MOD:
return true;
default:
UNREACHABLE();
}
return false;
}
BinaryOperation::BinaryOperation(Assignment* assignment) {
ASSERT(assignment->is_compound());
op_ = assignment->binary_op();

View File

@ -201,6 +201,10 @@ class Expression: public AstNode {
// (faster) prefix increments.
virtual void MarkAsStatement() { /* do nothing */ }
// True iff the result can be safely overwritten (to avoid allocation).
// False for operations that can return one of their operands.
virtual bool ResultOverwriteAllowed() { return false; }
// Static type information for this expression.
StaticType* type() { return &type_; }
@ -1187,6 +1191,7 @@ class UnaryOperation: public Expression {
}
virtual void Accept(AstVisitor* v);
virtual bool ResultOverwriteAllowed();
// Type testing & conversion
virtual UnaryOperation* AsUnaryOperation() { return this; }
@ -1214,36 +1219,11 @@ class BinaryOperation: public Expression {
explicit BinaryOperation(Assignment* assignment);
virtual void Accept(AstVisitor* v);
virtual bool ResultOverwriteAllowed();
// Type testing & conversion
virtual BinaryOperation* AsBinaryOperation() { return this; }
// True iff the result can be safely overwritten (to avoid allocation).
// False for operations that can return one of their operands.
bool ResultOverwriteAllowed() {
switch (op_) {
case Token::COMMA:
case Token::OR:
case Token::AND:
return false;
case Token::BIT_OR:
case Token::BIT_XOR:
case Token::BIT_AND:
case Token::SHL:
case Token::SAR:
case Token::SHR:
case Token::ADD:
case Token::SUB:
case Token::MUL:
case Token::DIV:
case Token::MOD:
return true;
default:
UNREACHABLE();
}
return false;
}
Token::Value op() const { return op_; }
Expression* left() const { return left_; }
Expression* right() const { return right_; }

View File

@ -317,6 +317,13 @@ int FullCodeGenerator::SlotOffset(Slot* slot) {
}
bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) {
if (Debugger::IsDebuggerActive()) return false;
if (op == Token::DIV ||op == Token::MOD) return false;
return loop_depth_ > 0;
}
void FullCodeGenerator::PrepareTest(Label* materialize_true,
Label* materialize_false,
Label** if_true,
@ -503,6 +510,14 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) {
void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
Comment cmnt(masm_, "[ BinaryOperation");
OverwriteMode overwrite_mode = NO_OVERWRITE;
if (expr->left()->ResultOverwriteAllowed()) {
overwrite_mode = OVERWRITE_LEFT;
} else if (expr->right()->ResultOverwriteAllowed()) {
overwrite_mode = OVERWRITE_RIGHT;
}
switch (expr->op()) {
case Token::COMMA:
VisitForEffect(expr->left());
@ -528,7 +543,7 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
VisitForValue(expr->left(), kStack);
VisitForValue(expr->right(), kAccumulator);
SetSourcePosition(expr->position());
EmitBinaryOp(expr->op(), context_);
EmitBinaryOp(expr->op(), context_, overwrite_mode);
break;
default:

View File

@ -237,8 +237,14 @@ class FullCodeGenerator: public AstVisitor {
kStack
};
// Compute the frame pointer relative offset for a given local or
// parameter slot.
int SlotOffset(Slot* slot);
// Determine whether or not to inline the smi case for the given
// operation.
bool ShouldInlineSmiCase(Token::Value op);
// Emit code to convert a pure value (in a register, slot, as a literal,
// or on top of the stack) into the result expected according to an
// expression context.
@ -383,7 +389,9 @@ class FullCodeGenerator: public AstVisitor {
// Apply the compound assignment operator. Expects the left operand on top
// of the stack and the right one in the accumulator.
void EmitBinaryOp(Token::Value op, Expression::Context context);
void EmitBinaryOp(Token::Value op,
Expression::Context context,
OverwriteMode mode);
// Assign to the given expression as if via '='. The right-hand-side value
// is expected in the accumulator.

View File

@ -117,6 +117,11 @@ class GenericBinaryOpStub: public CodeStub {
Result* left,
Result* right);
bool ArgsInRegistersSupported() {
return op_ == Token::ADD || op_ == Token::SUB
|| op_ == Token::MUL || op_ == Token::DIV;
}
private:
Token::Value op_;
OverwriteMode mode_;
@ -181,10 +186,6 @@ class GenericBinaryOpStub: public CodeStub {
void GenerateRegisterArgsPush(MacroAssembler* masm);
void GenerateTypeTransition(MacroAssembler* masm);
bool ArgsInRegistersSupported() {
return op_ == Token::ADD || op_ == Token::SUB
|| op_ == Token::MUL || op_ == Token::DIV;
}
bool IsOperationCommutative() {
return (op_ == Token::ADD) || (op_ == Token::MUL);
}

View File

@ -5692,9 +5692,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) {
Load(node->value());
// Perform the binary operation.
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
// Construct the implicit binary operation.
BinaryOperation expr(node);
GenericBinaryOperation(&expr,
@ -5783,9 +5781,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
frame()->Push(&value);
Load(node->value());
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
// Construct the implicit binary operation.
BinaryOperation expr(node);
GenericBinaryOperation(&expr,
@ -5885,9 +5881,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
Load(node->value());
// Perform the binary operation.
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
BinaryOperation expr(node);
GenericBinaryOperation(&expr,
overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
@ -8087,9 +8081,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
frame_->Push(&value);
} else {
Load(node->expression());
bool can_overwrite =
(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = node->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
bool no_negative_zero = node->expression()->no_negative_zero();
@ -8794,11 +8786,9 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// NOTE: The code below assumes that the slow cases (calls to runtime)
// never return a constant/immutable object.
OverwriteMode overwrite_mode = NO_OVERWRITE;
if (node->left()->AsBinaryOperation() != NULL &&
node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
if (node->left()->ResultOverwriteAllowed()) {
overwrite_mode = OVERWRITE_LEFT;
} else if (node->right()->AsBinaryOperation() != NULL &&
node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
} else if (node->right()->ResultOverwriteAllowed()) {
overwrite_mode = OVERWRITE_RIGHT;
}

View File

@ -1214,7 +1214,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
if (expr->is_compound()) {
Location saved_location = location_;
location_ = kAccumulator;
EmitBinaryOp(expr->binary_op(), Expression::kValue);
OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
? OVERWRITE_RIGHT
: NO_OVERWRITE;
EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
location_ = saved_location;
}
@ -1257,13 +1260,17 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
Expression::Context context) {
__ push(result_register());
GenericBinaryOpStub stub(op,
NO_OVERWRITE,
NO_GENERIC_BINARY_FLAGS,
TypeInfo::Unknown());
__ CallStub(&stub);
Expression::Context context,
OverwriteMode mode) {
TypeInfo type = TypeInfo::Unknown();
GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS, type);
if (stub.ArgsInRegistersSupported()) {
__ pop(edx);
stub.GenerateCall(masm_, edx, eax);
} else {
__ push(result_register());
__ CallStub(&stub);
}
Apply(context, eax);
}
@ -2651,9 +2658,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::SUB: {
Comment cmt(masm_, "[ UnaryOperation (SUB)");
bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite);
@ -2667,9 +2672,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
@ -2750,8 +2753,10 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Call ToNumber only if operand is not a smi.
Label no_conversion;
__ test(eax, Immediate(kSmiTagMask));
__ j(zero, &no_conversion);
if (ShouldInlineSmiCase(expr->op())) {
__ test(eax, Immediate(kSmiTagMask));
__ j(zero, &no_conversion);
}
__ push(eax);
__ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
__ bind(&no_conversion);
@ -2786,7 +2791,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Inline smi case if we are in a loop.
Label stub_call, done;
if (loop_depth() > 0) {
if (ShouldInlineSmiCase(expr->op())) {
if (expr->op() == Token::INC) {
__ add(Operand(eax), Immediate(Smi::FromInt(1)));
} else {
@ -3027,7 +3032,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForValue(expr->right(), kAccumulator);
Condition cc = no_condition;
bool strict = false;
switch (expr->op()) {
switch (op) {
case Token::EQ_STRICT:
strict = true;
// Fall through
@ -3061,8 +3066,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
UNREACHABLE();
}
// The comparison stub expects the smi vs. smi case to be handled
// before it is called.
// The comparison stub expects the smi vs. smi case to be
// handled before it is called.
Label slow_case;
__ mov(ecx, Operand(edx));
__ or_(ecx, Operand(eax));

View File

@ -112,6 +112,11 @@ class GenericBinaryOpStub: public CodeStub {
Result* left,
Result* right);
bool ArgsInRegistersSupported() {
return (op_ == Token::ADD) || (op_ == Token::SUB)
|| (op_ == Token::MUL) || (op_ == Token::DIV);
}
private:
Token::Value op_;
OverwriteMode mode_;
@ -172,10 +177,6 @@ class GenericBinaryOpStub: public CodeStub {
void GenerateRegisterArgsPush(MacroAssembler* masm);
void GenerateTypeTransition(MacroAssembler* masm);
bool ArgsInRegistersSupported() {
return (op_ == Token::ADD) || (op_ == Token::SUB)
|| (op_ == Token::MUL) || (op_ == Token::DIV);
}
bool IsOperationCommutative() {
return (op_ == Token::ADD) || (op_ == Token::MUL);
}

View File

@ -5009,9 +5009,7 @@ void CodeGenerator::EmitSlotAssignment(Assignment* node) {
Load(node->value());
// Perform the binary operation.
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
// Construct the implicit binary operation.
BinaryOperation expr(node);
GenericBinaryOperation(&expr,
@ -5100,9 +5098,7 @@ void CodeGenerator::EmitNamedPropertyAssignment(Assignment* node) {
frame()->Push(&value);
Load(node->value());
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
// Construct the implicit binary operation.
BinaryOperation expr(node);
GenericBinaryOperation(&expr,
@ -5202,9 +5198,7 @@ void CodeGenerator::EmitKeyedPropertyAssignment(Assignment* node) {
Load(node->value());
// Perform the binary operation.
bool overwrite_value =
(node->value()->AsBinaryOperation() != NULL &&
node->value()->AsBinaryOperation()->ResultOverwriteAllowed());
bool overwrite_value = node->value()->ResultOverwriteAllowed();
BinaryOperation expr(node);
GenericBinaryOperation(&expr,
overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE);
@ -7357,9 +7351,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
}
} else {
bool can_overwrite =
(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = node->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
bool no_negative_zero = node->expression()->no_negative_zero();
@ -7777,11 +7769,9 @@ void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
// NOTE: The code below assumes that the slow cases (calls to runtime)
// never return a constant/immutable object.
OverwriteMode overwrite_mode = NO_OVERWRITE;
if (node->left()->AsBinaryOperation() != NULL &&
node->left()->AsBinaryOperation()->ResultOverwriteAllowed()) {
if (node->left()->ResultOverwriteAllowed()) {
overwrite_mode = OVERWRITE_LEFT;
} else if (node->right()->AsBinaryOperation() != NULL &&
node->right()->AsBinaryOperation()->ResultOverwriteAllowed()) {
} else if (node->right()->ResultOverwriteAllowed()) {
overwrite_mode = OVERWRITE_RIGHT;
}

View File

@ -1218,7 +1218,10 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
if (expr->is_compound()) {
Location saved_location = location_;
location_ = kAccumulator;
EmitBinaryOp(expr->binary_op(), Expression::kValue);
OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
? OVERWRITE_RIGHT
: NO_OVERWRITE;
EmitBinaryOp(expr->binary_op(), Expression::kValue, mode);
location_ = saved_location;
}
@ -1261,12 +1264,16 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
void FullCodeGenerator::EmitBinaryOp(Token::Value op,
Expression::Context context) {
__ push(result_register());
GenericBinaryOpStub stub(op,
NO_OVERWRITE,
NO_GENERIC_BINARY_FLAGS);
__ CallStub(&stub);
Expression::Context context,
OverwriteMode mode) {
GenericBinaryOpStub stub(op, mode, NO_GENERIC_BINARY_FLAGS);
if (stub.ArgsInRegistersSupported()) {
__ pop(rdx);
stub.GenerateCall(masm_, rdx, rax);
} else {
__ push(result_register());
__ CallStub(&stub);
}
Apply(context, rax);
}
@ -2646,9 +2653,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::SUB: {
Comment cmt(masm_, "[ UnaryOperation (SUB)");
bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite);
@ -2662,9 +2667,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
bool can_overwrite = expr->expression()->ResultOverwriteAllowed();
UnaryOverwriteMode overwrite =
can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
@ -2780,7 +2783,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Inline smi case if we are in a loop.
Label stub_call, done;
if (loop_depth() > 0) {
if (ShouldInlineSmiCase(expr->op())) {
if (expr->op() == Token::INC) {
__ SmiAddConstant(rax, rax, Smi::FromInt(1));
} else {
@ -2995,7 +2998,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
VisitForValue(expr->left(), kStack);
switch (expr->op()) {
switch (op) {
case Token::IN:
VisitForValue(expr->right(), kStack);
__ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
@ -3017,7 +3020,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForValue(expr->right(), kAccumulator);
Condition cc = no_condition;
bool strict = false;
switch (expr->op()) {
switch (op) {
case Token::EQ_STRICT:
strict = true;
// Fall through.