Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(784)

Unified Diff: src/x64/lithium-codegen-x64.cc

Issue 21014003: Optionally use 31-bits SMI value for 64-bit system (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed danno's comments Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index dbdc12e63f207bfe1e35ef52ce50488ecd133980..91d14e7b5db5e8c19705841d54f4968825324b0e 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -64,6 +64,33 @@ class SafepointGenerator : public CallWrapper {
};
+class LithiumSmiInstructionWrapper
+ : public MacroAssembler::SmiInstructionWrapper {
+ public:
+ LithiumSmiInstructionWrapper(LCodeGen* codegen,
+ LEnvironment* environment,
+ bool check_overflow = false,
+ bool check_minus_zero = false)
+ : codegen_(codegen),
+ environment_(environment),
+ check_overflow_(check_overflow),
+ check_minus_zero_(check_minus_zero) { }
+ virtual ~LithiumSmiInstructionWrapper() { }
+ virtual bool NeedsCheckOverflow() const { return check_overflow_; }
+ virtual bool NeedsCheckMinusZero() const { return check_minus_zero_; }
+ virtual bool NeedsKeepSourceOperandsIntact() const { return false; }
+ virtual void BailoutIf(Condition cc) const {
+ codegen_->DeoptimizeIf(cc, environment_);
+ }
+
+ private:
+ LCodeGen* codegen_;
+ LEnvironment* environment_;
+ bool check_overflow_;
+ bool check_minus_zero_;
+};
+
+
#define __ masm()->
bool LCodeGen::GenerateCode() {
@@ -416,8 +443,17 @@ bool LCodeGen::IsTaggedConstant(LConstantOperand* op) const {
int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
+ return ToRepresentation(op, Representation::Integer32());
+}
+
+
+int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
+ const Representation& r) const {
HConstant* constant = chunk_->LookupConstant(op);
- return constant->Integer32Value();
+ int32_t value = constant->Integer32Value();
+ if (r.IsInteger32()) return value;
+ ASSERT(r.IsSmiOrTagged());
+ return static_cast<int32_t>(reinterpret_cast<intptr_t>(Smi::FromInt(value)));
}
@@ -1362,16 +1398,31 @@ void LCodeGen::DoBitI(LBitI* instr) {
ASSERT(left->IsRegister());
if (right->IsConstantOperand()) {
- int right_operand = ToInteger32(LConstantOperand::cast(right));
+ int32_t right_value = ToInteger32(LConstantOperand::cast(right));
switch (instr->op()) {
case Token::BIT_AND:
- __ andl(ToRegister(left), Immediate(right_operand));
+ if (instr->hydrogen()->representation().IsSmi()) {
+ __ SmiAndConstant(ToRegister(left), ToRegister(left),
+ Smi::FromInt(right_value));
+ } else {
+ __ andl(ToRegister(left), Immediate(right_value));
+ }
break;
case Token::BIT_OR:
- __ orl(ToRegister(left), Immediate(right_operand));
+ if (instr->hydrogen()->representation().IsSmi()) {
+ __ SmiOrConstant(ToRegister(left), ToRegister(left),
+ Smi::FromInt(right_value));
+ } else {
+ __ orl(ToRegister(left), Immediate(right_value));
+ }
break;
case Token::BIT_XOR:
- __ xorl(ToRegister(left), Immediate(right_operand));
+ if (instr->hydrogen()->representation().IsSmi()) {
+ __ SmiXorConstant(ToRegister(left), ToRegister(left),
+ Smi::FromInt(right_value));
+ } else {
+ __ xorl(ToRegister(left), Immediate(right_value));
+ }
break;
default:
UNREACHABLE();
@@ -1466,7 +1517,14 @@ void LCodeGen::DoShiftI(LShiftI* instr) {
case Token::SHL:
if (shift_count != 0) {
if (instr->hydrogen_value()->representation().IsSmi()) {
- __ shl(ToRegister(left), Immediate(shift_count));
+ if (SmiValuesAre32Bits() || !instr->can_deopt()) {
+ __ shl(ToRegister(left), Immediate(shift_count));
+ } else {
+ ASSERT(SmiValuesAre31Bits() && instr->can_deopt());
+ LithiumSmiInstructionWrapper wrapper(this, instr->environment());
+ __ SmiShiftLeftConstant(ToRegister(left), ToRegister(left),
+ shift_count, wrapper);
+ }
} else {
__ shll(ToRegister(left), Immediate(shift_count));
}
@@ -1485,24 +1543,33 @@ void LCodeGen::DoSubI(LSubI* instr) {
LOperand* right = instr->right();
ASSERT(left->Equals(instr->result()));
+ bool check_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+ LithiumSmiInstructionWrapper wrapper(this, instr->environment(),
+ check_overflow);
if (right->IsConstantOperand()) {
- __ subl(ToRegister(left),
- Immediate(ToInteger32(LConstantOperand::cast(right))));
+ int32_t right_value = ToInteger32(LConstantOperand::cast(right));
+ if (instr->hydrogen()->representation().IsSmi()) {
+ __ SmiSubConstant(ToRegister(left), ToRegister(left),
+ Smi::FromInt(right_value), wrapper);
+ } else {
+ __ subl(ToRegister(left), Immediate(right_value));
+ }
} else if (right->IsRegister()) {
if (instr->hydrogen_value()->representation().IsSmi()) {
- __ subq(ToRegister(left), ToRegister(right));
+ __ SmiSub(ToRegister(left), ToRegister(left), ToRegister(right), wrapper);
} else {
__ subl(ToRegister(left), ToRegister(right));
}
} else {
if (instr->hydrogen_value()->representation().IsSmi()) {
- __ subq(ToRegister(left), ToOperand(right));
+ __ SmiSub(ToRegister(left), ToRegister(left), ToOperand(right), wrapper);
} else {
__ subl(ToRegister(left), ToOperand(right));
}
}
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ if (instr->hydrogen_value()->representation().IsInteger32() &&
+ check_overflow) {
DeoptimizeIf(overflow, instr->environment());
}
}
@@ -1680,9 +1747,15 @@ void LCodeGen::DoAddI(LAddI* instr) {
if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
if (right->IsConstantOperand()) {
- int32_t offset = ToInteger32(LConstantOperand::cast(right));
- __ leal(ToRegister(instr->result()),
- MemOperand(ToRegister(left), offset));
+ int32_t offset = ToRepresentation(LConstantOperand::cast(right),
+ instr->hydrogen()->representation());
+ if (instr->hydrogen()->representation().IsSmi()) {
+ __ lea(ToRegister(instr->result()),
+ MemOperand(ToRegister(left), offset));
+ } else {
+ __ leal(ToRegister(instr->result()),
+ MemOperand(ToRegister(left), offset));
+ }
} else {
Operand address(ToRegister(left), ToRegister(right), times_1, 0);
if (instr->hydrogen()->representation().IsSmi()) {
@@ -1692,23 +1765,35 @@ void LCodeGen::DoAddI(LAddI* instr) {
}
}
} else {
+ bool check_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
+ LithiumSmiInstructionWrapper wrapper(this, instr->environment(),
+ check_overflow);
if (right->IsConstantOperand()) {
- __ addl(ToRegister(left),
- Immediate(ToInteger32(LConstantOperand::cast(right))));
+ int32_t right_value = ToInteger32(LConstantOperand::cast(right));
+ if (instr->hydrogen()->representation().IsSmi()) {
+ __ SmiAddConstant(ToRegister(left), ToRegister(left),
+ Smi::FromInt(right_value), wrapper);
+ } else {
+ __ addl(ToRegister(left), Immediate(right_value));
+ }
} else if (right->IsRegister()) {
if (instr->hydrogen_value()->representation().IsSmi()) {
- __ addq(ToRegister(left), ToRegister(right));
+ __ SmiAdd(ToRegister(left), ToRegister(left), ToRegister(right),
+ wrapper);
} else {
__ addl(ToRegister(left), ToRegister(right));
}
} else {
if (instr->hydrogen_value()->representation().IsSmi()) {
- __ addq(ToRegister(left), ToOperand(right));
+ __ SmiAdd(ToRegister(left), ToRegister(left), ToOperand(right),
+ wrapper);
} else {
__ addl(ToRegister(left), ToOperand(right));
}
}
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+
+ if (instr->hydrogen_value()->representation().IsInteger32() &&
+ check_overflow) {
DeoptimizeIf(overflow, instr->environment());
}
}
@@ -1728,8 +1813,8 @@ void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
Register left_reg = ToRegister(left);
if (right->IsConstantOperand()) {
Immediate right_imm =
- Immediate(ToInteger32(LConstantOperand::cast(right)));
- ASSERT(!instr->hydrogen_value()->representation().IsSmi());
+ Immediate(ToRepresentation(LConstantOperand::cast(right),
+ instr->hydrogen()->representation()));
__ cmpl(left_reg, right_imm);
__ j(condition, &return_left, Label::kNear);
__ movq(left_reg, right_imm);
@@ -2927,7 +3012,10 @@ void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
// gets replaced during bound check elimination with the index argument
// to the bounds check, which can be tagged, so that case must be
// handled here, too.
- if (instr->hydrogen()->IsDehoisted()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
+ ASSERT(SmiValuesAre31Bits());
+ __ SmiToInteger64(key_reg, key_reg);
+ } else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
@@ -2998,7 +3086,10 @@ void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
// representation for the key to be an integer, the input gets replaced
// during bound check elimination with the index argument to the bounds
// check, which can be tagged, so that case must be handled here, too.
- if (instr->hydrogen()->IsDehoisted()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
+ ASSERT(SmiValuesAre31Bits());
+ __ SmiToInteger64(key_reg, key_reg);
+ } else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
@@ -3038,7 +3129,10 @@ void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
// gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that
// case must be handled here, too.
- if (instr->hydrogen()->IsDehoisted()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
+ ASSERT(SmiValuesAre31Bits());
+ __ SmiToInteger64(key_reg, key_reg);
+ } else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
@@ -3426,12 +3520,17 @@ void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
}
-void LCodeGen::EmitInteger64MathAbs(LMathAbs* instr) {
+void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
Register input_reg = ToRegister(instr->value());
__ testq(input_reg, input_reg);
Label is_positive;
__ j(not_sign, &is_positive, Label::kNear);
- __ neg(input_reg); // Sets flags.
+ if (SmiValuesAre32Bits()) {
+ __ neg(input_reg); // Sets flags.
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ __ negl(input_reg); // Sets flags.
+ }
DeoptimizeIf(negative, instr->environment());
__ bind(&is_positive);
}
@@ -3463,16 +3562,14 @@ void LCodeGen::DoMathAbs(LMathAbs* instr) {
} else if (r.IsInteger32()) {
EmitIntegerMathAbs(instr);
} else if (r.IsSmi()) {
- EmitInteger64MathAbs(instr);
+ EmitSmiMathAbs(instr);
} else { // Tagged case.
DeferredMathAbsTaggedHeapNumber* deferred =
new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr);
Register input_reg = ToRegister(instr->value());
// Smi check.
__ JumpIfNotSmi(input_reg, deferred->entry());
- __ SmiToInteger32(input_reg, input_reg);
- EmitIntegerMathAbs(instr);
- __ Integer32ToSmi(input_reg, input_reg);
+ EmitSmiMathAbs(instr);
__ bind(deferred->exit());
}
}
@@ -4140,7 +4237,10 @@ void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
// gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that case
// must be handled here, too.
- if (instr->hydrogen()->IsDehoisted()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
+ ASSERT(SmiValuesAre31Bits());
+ __ SmiToInteger64(key_reg, key_reg);
+ } else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
@@ -4202,7 +4302,10 @@ void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
// input gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that case
// must be handled here, too.
- if (instr->hydrogen()->IsDehoisted()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
+ ASSERT(SmiValuesAre31Bits());
+ __ SmiToInteger64(key_reg, key_reg);
+ } else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
@@ -4243,7 +4346,10 @@ void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
// input gets replaced during bound check elimination with the index
// argument to the bounds check, which can be tagged, so that case
// must be handled here, too.
- if (instr->hydrogen()->IsDehoisted()) {
+ if (instr->hydrogen()->key()->representation().IsSmi()) {
+ ASSERT(SmiValuesAre31Bits());
+ __ SmiToInteger64(key_reg, key_reg);
+ } else if (instr->hydrogen()->IsDehoisted()) {
// Sign extend key because it could be a 32 bit negative value
// and the dehoisted address computation happens in 64 bits
__ movsxlq(key_reg, key_reg);
@@ -4500,11 +4606,77 @@ void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
- LOperand* input = instr->value();
- ASSERT(input->IsRegister() && input->Equals(instr->result()));
- Register reg = ToRegister(input);
+ if (SmiValuesAre32Bits()) {
+ LOperand* input = instr->value();
+ ASSERT(input->IsRegister() && input->Equals(instr->result()));
+ Register reg = ToRegister(input);
- __ Integer32ToSmi(reg, reg);
+ __ Integer32ToSmi(reg, reg);
+ } else {
+ ASSERT(SmiValuesAre31Bits());
+ class DeferredNumberTagI: public LDeferredCode {
+ public:
+ DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
+ : LDeferredCode(codegen), instr_(instr) { }
+ virtual void Generate() {
+ codegen()->DoDeferredNumberTagI(instr_);
+ }
+ virtual LInstruction* instr() { return instr_; }
+ private:
+ LNumberTagI* instr_;
+ };
+
+ LOperand* input = instr->value();
+ ASSERT(input->IsRegister() && input->Equals(instr->result()));
+ Register reg = ToRegister(input);
+
+ DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
+ __ shll(reg, Immediate(kSmiTagSize + kSmiShiftSize));
+ __ j(overflow, deferred->entry());
+ __ movsxlq(reg, reg);
+ __ bind(deferred->exit());
+ }
+}
+
+
+void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) {
+ ASSERT(SmiValuesAre31Bits());
+ Label slow;
+ Register reg = ToRegister(instr->value());
+ Register tmp = reg.is(rax) ? kScratchRegister : rax;
+
+ // Preserve the value of all registers.
+ PushSafepointRegistersScope scope(this);
+
+ Label done;
+ // There was overflow, so bits 30 and 31 of the original integer
+ // disagree. Try to allocate a heap number in new space and store
+ // the value in there. If that fails, call the runtime system.
+ __ SmiToInteger32(reg, reg);
+ __ xorl(reg, Immediate(0x80000000));
+ __ cvtlsi2sd(xmm1, reg);
+
+ if (FLAG_inline_new) {
+ __ AllocateHeapNumber(reg, tmp, &slow);
+ __ jmp(&done, Label::kNear);
+ }
+
+ // Slow case: Call the runtime system to do the number allocation.
+ __ bind(&slow);
+
+ // Put a valid pointer value in the stack slot where the result
+ // register is stored, as this register is in the pointer map, but contains an
+ // integer value.
+ __ StoreToSafepointRegisterSlot(reg, Immediate(0));
+ CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
+ // Set the pointer to the new heap number in tmp.
+ if (!reg.is(rax)) __ movq(reg, rax);
+
+ // Heap number allocated. Put the value in xmm0 into the value of the
+ // allocated heap number.
+ __ bind(&done);
+ __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm1);
+ __ StoreToSafepointRegisterSlot(reg, reg);
}

Powered by Google App Engine
This is Rietveld 408576698