Index: src/x64/codegen-x64.cc |
=================================================================== |
--- src/x64/codegen-x64.cc (revision 4699) |
+++ src/x64/codegen-x64.cc (working copy) |
@@ -27,6 +27,8 @@ |
#include "v8.h" |
+#if defined(V8_TARGET_ARCH_X64) |
+ |
#include "bootstrapper.h" |
#include "codegen-inl.h" |
#include "compiler.h" |
@@ -678,11 +680,51 @@ |
void DeferredReferenceSetKeyedValue::Generate() { |
__ IncrementCounter(&Counters::keyed_store_inline_miss, 1); |
- // Push receiver and key arguments on the stack. |
- __ push(receiver_); |
- __ push(key_); |
- // Move value argument to eax as expected by the IC stub. |
- if (!value_.is(rax)) __ movq(rax, value_); |
+ // Move value, receiver, and key to registers rax, rdx, and rcx, as |
+ // the IC stub expects. |
+ // Move value to rax, using xchg if the receiver or key is in rax. |
+ if (!value_.is(rax)) { |
+ if (!receiver_.is(rax) && !key_.is(rax)) { |
+ __ movq(rax, value_); |
+ } else { |
+ __ xchg(rax, value_); |
+ // Update receiver_ and key_ if they are affected by the swap. |
+ if (receiver_.is(rax)) { |
+ receiver_ = value_; |
+ } else if (receiver_.is(value_)) { |
+ receiver_ = rax; |
+ } |
+ if (key_.is(rax)) { |
+ key_ = value_; |
+ } else if (key_.is(value_)) { |
+ key_ = rax; |
+ } |
+ } |
+ } |
+ // Value is now in rax. Its original location is remembered in value_, |
+ // and the value is restored to value_ before returning. |
+ // The variables receiver_ and key_ are not preserved. |
+ // Move receiver and key to rdx and rcx, swapping if necessary. |
+ if (receiver_.is(rdx)) { |
+ if (!key_.is(rcx)) { |
+ __ movq(rcx, key_); |
+ } // Else everything is already in the right place. |
+ } else if (receiver_.is(rcx)) { |
+ if (key_.is(rdx)) { |
+ __ xchg(rcx, rdx); |
+ } else if (key_.is(rcx)) { |
+ __ movq(rdx, receiver_); |
+ } else { |
+ __ movq(rdx, receiver_); |
+ __ movq(rcx, key_); |
+ } |
+ } else if (key_.is(rcx)) { |
+ __ movq(rdx, receiver_); |
+ } else { |
+ __ movq(rcx, key_); |
+ __ movq(rdx, receiver_); |
+ } |
+ |
// Call the IC stub. |
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
__ Call(ic, RelocInfo::CODE_TARGET); |
@@ -695,11 +737,8 @@ |
// Here we use masm_-> instead of the __ macro because this is the |
// instruction that gets patched and coverage code gets in the way. |
masm_->testl(rax, Immediate(-delta_to_patch_site)); |
- // Restore value (returned from store IC), key and receiver |
- // registers. |
+ // Restore value (returned from store IC). |
if (!value_.is(rax)) __ movq(value_, rax); |
- __ pop(key_); |
- __ pop(receiver_); |
} |
@@ -1546,7 +1585,7 @@ |
} |
Result var = frame_->Pop(); |
var.ToRegister(); |
- __ AbortIfNotSmi(var.reg(), "Non-smi value in smi-typed stack slot."); |
+ __ AbortIfNotSmi(var.reg()); |
} |
} |
@@ -2799,6 +2838,7 @@ |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
Load(args->at(i)); |
+ frame_->SpillTop(); |
} |
// Prepare the stack for the call to ResolvePossiblyDirectEval. |
@@ -2848,6 +2888,7 @@ |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
Load(args->at(i)); |
+ frame_->SpillTop(); |
} |
// Push the name of the function on the frame. |
@@ -2953,6 +2994,7 @@ |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
Load(args->at(i)); |
+ frame_->SpillTop(); |
} |
// Push the name of the function onto the frame. |
@@ -3399,7 +3441,11 @@ |
new_value.type_info()); |
} |
- __ JumpIfNotSmi(new_value.reg(), deferred->entry_label()); |
+ if (new_value.is_smi()) { |
+ if (FLAG_debug_code) { __ AbortIfNotSmi(new_value.reg()); } |
+ } else { |
+ __ JumpIfNotSmi(new_value.reg(), deferred->entry_label()); |
+ } |
if (is_increment) { |
__ SmiAddConstant(kScratchRegister, |
new_value.reg(), |
@@ -3833,11 +3879,13 @@ |
__ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), |
Immediate(1 << Map::kIsUndetectable)); |
destination()->false_target()->Branch(not_zero); |
- __ CmpInstanceType(kScratchRegister, FIRST_JS_OBJECT_TYPE); |
- destination()->false_target()->Branch(less); |
- __ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); |
+ __ movzxbq(kScratchRegister, |
+ FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
+ __ cmpq(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE)); |
+ destination()->false_target()->Branch(below); |
+ __ cmpq(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE)); |
obj.Unuse(); |
- destination()->Split(less_equal); |
+ destination()->Split(below_equal); |
} |
@@ -3921,7 +3969,7 @@ |
__ bind(&exit); |
result.set_type_info(TypeInfo::Smi()); |
if (FLAG_debug_code) { |
- __ AbortIfNotSmi(result.reg(), "Computed arguments.length is not a smi."); |
+ __ AbortIfNotSmi(result.reg()); |
} |
frame_->Push(&result); |
} |
@@ -4329,7 +4377,7 @@ |
__ PrepareCallCFunction(0); |
__ CallCFunction(ExternalReference::random_uint32_function(), 0); |
- // Convert 32 random bits in eax to 0.(32 random bits) in a double |
+ // Convert 32 random bits in rax to 0.(32 random bits) in a double |
// by computing: |
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
__ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
@@ -5100,10 +5148,9 @@ |
value.ToRegister(); |
if (value.is_number()) { |
- Comment cmnt(masm_, "ONLY_NUMBER"); |
// Fast case if TypeInfo indicates only numbers. |
if (FLAG_debug_code) { |
- __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number."); |
+ __ AbortIfNotNumber(value.reg()); |
} |
// Smi => false iff zero. |
__ SmiCompare(value.reg(), Smi::FromInt(0)); |
@@ -5876,7 +5923,7 @@ |
if (left_side.is_smi()) { |
if (FLAG_debug_code) { |
- __ AbortIfNotSmi(left_side.reg(), "Non-smi value inferred as smi."); |
+ __ AbortIfNotSmi(left_side.reg()); |
} |
} else { |
Condition left_is_smi = masm_->CheckSmi(left_side.reg()); |
@@ -6748,8 +6795,7 @@ |
Condition is_smi = masm_->CheckSmi(operand->reg()); |
deferred->Branch(NegateCondition(is_smi)); |
} else if (FLAG_debug_code) { |
- __ AbortIfNotSmi(operand->reg(), |
- "Static type info claims non-smi is smi in (const SHL smi)."); |
+ __ AbortIfNotSmi(operand->reg()); |
} |
__ Move(answer.reg(), smi_value); |
@@ -7011,8 +7057,44 @@ |
left->reg(), |
rcx, |
overwrite_mode); |
- __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); |
+ Label do_op; |
+ if (right_type_info.IsSmi()) { |
+ if (FLAG_debug_code) { |
+ __ AbortIfNotSmi(right->reg()); |
+ } |
+ __ movq(answer.reg(), left->reg()); |
+ // If left is not known to be a smi, check if it is. |
+ // If left is not known to be a number, and it isn't a smi, check if |
+ // it is a HeapNumber. |
+ if (!left_type_info.IsSmi()) { |
+ __ JumpIfSmi(answer.reg(), &do_op); |
+ if (!left_type_info.IsNumber()) { |
+ // Branch if not a heapnumber. |
+ __ Cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), |
+ Factory::heap_number_map()); |
+ deferred->Branch(not_equal); |
+ } |
+ // Load integer value into answer register using truncation. |
+ __ cvttsd2si(answer.reg(), |
+ FieldOperand(answer.reg(), HeapNumber::kValueOffset)); |
+ // Branch if we might have overflowed. |
+ // (False negative for Smi::kMinValue) |
+ __ cmpq(answer.reg(), Immediate(0x80000000)); |
+ deferred->Branch(equal); |
+ // TODO(lrn): Inline shifts on int32 here instead of first smi-tagging. |
+ __ Integer32ToSmi(answer.reg(), answer.reg()); |
+ } else { |
+ // Fast case - both are actually smis. |
+ if (FLAG_debug_code) { |
+ __ AbortIfNotSmi(left->reg()); |
+ } |
+ } |
+ } else { |
+ __ JumpIfNotBothSmi(left->reg(), rcx, deferred->entry_label()); |
+ } |
+ __ bind(&do_op); |
+ |
// Perform the operation. |
switch (op) { |
case Token::SAR: |
@@ -7469,7 +7551,7 @@ |
if (!key.is_smi()) { |
__ JumpIfNotSmi(key.reg(), deferred->entry_label()); |
} else if (FLAG_debug_code) { |
- __ AbortIfNotSmi(key.reg(), "Non-smi value in smi-typed value."); |
+ __ AbortIfNotSmi(key.reg()); |
} |
// Check that the receiver is a JSArray. |
@@ -7524,8 +7606,6 @@ |
deferred->BindExit(); |
- cgen_->frame()->Push(&receiver); |
- cgen_->frame()->Push(&key); |
cgen_->frame()->Push(&value); |
} else { |
Result answer = cgen_->frame()->CallKeyedStoreIC(); |
@@ -7536,7 +7616,7 @@ |
masm->nop(); |
cgen_->frame()->Push(&answer); |
} |
- cgen_->UnloadReference(this); |
+ set_unloaded(); |
break; |
} |
@@ -8898,6 +8978,7 @@ |
int arg_count = args->length(); |
for (int i = 0; i < arg_count; i++) { |
Load(args->at(i)); |
+ frame_->SpillTop(); |
} |
// Record the position for debugging purposes. |
@@ -10014,8 +10095,8 @@ |
if (static_operands_type_.IsSmi()) { |
// Skip smi check if we know that both arguments are smis. |
if (FLAG_debug_code) { |
- __ AbortIfNotSmi(left, "Static type check claimed non-smi is smi."); |
- __ AbortIfNotSmi(right, "Static type check claimed non-smi is smi."); |
+ __ AbortIfNotSmi(left); |
+ __ AbortIfNotSmi(right); |
} |
if (op_ == Token::BIT_OR) { |
// Handle OR here, since we do extra smi-checking in the or code below. |
@@ -10198,8 +10279,8 @@ |
// rdx: x |
if (static_operands_type_.IsNumber() && FLAG_debug_code) { |
// Assert at runtime that inputs are only numbers. |
- __ AbortIfNotNumber(rdx, "GenericBinaryOpStub operand not a number."); |
- __ AbortIfNotNumber(rax, "GenericBinaryOpStub operand not a number."); |
+ __ AbortIfNotNumber(rdx); |
+ __ AbortIfNotNumber(rax); |
} else { |
FloatingPointHelper::CheckNumberOperands(masm, &call_runtime); |
} |
@@ -11589,3 +11670,5 @@ |
#undef __ |
} } // namespace v8::internal |
+ |
+#endif // V8_TARGET_ARCH_X64 |