Index: src/x64/lithium-codegen-x64.cc |
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
index dc988b1a652fa97bb2c97a2eb72888d0464518ec..9e3659dc48468c6a4a3d651b51e00cf3867f09af 100644 |
--- a/src/x64/lithium-codegen-x64.cc |
+++ b/src/x64/lithium-codegen-x64.cc |
@@ -1146,7 +1146,17 @@ void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
- Abort("Unimplemented: %s", "DoCmpJSObjectEq"); |
+ Register left = ToRegister(instr->InputAt(0)); |
+ Register right = ToRegister(instr->InputAt(1)); |
+ Register result = ToRegister(instr->result()); |
+ |
+ __ cmpq(left, right); |
+ __ movl(result, Immediate(Heap::kTrueValueRootIndex)); |
+ NearLabel load; |
+ __ j(equal, &load); |
+ __ movl(result, Immediate(Heap::kFalseValueRootIndex)); |
William Hesse
2011/01/24 16:25:27
Why not move True and False directly to the result
Lasse Reichstein
2011/01/25 10:13:27
The change to the code relative to ia32 is because
|
+ __ bind(&load); |
+ __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); |
} |
@@ -1162,7 +1172,45 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
void LCodeGen::DoIsNull(LIsNull* instr) { |
- Abort("Unimplemented: %s", "DoIsNull"); |
+ Register reg = ToRegister(instr->InputAt(0)); |
+ Register result = ToRegister(instr->result()); |
+ |
+ // If the expression is known to be a smi, then it's |
+ // definitely not null. Materialize false. |
+ // Consider adding other type and representation tests too. |
+ if (instr->hydrogen()->value()->type().IsSmi()) { |
+ __ LoadRoot(result, Heap::kFalseValueRootIndex); |
+ return; |
+ } |
+ |
+ __ CompareRoot(reg, Heap::kNullValueRootIndex); |
+ if (instr->is_strict()) { |
+ __ movl(result, Immediate(Heap::kTrueValueRootIndex)); |
+ NearLabel load; |
+ __ j(equal, &load); |
+ __ movl(result, Immediate(Heap::kFalseValueRootIndex)); |
+ __ bind(&load); |
+ __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); |
+ } else { |
+ NearLabel true_value, false_value, done; |
+ __ j(equal, &true_value); |
+ __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
+ __ j(equal, &true_value); |
+ __ JumpIfSmi(reg, &false_value); |
+ // Check for undetectable objects by looking in the bit field in |
+ // the map. The object has already been smi checked. |
+ Register scratch = result; |
+ __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
+ __ testb(FieldOperand(scratch, Map::kBitFieldOffset), |
+ Immediate(1 << Map::kIsUndetectable)); |
+ __ j(not_zero, &true_value); |
+ __ bind(&false_value); |
+ __ LoadRoot(result, Heap::kFalseValueRootIndex); |
+ __ jmp(&done); |
+ __ bind(&true_value); |
+ __ LoadRoot(result, Heap::kTrueValueRootIndex); |
+ __ bind(&done); |
+ } |
} |
@@ -1232,7 +1280,22 @@ Condition LCodeGen::EmitIsObject(Register input, |
void LCodeGen::DoIsObject(LIsObject* instr) { |
- Abort("Unimplemented: %s", "DoIsObject"); |
+ Register reg = ToRegister(instr->InputAt(0)); |
+ Register result = ToRegister(instr->result()); |
+ Register temp = ToRegister(instr->TempAt(0)); |
Rico
2011/01/25 07:13:28
No need to the temp register here (and in the lith
Lasse Reichstein
2011/01/25 10:13:27
Removed, and EmitIsObject rewritten to use only kS
|
+ Label is_false, is_true, done; |
+ |
+ Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); |
+ __ j(true_cond, &is_true); |
+ |
+ __ bind(&is_false); |
+ __ LoadRoot(result, Heap::kFalseValueRootIndex); |
+ __ jmp(&done); |
+ |
+ __ bind(&is_true); |
+ __ LoadRoot(result, Heap::kTrueValueRootIndex); |
+ |
+ __ bind(&done); |
} |
@@ -1253,7 +1316,19 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
void LCodeGen::DoIsSmi(LIsSmi* instr) { |
- Abort("Unimplemented: %s", "DoIsSmi"); |
+ LOperand* input_operand = instr->InputAt(0); |
+ Register result = ToRegister(instr->result()); |
+ if (input_operand->IsRegister()) { |
+ Register input = ToRegister(input_operand); |
+ __ CheckSmiToIndicator(result, input); |
+ } else { |
+ Operand input = ToOperand(instr->InputAt(0)); |
+ __ CheckSmiToIndicator(result, input); |
+ } |
+ // result is zero if input is a smi, and one otherwise. |
+ ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); |
+ __ movq(result, Operand(kRootRegister, result, times_pointer_size, |
+ Heap::kTrueValueRootIndex)); |
William Hesse
2011/01/24 16:25:27
I think you need to multiply the kTrueValueRootInd
Lasse Reichstein
2011/01/25 10:13:27
Well spotted.
|
} |
@@ -1386,7 +1461,25 @@ void LCodeGen::EmitClassOfTest(Label* is_true, |
void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
- Abort("Unimplemented: %s", "DoClassOfTest"); |
+ Register input = ToRegister(instr->InputAt(0)); |
+ Register result = ToRegister(instr->result()); |
+ ASSERT(input.is(result)); |
+ Register temp = ToRegister(instr->TempAt(0)); |
Rico
2011/01/25 07:13:28
Use r10?
Lasse Reichstein
2011/01/25 10:13:27
This temp is needed in EmitClassOfTest. It uses th
|
+ Handle<String> class_name = instr->hydrogen()->class_name(); |
+ NearLabel done; |
+ Label is_true, is_false; |
+ |
+ EmitClassOfTest(&is_true, &is_false, class_name, input, temp); |
+ |
+ __ j(not_equal, &is_false); |
+ |
+ __ bind(&is_true); |
+ __ LoadRoot(result, Heap::kTrueValueRootIndex); |
+ __ jmp(&done); |
+ |
+ __ bind(&is_false); |
+ __ LoadRoot(result, Heap::kFalseValueRootIndex); |
+ __ bind(&done); |
} |
@@ -1408,7 +1501,12 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
- Abort("Unimplemented: %s", "DoCmpMapAndBranch"); |
+ Register reg = ToRegister(instr->InputAt(0)); |
+ int true_block = instr->true_block_id(); |
+ int false_block = instr->false_block_id(); |
+ |
+ __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
+ EmitBranch(true_block, false_block, equal); |
} |
@@ -1700,27 +1798,63 @@ void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
- Abort("Unimplemented: %s", "DoInteger32ToDouble"); |
+ LOperand* input = instr->InputAt(0); |
+ ASSERT(input->IsRegister() || input->IsStackSlot()); |
+ LOperand* output = instr->result(); |
+ ASSERT(output->IsDoubleRegister()); |
+ __ cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); |
William Hesse
2011/01/24 16:25:27
Operand cannot represent a register, so you need t
Lasse Reichstein
2011/01/25 10:13:27
We assert just above that input is not a register
|
} |
void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
- Abort("Unimplemented: %s", "DoNumberTagI"); |
-} |
- |
+ LOperand* input = instr->InputAt(0); |
+ ASSERT(input->IsRegister() && input->Equals(instr->result())); |
+ Register reg = ToRegister(input); |
-void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
- Abort("Unimplemented: %s", "DoDeferredNumberTagI"); |
+ __ Integer32ToSmi(reg, reg); |
} |
void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
- Abort("Unimplemented: %s", "DoNumberTagD"); |
+ class DeferredNumberTagD: public LDeferredCode { |
+ public: |
+ DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
+ : LDeferredCode(codegen), instr_(instr) { } |
+ virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
+ private: |
+ LNumberTagD* instr_; |
+ }; |
+ |
+ XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
+ Register reg = ToRegister(instr->result()); |
+ Register tmp = ToRegister(instr->TempAt(0)); |
+ |
+ DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
+ if (FLAG_inline_new) { |
+ __ AllocateHeapNumber(reg, tmp, deferred->entry()); |
+ } else { |
+ __ jmp(deferred->entry()); |
+ } |
+ __ bind(deferred->exit()); |
+ __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
} |
void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
- Abort("Unimplemented: %s", "DoDeferredNumberTagD"); |
+ // TODO(3095996): Get rid of this. For now, we need to make the |
+ // result register contain a valid pointer because it is already |
+ // contained in the register pointer map. |
+ Register reg = ToRegister(instr->result()); |
+ __ Set(reg, 0); |
William Hesse
2011/01/24 16:25:27
How can 0 be a valid pointer? It isn't tagged.
Lasse Reichstein
2011/01/25 10:13:27
By chance, since it's the representation of Smi ze
|
+ |
+ __ PushSafepointRegisters(); |
+ __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
+ RecordSafepointWithRegisters( |
+ instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
+ // Ensure that value in rax survives popping registers. |
+ __ movq(kScratchRegister, rax); |
+ __ PopSafepointRegisters(); |
+ __ movq(reg, kScratchRegister); |
} |
@@ -1737,7 +1871,35 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
void LCodeGen::EmitNumberUntagD(Register input_reg, |
XMMRegister result_reg, |
LEnvironment* env) { |
- Abort("Unimplemented: %s", "EmitNumberUntagD"); |
+ NearLabel load_smi, heap_number, done; |
+ |
+ // Smi check. |
+ __ JumpIfSmi(input_reg, &load_smi); |
+ |
+ // Heap number map check. |
+ __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
+ Heap::kHeapNumberMapRootIndex); |
+ __ j(equal, &heap_number); |
+ |
+ __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
+ DeoptimizeIf(not_equal, env); |
+ |
+ // Convert undefined to NaN. Compute NaN as 0/0. |
+ __ xorpd(result_reg, result_reg); |
+ __ divsd(result_reg, result_reg); |
+ __ jmp(&done); |
+ |
+ // Heap number to XMM conversion. |
+ __ bind(&heap_number); |
+ __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
+ __ jmp(&done); |
+ |
+ // Smi to XMM conversion |
+ __ bind(&load_smi); |
+ __ SmiToInteger32(input_reg, input_reg); // Untag smi first. |
+ __ cvtlsi2sd(result_reg, input_reg); |
+ __ Integer32ToSmi(input_reg, input_reg); // Retag smi. |
William Hesse
2011/01/24 16:25:27
Can't we have some way to make this optional, or u
Lasse Reichstein
2011/01/25 10:13:27
Using kScratchRegister seems like the easy way. We
|
+ __ bind(&done); |
} |