Revision: 5018
Author: [email protected]
Date: Mon Jul 5 04:03:16 2010
Log: Specialize GenericUnaryStub so that it knows whether it needs to
take negative zero into account.
Review URL: http://codereview.chromium.org/2850043
http://code.google.com/p/v8/source/detail?r=5018
Modified:
/branches/bleeding_edge/src/arm/codegen-arm.cc
/branches/bleeding_edge/src/arm/full-codegen-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/codegen.cc
/branches/bleeding_edge/src/codegen.h
/branches/bleeding_edge/src/ia32/codegen-ia32.cc
/branches/bleeding_edge/src/ia32/full-codegen-ia32.cc
/branches/bleeding_edge/src/x64/codegen-x64.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Fri Jul 2 13:03:07 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc Mon Jul 5 04:03:16 2010
@@ -5423,9 +5423,13 @@
frame_->EmitPush(r0); // r0 has result
} else {
- bool overwrite =
+ bool can_overwrite =
(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
+
+ bool no_negative_zero = node->expression()->no_negative_zero();
Load(node->expression());
switch (op) {
case Token::NOT:
@@ -5436,7 +5440,10 @@
case Token::SUB: {
frame_->PopToR0();
- GenericUnaryOpStub stub(Token::SUB, overwrite);
+ GenericUnaryOpStub stub(
+ Token::SUB,
+ overwrite,
+ no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero);
frame_->CallStub(&stub, 0);
frame_->EmitPush(r0); // r0 has result
break;
@@ -8899,16 +8906,23 @@
// Go slow case if the value of the expression is zero
// to make sure that we switch between 0 and -0.
- __ cmp(r0, Operand(0));
- __ b(eq, &slow);
-
- // The value of the expression is a smi that is not zero. Try
- // optimistic subtraction '0 - value'.
- __ rsb(r1, r0, Operand(0), SetCC);
- __ b(vs, &slow);
-
- __ mov(r0, Operand(r1)); // Set r0 to result.
- __ b(&done);
+ if (negative_zero_ == kStrictNegativeZero) {
+ // If we have to check for zero, then we can check for the max
negative
+ // smi while we are at it.
+ __ bic(ip, r0, Operand(0x80000000), SetCC);
+ __ b(eq, &slow);
+ __ rsb(r0, r0, Operand(0));
+ __ StubReturn(1);
+ } else {
+ // The value of the expression is a smi and 0 is OK for -0. Try
+ // optimistic subtraction '0 - value'.
+ __ rsb(r0, r0, Operand(0), SetCC);
+ __ StubReturn(1, vc);
+ // We don't have to reverse the optimistic neg since the only case
+ // where we fall through is the minimum negative Smi, which is the
case
+ // where the neg leaves the register unchanged.
+ __ jmp(&slow); // Go slow on max negative Smi.
+ }
__ bind(&try_float);
__ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
@@ -8916,7 +8930,7 @@
__ cmp(r1, heap_number_map);
__ b(ne, &slow);
// r0 is a heap number. Get a new heap number in r1.
- if (overwrite_) {
+ if (overwrite_ == UNARY_OVERWRITE) {
__ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
__ eor(r2, r2, Operand(HeapNumber::kSignMask)); // Flip sign.
__ str(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
@@ -8949,7 +8963,7 @@
__ b(&done);
__ bind(&try_float);
- if (!overwrite_) {
+ if (!overwrite_ == UNARY_OVERWRITE) {
// Allocate a fresh heap number, but don't overwrite r0 until
// we're sure we can do it without going through the slow case
// that needs the value in r0.
=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Thu Jun 17 14:51:51
2010
+++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Mon Jul 5 04:03:16
2010
@@ -2736,9 +2736,11 @@
case Token::SUB: {
Comment cmt(masm_, "[ UnaryOperation (SUB)");
- bool overwrite =
+ bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register r0.
@@ -2750,9 +2752,11 @@
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
- bool overwrite =
+ bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register r0.
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Jun 30
05:27:49 2010
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Jul 5
04:03:16 2010
@@ -1372,12 +1372,12 @@
}
-void MacroAssembler::StubReturn(int argc) {
+void MacroAssembler::StubReturn(int argc, Condition cond) {
ASSERT(argc >= 1 && generating_stub());
if (argc > 1) {
- add(sp, sp, Operand((argc - 1) * kPointerSize));
- }
- Ret();
+ add(sp, sp, Operand((argc - 1) * kPointerSize), LeaveCC, cond);
+ }
+ Ret(cond);
}
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Jun 30
05:27:49 2010
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Jul 5
04:03:16 2010
@@ -537,7 +537,7 @@
void TailCallStub(CodeStub* stub, Condition cond = al);
// Return from a code stub after popping its arguments.
- void StubReturn(int argc);
+ void StubReturn(int argc, Condition cond = al);
// Call a runtime routine.
void CallRuntime(Runtime::Function* f, int num_arguments);
=======================================
--- /branches/bleeding_edge/src/codegen.cc Wed Jun 23 00:03:34 2010
+++ /branches/bleeding_edge/src/codegen.cc Mon Jul 5 04:03:16 2010
@@ -460,11 +460,17 @@
const char* GenericUnaryOpStub::GetName() {
switch (op_) {
case Token::SUB:
- return overwrite_
- ? "GenericUnaryOpStub_SUB_Overwrite"
- : "GenericUnaryOpStub_SUB_Alloc";
+ if (negative_zero_ == kStrictNegativeZero) {
+ return overwrite_ == UNARY_OVERWRITE
+ ? "GenericUnaryOpStub_SUB_Overwrite_Strict0"
+ : "GenericUnaryOpStub_SUB_Alloc_Strict0";
+ } else {
+ return overwrite_ == UNARY_OVERWRITE
+ ? "GenericUnaryOpStub_SUB_Overwrite_Ignore0"
+ : "GenericUnaryOpStub_SUB_Alloc_Ignore0";
+ }
case Token::BIT_NOT:
- return overwrite_
+ return overwrite_ == UNARY_OVERWRITE
? "GenericUnaryOpStub_BIT_NOT_Overwrite"
: "GenericUnaryOpStub_BIT_NOT_Alloc";
default:
=======================================
--- /branches/bleeding_edge/src/codegen.h Thu May 27 06:48:52 2010
+++ /branches/bleeding_edge/src/codegen.h Mon Jul 5 04:03:16 2010
@@ -75,6 +75,7 @@
// Mode to overwrite BinaryExpression values.
enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
// Types of uncatchable exceptions.
enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
@@ -414,21 +415,33 @@
};
+enum NegativeZeroHandling {
+ kStrictNegativeZero,
+ kIgnoreNegativeZero
+};
+
+
class GenericUnaryOpStub : public CodeStub {
public:
- GenericUnaryOpStub(Token::Value op, bool overwrite)
- : op_(op), overwrite_(overwrite) { }
+ GenericUnaryOpStub(Token::Value op,
+ UnaryOverwriteMode overwrite,
+ NegativeZeroHandling negative_zero =
kStrictNegativeZero)
+ : op_(op), overwrite_(overwrite), negative_zero_(negative_zero) { }
private:
Token::Value op_;
- bool overwrite_;
-
- class OverwriteField: public BitField<int, 0, 1> {};
- class OpField: public BitField<Token::Value, 1, kMinorBits - 1> {};
+ UnaryOverwriteMode overwrite_;
+ NegativeZeroHandling negative_zero_;
+
+ class OverwriteField: public BitField<UnaryOverwriteMode, 0, 1> {};
+ class NegativeZeroField: public BitField<NegativeZeroHandling, 1, 1> {};
+ class OpField: public BitField<Token::Value, 2, kMinorBits - 2> {};
Major MajorKey() { return GenericUnaryOp; }
int MinorKey() {
- return OpField::encode(op_) | OverwriteField::encode(overwrite_);
+ return OpField::encode(op_) |
+ OverwriteField::encode(overwrite_) |
+ NegativeZeroField::encode(negative_zero_);
}
void Generate(MacroAssembler* masm);
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Thu Jul 1 08:18:07
2010
+++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Jul 5 04:03:16
2010
@@ -7583,9 +7583,12 @@
frame_->Push(&value);
} else {
Load(node->expression());
- bool overwrite =
+ bool can_overwrite =
(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
+ bool no_negative_zero = node->expression()->no_negative_zero();
switch (op) {
case Token::NOT:
case Token::DELETE:
@@ -7594,7 +7597,10 @@
break;
case Token::SUB: {
- GenericUnaryOpStub stub(Token::SUB, overwrite);
+ GenericUnaryOpStub stub(
+ Token::SUB,
+ overwrite,
+ no_negative_zero ? kIgnoreNegativeZero :
kStrictNegativeZero);
Result operand = frame_->Pop();
Result answer = frame_->CallStub(&stub, &operand);
answer.set_type_info(TypeInfo::Number());
@@ -10934,10 +10940,12 @@
__ test(eax, Immediate(kSmiTagMask));
__ j(not_zero, &try_float, not_taken);
- // Go slow case if the value of the expression is zero
- // to make sure that we switch between 0 and -0.
- __ test(eax, Operand(eax));
- __ j(zero, &slow, not_taken);
+ if (negative_zero_ == kStrictNegativeZero) {
+ // Go slow case if the value of the expression is zero
+ // to make sure that we switch between 0 and -0.
+ __ test(eax, Operand(eax));
+ __ j(zero, &slow, not_taken);
+ }
// The value of the expression is a smi that is not zero. Try
// optimistic subtraction '0 - value'.
@@ -10945,11 +10953,7 @@
__ mov(edx, Operand(eax));
__ Set(eax, Immediate(0));
__ sub(eax, Operand(edx));
- __ j(overflow, &undo, not_taken);
-
- // If result is a smi we are done.
- __ test(eax, Immediate(kSmiTagMask));
- __ j(zero, &done, taken);
+ __ j(no_overflow, &done, taken);
// Restore eax and go slow case.
__ bind(&undo);
@@ -10961,7 +10965,7 @@
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
__ cmp(edx, Factory::heap_number_map());
__ j(not_equal, &slow);
- if (overwrite_) {
+ if (overwrite_ == UNARY_OVERWRITE) {
__ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
__ xor_(edx, HeapNumber::kSignMask); // Flip sign.
__ mov(FieldOperand(eax, HeapNumber::kExponentOffset), edx);
@@ -11002,7 +11006,7 @@
// Try to store the result in a heap number.
__ bind(&try_float);
- if (!overwrite_) {
+ if (overwrite_ == UNARY_NO_OVERWRITE) {
// Allocate a fresh heap number, but don't overwrite eax until
// we're sure we can do it without going through the slow case
// that needs the value in eax.
=======================================
--- /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Thu Jun 24
05:31:49 2010
+++ /branches/bleeding_edge/src/ia32/full-codegen-ia32.cc Mon Jul 5
04:03:16 2010
@@ -2813,9 +2813,11 @@
case Token::SUB: {
Comment cmt(masm_, "[ UnaryOperation (SUB)");
- bool overwrite =
+ bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register eax.
@@ -2827,9 +2829,11 @@
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
- bool overwrite =
+ bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register eax.
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Fri Jul 2 07:09:35 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc Mon Jul 5 04:03:16 2010
@@ -3373,9 +3373,12 @@
}
} else {
- bool overwrite =
+ bool can_overwrite =
(node->expression()->AsBinaryOperation() != NULL &&
node->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
+ bool no_negative_zero = node->expression()->no_negative_zero();
Load(node->expression());
switch (op) {
case Token::NOT:
@@ -3385,7 +3388,10 @@
break;
case Token::SUB: {
- GenericUnaryOpStub stub(Token::SUB, overwrite);
+ GenericUnaryOpStub stub(
+ Token::SUB,
+ overwrite,
+ no_negative_zero ? kIgnoreNegativeZero : kStrictNegativeZero);
Result operand = frame_->Pop();
Result answer = frame_->CallStub(&stub, &operand);
answer.set_type_info(TypeInfo::Number());
@@ -8506,6 +8512,11 @@
Label try_float;
__ JumpIfNotSmi(rax, &try_float);
+ if (negative_zero_ == kIgnoreNegativeZero) {
+ __ SmiCompare(rax, Smi::FromInt(0));
+ __ j(equal, &done);
+ }
+
// Enter runtime system if the value of the smi is zero
// to make sure that we switch between 0 and -0.
// Also enter it if the value of the smi is Smi::kMinValue.
@@ -8513,10 +8524,14 @@
// Either zero or Smi::kMinValue, neither of which become a smi when
// negated.
- __ SmiCompare(rax, Smi::FromInt(0));
- __ j(not_equal, &slow);
- __ Move(rax, Factory::minus_zero_value());
- __ jmp(&done);
+ if (negative_zero_ == kStrictNegativeZero) {
+ __ SmiCompare(rax, Smi::FromInt(0));
+ __ j(not_equal, &slow);
+ __ Move(rax, Factory::minus_zero_value());
+ __ jmp(&done);
+ } else {
+ __ jmp(&slow);
+ }
// Try floating point case.
__ bind(&try_float);
@@ -8529,7 +8544,7 @@
__ shl(kScratchRegister, Immediate(63));
__ xor_(rdx, kScratchRegister); // Flip sign.
// rdx is value to store.
- if (overwrite_) {
+ if (overwrite_ == UNARY_OVERWRITE) {
__ movq(FieldOperand(rax, HeapNumber::kValueOffset), rdx);
} else {
__ AllocateHeapNumber(rcx, rbx, &slow);
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Thu Jun 24 07:02:36
2010
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Mon Jul 5 04:03:16
2010
@@ -2807,9 +2807,11 @@
case Token::SUB: {
Comment cmt(masm_, "[ UnaryOperation (SUB)");
- bool overwrite =
+ bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::SUB, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register rax.
@@ -2821,9 +2823,11 @@
case Token::BIT_NOT: {
Comment cmt(masm_, "[ UnaryOperation (BIT_NOT)");
- bool overwrite =
+ bool can_overwrite =
(expr->expression()->AsBinaryOperation() != NULL &&
expr->expression()->AsBinaryOperation()->ResultOverwriteAllowed());
+ UnaryOverwriteMode overwrite =
+ can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
GenericUnaryOpStub stub(Token::BIT_NOT, overwrite);
// GenericUnaryOpStub expects the argument to be in the
// accumulator register rax.
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev