Index: src/x64/macro-assembler-x64.cc |
=================================================================== |
--- src/x64/macro-assembler-x64.cc (revision 9808) |
+++ src/x64/macro-assembler-x64.cc (working copy) |
@@ -55,7 +55,7 @@ |
static intptr_t RootRegisterDelta(ExternalReference other, Isolate* isolate) { |
Address roots_register_value = kRootRegisterBias + |
- reinterpret_cast<Address>(isolate->heap()->roots_address()); |
+ reinterpret_cast<Address>(isolate->heap()->roots_array_start()); |
intptr_t delta = other.address() - roots_register_value; |
return delta; |
} |
@@ -326,6 +326,40 @@ |
} |
+void MacroAssembler::RecordWriteArray(Register object, |
+ Register value, |
+ Register index, |
+ SaveFPRegsMode save_fp, |
+ RememberedSetAction remembered_set_action, |
+ SmiCheck smi_check) { |
+ // First, check if a write barrier is even needed. The tests below |
+ // catch stores of Smis. |
+ Label done; |
+ |
+ // Skip barrier if writing a smi. |
+ if (smi_check == INLINE_SMI_CHECK) { |
+ JumpIfSmi(value, &done); |
+ } |
+ |
+ // Array access: calculate the destination address. Index is not a smi. |
+ Register dst = index; |
+ lea(dst, Operand(object, index, times_pointer_size, |
+ FixedArray::kHeaderSize - kHeapObjectTag)); |
+ |
+ RecordWrite( |
+ object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK); |
+ |
+ bind(&done); |
+ |
+ // Clobber clobbered input registers when running with the debug-code flag |
+ // turned on to provoke errors. |
+ if (emit_debug_code()) { |
+ movq(value, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
+ movq(index, BitCast<int64_t>(kZapValue), RelocInfo::NONE); |
+ } |
+} |
+ |
+ |
void MacroAssembler::RecordWrite(Register object, |
Register address, |
Register value, |
@@ -2317,6 +2351,13 @@ |
} |
+void MacroAssembler::TestBit(const Operand& src, int bits) { |
+ int byte_offset = bits / kBitsPerByte; |
+ int bit_in_byte = bits & (kBitsPerByte - 1); |
+ testb(Operand(src, byte_offset), Immediate(1 << bit_in_byte)); |
+} |
+ |
+ |
void MacroAssembler::Jump(ExternalReference ext) { |
LoadAddress(kScratchRegister, ext); |
jmp(kScratchRegister); |
@@ -2683,7 +2724,7 @@ |
void MacroAssembler::StoreNumberToDoubleElements( |
Register maybe_number, |
Register elements, |
- Register key, |
+ Register index, |
XMMRegister xmm_scratch, |
Label* fail) { |
Label smi_value, is_nan, maybe_nan, not_nan, have_double_value, done; |
@@ -2704,7 +2745,7 @@ |
bind(¬_nan); |
movsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset)); |
bind(&have_double_value); |
- movsd(FieldOperand(elements, key, times_8, FixedDoubleArray::kHeaderSize), |
+ movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize), |
xmm_scratch); |
jmp(&done); |
@@ -2727,7 +2768,7 @@ |
// Preserve original value. |
SmiToInteger32(kScratchRegister, maybe_number); |
cvtlsi2sd(xmm_scratch, kScratchRegister); |
- movsd(FieldOperand(elements, key, times_8, FixedDoubleArray::kHeaderSize), |
+ movsd(FieldOperand(elements, index, times_8, FixedDoubleArray::kHeaderSize), |
xmm_scratch); |
bind(&done); |
} |
@@ -2866,7 +2907,8 @@ |
void MacroAssembler::TryGetFunctionPrototype(Register function, |
Register result, |
- Label* miss) { |
+ Label* miss, |
+ bool miss_on_bound_function) { |
// Check that the receiver isn't a smi. |
testl(function, Immediate(kSmiTagMask)); |
j(zero, miss); |
@@ -2875,6 +2917,17 @@ |
CmpObjectType(function, JS_FUNCTION_TYPE, result); |
j(not_equal, miss); |
+ if (miss_on_bound_function) { |
+ movq(kScratchRegister, |
+ FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
+ // It's not smi-tagged (stored in the top half of a smi-tagged 8-byte |
+ // field). |
+ TestBit(FieldOperand(kScratchRegister, |
+ SharedFunctionInfo::kCompilerHintsOffset), |
+ SharedFunctionInfo::kBoundFunction); |
+ j(not_zero, miss); |
+ } |
+ |
// Make sure that the function has an instance prototype. |
Label non_instance; |
testb(FieldOperand(result, Map::kBitFieldOffset), |
@@ -3067,29 +3120,16 @@ |
// You can't call a function without a valid frame. |
ASSERT(flag == JUMP_FUNCTION || has_frame()); |
- ASSERT(function->is_compiled()); |
// Get the function and setup the context. |
Move(rdi, Handle<JSFunction>(function)); |
movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
- if (V8::UseCrankshaft()) { |
- // Since Crankshaft can recompile a function, we need to load |
- // the Code object every time we call the function. |
- movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
- ParameterCount expected(function->shared()->formal_parameter_count()); |
- InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); |
- } else { |
- // Invoke the cached code. |
- Handle<Code> code(function->code()); |
- ParameterCount expected(function->shared()->formal_parameter_count()); |
- InvokeCode(code, |
- expected, |
- actual, |
- RelocInfo::CODE_TARGET, |
- flag, |
- call_wrapper, |
- call_kind); |
- } |
+ // We call indirectly through the code field in the function to |
+ // allow recompilation to take effect without changing any of the |
+ // call sites. |
+ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
+ ParameterCount expected(function->shared()->formal_parameter_count()); |
+ InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind); |
} |