Chromium Code Reviews| Index: src/x64/lithium-x64.cc |
| =================================================================== |
| --- src/x64/lithium-x64.cc (revision 6629) |
| +++ 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); |
|
Lasse Reichstein
2011/02/04 09:51:25
Why fixed registers? Is it to match the calling co
William Hesse
2011/02/04 14:37:12
Yes.
On 2011/02/04 09:51:25, Lasse Reichstein wrot
|
| + 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. |
|
Lasse Reichstein
2011/02/04 09:51:25
It's a little tricky to have a constant value that
William Hesse
2011/02/04 14:37:12
This is the way it is done on all the other platfo
|
| + 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); |
| } |