Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(638)

Unified Diff: runtime/vm/assembler_x64.cc

Issue 25118002: Eliminates more large immediates from x64 code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/assembler_x64.h ('k') | runtime/vm/assembler_x64_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/assembler_x64.cc
===================================================================
--- runtime/vm/assembler_x64.cc (revision 28057)
+++ runtime/vm/assembler_x64.cc (working copy)
@@ -204,6 +204,16 @@
}
+void Assembler::PushImmediate(const Immediate& imm, Register pp) {
+ if (imm.is_int32()) {
+ pushq(imm);
+ } else {
+ LoadImmediate(TMP, imm, pp);
+ pushq(TMP);
+ }
+}
+
+
void Assembler::popq(Register reg) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitRegisterREX(reg, REX_NONE);
@@ -813,7 +823,8 @@
uint32_t d;
} float_not_constant =
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)));
+ LoadImmediate(
+ TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)), PP);
xorps(dst, Address(TMP, 0));
}
@@ -826,7 +837,8 @@
uint32_t d;
} float_negate_constant =
{ 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)));
+ LoadImmediate(
+ TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)), PP);
xorps(dst, Address(TMP, 0));
}
@@ -839,7 +851,8 @@
uint32_t d;
} float_absolute_constant =
{ 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF };
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)));
+ LoadImmediate(
+ TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)), PP);
andps(dst, Address(TMP, 0));
}
@@ -852,7 +865,8 @@
uint32_t d;
} float_zerow_constant =
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 };
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)));
+ LoadImmediate(
+ TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)), PP);
andps(dst, Address(TMP, 0));
}
@@ -1342,6 +1356,28 @@
}
+void Assembler::CompareImmediate(Register reg, const Immediate& imm,
+ Register pp) {
+ if (imm.is_int32()) {
+ cmpq(reg, imm);
+ } else {
+ LoadImmediate(TMP, imm, pp);
+ cmpq(reg, TMP);
+ }
+}
+
+
+void Assembler::CompareImmediate(const Address& address, const Immediate& imm,
+ Register pp) {
+ if (imm.is_int32()) {
+ cmpq(address, imm);
+ } else {
+ LoadImmediate(TMP, imm, pp);
+ cmpq(address, TMP);
+ }
+}
+
+
void Assembler::testl(Register reg1, Register reg2) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
Operand operand(reg2);
@@ -1492,6 +1528,17 @@
}
+void Assembler::AndImmediate(Register dst, const Immediate& imm, Register pp) {
+ if (imm.is_int32()) {
+ andq(dst, imm);
+ } else {
+ ASSERT(dst != TMP);
+ LoadImmediate(TMP, imm, pp);
+ andq(dst, TMP);
+ }
+}
+
+
void Assembler::orq(Register dst, Register src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
Operand operand(src);
@@ -1521,6 +1568,17 @@
}
+void Assembler::OrImmediate(Register dst, const Immediate& imm, Register pp) {
+ if (imm.is_int32()) {
+ orq(dst, imm);
+ } else {
+ ASSERT(dst != TMP);
+ LoadImmediate(TMP, imm, pp);
+ orq(dst, TMP);
+ }
+}
+
+
void Assembler::xorq(Register dst, Register src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
Operand operand(src);
@@ -1558,6 +1616,17 @@
}
+void Assembler::XorImmediate(Register dst, const Immediate& imm, Register pp) {
+ if (imm.is_int32()) {
+ xorq(dst, imm);
+ } else {
+ ASSERT(dst != TMP);
+ LoadImmediate(TMP, imm, pp);
+ xorq(dst, TMP);
+ }
+}
+
+
void Assembler::addl(Register dst, Register src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
Operand operand(src);
@@ -1708,6 +1777,17 @@
}
+void Assembler::MulImmediate(Register reg, const Immediate& imm, Register pp) {
+ if (imm.is_int32()) {
+ imulq(reg, imm);
+ } else {
+ ASSERT(reg != TMP);
+ LoadImmediate(TMP, imm, pp);
+ imulq(reg, TMP);
+ }
+}
+
+
void Assembler::imulq(Register dst, const Address& address) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOperandREX(dst, address, REX_W);
@@ -1746,6 +1826,21 @@
}
+void Assembler::subq(const Address& address, Register reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOperandREX(reg, address, REX_W);
+ EmitUint8(0x29);
+ EmitOperand(reg & 7, address);
+}
+
+
+void Assembler::subq(const Address& address, const Immediate& imm) {
+ // TODO(srdjan): Implement shorter version for imm32.
+ movq(TMP, imm);
+ subq(address, TMP);
+}
+
+
void Assembler::shll(Register reg, const Immediate& imm) {
EmitGenericShift(false, 4, reg, imm);
}
@@ -2138,25 +2233,69 @@
}
-void Assembler::AddImmediate(Register reg, const Immediate& imm) {
+void Assembler::AddImmediate(Register reg, const Immediate& imm, Register pp) {
int64_t value = imm.value();
if (value > 0) {
if (value == 1) {
incq(reg);
} else if (value != 0) {
- addq(reg, imm);
+ if (imm.is_int32()) {
+ addq(reg, imm);
+ } else {
+ ASSERT(reg != TMP);
+ LoadImmediate(TMP, imm, pp);
+ addq(reg, TMP);
+ }
}
} else if (value < 0) {
value = -value;
if (value == 1) {
decq(reg);
} else if (value != 0) {
- subq(reg, Immediate(value));
+ const Immediate& s = Immediate(value);
+ if (s.is_int32()) {
+ subq(reg, Immediate(value));
+ } else {
+ ASSERT(reg != TMP);
+ LoadImmediate(TMP, s, pp);
+ subq(reg, TMP);
+ }
}
}
}
+void Assembler::AddImmediate(const Address& address, const Immediate& imm,
+ Register pp) {
+ int64_t value = imm.value();
+ if (value > 0) {
+ if (value == 1) {
+ incq(address);
+ } else if (value != 0) {
+ if (imm.is_int32()) {
+ addq(address, imm);
+ } else {
+ LoadImmediate(TMP, imm, pp);
+ addq(address, TMP);
+ }
+ }
+ } else if (value < 0) {
+ value = -value;
+ if (value == 1) {
+ decq(address);
+ } else if (value != 0) {
+ const Immediate& s = Immediate(value);
+ if (s.is_int32()) {
+ subq(address, s);
+ } else {
+ LoadImmediate(TMP, s, pp);
+ subq(address, TMP);
+ }
+ }
+ }
+}
+
+
void Assembler::Drop(intptr_t stack_elements) {
ASSERT(stack_elements >= 0);
if (stack_elements <= 4) {
@@ -2261,42 +2400,87 @@
ASSERT((Isolate::Current() == Dart::vm_isolate()) ||
object.IsSmi() ||
object.InVMHeap());
- movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
+ LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
}
}
-void Assembler::StoreObject(const Address& dst, const Object& object) {
+void Assembler::StoreObject(const Address& dst, const Object& object,
+ Register pp) {
if (CanLoadFromObjectPool(object)) {
- LoadObject(TMP, object, PP);
+ LoadObject(TMP, object, pp);
movq(dst, TMP);
} else {
- movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw())));
+ LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
}
}
-void Assembler::PushObject(const Object& object) {
+void Assembler::PushObject(const Object& object, Register pp) {
if (CanLoadFromObjectPool(object)) {
- LoadObject(TMP, object, PP);
+ LoadObject(TMP, object, pp);
pushq(TMP);
} else {
- pushq(Immediate(reinterpret_cast<int64_t>(object.raw())));
+ PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
}
}
-void Assembler::CompareObject(Register reg, const Object& object) {
+void Assembler::CompareObject(Register reg, const Object& object, Register pp) {
if (CanLoadFromObjectPool(object)) {
ASSERT(reg != TMP);
- LoadObject(TMP, object, PP);
+ LoadObject(TMP, object, pp);
cmpq(reg, TMP);
} else {
- cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw())));
+ CompareImmediate(
+ reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp);
}
}
+intptr_t Assembler::FindImmediate(int64_t imm) {
+ ASSERT(Isolate::Current() != Dart::vm_isolate());
+ ASSERT(!object_pool_.IsNull());
+ const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm));
+ return FindObject(smi, kNotPatchable);
+}
+
+
+void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) {
+ if (imm.is_int32() ||
+ (pp == kNoRegister) ||
+ (Isolate::Current() == Dart::vm_isolate())) {
+ movq(reg, imm);
+ } else {
+ // It's a 64-bit constant and we're not in the VM isolate, so load from
+ // object pool.
+ int64_t val = imm.value();
+ // Save the bits that must be masked-off for the SmiTag
+ int64_t val_smi_tag = val & kSmiTagMask;
+ val &= ~kSmiTagMask; // Mask off the tag bits.
+ const int32_t offset = Array::element_offset(FindImmediate(val));
+ LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag);
+ if (val_smi_tag != 0) {
+ // Add back the tag bits.
+ orq(reg, Immediate(val_smi_tag));
+ }
+ }
+}
+
+
+void Assembler::LoadImmediate(const Address& dst, const Immediate& imm,
+ Register pp) {
+ if (imm.is_int32() ||
+ (pp == kNoRegister) ||
+ (Isolate::Current() == Dart::vm_isolate())) {
Florian Schneider 2013/09/30 18:43:35 These 3 conditions seem to be repeated a couple of
zra 2013/09/30 19:59:31 Done.
+ movq(dst, imm);
+ } else {
+ LoadImmediate(TMP, imm, pp);
+ movq(dst, TMP);
+ }
+}
+
+
// Destroys the value register.
void Assembler::StoreIntoObjectFilterNoSmi(Register object,
Register value,
@@ -2383,7 +2567,8 @@
uint64_t b;
} double_negate_constant =
{0x8000000000000000LL, 0x8000000000000000LL};
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)));
+ LoadImmediate(
+ TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP);
xorpd(d, Address(TMP, 0));
}
@@ -2394,7 +2579,8 @@
uint64_t b;
} double_abs_constant =
{0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL};
- movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)));
+ LoadImmediate(TMP,
+ Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)), PP);
andpd(reg, Address(TMP, 0));
}
@@ -2404,7 +2590,7 @@
if (FLAG_print_stop_message) {
pushq(TMP); // Preserve TMP register.
pushq(RDI); // Preserve RDI register.
- movq(RDI, Immediate(message_address));
+ LoadImmediate(RDI, Immediate(message_address), PP);
call(&StubCode::PrintStopMessageLabel());
popq(RDI); // Restore RDI register.
popq(TMP); // Restore TMP register.
@@ -2477,7 +2663,9 @@
void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
// Reserve space for arguments and align frame before entering
// the C++ world.
- AddImmediate(RSP, Immediate(-frame_space));
+ if (frame_space != 0) {
+ subq(RSP, Immediate(frame_space));
+ }
if (OS::ActivationFrameAlignment() > 1) {
andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
}
@@ -2667,29 +2855,31 @@
void Assembler::TryAllocate(const Class& cls,
Label* failure,
bool near_jump,
- Register instance_reg) {
+ Register instance_reg,
+ Register pp) {
ASSERT(failure != NULL);
if (FLAG_inline_alloc) {
Heap* heap = Isolate::Current()->heap();
const intptr_t instance_size = cls.instance_size();
- movq(TMP, Immediate(heap->TopAddress()));
+ LoadImmediate(TMP, Immediate(heap->TopAddress()), pp);
movq(instance_reg, Address(TMP, 0));
- addq(instance_reg, Immediate(instance_size));
+ AddImmediate(instance_reg, Immediate(instance_size), pp);
// instance_reg: potential next object start.
- movq(TMP, Immediate(heap->EndAddress()));
+ LoadImmediate(TMP, Immediate(heap->EndAddress()), pp);
cmpq(instance_reg, Address(TMP, 0));
j(ABOVE_EQUAL, failure, near_jump);
// Successfully allocated the object, now update top to point to
// next object start and store the class in the class field of object.
- movq(TMP, Immediate(heap->TopAddress()));
+ LoadImmediate(TMP, Immediate(heap->TopAddress()), pp);
movq(Address(TMP, 0), instance_reg);
ASSERT(instance_size >= kHeapObjectTag);
- subq(instance_reg, Immediate(instance_size - kHeapObjectTag));
+ AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size), pp);
uword tags = 0;
tags = RawObject::SizeTag::update(instance_size, tags);
ASSERT(cls.id() != kIllegalCid);
tags = RawObject::ClassIdTag::update(cls.id(), tags);
- movq(FieldAddress(instance_reg, Object::tags_offset()), Immediate(tags));
+ LoadImmediate(FieldAddress(instance_reg, Object::tags_offset()),
+ Immediate(tags), pp);
} else {
jmp(failure);
}
« no previous file with comments | « runtime/vm/assembler_x64.h ('k') | runtime/vm/assembler_x64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698