diff -r 50c604cb0d5f -r 30245956af37 hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Mon Jul 23 13:04:59 2012 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Tue Jul 24 10:51:00 2012 -0700 @@ -41,6 +41,15 @@ #include "gc_implementation/g1/heapRegion.hpp" #endif +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#define STOP(error) stop(error) +#else +#define BLOCK_COMMENT(str) block_comment(str) +#define STOP(error) block_comment(error); stop(error) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") // Implementation of AddressLiteral AddressLiteral::AddressLiteral(address target, relocInfo::relocType rtype) { @@ -5508,23 +5517,7 @@ // To see where a verify_oop failed, get $ebx+40/X for this frame. // 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("eip = 0x%08x", eip); -#ifndef PRODUCT - if ((WizardMode || Verbose) && PrintMiscellaneous) { - tty->cr(); - findpc(eip); - tty->cr(); - } -#endif - tty->print_cr("rax = 0x%08x", rax); - tty->print_cr("rbx = 0x%08x", rbx); - tty->print_cr("rcx = 0x%08x", rcx); - tty->print_cr("rdx = 0x%08x", rdx); - tty->print_cr("rdi = 0x%08x", rdi); - tty->print_cr("rsi = 0x%08x", rsi); - tty->print_cr("rbp = 0x%08x", rbp); - tty->print_cr("rsp = 0x%08x", rsp); + print_state32(rdi, rsi, rbp, rsp, rbx, rdx, rcx, rax, eip); BREAKPOINT; assert(false, "start up GDB"); } @@ -5536,12 +5529,53 @@ ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); } +void MacroAssembler::print_state32(int rdi, int rsi, int rbp, int rsp, int rbx, int rdx, int rcx, int rax, int eip) { + ttyLocker ttyl; + FlagSetting fs(Debugging, true); + tty->print_cr("eip = 0x%08x", eip); +#ifndef PRODUCT + if ((WizardMode || Verbose) && PrintMiscellaneous) { + tty->cr(); + findpc(eip); + tty->cr(); + } +#endif +#define PRINT_REG(rax) \ + { tty->print("%s = ", #rax); os::print_location(tty, rax); } + PRINT_REG(rax); + PRINT_REG(rbx); + PRINT_REG(rcx); + PRINT_REG(rdx); + PRINT_REG(rdi); + PRINT_REG(rsi); + PRINT_REG(rbp); + PRINT_REG(rsp); +#undef PRINT_REG + // Print some words near top of staack. + int* dump_sp = (int*) rsp; + for (int col1 = 0; col1 < 8; col1++) { + tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); + os::print_location(tty, *dump_sp++); + } + for (int row = 0; row < 16; row++) { + tty->print("(rsp+0x%03x) 0x%08x: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); + for (int col = 0; col < 8; col++) { + tty->print(" 0x%08x", *dump_sp++); + } + tty->cr(); + } + // Print some instructions around pc: + Disassembler::decode((address)eip-64, (address)eip); + tty->print_cr("--------"); + Disassembler::decode((address)eip, (address)eip+32); +} + void MacroAssembler::stop(const char* msg) { ExternalAddress message((address)msg); // push address of message pushptr(message.addr()); { Label L; call(L, relocInfo::none); bind(L); } // push eip - pusha(); // push registers + pusha(); // push registers call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug32))); hlt(); } @@ -5558,6 +5592,18 @@ pop_CPU_state(); } +void MacroAssembler::print_state() { + { Label L; call(L, relocInfo::none); bind(L); } // push eip + pusha(); // push registers + + push_CPU_state(); + call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::print_state32))); + pop_CPU_state(); + + popa(); + addl(rsp, wordSize); +} + #else // _LP64 // 64 bit versions @@ -6023,14 +6069,33 @@ } void MacroAssembler::warn(const char* msg) { - push(rsp); + push(rbp); + movq(rbp, rsp); andq(rsp, -16); // align stack as required by push_CPU_state and call - push_CPU_state(); // keeps alignment at 16 bytes lea(c_rarg0, ExternalAddress((address) msg)); call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0); pop_CPU_state(); - pop(rsp); + mov(rsp, rbp); + pop(rbp); +} + +void MacroAssembler::print_state() { + address rip = pc(); + pusha(); // get regs on stack + push(rbp); + movq(rbp, rsp); + andq(rsp, -16); // align stack as required by push_CPU_state and call + push_CPU_state(); // keeps alignment at 16 bytes + + lea(c_rarg0, InternalAddress(rip)); + lea(c_rarg1, Address(rbp, wordSize)); // pass pointer to regs array + call_VM_leaf(CAST_FROM_FN_PTR(address, MacroAssembler::print_state64), c_rarg0, c_rarg1); + + pop_CPU_state(); + mov(rsp, rbp); + pop(rbp); + popa(); } #ifndef PRODUCT @@ -6039,7 +6104,7 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) { // In order to get locks to work, we need to fake a in_VM state - if (ShowMessageBoxOnError ) { + if (ShowMessageBoxOnError) { JavaThread* thread = JavaThread::current(); JavaThreadState saved_state = thread->thread_state(); thread->set_thread_state(_thread_in_vm); @@ -6053,30 +6118,9 @@ // 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); -#ifndef PRODUCT - tty->cr(); - findpc(pc); - tty->cr(); -#endif - tty->print_cr("rax = 0x%016lx", regs[15]); - tty->print_cr("rbx = 0x%016lx", regs[12]); - tty->print_cr("rcx = 0x%016lx", regs[14]); - tty->print_cr("rdx = 0x%016lx", regs[13]); - tty->print_cr("rdi = 0x%016lx", regs[8]); - tty->print_cr("rsi = 0x%016lx", regs[9]); - tty->print_cr("rbp = 0x%016lx", regs[10]); - tty->print_cr("rsp = 0x%016lx", regs[11]); - tty->print_cr("r8 = 0x%016lx", regs[7]); - tty->print_cr("r9 = 0x%016lx", regs[6]); - tty->print_cr("r10 = 0x%016lx", regs[5]); - tty->print_cr("r11 = 0x%016lx", regs[4]); - tty->print_cr("r12 = 0x%016lx", regs[3]); - tty->print_cr("r13 = 0x%016lx", regs[2]); - tty->print_cr("r14 = 0x%016lx", regs[1]); - tty->print_cr("r15 = 0x%016lx", regs[0]); + print_state64(pc, regs); BREAKPOINT; + assert(false, "start up GDB"); } ThreadStateTransition::transition(thread, _thread_in_vm, saved_state); } else { @@ -6087,6 +6131,54 @@ } } +void MacroAssembler::print_state64(int64_t pc, int64_t regs[]) { + ttyLocker ttyl; + FlagSetting fs(Debugging, true); + tty->print_cr("rip = 0x%016lx", pc); +#ifndef PRODUCT + tty->cr(); + findpc(pc); + tty->cr(); +#endif +#define PRINT_REG(rax, value) \ + { tty->print("%s = ", #rax); os::print_location(tty, value); } + PRINT_REG(rax, regs[15]); + PRINT_REG(rbx, regs[12]); + PRINT_REG(rcx, regs[14]); + PRINT_REG(rdx, regs[13]); + PRINT_REG(rdi, regs[8]); + PRINT_REG(rsi, regs[9]); + PRINT_REG(rbp, regs[10]); + PRINT_REG(rsp, regs[11]); + PRINT_REG(r8 , regs[7]); + PRINT_REG(r9 , regs[6]); + PRINT_REG(r10, regs[5]); + PRINT_REG(r11, regs[4]); + PRINT_REG(r12, regs[3]); + PRINT_REG(r13, regs[2]); + PRINT_REG(r14, regs[1]); + PRINT_REG(r15, regs[0]); +#undef PRINT_REG + // Print some words near top of staack. + int64_t* rsp = (int64_t*) regs[11]; + int64_t* dump_sp = rsp; + for (int col1 = 0; col1 < 8; col1++) { + tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); + os::print_location(tty, *dump_sp++); + } + for (int row = 0; row < 25; row++) { + tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); + for (int col = 0; col < 4; col++) { + tty->print(" 0x%016lx", *dump_sp++); + } + tty->cr(); + } + // Print some instructions around pc: + Disassembler::decode((address)pc-64, (address)pc); + tty->print_cr("--------"); + Disassembler::decode((address)pc, (address)pc+32); +} + #endif // _LP64 // Now versions that are common to 32/64 bit @@ -6456,7 +6548,7 @@ get_thread(rax); cmpptr(java_thread, rax); jcc(Assembler::equal, L); - stop("MacroAssembler::call_VM_base: rdi not callee saved?"); + STOP("MacroAssembler::call_VM_base: rdi not callee saved?"); bind(L); } pop(rax); @@ -7196,7 +7288,7 @@ jcc(Assembler::notZero, integer); cmpl(tmp3, 0x80000000); jcc(Assembler::notZero, integer); - stop("integer indefinite value shouldn't be seen here"); + STOP("integer indefinite value shouldn't be seen here"); bind(integer); } #else @@ -7206,7 +7298,7 @@ shlq(tmp3, 1); jcc(Assembler::carryClear, integer); jcc(Assembler::notZero, integer); - stop("integer indefinite value shouldn't be seen here"); + STOP("integer indefinite value shouldn't be seen here"); bind(integer); } #endif @@ -8388,7 +8480,7 @@ shlptr(tsize, LogHeapWordSize); cmpptr(t1, tsize); jcc(Assembler::equal, ok); - stop("assert(t1 != tlab size)"); + STOP("assert(t1 != tlab size)"); should_not_reach_here(); bind(ok); @@ -8727,6 +8819,19 @@ } +// virtual method calling +void MacroAssembler::lookup_virtual_method(Register recv_klass, + RegisterOrConstant vtable_index, + Register method_result) { + const int base = instanceKlass::vtable_start_offset() * wordSize; + assert(vtableEntry::size() * wordSize == wordSize, "else adjust the scaling in the code below"); + Address vtable_entry_addr(recv_klass, + vtable_index, Address::times_ptr, + base + vtableEntry::method_offset_in_bytes()); + movptr(method_result, vtable_entry_addr); +} + + void MacroAssembler::check_klass_subtype(Register sub_klass, Register super_klass, Register temp_reg, @@ -8976,6 +9081,7 @@ // Pass register number to verify_oop_subroutine char* b = new char[strlen(s) + 50]; sprintf(b, "verify_oop: %s: %s", reg->name(), s); + BLOCK_COMMENT("verify_oop {"); #ifdef _LP64 push(rscratch1); // save r10, trashed by movptr() #endif @@ -8990,6 +9096,7 @@ movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address())); call(rax); // Caller pops the arguments (oop, message) and restores rax, r10 + BLOCK_COMMENT("} verify_oop"); } @@ -9010,7 +9117,7 @@ jcc(Assembler::notZero, L); char* buf = new char[40]; sprintf(buf, "DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]); - stop(buf); + STOP(buf); } else { jccb(Assembler::notZero, L); hlt(); @@ -9026,60 +9133,6 @@ } -// registers on entry: -// - rax ('check' register): required MethodType -// - rcx: method handle -// - rdx, rsi, or ?: killable temp -void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg, - Register temp_reg, - Label& wrong_method_type) { - Address type_addr(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg)); - // compare method type against that of the receiver - if (UseCompressedOops) { - load_heap_oop(temp_reg, type_addr); - cmpptr(mtype_reg, temp_reg); - } else { - cmpptr(mtype_reg, type_addr); - } - jcc(Assembler::notEqual, wrong_method_type); -} - - -// A method handle has a "vmslots" field which gives the size of its -// argument list in JVM stack slots. This field is either located directly -// in every method handle, or else is indirectly accessed through the -// method handle's MethodType. This macro hides the distinction. -void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg, - Register temp_reg) { - assert_different_registers(vmslots_reg, mh_reg, temp_reg); - // load mh.type.form.vmslots - Register temp2_reg = vmslots_reg; - load_heap_oop(temp2_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::type_offset_in_bytes, temp_reg))); - load_heap_oop(temp2_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodType::form_offset_in_bytes, temp_reg))); - movl(vmslots_reg, Address(temp2_reg, delayed_value(java_lang_invoke_MethodTypeForm::vmslots_offset_in_bytes, temp_reg))); -} - - -// registers on entry: -// - rcx: method handle -// - rdx: killable temp (interpreted only) -// - rax: killable temp (compiled only) -void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) { - assert(mh_reg == rcx, "caller must put MH object in rcx"); - assert_different_registers(mh_reg, temp_reg); - - // pick out the interpreted side of the handler - // NOTE: vmentry is not an oop! - movptr(temp_reg, Address(mh_reg, delayed_value(java_lang_invoke_MethodHandle::vmentry_offset_in_bytes, temp_reg))); - - // off we go... - jmp(Address(temp_reg, MethodHandleEntry::from_interpreted_entry_offset_in_bytes())); - - // for the various stubs which take control at this point, - // see MethodHandles::generate_method_handle_stub -} - - Address MacroAssembler::argument_address(RegisterOrConstant arg_slot, int extra_slot_offset) { // cf. TemplateTable::prepare_invoke(), if (load_receiver). @@ -9152,14 +9205,14 @@ movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_start_offset()))); jcc(Assembler::aboveEqual, next); - stop("assert(top >= start)"); + STOP("assert(top >= start)"); should_not_reach_here(); bind(next); movptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_end_offset()))); cmpptr(t1, Address(thread_reg, in_bytes(JavaThread::tlab_top_offset()))); jcc(Assembler::aboveEqual, ok); - stop("assert(top <= end)"); + STOP("assert(top <= end)"); should_not_reach_here(); bind(ok); @@ -9592,6 +9645,25 @@ movptr(dst, src); } +void MacroAssembler::cmp_heap_oop(Register src1, Address src2, Register tmp) { + assert_different_registers(src1, tmp); +#ifdef _LP64 + if (UseCompressedOops) { + bool did_push = false; + if (tmp == noreg) { + tmp = rax; + push(tmp); + did_push = true; + assert(!src2.uses(rsp), "can't push"); + } + load_heap_oop(tmp, src2); + cmpptr(src1, tmp); + if (did_push) pop(tmp); + } else +#endif + cmpptr(src1, src2); +} + // Used for storing NULLs. void MacroAssembler::store_heap_oop_null(Address dst) { #ifdef _LP64 @@ -9622,7 +9694,7 @@ push(rscratch1); // cmpptr trashes rscratch1 cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); jcc(Assembler::equal, ok); - stop(msg); + STOP(msg); bind(ok); pop(rscratch1); } @@ -9655,7 +9727,7 @@ Label ok; testq(r, r); jcc(Assembler::notEqual, ok); - stop("null oop passed to encode_heap_oop_not_null"); + STOP("null oop passed to encode_heap_oop_not_null"); bind(ok); } #endif @@ -9676,7 +9748,7 @@ Label ok; testq(src, src); jcc(Assembler::notEqual, ok); - stop("null oop passed to encode_heap_oop_not_null2"); + STOP("null oop passed to encode_heap_oop_not_null2"); bind(ok); } #endif @@ -9867,7 +9939,7 @@ cmpptr(rax, StackAlignmentInBytes-wordSize); pop(rax); jcc(Assembler::equal, L); - stop("Stack is not properly aligned!"); + STOP("Stack is not properly aligned!"); bind(L); } #endif @@ -10541,13 +10613,6 @@ bind(DONE); } -#ifdef PRODUCT -#define BLOCK_COMMENT(str) /* nothing */ -#else -#define BLOCK_COMMENT(str) block_comment(str) -#endif - -#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") void MacroAssembler::generate_fill(BasicType t, bool aligned, Register to, Register value, Register count, Register rtmp, XMMRegister xtmp) {