Index: src/x64/lithium-x64.cc |
=================================================================== |
--- src/x64/lithium-x64.cc (revision 6631) |
+++ src/x64/lithium-x64.cc (working copy) |
@@ -162,6 +162,12 @@ |
case Token::MUL: return "mul-t"; |
case Token::MOD: return "mod-t"; |
case Token::DIV: return "div-t"; |
+ case Token::BIT_AND: return "bit-and-t"; |
+ case Token::BIT_OR: return "bit-or-t"; |
+ case Token::BIT_XOR: return "bit-xor-t"; |
+ case Token::SHL: return "sal-t"; |
+ case Token::SAR: return "sar-t"; |
+ case Token::SHR: return "shr-t"; |
default: |
UNREACHABLE(); |
return NULL; |
@@ -319,7 +325,7 @@ |
} |
-LOperand* LChunk::GetNextSpillSlot(bool is_double) { |
+LOperand* LChunk::GetNextSpillSlot(bool is_double) { |
// All stack slots are Double stack slots on x64. |
// Alternatively, at some point, start using half-size |
// stack slots for int32 values. |
@@ -741,11 +747,75 @@ |
LInstruction* LChunkBuilder::DoBit(Token::Value op, |
HBitwiseBinaryOperation* instr) { |
- Abort("Unimplemented: %s", "DoBit"); |
- return NULL; |
+ if (instr->representation().IsInteger32()) { |
+ ASSERT(instr->left()->representation().IsInteger32()); |
+ ASSERT(instr->right()->representation().IsInteger32()); |
+ |
+ LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
+ LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); |
+ return DefineSameAsFirst(new LBitI(op, left, right)); |
+ } else { |
+ ASSERT(instr->representation().IsTagged()); |
+ ASSERT(instr->left()->representation().IsTagged()); |
+ ASSERT(instr->right()->representation().IsTagged()); |
+ |
+ LOperand* left = UseFixed(instr->left(), rdx); |
+ LOperand* right = UseFixed(instr->right(), rax); |
+ LArithmeticT* result = new LArithmeticT(op, left, right); |
+ return MarkAsCall(DefineFixed(result, rax), instr); |
+ } |
} |
+LInstruction* LChunkBuilder::DoShift(Token::Value op, |
+ HBitwiseBinaryOperation* instr) { |
+ if (instr->representation().IsTagged()) { |
+ ASSERT(instr->left()->representation().IsTagged()); |
+ ASSERT(instr->right()->representation().IsTagged()); |
+ |
+ LOperand* left = UseFixed(instr->left(), rdx); |
+ LOperand* right = UseFixed(instr->right(), rax); |
+ LArithmeticT* result = new LArithmeticT(op, left, right); |
+ return MarkAsCall(DefineFixed(result, rax), instr); |
+ } |
+ |
+ ASSERT(instr->representation().IsInteger32()); |
+ ASSERT(instr->OperandAt(0)->representation().IsInteger32()); |
+ ASSERT(instr->OperandAt(1)->representation().IsInteger32()); |
+ LOperand* left = UseRegisterAtStart(instr->OperandAt(0)); |
+ |
+ HValue* right_value = instr->OperandAt(1); |
+ LOperand* right = NULL; |
+ int constant_value = 0; |
+ if (right_value->IsConstant()) { |
+ HConstant* constant = HConstant::cast(right_value); |
+ right = chunk_->DefineConstantOperand(constant); |
+ constant_value = constant->Integer32Value() & 0x1f; |
+ } else { |
+ right = UseFixed(right_value, rcx); |
+ } |
+ |
+ // Shift operations can only deoptimize if we do a logical shift |
+ // by 0 and the result cannot be truncated to int32. |
+ bool can_deopt = (op == Token::SHR && constant_value == 0); |
+ if (can_deopt) { |
+ bool can_truncate = true; |
+ for (int i = 0; i < instr->uses()->length(); i++) { |
+ if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { |
+ can_truncate = false; |
+ break; |
+ } |
+ } |
+ can_deopt = !can_truncate; |
+ } |
+ |
+ LShiftI* result = new LShiftI(op, left, right, can_deopt); |
+ return can_deopt |
+ ? AssignEnvironment(DefineSameAsFirst(result)) |
+ : DefineSameAsFirst(result); |
+} |
+ |
+ |
LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
HArithmeticBinaryOperation* instr) { |
Abort("Unimplemented: %s", "DoArithmeticD"); |
@@ -1131,44 +1201,41 @@ |
LInstruction* LChunkBuilder::DoShr(HShr* instr) { |
- Abort("Unimplemented: %s", "DoShr"); |
- return NULL; |
+ return DoShift(Token::SHR, instr); |
} |
LInstruction* LChunkBuilder::DoSar(HSar* instr) { |
- Abort("Unimplemented: %s", "DoSar"); |
- return NULL; |
+ return DoShift(Token::SAR, instr); |
} |
LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
- Abort("Unimplemented: %s", "DoShl"); |
- return NULL; |
+ return DoShift(Token::SHL, instr); |
} |
LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { |
- Abort("Unimplemented: %s", "DoBitAnd"); |
- return NULL; |
+ return DoBit(Token::BIT_AND, instr); |
} |
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { |
- Abort("Unimplemented: %s", "DoBitNot"); |
- return NULL; |
+ ASSERT(instr->value()->representation().IsInteger32()); |
+ ASSERT(instr->representation().IsInteger32()); |
+ LOperand* input = UseRegisterAtStart(instr->value()); |
+ LBitNotI* result = new LBitNotI(input); |
+ return DefineSameAsFirst(result); |
} |
LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { |
- Abort("Unimplemented: %s", "DoBitOr"); |
- return NULL; |
+ return DoBit(Token::BIT_OR, instr); |
} |
LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { |
- Abort("Unimplemented: %s", "DoBitXor"); |
- return NULL; |
+ return DoBit(Token::BIT_XOR, instr); |
} |