summaryrefslogtreecommitdiff
path: root/deps/v8/src/x64/macro-assembler-x64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/x64/macro-assembler-x64.cc')
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc205
1 files changed, 153 insertions, 52 deletions
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index 9952eb3b65..e72d40b4ae 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -251,38 +251,9 @@ void MacroAssembler::InNewSpace(Register object,
Condition cc,
Label* branch,
Label::Distance distance) {
- if (serializer_enabled()) {
- // Can't do arithmetic on external references if it might get serialized.
- // The mask isn't really an address. We load it as an external reference in
- // case the size of the new space is different between the snapshot maker
- // and the running system.
- if (scratch.is(object)) {
- Move(kScratchRegister, ExternalReference::new_space_mask(isolate()));
- andp(scratch, kScratchRegister);
- } else {
- Move(scratch, ExternalReference::new_space_mask(isolate()));
- andp(scratch, object);
- }
- Move(kScratchRegister, ExternalReference::new_space_start(isolate()));
- cmpp(scratch, kScratchRegister);
- j(cc, branch, distance);
- } else {
- DCHECK(kPointerSize == kInt64Size
- ? is_int32(static_cast<int64_t>(isolate()->heap()->NewSpaceMask()))
- : kPointerSize == kInt32Size);
- intptr_t new_space_start =
- reinterpret_cast<intptr_t>(isolate()->heap()->NewSpaceStart());
- Move(kScratchRegister, reinterpret_cast<Address>(-new_space_start),
- Assembler::RelocInfoNone());
- if (scratch.is(object)) {
- addp(scratch, kScratchRegister);
- } else {
- leap(scratch, Operand(object, kScratchRegister, times_1, 0));
- }
- andp(scratch,
- Immediate(static_cast<int32_t>(isolate()->heap()->NewSpaceMask())));
- j(cc, branch, distance);
- }
+ const int mask =
+ (1 << MemoryChunk::IN_FROM_SPACE) | (1 << MemoryChunk::IN_TO_SPACE);
+ CheckPageFlag(object, scratch, mask, cc, branch, distance);
}
@@ -507,6 +478,90 @@ void MacroAssembler::RecordWrite(
}
}
+void MacroAssembler::RecordWriteCodeEntryField(Register js_function,
+ Register code_entry,
+ Register scratch) {
+ const int offset = JSFunction::kCodeEntryOffset;
+
+ // The input registers are fixed to make calling the C write barrier function
+ // easier.
+ DCHECK(js_function.is(rdi));
+ DCHECK(code_entry.is(rcx));
+ DCHECK(scratch.is(rax));
+
+ // Since a code entry (value) is always in old space, we don't need to update
+ // remembered set. If incremental marking is off, there is nothing for us to
+ // do.
+ if (!FLAG_incremental_marking) return;
+
+ AssertNotSmi(js_function);
+
+ if (emit_debug_code()) {
+ Label ok;
+ leap(scratch, FieldOperand(js_function, offset));
+ cmpp(code_entry, Operand(scratch, 0));
+ j(equal, &ok, Label::kNear);
+ int3();
+ bind(&ok);
+ }
+
+ // First, check if a write barrier is even needed. The tests below
+ // catch stores of Smis and stores into young gen.
+ Label done;
+
+ CheckPageFlag(code_entry, scratch,
+ MemoryChunk::kPointersToHereAreInterestingMask, zero, &done,
+ Label::kNear);
+ CheckPageFlag(js_function, scratch,
+ MemoryChunk::kPointersFromHereAreInterestingMask, zero, &done,
+ Label::kNear);
+
+ // Save input registers.
+ Push(js_function);
+ Push(code_entry);
+
+ const Register dst = scratch;
+ leap(dst, FieldOperand(js_function, offset));
+
+ // Save caller-saved registers.
+ PushCallerSaved(kDontSaveFPRegs, js_function, code_entry);
+
+ int argument_count = 3;
+ PrepareCallCFunction(argument_count);
+
+ // Load the argument registers.
+ if (arg_reg_1.is(rcx)) {
+ // Windows calling convention.
+ DCHECK(arg_reg_2.is(rdx) && arg_reg_3.is(r8));
+
+ movp(arg_reg_1, js_function); // rcx gets rdi.
+ movp(arg_reg_2, dst); // rdx gets rax.
+ } else {
+ // AMD64 calling convention.
+ DCHECK(arg_reg_1.is(rdi) && arg_reg_2.is(rsi) && arg_reg_3.is(rdx));
+
+ // rdi is already loaded with js_function.
+ movp(arg_reg_2, dst); // rsi gets rax.
+ }
+ Move(arg_reg_3, ExternalReference::isolate_address(isolate()));
+
+ {
+ AllowExternalCallThatCantCauseGC scope(this);
+ CallCFunction(
+ ExternalReference::incremental_marking_record_write_code_entry_function(
+ isolate()),
+ argument_count);
+ }
+
+ // Restore caller-saved registers.
+ PopCallerSaved(kDontSaveFPRegs, js_function, code_entry);
+
+ // Restore input registers.
+ Pop(code_entry);
+ Pop(js_function);
+
+ bind(&done);
+}
void MacroAssembler::Assert(Condition cc, BailoutReason reason) {
if (emit_debug_code()) Check(cc, reason);
@@ -589,9 +644,9 @@ void MacroAssembler::Abort(BailoutReason reason) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(this, StackFrame::NONE);
- CallRuntime(Runtime::kAbort, 1);
+ CallRuntime(Runtime::kAbort);
} else {
- CallRuntime(Runtime::kAbort, 1);
+ CallRuntime(Runtime::kAbort);
}
// Control will not return here.
int3();
@@ -690,18 +745,6 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
}
-void MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag,
- const CallWrapper& call_wrapper) {
- // You can't call a builtin without a valid frame.
- DCHECK(flag == JUMP_FUNCTION || has_frame());
-
- // Fake a parameter count to avoid emitting code to do the check.
- ParameterCount expected(0);
- LoadNativeContextSlot(native_context_index, rdi);
- InvokeFunctionCode(rdi, no_reg, expected, expected, flag, call_wrapper);
-}
-
-
#define REG(Name) \
{ Register::kCode_##Name }
@@ -823,6 +866,30 @@ void MacroAssembler::Cvtlsi2sd(XMMRegister dst, const Operand& src) {
}
+void MacroAssembler::Cvtlsi2ss(XMMRegister dst, Register src) {
+ if (CpuFeatures::IsSupported(AVX)) {
+ CpuFeatureScope scope(this, AVX);
+ vxorps(dst, dst, dst);
+ vcvtlsi2ss(dst, dst, src);
+ } else {
+ xorps(dst, dst);
+ cvtlsi2ss(dst, src);
+ }
+}
+
+
+void MacroAssembler::Cvtlsi2ss(XMMRegister dst, const Operand& src) {
+ if (CpuFeatures::IsSupported(AVX)) {
+ CpuFeatureScope scope(this, AVX);
+ vxorps(dst, dst, dst);
+ vcvtlsi2ss(dst, dst, src);
+ } else {
+ xorps(dst, dst);
+ cvtlsi2ss(dst, src);
+ }
+}
+
+
void MacroAssembler::Cvtqsi2ss(XMMRegister dst, Register src) {
if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(this, AVX);
@@ -918,6 +985,26 @@ void MacroAssembler::Cvtsd2si(Register dst, XMMRegister src) {
}
+void MacroAssembler::Cvttss2si(Register dst, XMMRegister src) {
+ if (CpuFeatures::IsSupported(AVX)) {
+ CpuFeatureScope scope(this, AVX);
+ vcvttss2si(dst, src);
+ } else {
+ cvttss2si(dst, src);
+ }
+}
+
+
+void MacroAssembler::Cvttss2si(Register dst, const Operand& src) {
+ if (CpuFeatures::IsSupported(AVX)) {
+ CpuFeatureScope scope(this, AVX);
+ vcvttss2si(dst, src);
+ } else {
+ cvttss2si(dst, src);
+ }
+}
+
+
void MacroAssembler::Cvttsd2si(Register dst, XMMRegister src) {
if (CpuFeatures::IsSupported(AVX)) {
CpuFeatureScope scope(this, AVX);
@@ -3865,6 +3952,19 @@ void MacroAssembler::AssertBoundFunction(Register object) {
}
+void MacroAssembler::AssertReceiver(Register object) {
+ if (emit_debug_code()) {
+ testb(object, Immediate(kSmiTagMask));
+ Check(not_equal, kOperandIsASmiAndNotAReceiver);
+ Push(object);
+ STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
+ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, object);
+ Pop(object);
+ Check(above_equal, kOperandIsNotAReceiver);
+ }
+}
+
+
void MacroAssembler::AssertUndefinedOrAllocationSite(Register object) {
if (emit_debug_code()) {
Label done_checking;
@@ -4168,7 +4268,7 @@ void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target,
}
Push(fun);
Push(fun);
- CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1);
+ CallRuntime(Runtime::kDebugPrepareStepInIfStepping);
Pop(fun);
if (new_target.is_valid()) {
Pop(new_target);
@@ -5040,7 +5140,7 @@ void MacroAssembler::CopyBytes(Register destination,
incp(source);
incp(destination);
decl(length);
- j(not_zero, &short_loop);
+ j(not_zero, &short_loop, Label::kNear);
}
bind(&done);
@@ -5051,13 +5151,13 @@ void MacroAssembler::InitializeFieldsWithFiller(Register current_address,
Register end_address,
Register filler) {
Label loop, entry;
- jmp(&entry);
+ jmp(&entry, Label::kNear);
bind(&loop);
movp(Operand(current_address, 0), filler);
addp(current_address, Immediate(kPointerSize));
bind(&entry);
cmpp(current_address, end_address);
- j(below, &loop);
+ j(below, &loop, Label::kNear);
}
@@ -5363,7 +5463,7 @@ void MacroAssembler::JumpIfWhite(Register value, Register bitmap_scratch,
}
-void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
+void MacroAssembler::CheckEnumCache(Label* call_runtime) {
Label next, start;
Register empty_fixed_array_value = r8;
LoadRoot(empty_fixed_array_value, Heap::kEmptyFixedArrayRootIndex);
@@ -5404,10 +5504,11 @@ void MacroAssembler::CheckEnumCache(Register null_value, Label* call_runtime) {
bind(&no_elements);
movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset));
- cmpp(rcx, null_value);
+ CompareRoot(rcx, Heap::kNullValueRootIndex);
j(not_equal, &next);
}
+
void MacroAssembler::TestJSArrayForAllocationMemento(
Register receiver_reg,
Register scratch_reg,