Mercurial > hg > truffle
diff src/cpu/x86/vm/assembler_x86_64.cpp @ 113:ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
Summary: Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv
Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
author | coleenp |
---|---|
date | Sun, 13 Apr 2008 17:43:42 -0400 |
parents | d6fe2e4959d6 |
children | fb75a7673531 |
line wrap: on
line diff
--- a/src/cpu/x86/vm/assembler_x86_64.cpp Fri Apr 11 09:56:35 2008 -0400 +++ b/src/cpu/x86/vm/assembler_x86_64.cpp Sun Apr 13 17:43:42 2008 -0400 @@ -127,6 +127,7 @@ bool Assembler::reachable(AddressLiteral adr) { int64_t disp; + // None will force a 64bit literal to the code stream. Likely a placeholder // for something that will be patched later and we need to certain it will // always be reachable. @@ -636,7 +637,7 @@ case 0x8A: // movb r, a case 0x8B: // movl r, a case 0x8F: // popl a - debug_only(has_disp32 = true); + debug_only(has_disp32 = true;) break; case 0x68: // pushq #32 @@ -2891,7 +2892,7 @@ } // scans rcx double words (m64) at [rdi] for occurance of rax -void Assembler::repne_scan() { +void Assembler::repne_scanq() { // REPNE/REPNZ emit_byte(0xF2); // SCASQ @@ -2899,6 +2900,14 @@ emit_byte(0xAF); } +void Assembler::repne_scanl() { + // REPNE/REPNZ + emit_byte(0xF2); + // SCASL + emit_byte(0xAF); +} + + void Assembler::setb(Condition cc, Register dst) { assert(0 <= cc && cc < 16, "illegal cc"); int encode = prefix_and_encode(dst->encoding(), true); @@ -4597,7 +4606,6 @@ // pass args on stack, only touch rax pushq(reg); - // avoid using pushptr, as it modifies scratch registers // and our contract is not to modify anything ExternalAddress buffer((address)b); @@ -4664,9 +4672,9 @@ JavaThread* thread = JavaThread::current(); JavaThreadState saved_state = thread->thread_state(); thread->set_thread_state(_thread_in_vm); - ttyLocker ttyl; #ifndef PRODUCT if (CountBytecodes || TraceBytecodes || StopInterpreterAt) { + ttyLocker ttyl; BytecodeCounter::print(); } #endif @@ -4674,6 +4682,7 @@ // XXX correct this offset for amd64 // This is the value of eip which points to where verify_oop will return. if (os::message_box(msg, "Execution stopped, print registers?")) { + ttyLocker ttyl; tty->print_cr("rip = 0x%016lx", pc); tty->print_cr("rax = 0x%016lx", regs[15]); tty->print_cr("rbx = 0x%016lx", regs[12]); @@ -4695,6 +4704,7 @@ } ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); } else { + ttyLocker ttyl; ::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n", msg); } @@ -4891,7 +4901,7 @@ movq(Address(top, arrayOopDesc::length_offset_in_bytes()), t1); // set klass to intArrayKlass movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr())); - movq(Address(top, oopDesc::klass_offset_in_bytes()), t1); + store_klass(top, t1); // refill the tlab with an eden allocation bind(do_refill); @@ -4938,7 +4948,6 @@ assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg); assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); - Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes()); Address saved_mark_addr(lock_reg, 0); if (PrintBiasedLockingStatistics && counters == NULL) @@ -4962,7 +4971,7 @@ jcc(Assembler::notEqual, cas_label); // The bias pattern is present in the object's header. Need to check // whether the bias owner and the epoch are both still current. - movq(tmp_reg, klass_addr); + load_klass(tmp_reg, obj_reg); movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); orq(tmp_reg, r15_thread); xorq(tmp_reg, swap_reg); @@ -5037,7 +5046,7 @@ // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - movq(tmp_reg, klass_addr); + load_klass(tmp_reg, obj_reg); movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); orq(tmp_reg, r15_thread); if (os::is_MP()) { @@ -5068,7 +5077,7 @@ // // FIXME: due to a lack of registers we currently blow away the age // bits in this situation. Should attempt to preserve them. - movq(tmp_reg, klass_addr); + load_klass(tmp_reg, obj_reg); movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes())); if (os::is_MP()) { lock(); @@ -5104,6 +5113,113 @@ } +void MacroAssembler::load_klass(Register dst, Register src) { + if (UseCompressedOops) { + movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); + decode_heap_oop_not_null(dst); + } else { + movq(dst, Address(src, oopDesc::klass_offset_in_bytes())); + } +} + +void MacroAssembler::store_klass(Register dst, Register src) { + if (UseCompressedOops) { + encode_heap_oop_not_null(src); + // zero the entire klass field first as the gap needs to be zeroed too. + movptr(Address(dst, oopDesc::klass_offset_in_bytes()), NULL_WORD); + movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); + } else { + movq(Address(dst, oopDesc::klass_offset_in_bytes()), src); + } +} + +void MacroAssembler::load_heap_oop(Register dst, Address src) { + if (UseCompressedOops) { + movl(dst, src); + decode_heap_oop(dst); + } else { + movq(dst, src); + } +} + +void MacroAssembler::store_heap_oop(Address dst, Register src) { + if (UseCompressedOops) { + assert(!dst.uses(src), "not enough registers"); + encode_heap_oop(src); + movl(dst, src); + } else { + movq(dst, src); + } +} + +// Algorithm must match oop.inline.hpp encode_heap_oop. +void MacroAssembler::encode_heap_oop(Register r) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + pushq(rscratch1); // cmpptr trashes rscratch1 + cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); + jcc(Assembler::equal, ok); + stop("MacroAssembler::encode_heap_oop: heap base corrupted?"); + bind(ok); + popq(rscratch1); +#endif + verify_oop(r); + testq(r, r); + cmovq(Assembler::equal, r, r12_heapbase); + subq(r, r12_heapbase); + shrq(r, LogMinObjAlignmentInBytes); +} + +void MacroAssembler::encode_heap_oop_not_null(Register r) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + testq(r, r); + jcc(Assembler::notEqual, ok); + stop("null oop passed to encode_heap_oop_not_null"); + bind(ok); +#endif + verify_oop(r); + subq(r, r12_heapbase); + shrq(r, LogMinObjAlignmentInBytes); +} + +void MacroAssembler::decode_heap_oop(Register r) { + assert (UseCompressedOops, "should be compressed"); +#ifdef ASSERT + Label ok; + pushq(rscratch1); + cmpptr(r12_heapbase, + ExternalAddress((address)Universe::heap_base_addr())); + jcc(Assembler::equal, ok); + stop("MacroAssembler::decode_heap_oop: heap base corrupted?"); + bind(ok); + popq(rscratch1); +#endif + + Label done; + shlq(r, LogMinObjAlignmentInBytes); + jccb(Assembler::equal, done); + addq(r, r12_heapbase); +#if 0 + // alternate decoding probably a wash. + testq(r, r); + jccb(Assembler::equal, done); + leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); +#endif + bind(done); + verify_oop(r); +} + +void MacroAssembler::decode_heap_oop_not_null(Register r) { + assert (UseCompressedOops, "should only be used for compressed headers"); + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong"); + leaq(r, Address(r12_heapbase, r, Address::times_8, 0)); +} + Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) { switch (cond) { // Note some conditions are synonyms for others @@ -5173,3 +5289,9 @@ movq(Address(tmp, (-i*os::vm_page_size())), size ); } } + +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops) { + movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr())); + } +}