Mercurial > hg > graal-compiler
changeset 4952:15085a6eb50c
Merge
author | never |
---|---|
date | Fri, 17 Feb 2012 12:18:52 -0800 |
parents | 72c425c46102 (diff) d3384450b649 (current diff) |
children | f92a171cf007 |
files | src/cpu/x86/vm/globals_x86.hpp src/share/vm/runtime/arguments.cpp |
diffstat | 45 files changed, 632 insertions(+), 1462 deletions(-) [+] |
line wrap: on
line diff
--- a/make/Makefile Fri Feb 17 06:34:49 2012 -0800 +++ b/make/Makefile Fri Feb 17 12:18:52 2012 -0800 @@ -402,7 +402,6 @@ $(install-file) else $(EXPORT_INCLUDE_DIR)/jfr.h: - endif # Doc files (jvmti.html) @@ -448,12 +447,18 @@ ($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -) test_jdk: - ifneq ($(ZERO_BUILD), true) ifeq ($(ARCH_DATA_MODEL), 32) - $(JDK_IMAGE_DIR)/bin/java -client -version + ifneq ($(ZERO_BUILD), true) + $(JDK_IMAGE_DIR)/bin/java -d32 -client -Xinternalversion + $(JDK_IMAGE_DIR)/bin/java -d32 -client -version + endif + $(JDK_IMAGE_DIR)/bin/java -d32 -server -Xinternalversion + $(JDK_IMAGE_DIR)/bin/java -d32 -server -version endif - endif - $(JDK_IMAGE_DIR)/bin/java -server -version + ifeq ($(ARCH_DATA_MODEL), 64) + $(JDK_IMAGE_DIR)/bin/java -d64 -server -Xinternalversion + $(JDK_IMAGE_DIR)/bin/java -d64 -server -version + endif copy_product_jdk:: $(RM) -r $(JDK_IMAGE_DIR) @@ -545,6 +550,7 @@ OUTPUTDIR.desc = Output directory, default is build/<osname> BOOTDIR.desc = JDK used to compile agent java source and test with JDK_IMPORT_PATH.desc = Promoted JDK to copy for 'create_jdk' +JDK_IMAGE_DIR.desc = Directory to place JDK to copy EXPORT_PATH.desc = Directory to place files to export for JDK build # Make variables to print out (description and value) @@ -553,6 +559,7 @@ OUTPUTDIR \ BOOTDIR \ JDK_IMPORT_PATH \ + JDK_IMAGE_DIR \ EXPORT_PATH # Make variables that should refer to directories that exist
--- a/make/bsd/makefiles/defs.make Fri Feb 17 06:34:49 2012 -0800 +++ b/make/bsd/makefiles/defs.make Fri Feb 17 12:18:52 2012 -0800 @@ -191,6 +191,9 @@ # Set universal image dir JDK_IMAGE_DIR=$(OUTPUTDIR)/jdk-universal$(EXPORT_SUBDIR) + ifneq ($(ALT_JDK_IMAGE_DIR),) + JDK_IMAGE_DIR=$(ALT_JDK_IMAGE_DIR) + endif # Binaries to 'universalize' if built UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX)
--- a/make/bsd/makefiles/top.make Fri Feb 17 06:34:49 2012 -0800 +++ b/make/bsd/makefiles/top.make Fri Feb 17 12:18:52 2012 -0800 @@ -124,8 +124,8 @@ @$(UpdatePCH) @$(MAKE) -f vm.make $(MFLAGS-adjusted) -install: the_vm - @$(MAKE) -f vm.make install +install gamma: the_vm + @$(MAKE) -f vm.make $@ # next rules support "make foo.[ois]"
--- a/make/defs.make Fri Feb 17 06:34:49 2012 -0800 +++ b/make/defs.make Fri Feb 17 12:18:52 2012 -0800 @@ -193,6 +193,9 @@ # Default jdk image if one is created for you with create_jdk JDK_IMAGE_DIR=$(OUTPUTDIR)/jdk-$(PLATFORM) +ifneq ($(ALT_JDK_IMAGE_DIR),) + JDK_IMAGE_DIR=$(ALT_JDK_IMAGE_DIR) +endif # The platform dependent defs.make defines platform specific variable such # as ARCH, EXPORT_LIST etc. We must place the include here after BOOTDIR is defined.
--- a/make/linux/makefiles/top.make Fri Feb 17 06:34:49 2012 -0800 +++ b/make/linux/makefiles/top.make Fri Feb 17 12:18:52 2012 -0800 @@ -115,8 +115,8 @@ @$(UpdatePCH) @$(MAKE) -f vm.make $(MFLAGS-adjusted) -install: the_vm - @$(MAKE) -f vm.make install +install gamma: the_vm + @$(MAKE) -f vm.make $@ # next rules support "make foo.[ois]"
--- a/make/solaris/makefiles/top.make Fri Feb 17 06:34:49 2012 -0800 +++ b/make/solaris/makefiles/top.make Fri Feb 17 12:18:52 2012 -0800 @@ -107,8 +107,8 @@ the_vm: vm_build_preliminaries $(adjust-mflags) @$(MAKE) -f vm.make $(MFLAGS-adjusted) -install: the_vm - @$(MAKE) -f vm.make install +install gamma: the_vm + @$(MAKE) -f vm.make $@ # next rules support "make foo.[oi]"
--- a/src/cpu/x86/vm/assembler_x86.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/assembler_x86.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -236,6 +236,16 @@ } } +// Force generation of a 4 byte immediate value even if it fits into 8bit +void Assembler::emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32) { + assert(isByte(op1) && isByte(op2), "wrong opcode"); + assert((op1 & 0x01) == 1, "should be 32bit operation"); + assert((op1 & 0x02) == 0, "sign-extension bit should not be set"); + emit_byte(op1); + emit_byte(op2 | encode(dst)); + emit_long(imm32); +} + // immediate-to-memory forms void Assembler::emit_arith_operand(int op1, Register rm, Address adr, int32_t imm32) { assert((op1 & 0x01) == 1, "should be 32bit operation"); @@ -939,6 +949,7 @@ } void Assembler::addr_nop_4() { + assert(UseAddressNop, "no CPU support"); // 4 bytes: NOP DWORD PTR [EAX+0] emit_byte(0x0F); emit_byte(0x1F); @@ -947,6 +958,7 @@ } void Assembler::addr_nop_5() { + assert(UseAddressNop, "no CPU support"); // 5 bytes: NOP DWORD PTR [EAX+EAX*0+0] 8-bits offset emit_byte(0x0F); emit_byte(0x1F); @@ -956,6 +968,7 @@ } void Assembler::addr_nop_7() { + assert(UseAddressNop, "no CPU support"); // 7 bytes: NOP DWORD PTR [EAX+0] 32-bits offset emit_byte(0x0F); emit_byte(0x1F); @@ -964,6 +977,7 @@ } void Assembler::addr_nop_8() { + assert(UseAddressNop, "no CPU support"); // 8 bytes: NOP DWORD PTR [EAX+EAX*0+0] 32-bits offset emit_byte(0x0F); emit_byte(0x1F); @@ -2769,6 +2783,12 @@ emit_arith(0x81, 0xE8, dst, imm32); } +// Force generation of a 4 byte immediate value even if it fits into 8bit +void Assembler::subl_imm32(Register dst, int32_t imm32) { + prefix(dst); + emit_arith_imm32(0x81, 0xE8, dst, imm32); +} + void Assembler::subl(Register dst, Address src) { InstructionMark im(this); prefix(src, dst); @@ -4760,6 +4780,12 @@ emit_arith(0x81, 0xE8, dst, imm32); } +// Force generation of a 4 byte immediate value even if it fits into 8bit +void Assembler::subq_imm32(Register dst, int32_t imm32) { + (void) prefixq_and_encode(dst->encoding()); + emit_arith_imm32(0x81, 0xE8, dst, imm32); +} + void Assembler::subq(Register dst, Address src) { InstructionMark im(this); prefixq(src, dst); @@ -5101,15 +5127,6 @@ } } -void MacroAssembler::fat_nop() { - // A 5 byte nop that is safe for patching (see patch_verified_entry) - emit_byte(0x26); // es: - emit_byte(0x2e); // cs: - emit_byte(0x64); // fs: - emit_byte(0x65); // gs: - emit_byte(0x90); -} - void MacroAssembler::jC2(Register tmp, Label& L) { // set parity bit if FPU flag C2 is set (via rax) save_rax(tmp); @@ -5704,17 +5721,6 @@ /* else */ { subq(dst, value) ; return; } } -void MacroAssembler::fat_nop() { - // A 5 byte nop that is safe for patching (see patch_verified_entry) - // Recommened sequence from 'Software Optimization Guide for the AMD - // Hammer Processor' - emit_byte(0x66); - emit_byte(0x66); - emit_byte(0x90); - emit_byte(0x66); - emit_byte(0x90); -} - void MacroAssembler::incrementq(Register reg, int value) { if (value == min_jint) { addq(reg, value); return; } if (value < 0) { decrementq(reg, -value); return; } @@ -6766,6 +6772,19 @@ mov(rbp, rsp); } +// A 5 byte nop that is safe for patching (see patch_verified_entry) +void MacroAssembler::fat_nop() { + if (UseAddressNop) { + addr_nop_5(); + } else { + emit_byte(0x26); // es: + emit_byte(0x2e); // cs: + emit_byte(0x64); // fs: + emit_byte(0x65); // gs: + emit_byte(0x90); + } +} + void MacroAssembler::fcmp(Register tmp) { fcmp(tmp, 1, true, true); } @@ -7825,6 +7844,11 @@ LP64_ONLY(subq(dst, imm32)) NOT_LP64(subl(dst, imm32)); } +// Force generation of a 4 byte immediate value even if it fits into 8bit +void MacroAssembler::subptr_imm32(Register dst, int32_t imm32) { + LP64_ONLY(subq_imm32(dst, imm32)) NOT_LP64(subl_imm32(dst, imm32)); +} + void MacroAssembler::subptr(Register dst, Register src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } @@ -9292,6 +9316,80 @@ } #endif // _LP64 + +// C2 compiled method's prolog code. +void MacroAssembler::verified_entry(int framesize, bool stack_bang, bool fp_mode_24b) { + + // WARNING: Initial instruction MUST be 5 bytes or longer so that + // NativeJump::patch_verified_entry will be able to patch out the entry + // code safely. The push to verify stack depth is ok at 5 bytes, + // the frame allocation can be either 3 or 6 bytes. So if we don't do + // stack bang then we must use the 6 byte frame allocation even if + // we have no frame. :-( + + assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); + // Remove word for return addr + framesize -= wordSize; + + // Calls to C2R adapters often do not accept exceptional returns. + // We require that their callers must bang for them. But be careful, because + // some VM calls (such as call site linkage) can use several kilobytes of + // stack. But the stack safety zone should account for that. + // See bugs 4446381, 4468289, 4497237. + if (stack_bang) { + generate_stack_overflow_check(framesize); + + // We always push rbp, so that on return to interpreter rbp, will be + // restored correctly and we can correct the stack. + push(rbp); + // Remove word for ebp + framesize -= wordSize; + + // Create frame + if (framesize) { + subptr(rsp, framesize); + } + } else { + // Create frame (force generation of a 4 byte immediate value) + subptr_imm32(rsp, framesize); + + // Save RBP register now. + framesize -= wordSize; + movptr(Address(rsp, framesize), rbp); + } + + if (VerifyStackAtCalls) { // Majik cookie to verify stack depth + framesize -= wordSize; + movptr(Address(rsp, framesize), (int32_t)0xbadb100d); + } + +#ifndef _LP64 + // If method sets FPU control word do it now + if (fp_mode_24b) { + fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); + } + if (UseSSE >= 2 && VerifyFPU) { + verify_FPU(0, "FPU stack must be clean on entry"); + } +#endif + +#ifdef ASSERT + if (VerifyStackAtCalls) { + Label L; + push(rax); + mov(rax, rsp); + andptr(rax, StackAlignmentInBytes-1); + cmpptr(rax, StackAlignmentInBytes-wordSize); + pop(rax); + jcc(Assembler::equal, L); + stop("Stack is not properly aligned!"); + bind(L); + } +#endif + +} + + // IndexOf for constant substrings with size >= 8 chars // which don't need to be loaded through stack. void MacroAssembler::string_indexofC8(Register str1, Register str2,
--- a/src/cpu/x86/vm/assembler_x86.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/assembler_x86.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -667,6 +667,8 @@ void emit_arith_b(int op1, int op2, Register dst, int imm8); void emit_arith(int op1, int op2, Register dst, int32_t imm32); + // Force generation of a 4 byte immediate value even if it fits into 8bit + void emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32); // only 32bit?? void emit_arith(int op1, int op2, Register dst, jobject obj); void emit_arith(int op1, int op2, Register dst, Register src); @@ -1526,6 +1528,9 @@ void subq(Register dst, Address src); void subq(Register dst, Register src); + // Force generation of a 4 byte immediate value even if it fits into 8bit + void subl_imm32(Register dst, int32_t imm32); + void subq_imm32(Register dst, int32_t imm32); // Subtract Scalar Double-Precision Floating-Point Values void subsd(XMMRegister dst, Address src); @@ -1763,8 +1768,8 @@ // Alignment void align(int modulus); - // Misc - void fat_nop(); // 5 byte nop + // A 5 byte nop that is safe for patching (see patch_verified_entry) + void fat_nop(); // Stack frame creation/removal void enter(); @@ -2275,6 +2280,8 @@ void subptr(Register dst, Address src) { LP64_ONLY(subq(dst, src)) NOT_LP64(subl(dst, src)); } void subptr(Register dst, int32_t src); + // Force generation of a 4 byte immediate value even if it fits into 8bit + void subptr_imm32(Register dst, int32_t src); void subptr(Register dst, Register src); void subptr(Register dst, RegisterOrConstant src) { if (src.is_constant()) subptr(dst, (int) src.as_constant()); @@ -2566,6 +2573,9 @@ void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); } void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } + // C2 compiled method's prolog code. + void verified_entry(int framesize, bool stack_bang, bool fp_mode_24b); + // IndexOf strings. // Small strings are loaded through stack if they cross page boundary. void string_indexof(Register str1, Register str2,
--- a/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -381,6 +381,16 @@ void C1_MacroAssembler::verified_entry() { + if (C1Breakpoint || VerifyFPU || !UseStackBanging) { + // Verified Entry first instruction should be 5 bytes long for correct + // patching by patch_verified_entry(). + // + // C1Breakpoint and VerifyFPU have one byte first instruction. + // Also first instruction will be one byte "push(rbp)" if stack banging + // code is not generated (see build_frame() above). + // For all these cases generate long instruction first. + fat_nop(); + } if (C1Breakpoint)int3(); // build frame verify_FPU(0, "method_entry");
--- a/src/cpu/x86/vm/globals_x86.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/globals_x86.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -62,7 +62,7 @@ // due to lack of optimization caused by C++ compiler bugs define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2)); #else -define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+5)); +define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5)); #endif // AMD64 define_pd_global(intx, PreInflateSpin, 10);
--- a/src/cpu/x86/vm/methodHandles_x86.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -1018,41 +1018,26 @@ void trace_method_handle_stub(const char* adaptername, oop mh, intptr_t* saved_regs, - intptr_t* entry_sp, - intptr_t* saved_sp, - intptr_t* saved_bp) { + intptr_t* entry_sp) { // called as a leaf from native code: do not block the JVM! bool has_mh = (strstr(adaptername, "return/") == NULL); // return adapters don't have rcx_mh + const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx"; + tty->print_cr("MH %s %s="PTR_FORMAT" sp="PTR_FORMAT, adaptername, mh_reg_name, mh, entry_sp); - intptr_t* last_sp = (intptr_t*) saved_bp[frame::interpreter_frame_last_sp_offset]; - intptr_t* base_sp = last_sp; - typedef MethodHandles::RicochetFrame RicochetFrame; - RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes()); - if (Universe::heap()->is_in((address) rfp->saved_args_base())) { - // Probably an interpreter frame. - base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; - } - intptr_t mh_reg = (intptr_t)mh; - const char* mh_reg_name = "rcx_mh"; - if (!has_mh) mh_reg_name = "rcx"; - tty->print_cr("MH %s %s="PTR_FORMAT" sp=("PTR_FORMAT"+"INTX_FORMAT") stack_size="INTX_FORMAT" bp="PTR_FORMAT, - adaptername, mh_reg_name, mh_reg, - (intptr_t)entry_sp, (intptr_t)(saved_sp - entry_sp), (intptr_t)(base_sp - last_sp), (intptr_t)saved_bp); if (Verbose) { - tty->print(" reg dump: "); - int saved_regs_count = (entry_sp-1) - saved_regs; - // 32 bit: rdi rsi rbp rsp; rbx rdx rcx (*) rax - int i; - for (i = 0; i <= saved_regs_count; i++) { - if (i > 0 && i % 4 == 0 && i != saved_regs_count) { + tty->print_cr("Registers:"); + const int saved_regs_count = RegisterImpl::number_of_registers; + for (int i = 0; i < saved_regs_count; i++) { + Register r = as_Register(i); + // The registers are stored in reverse order on the stack (by pusha). + tty->print("%3s=" PTR_FORMAT, r->name(), saved_regs[((saved_regs_count - 1) - i)]); + if ((i + 1) % 4 == 0) { tty->cr(); - tty->print(" + dump: "); + } else { + tty->print(", "); } - tty->print(" %d: "PTR_FORMAT, i, saved_regs[i]); } tty->cr(); - if (last_sp != saved_sp && last_sp != NULL) - tty->print_cr("*** last_sp="PTR_FORMAT, (intptr_t)last_sp); { // dumping last frame with frame::describe @@ -1102,14 +1087,7 @@ values.describe(-1, dump_sp, "sp for #1"); } - // mark saved_sp if seems valid - if (has_mh) { - if ((saved_sp >= dump_sp - UNREASONABLE_STACK_MOVE) && (saved_sp < dump_fp)) { - values.describe(-1, saved_sp, "*saved_sp"); - } - } - - tty->print_cr(" stack layout:"); + tty->print_cr("Stack layout:"); values.print(p); } if (has_mh) @@ -1125,16 +1103,12 @@ oopDesc* mh; intptr_t* saved_regs; intptr_t* entry_sp; - intptr_t* saved_sp; - intptr_t* saved_bp; }; void trace_method_handle_stub_wrapper(MethodHandleStubArguments* args) { trace_method_handle_stub(args->adaptername, args->mh, args->saved_regs, - args->entry_sp, - args->saved_sp, - args->saved_bp); + args->entry_sp); } void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { @@ -1157,20 +1131,18 @@ __ fst_d(Address(rsp, 0)); } - // incoming state: + // Incoming state: // rcx: method handle - // r13 or rsi: saved sp - // To avoid calling convention issues, build a record on the stack and pass the pointer to that instead. - // Note: fix the increment below if pushing more arguments - __ push(rbp); // saved_bp - __ push(saved_last_sp_register()); // saved_sp + // + // To avoid calling convention issues, build a record on the stack + // and pass the pointer to that instead. __ push(rbp); // entry_sp (with extra align space) __ push(rbx); // pusha saved_regs __ push(rcx); // mh __ push(rcx); // slot for adaptername __ movptr(Address(rsp, 0), (intptr_t) adaptername); __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub_wrapper), rsp); - __ increment(rsp, 6 * wordSize); // MethodHandleStubArguments + __ increment(rsp, sizeof(MethodHandleStubArguments)); if (UseSSE >= 2) { __ movdbl(xmm0, Address(rsp, 0));
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -2997,7 +2997,7 @@ // Generate oop map OopMap* map = new OopMap(framesize, 0); - oop_maps->add_gc_map(__ pc() - start, map); + oop_maps->add_gc_map(the_pc - start, map); __ reset_last_Java_frame(true, true);
--- a/src/cpu/x86/vm/x86.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/x86.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -37,10 +37,87 @@ static address double_signmask() { return (address)double_signmask_pool; } static address double_signflip() { return (address)double_signflip_pool; } #endif + +#ifndef PRODUCT + void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const { + st->print("nop \t# %d bytes pad for loops and calls", _count); + } +#endif + + void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const { + MacroAssembler _masm(&cbuf); + __ nop(_count); + } + + uint MachNopNode::size(PhaseRegAlloc*) const { + return _count; + } + +#ifndef PRODUCT + void MachBreakpointNode::format(PhaseRegAlloc*, outputStream* st) const { + st->print("# breakpoint"); + } +#endif + + void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc* ra_) const { + MacroAssembler _masm(&cbuf); + __ int3(); + } + + uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const { + return MachNode::size(ra_); + } + +%} + +encode %{ + + enc_class preserve_SP %{ + debug_only(int off0 = cbuf.insts_size()); + MacroAssembler _masm(&cbuf); + // RBP is preserved across all calls, even compiled calls. + // Use it to preserve RSP in places where the callee might change the SP. + __ movptr(rbp_mh_SP_save, rsp); + debug_only(int off1 = cbuf.insts_size()); + assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); + %} + + enc_class restore_SP %{ + MacroAssembler _masm(&cbuf); + __ movptr(rsp, rbp_mh_SP_save); + %} + + enc_class call_epilog %{ + if (VerifyStackAtCalls) { + // Check that stack depth is unchanged: find majik cookie on stack + int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); + MacroAssembler _masm(&cbuf); + Label L; + __ cmpptr(Address(rsp, framesize), (int32_t)0xbadb100d); + __ jccb(Assembler::equal, L); + // Die if stack mismatch + __ int3(); + __ bind(L); + } + %} + %} // INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit) +// ============================================================================ + +instruct ShouldNotReachHere() %{ + match(Halt); + format %{ "int3\t# ShouldNotReachHere" %} + ins_encode %{ + __ int3(); + %} + ins_pipe(pipe_slow); +%} + +// ============================================================================ + instruct addF_reg(regF dst, regF src) %{ predicate((UseSSE>=1) && (UseAVX == 0)); match(Set dst (AddF dst src));
--- a/src/cpu/x86/vm/x86_32.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/x86_32.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -341,12 +341,6 @@ return round_to(current_offset, alignment_required()) - current_offset; } -#ifndef PRODUCT -void MachBreakpointNode::format( PhaseRegAlloc *, outputStream* st ) const { - st->print("INT3"); -} -#endif - // EMIT_RM() void emit_rm(CodeBuffer &cbuf, int f1, int f2, int f3) { unsigned char c = (unsigned char)((f1 << 6) | (f2 << 3) | f3); @@ -550,118 +544,66 @@ //============================================================================= #ifndef PRODUCT -void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { +void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; - if( C->in_24_bit_fp_mode() ) { - st->print("FLDCW 24 bit fpu control word"); - st->print_cr(""); st->print("\t"); - } int framesize = C->frame_slots() << LogBytesPerInt; assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); - // Remove two words for return addr and rbp, - framesize -= 2*wordSize; - - // Calls to C2R adapters often do not accept exceptional returns. - // We require that their callers must bang for them. But be careful, because - // some VM calls (such as call site linkage) can use several kilobytes of - // stack. But the stack safety zone should account for that. - // See bugs 4446381, 4468289, 4497237. + // Remove wordSize for return addr which is already pushed. + framesize -= wordSize; + if (C->need_stack_bang(framesize)) { - st->print_cr("# stack bang"); st->print("\t"); - } - st->print_cr("PUSHL EBP"); st->print("\t"); - - if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth - st->print("PUSH 0xBADB100D\t# Majik cookie for stack depth check"); - st->print_cr(""); st->print("\t"); framesize -= wordSize; - } - - if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { + st->print("# stack bang"); + st->print("\n\t"); + st->print("PUSH EBP\t# Save EBP"); if (framesize) { - st->print("SUB ESP,%d\t# Create frame",framesize); + st->print("\n\t"); + st->print("SUB ESP, #%d\t# Create frame",framesize); } } else { - st->print("SUB ESP,%d\t# Create frame",framesize); + st->print("SUB ESP, #%d\t# Create frame",framesize); + st->print("\n\t"); + framesize -= wordSize; + st->print("MOV [ESP + #%d], EBP\t# Save EBP",framesize); + } + + if (VerifyStackAtCalls) { + st->print("\n\t"); + framesize -= wordSize; + st->print("MOV [ESP + #%d], 0xBADB100D\t# Majik cookie for stack depth check",framesize); } + + if( C->in_24_bit_fp_mode() ) { + st->print("\n\t"); + st->print("FLDCW \t# load 24 bit fpu control word"); + } + if (UseSSE >= 2 && VerifyFPU) { + st->print("\n\t"); + st->print("# verify FPU stack (must be clean on entry)"); + } + +#ifdef ASSERT + if (VerifyStackAtCalls) { + st->print("\n\t"); + st->print("# stack alignment check"); + } +#endif + st->cr(); } #endif void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Compile* C = ra_->C; - - if (UseSSE >= 2 && VerifyFPU) { - MacroAssembler masm(&cbuf); - masm.verify_FPU(0, "FPU stack must be clean on entry"); - } - - // WARNING: Initial instruction MUST be 5 bytes or longer so that - // NativeJump::patch_verified_entry will be able to patch out the entry - // code safely. The fldcw is ok at 6 bytes, the push to verify stack - // depth is ok at 5 bytes, the frame allocation can be either 3 or - // 6 bytes. So if we don't do the fldcw or the push then we must - // use the 6 byte frame allocation even if we have no frame. :-( - // If method sets FPU control word do it now - if( C->in_24_bit_fp_mode() ) { - MacroAssembler masm(&cbuf); - masm.fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_24())); - } + MacroAssembler _masm(&cbuf); int framesize = C->frame_slots() << LogBytesPerInt; - assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); - // Remove two words for return addr and rbp, - framesize -= 2*wordSize; - - // Calls to C2R adapters often do not accept exceptional returns. - // We require that their callers must bang for them. But be careful, because - // some VM calls (such as call site linkage) can use several kilobytes of - // stack. But the stack safety zone should account for that. - // See bugs 4446381, 4468289, 4497237. - if (C->need_stack_bang(framesize)) { - MacroAssembler masm(&cbuf); - masm.generate_stack_overflow_check(framesize); - } - - // We always push rbp, so that on return to interpreter rbp, will be - // restored correctly and we can correct the stack. - emit_opcode(cbuf, 0x50 | EBP_enc); - - if( VerifyStackAtCalls ) { // Majik cookie to verify stack depth - emit_opcode(cbuf, 0x68); // push 0xbadb100d - emit_d32(cbuf, 0xbadb100d); - framesize -= wordSize; - } - - if ((C->in_24_bit_fp_mode() || VerifyStackAtCalls ) && framesize < 128 ) { - if (framesize) { - emit_opcode(cbuf, 0x83); // sub SP,#framesize - emit_rm(cbuf, 0x3, 0x05, ESP_enc); - emit_d8(cbuf, framesize); - } - } else { - emit_opcode(cbuf, 0x81); // sub SP,#framesize - emit_rm(cbuf, 0x3, 0x05, ESP_enc); - emit_d32(cbuf, framesize); - } + + __ verified_entry(framesize, C->need_stack_bang(framesize), C->in_24_bit_fp_mode()); + C->set_frame_complete(cbuf.insts_size()); -#ifdef ASSERT - if (VerifyStackAtCalls) { - Label L; - MacroAssembler masm(&cbuf); - masm.push(rax); - masm.mov(rax, rsp); - masm.andptr(rax, StackAlignmentInBytes-1); - masm.cmpptr(rax, StackAlignmentInBytes-wordSize); - masm.pop(rax); - masm.jcc(Assembler::equal, L); - masm.stop("Stack is not properly aligned!"); - masm.bind(L); - } -#endif - if (C->has_mach_constant_base_node()) { // NOTE: We set the table base offset here because users might be // emitted before MachConstantBaseNode. @@ -1169,7 +1111,7 @@ } #ifndef PRODUCT -void MachSpillCopyNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { +void MachSpillCopyNode::format(PhaseRegAlloc *ra_, outputStream* st) const { implementation( NULL, ra_, false, st ); } #endif @@ -1182,22 +1124,6 @@ return implementation( NULL, ra_, true, NULL ); } -//============================================================================= -#ifndef PRODUCT -void MachNopNode::format( PhaseRegAlloc *, outputStream* st ) const { - st->print("NOP \t# %d bytes pad for loops and calls", _count); -} -#endif - -void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { - MacroAssembler _masm(&cbuf); - __ nop(_count); -} - -uint MachNopNode::size(PhaseRegAlloc *) const { - return _count; -} - //============================================================================= #ifndef PRODUCT @@ -1883,21 +1809,6 @@ } %} - enc_class preserve_SP %{ - debug_only(int off0 = cbuf.insts_size()); - MacroAssembler _masm(&cbuf); - // RBP is preserved across all calls, even compiled calls. - // Use it to preserve RSP in places where the callee might change the SP. - __ movptr(rbp_mh_SP_save, rsp); - debug_only(int off1 = cbuf.insts_size()); - assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); - %} - - enc_class restore_SP %{ - MacroAssembler _masm(&cbuf); - __ movptr(rsp, rbp_mh_SP_save); - %} - enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine // who we intended to call. @@ -3846,9 +3757,9 @@ // Ret Addr is on stack in slot 0 if no locks or verification or alignment. // Otherwise, it is above the locks and verification slot and alignment word return_addr(STACK - 1 + - round_to(1+VerifyStackAtCalls+ - Compile::current()->fixed_slots(), - (StackAlignmentInBytes/wordSize))); + round_to((Compile::current()->in_preserve_stack_slots() + + Compile::current()->fixed_slots()), + stack_alignment_in_slots())); // Body of function which returns an integer array locating // arguments either in registers or in stack slots. Passed an array @@ -13476,6 +13387,25 @@ ins_pipe( ialu_reg_mem ); %} + +// ============================================================================ +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ + match(Set dst (ThreadLocal)); + effect(DEF dst, KILL cr); + + format %{ "MOV $dst, Thread::current()" %} + ins_encode %{ + Register dstReg = as_Register($dst$$reg); + __ get_thread(dstReg); + %} + ins_pipe( ialu_reg_fat ); +%} + + + //----------PEEPHOLE RULES----------------------------------------------------- // These must follow all instruction definitions as they use the names // defined in the instructions definitions.
--- a/src/cpu/x86/vm/x86_64.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/cpu/x86/vm/x86_64.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -610,13 +610,6 @@ return round_to(current_offset, alignment_required()) - current_offset; } -#ifndef PRODUCT -void MachBreakpointNode::format(PhaseRegAlloc*, outputStream* st) const -{ - st->print("INT3"); -} -#endif - // EMIT_RM() void emit_rm(CodeBuffer &cbuf, int f1, int f2, int f3) { unsigned char c = (unsigned char) ((f1 << 6) | (f2 << 3) | f3); @@ -853,121 +846,53 @@ //============================================================================= #ifndef PRODUCT -void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const -{ +void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; int framesize = C->frame_slots() << LogBytesPerInt; assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); - // Remove wordSize for return adr already pushed - // and another for the RBP we are going to save - framesize -= 2*wordSize; - bool need_nop = true; - - // Calls to C2R adapters often do not accept exceptional returns. - // We require that their callers must bang for them. But be - // careful, because some VM calls (such as call site linkage) can - // use several kilobytes of stack. But the stack safety zone should - // account for that. See bugs 4446381, 4468289, 4497237. + // Remove wordSize for return addr which is already pushed. + framesize -= wordSize; + if (C->need_stack_bang(framesize)) { - st->print_cr("# stack bang"); st->print("\t"); - need_nop = false; + framesize -= wordSize; + st->print("# stack bang"); + st->print("\n\t"); + st->print("pushq rbp\t# Save rbp"); + if (framesize) { + st->print("\n\t"); + st->print("subq rsp, #%d\t# Create frame",framesize); + } + } else { + st->print("subq rsp, #%d\t# Create frame",framesize); + st->print("\n\t"); + framesize -= wordSize; + st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize); } - st->print_cr("pushq rbp"); st->print("\t"); if (VerifyStackAtCalls) { - // Majik cookie to verify stack depth - st->print_cr("pushq 0xffffffffbadb100d" - "\t# Majik cookie for stack depth check"); - st->print("\t"); - framesize -= wordSize; // Remove 2 for cookie - need_nop = false; + st->print("\n\t"); + framesize -= wordSize; + st->print("movq [rsp + #%d], 0xbadb100d\t# Majik cookie for stack depth check",framesize); +#ifdef ASSERT + st->print("\n\t"); + st->print("# stack alignment check"); +#endif } - - if (framesize) { - st->print("subq rsp, #%d\t# Create frame", framesize); - if (framesize < 0x80 && need_nop) { - st->print("\n\tnop\t# nop for patch_verified_entry"); - } - } + st->cr(); } #endif -void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const -{ +void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Compile* C = ra_->C; - - // WARNING: Initial instruction MUST be 5 bytes or longer so that - // NativeJump::patch_verified_entry will be able to patch out the entry - // code safely. The fldcw is ok at 6 bytes, the push to verify stack - // depth is ok at 5 bytes, the frame allocation can be either 3 or - // 6 bytes. So if we don't do the fldcw or the push then we must - // use the 6 byte frame allocation even if we have no frame. :-( - // If method sets FPU control word do it now + MacroAssembler _masm(&cbuf); int framesize = C->frame_slots() << LogBytesPerInt; - assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); - // Remove wordSize for return adr already pushed - // and another for the RBP we are going to save - framesize -= 2*wordSize; - bool need_nop = true; - - // Calls to C2R adapters often do not accept exceptional returns. - // We require that their callers must bang for them. But be - // careful, because some VM calls (such as call site linkage) can - // use several kilobytes of stack. But the stack safety zone should - // account for that. See bugs 4446381, 4468289, 4497237. - if (C->need_stack_bang(framesize)) { - MacroAssembler masm(&cbuf); - masm.generate_stack_overflow_check(framesize); - need_nop = false; - } - - // We always push rbp so that on return to interpreter rbp will be - // restored correctly and we can correct the stack. - emit_opcode(cbuf, 0x50 | RBP_enc); - - if (VerifyStackAtCalls) { - // Majik cookie to verify stack depth - emit_opcode(cbuf, 0x68); // pushq (sign-extended) 0xbadb100d - emit_d32(cbuf, 0xbadb100d); - framesize -= wordSize; // Remove 2 for cookie - need_nop = false; - } - - if (framesize) { - emit_opcode(cbuf, Assembler::REX_W); - if (framesize < 0x80) { - emit_opcode(cbuf, 0x83); // sub SP,#framesize - emit_rm(cbuf, 0x3, 0x05, RSP_enc); - emit_d8(cbuf, framesize); - if (need_nop) { - emit_opcode(cbuf, 0x90); // nop - } - } else { - emit_opcode(cbuf, 0x81); // sub SP,#framesize - emit_rm(cbuf, 0x3, 0x05, RSP_enc); - emit_d32(cbuf, framesize); - } - } + + __ verified_entry(framesize, C->need_stack_bang(framesize), false); C->set_frame_complete(cbuf.insts_size()); -#ifdef ASSERT - if (VerifyStackAtCalls) { - Label L; - MacroAssembler masm(&cbuf); - masm.push(rax); - masm.mov(rax, rsp); - masm.andptr(rax, StackAlignmentInBytes-1); - masm.cmpptr(rax, StackAlignmentInBytes-wordSize); - masm.pop(rax); - masm.jcc(Assembler::equal, L); - masm.stop("Stack is not properly aligned!"); - masm.bind(L); - } -#endif - if (C->has_mach_constant_base_node()) { // NOTE: We set the table base offset here because users might be // emitted before MachConstantBaseNode. @@ -1598,26 +1523,6 @@ //============================================================================= #ifndef PRODUCT -void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const -{ - st->print("nop \t# %d bytes pad for loops and calls", _count); -} -#endif - -void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const -{ - MacroAssembler _masm(&cbuf); - __ nop(_count); -} - -uint MachNopNode::size(PhaseRegAlloc*) const -{ - return _count; -} - - -//============================================================================= -#ifndef PRODUCT void BoxLockNode::format(PhaseRegAlloc* ra_, outputStream* st) const { int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); @@ -2323,21 +2228,6 @@ RELOC_DISP32); %} - enc_class preserve_SP %{ - debug_only(int off0 = cbuf.insts_size()); - MacroAssembler _masm(&cbuf); - // RBP is preserved across all calls, even compiled calls. - // Use it to preserve RSP in places where the callee might change the SP. - __ movptr(rbp_mh_SP_save, rsp); - debug_only(int off1 = cbuf.insts_size()); - assert(off1 - off0 == preserve_SP_size(), "correct size prediction"); - %} - - enc_class restore_SP %{ - MacroAssembler _masm(&cbuf); - __ movptr(rsp, rbp_mh_SP_save); - %} - enc_class Java_Static_Call(method meth) %{ // JAVA STATIC CALL @@ -3276,9 +3166,9 @@ // Ret Addr is on stack in slot 0 if no locks or verification or alignment. // Otherwise, it is above the locks and verification slot and alignment word return_addr(STACK - 2 + - round_to(2 + 2 * VerifyStackAtCalls + - Compile::current()->fixed_slots(), - WordsPerLong * 2)); + round_to((Compile::current()->in_preserve_stack_slots() + + Compile::current()->fixed_slots()), + stack_alignment_in_slots())); // Body of function which returns an integer array locating // arguments either in registers or in stack slots. Passed an array @@ -11736,6 +11626,21 @@ %} +// ============================================================================ +// This name is KNOWN by the ADLC and cannot be changed. +// The ADLC forces a 'TypeRawPtr::BOTTOM' output type +// for this guy. +instruct tlsLoadP(r15_RegP dst) %{ + match(Set dst (ThreadLocal)); + effect(DEF dst); + + size(0); + format %{ "# TLS is in R15" %} + ins_encode( /*empty encoding*/ ); + ins_pipe(ialu_reg_reg); +%} + + //----------PEEPHOLE RULES----------------------------------------------------- // These must follow all instruction definitions as they use the names // defined in the instructions definitions.
--- a/src/os_cpu/bsd_x86/vm/bsd_x86_32.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_32.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -24,137 +24,3 @@ // X86 Bsd Architecture Description File -//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- -// This block specifies the encoding classes used by the compiler to output -// byte streams. Encoding classes generate functions which are called by -// Machine Instruction Nodes in order to generate the bit encoding of the -// instruction. Operands specify their base encoding interface with the -// interface keyword. There are currently supported four interfaces, -// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an -// operand to generate a function which returns its register number when -// queried. CONST_INTER causes an operand to generate a function which -// returns the value of the constant when queried. MEMORY_INTER causes an -// operand to generate four functions which return the Base Register, the -// Index Register, the Scale Value, and the Offset Value of the operand when -// queried. COND_INTER causes an operand to generate six functions which -// return the encoding code (ie - encoding bits for the instruction) -// associated with each basic boolean condition for a conditional instruction. -// Instructions specify two basic values for encoding. They use the -// ins_encode keyword to specify their encoding class (which must be one of -// the class names specified in the encoding block), and they use the -// opcode keyword to specify, in order, their primary, secondary, and -// tertiary opcode. Only the opcode sections which a particular instruction -// needs for encoding need to be specified. -encode %{ - // Build emit functions for each basic byte or larger field in the intel - // encoding scheme (opcode, rm, sib, immediate), and call them from C++ - // code in the enc_class source block. Emit functions will live in the - // main source block for now. In future, we can generalize this by - // adding a syntax that specifies the sizes of fields in an order, - // so that the adlc can build the emit functions automagically - - enc_class bsd_tlsencode (eRegP dst) %{ - Register dstReg = as_Register($dst$$reg); - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->get_thread(dstReg); - %} - - enc_class bsd_breakpoint %{ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); - %} - - enc_class call_epilog %{ - if( VerifyStackAtCalls ) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); - if(framesize >= 128) { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0xBC); - emit_d8(cbuf,0x24); - emit_d32(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - else { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0x7C); - emit_d8(cbuf,0x24); - emit_d8(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 5; // size of call to breakpoint, 1 for CC - emit_opcode(cbuf,0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); - } - %} - -%} - -// INSTRUCTIONS -- Platform dependent - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ - match(Set dst (ThreadLocal)); - effect(DEF dst, KILL cr); - - format %{ "MOV $dst, Thread::current()" %} - ins_encode( bsd_tlsencode(dst) ); - ins_pipe( ialu_reg_fat ); -%} - -instruct TLS(eRegP dst) %{ - match(Set dst (ThreadLocal)); - - expand %{ - tlsLoadP(dst); - %} -%} - -// Die now -instruct ShouldNotReachHere( ) -%{ - match(Halt); - - // Use the following format syntax - format %{ "INT3 ; ShouldNotReachHere" %} - // QQQ TODO for now call breakpoint - // opcode(0xCC); - // ins_encode(Opc); - ins_encode(bsd_breakpoint); - ins_pipe( pipe_slow ); -%} - - - -// Platform dependent source - -source %{ - -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer &cbuf) { - - // Debugger doesn't really catch this but best we can do so far QQQ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - emit_break(cbuf); -} - - -uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - return 5; -} - -%}
--- a/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/bsd_x86/vm/bsd_x86_64.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -55,8 +55,7 @@ // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class Java_To_Runtime(method meth) - %{ + enc_class Java_To_Runtime(method meth) %{ // No relocation needed // movq r10, <meth> @@ -70,104 +69,15 @@ emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); %} - enc_class bsd_breakpoint - %{ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); - %} - - enc_class call_epilog - %{ - if (VerifyStackAtCalls) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = - ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); - if (framesize) { - if (framesize < 0x80) { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0x7C); - emit_d8(cbuf, 0x24); - emit_d8(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } else { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0xBC); - emit_d8(cbuf, 0x24); - emit_d32(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 5; // size of call to breakpoint, 1 for CC - emit_opcode(cbuf, 0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); - } - %} - -%} - -// INSTRUCTIONS -- Platform dependent - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(r15_RegP dst) -%{ - match(Set dst (ThreadLocal)); - effect(DEF dst); - - size(0); - format %{ "# TLS is in R15" %} - ins_encode( /*empty encoding*/ ); - ins_pipe(ialu_reg_reg); -%} - -// Die now -instruct ShouldNotReachHere() -%{ - match(Halt); - - // Use the following format syntax - format %{ "int3\t# ShouldNotReachHere" %} - // QQQ TODO for now call breakpoint - // opcode(0xCC); - // ins_encode(Opc); - ins_encode(bsd_breakpoint); - ins_pipe(pipe_slow); %} // Platform dependent source -source -%{ +source %{ int MachCallRuntimeNode::ret_addr_offset() { return 13; // movq r10,#addr; callq (r10) } -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer& cbuf) { - // Debugger doesn't really catch this but best we can do so far QQQ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { - emit_break(cbuf); -} - -uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const { - return 5; -} - %}
--- a/src/os_cpu/linux_x86/vm/linux_x86_32.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/linux_x86/vm/linux_x86_32.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -24,137 +24,3 @@ // X86 Linux Architecture Description File -//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- -// This block specifies the encoding classes used by the compiler to output -// byte streams. Encoding classes generate functions which are called by -// Machine Instruction Nodes in order to generate the bit encoding of the -// instruction. Operands specify their base encoding interface with the -// interface keyword. There are currently supported four interfaces, -// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an -// operand to generate a function which returns its register number when -// queried. CONST_INTER causes an operand to generate a function which -// returns the value of the constant when queried. MEMORY_INTER causes an -// operand to generate four functions which return the Base Register, the -// Index Register, the Scale Value, and the Offset Value of the operand when -// queried. COND_INTER causes an operand to generate six functions which -// return the encoding code (ie - encoding bits for the instruction) -// associated with each basic boolean condition for a conditional instruction. -// Instructions specify two basic values for encoding. They use the -// ins_encode keyword to specify their encoding class (which must be one of -// the class names specified in the encoding block), and they use the -// opcode keyword to specify, in order, their primary, secondary, and -// tertiary opcode. Only the opcode sections which a particular instruction -// needs for encoding need to be specified. -encode %{ - // Build emit functions for each basic byte or larger field in the intel - // encoding scheme (opcode, rm, sib, immediate), and call them from C++ - // code in the enc_class source block. Emit functions will live in the - // main source block for now. In future, we can generalize this by - // adding a syntax that specifies the sizes of fields in an order, - // so that the adlc can build the emit functions automagically - - enc_class linux_tlsencode (eRegP dst) %{ - Register dstReg = as_Register($dst$$reg); - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->get_thread(dstReg); - %} - - enc_class linux_breakpoint %{ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); - %} - - enc_class call_epilog %{ - if( VerifyStackAtCalls ) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); - if(framesize >= 128) { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0xBC); - emit_d8(cbuf,0x24); - emit_d32(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - else { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0x7C); - emit_d8(cbuf,0x24); - emit_d8(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 5; // size of call to breakpoint, 1 for CC - emit_opcode(cbuf,0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); - } - %} - -%} - -// INSTRUCTIONS -- Platform dependent - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ - match(Set dst (ThreadLocal)); - effect(DEF dst, KILL cr); - - format %{ "MOV $dst, Thread::current()" %} - ins_encode( linux_tlsencode(dst) ); - ins_pipe( ialu_reg_fat ); -%} - -instruct TLS(eRegP dst) %{ - match(Set dst (ThreadLocal)); - - expand %{ - tlsLoadP(dst); - %} -%} - -// Die now -instruct ShouldNotReachHere( ) -%{ - match(Halt); - - // Use the following format syntax - format %{ "INT3 ; ShouldNotReachHere" %} - // QQQ TODO for now call breakpoint - // opcode(0xCC); - // ins_encode(Opc); - ins_encode(linux_breakpoint); - ins_pipe( pipe_slow ); -%} - - - -// Platform dependent source - -source %{ - -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer &cbuf) { - - // Debugger doesn't really catch this but best we can do so far QQQ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - emit_break(cbuf); -} - - -uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - return MachNode::size(ra_); -} - -%}
--- a/src/os_cpu/linux_x86/vm/linux_x86_64.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/linux_x86/vm/linux_x86_64.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -55,8 +55,7 @@ // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class Java_To_Runtime(method meth) - %{ + enc_class Java_To_Runtime(method meth) %{ // No relocation needed // movq r10, <meth> @@ -70,105 +69,15 @@ emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); %} - enc_class linux_breakpoint - %{ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); - %} - - enc_class call_epilog - %{ - if (VerifyStackAtCalls) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = - ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); - if (framesize) { - if (framesize < 0x80) { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0x7C); - emit_d8(cbuf, 0x24); - emit_d8(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } else { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0xBC); - emit_d8(cbuf, 0x24); - emit_d32(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 5; // size of call to breakpoint, 1 for CC - emit_opcode(cbuf, 0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); - } - %} - -%} - -// INSTRUCTIONS -- Platform dependent - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(r15_RegP dst) -%{ - match(Set dst (ThreadLocal)); - effect(DEF dst); - - size(0); - format %{ "# TLS is in R15" %} - ins_encode( /*empty encoding*/ ); - ins_pipe(ialu_reg_reg); -%} - -// Die now -instruct ShouldNotReachHere() -%{ - match(Halt); - - // Use the following format syntax - format %{ "int3\t# ShouldNotReachHere" %} - // QQQ TODO for now call breakpoint - // opcode(0xCC); - // ins_encode(Opc); - ins_encode(linux_breakpoint); - ins_pipe(pipe_slow); %} // Platform dependent source -source -%{ +source %{ int MachCallRuntimeNode::ret_addr_offset() { return 13; // movq r10,#addr; callq (r10) } -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer& cbuf) { - // Debugger doesn't really catch this but best we can do so far QQQ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { - emit_break(cbuf); -} - -uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const { - // distance could be far and requires load and call through register - return MachNode::size(ra_); -} - %}
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -24,144 +24,3 @@ // X86 Solaris Architecture Description File -//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- -// This block specifies the encoding classes used by the compiler to output -// byte streams. Encoding classes generate functions which are called by -// Machine Instruction Nodes in order to generate the bit encoding of the -// instruction. Operands specify their base encoding interface with the -// interface keyword. There are currently supported four interfaces, -// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an -// operand to generate a function which returns its register number when -// queried. CONST_INTER causes an operand to generate a function which -// returns the value of the constant when queried. MEMORY_INTER causes an -// operand to generate four functions which return the Base Register, the -// Index Register, the Scale Value, and the Offset Value of the operand when -// queried. COND_INTER causes an operand to generate six functions which -// return the encoding code (ie - encoding bits for the instruction) -// associated with each basic boolean condition for a conditional instruction. -// Instructions specify two basic values for encoding. They use the -// ins_encode keyword to specify their encoding class (which must be one of -// the class names specified in the encoding block), and they use the -// opcode keyword to specify, in order, their primary, secondary, and -// tertiary opcode. Only the opcode sections which a particular instruction -// needs for encoding need to be specified. -encode %{ - // Build emit functions for each basic byte or larger field in the intel - // encoding scheme (opcode, rm, sib, immediate), and call them from C++ - // code in the enc_class source block. Emit functions will live in the - // main source block for now. In future, we can generalize this by - // adding a syntax that specifies the sizes of fields in an order, - // so that the adlc can build the emit functions automagically - - enc_class solaris_tlsencode (eRegP dst) %{ - Register dstReg = as_Register($dst$$reg); - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->get_thread(dstReg); - %} - - enc_class solaris_breakpoint %{ - MacroAssembler* masm = new MacroAssembler(&cbuf); - // Really need to fix this - masm->push(rax); - masm->push(rcx); - masm->push(rdx); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); - masm->pop(rdx); - masm->pop(rcx); - masm->pop(rax); - %} - - enc_class call_epilog %{ - if( VerifyStackAtCalls ) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); - if(framesize >= 128) { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0xBC); - emit_d8(cbuf,0x24); - emit_d32(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - else { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0x7C); - emit_d8(cbuf,0x24); - emit_d8(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 11; // size of call to breakpoint (and register preserve), 1 for CC - emit_opcode(cbuf,0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); - } - %} - -%} - -// INSTRUCTIONS -- Platform dependent - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{ - match(Set dst (ThreadLocal)); - effect(DEF dst, KILL cr); - - format %{ "MOV $dst, Thread::current()" %} - ins_encode( solaris_tlsencode(dst) ); - ins_pipe( ialu_reg_fat ); -%} - -instruct TLS(eRegP dst) %{ - match(Set dst (ThreadLocal)); - - expand %{ - tlsLoadP(dst); - %} -%} - -// Die now -instruct ShouldNotReachHere( ) -%{ - match(Halt); - - // Use the following format syntax - format %{ "INT3 ; ShouldNotReachHere" %} - // QQQ TODO for now call breakpoint - // opcode(0xCC); - // ins_encode(Opc); - ins_encode(solaris_breakpoint); - ins_pipe( pipe_slow ); -%} - - - -// Platform dependent source - -source %{ - -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer &cbuf) { - - // Debugger doesn't really catch this but best we can do so far QQQ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - emit_break(cbuf); -} - - -uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - return MachNode::size(ra_); -} - -%}
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_64.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_64.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -55,8 +55,7 @@ // adding a syntax that specifies the sizes of fields in an order, // so that the adlc can build the emit functions automagically - enc_class Java_To_Runtime(method meth) - %{ + enc_class Java_To_Runtime(method meth) %{ // No relocation needed // movq r10, <meth> @@ -70,118 +69,24 @@ emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); %} - enc_class solaris_breakpoint - %{ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); - %} - - enc_class call_epilog - %{ - if (VerifyStackAtCalls) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = - ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); - if (framesize) { - if (framesize < 0x80) { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0x7C); - emit_d8(cbuf, 0x24); - emit_d8(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } else { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0xBC); - emit_d8(cbuf, 0x24); - emit_d32(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 5; // size of call to breakpoint, 1 for CC - emit_opcode(cbuf, 0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); + enc_class post_call_verify_mxcsr %{ + MacroAssembler _masm(&cbuf); + if (RestoreMXCSROnJNICalls) { + __ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); + } + else if (CheckJNICalls) { + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()))); } %} - - enc_class post_call_verify_mxcsr %{ - MacroAssembler masm(&cbuf); - if (RestoreMXCSROnJNICalls) { - masm.ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std())); - } - else if (CheckJNICalls) { - masm.call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry()))); - } - %} -%} - -// INSTRUCTIONS -- Platform dependent - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(r15_RegP dst) -%{ - match(Set dst (ThreadLocal)); - effect(DEF dst); - - size(0); - format %{ "# TLS is in R15" %} - ins_encode( /*empty encoding*/ ); - ins_pipe(ialu_reg_reg); -%} - -// Die now -instruct ShouldNotReachHere() -%{ - match(Halt); - - // Use the following format syntax - format %{ "int3\t# ShouldNotReachHere" %} - // QQQ TODO for now call breakpoint - // opcode(0xCC); - // ins_encode(Opc); - ins_encode(solaris_breakpoint); - ins_pipe(pipe_slow); %} // Platform dependent source -source -%{ +source %{ -int MachCallRuntimeNode::ret_addr_offset() -{ +int MachCallRuntimeNode::ret_addr_offset() { return 13; // movq r10,#addr; callq (r10) } -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer& cbuf) -{ - // Debugger doesn't really catch this but best we can do so far QQQ - MacroAssembler* masm = new MacroAssembler(&cbuf); - masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); -} - -void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const -{ - emit_break(cbuf); -} - -uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const -{ - // distance could be far and requires load and call through register - return MachNode::size(ra_); -} - %}
--- a/src/os_cpu/windows_x86/vm/windows_x86_32.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/windows_x86/vm/windows_x86_32.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -24,134 +24,3 @@ // X86 Win32 Architecture Description File -//----------OS-DEPENDENT ENCODING BLOCK----------------------------------------------------- -// This block specifies the encoding classes used by the compiler to output -// byte streams. Encoding classes generate functions which are called by -// Machine Instruction Nodes in order to generate the bit encoding of the -// instruction. Operands specify their base encoding interface with the -// interface keyword. There are currently supported four interfaces, -// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an -// operand to generate a function which returns its register number when -// queried. CONST_INTER causes an operand to generate a function which -// returns the value of the constant when queried. MEMORY_INTER causes an -// operand to generate four functions which return the Base Register, the -// Index Register, the Scale Value, and the Offset Value of the operand when -// queried. COND_INTER causes an operand to generate six functions which -// return the encoding code (ie - encoding bits for the instruction) -// associated with each basic boolean condition for a conditional instruction. -// Instructions specify two basic values for encoding. They use the -// ins_encode keyword to specify their encoding class (which must be one of -// the class names specified in the encoding block), and they use the -// opcode keyword to specify, in order, their primary, secondary, and -// tertiary opcode. Only the opcode sections which a particular instruction -// needs for encoding need to be specified. -encode %{ - // Build emit functions for each basic byte or larger field in the intel - // encoding scheme (opcode, rm, sib, immediate), and call them from C++ - // code in the enc_class source block. Emit functions will live in the - // main source block for now. In future, we can generalize this by - // adding a syntax that specifies the sizes of fields in an order, - // so that the adlc can build the emit functions automagically - - enc_class tlsencode (eRegP dst, eRegP src) %{ - emit_rm(cbuf, 0x2, $dst$$reg, $src$$reg); - emit_d32(cbuf, ThreadLocalStorage::get_thread_ptr_offset() ); - %} - - enc_class call_epilog %{ - if( VerifyStackAtCalls ) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word)); - if(framesize >= 128) { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0xBC); - emit_d8(cbuf,0x24); - emit_d32(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - else { - emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood - emit_d8(cbuf,0x7C); - emit_d8(cbuf,0x24); - emit_d8(cbuf,framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - // jmp EQ around INT3 - emit_opcode(cbuf,0x74); - emit_d8(cbuf,1); - // Die if stack mismatch - emit_opcode(cbuf,0xCC); - } - %} - -%} - -// INSTRUCTIONS -- Platform dependent - - -//----------OS and Locking Instructions---------------------------------------- - -// The prefix of this name is KNOWN by the ADLC and cannot be changed. -instruct tlsLoadP_prefixLoadP(eRegP t1) %{ - effect(DEF t1); - - format %{ "MOV $t1,FS:[0x00] "%} - opcode(0x8B, 0x64); - ins_encode(OpcS, OpcP, conmemref(t1)); - ins_pipe( ialu_reg_fat ); -%} - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -// %%% Should do this with a clause like: bottom_type(TypeRawPtr::BOTTOM); -instruct tlsLoadP(eRegP dst, eRegP t1) %{ - effect(DEF dst, USE t1); - - format %{ "MOV $dst,[$t1 + TLS::thread_ptr_offset()]" %} - opcode(0x8B); - ins_encode(OpcP, tlsencode(dst, t1)); - ins_pipe( ialu_reg_reg_fat ); -%} - -instruct TLS(eRegP dst) %{ - match(Set dst (ThreadLocal)); - expand %{ - eRegP t1; - tlsLoadP_prefixLoadP(t1); - tlsLoadP(dst, t1); - %} -%} - -// Die now -instruct ShouldNotReachHere( ) -%{ - match(Halt); - // Use the following format syntax - format %{ "INT3 ; ShouldNotReachHere" %} - opcode(0xCC); - ins_encode(OpcP); - ins_pipe( pipe_slow ); -%} - -// -// Platform dependent source -// -source %{ - -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer &cbuf) { - cbuf.insts()->emit_int8((unsigned char) 0xcc); -} - -void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - emit_break(cbuf); -} - - -uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - return 1; -} - - -%}
--- a/src/os_cpu/windows_x86/vm/windows_x86_64.ad Fri Feb 17 06:34:49 2012 -0800 +++ b/src/os_cpu/windows_x86/vm/windows_x86_64.ad Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -67,69 +67,6 @@ emit_opcode(cbuf, 0xD0 | (R10_enc - 8)); %} - enc_class call_epilog %{ - if (VerifyStackAtCalls) { - // Check that stack depth is unchanged: find majik cookie on stack - int framesize = - ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word)); - if (framesize) { - if (framesize < 0x80) { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0x7C); - emit_d8(cbuf, 0x24); - emit_d8(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } else { - emit_opcode(cbuf, Assembler::REX_W); - emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood - emit_d8(cbuf, 0xBC); - emit_d8(cbuf, 0x24); - emit_d32(cbuf, framesize); // Find majik cookie from ESP - emit_d32(cbuf, 0xbadb100d); - } - } - // jmp EQ around INT3 - // QQQ TODO - const int jump_around = 5; // size of call to breakpoint, 1 for CC - emit_opcode(cbuf, 0x74); - emit_d8(cbuf, jump_around); - // QQQ temporary - emit_break(cbuf); - // Die if stack mismatch - // emit_opcode(cbuf,0xCC); - } - %} -%} - -// INSTRUCTIONS -- Platform dependent - - -//----------OS and Locking Instructions---------------------------------------- - -// This name is KNOWN by the ADLC and cannot be changed. -// The ADLC forces a 'TypeRawPtr::BOTTOM' output type -// for this guy. -instruct tlsLoadP(r15_RegP dst) -%{ - match(Set dst (ThreadLocal)); - effect(DEF dst); - - size(0); - format %{ "# TLS is in R15" %} - ins_encode( /*empty encoding*/ ); - ins_pipe(ialu_reg_reg); -%} - -// Die now -instruct ShouldNotReachHere( ) -%{ - match(Halt); - // Use the following format syntax - format %{ "INT3 ; ShouldNotReachHere" %} - opcode(0xCC); - ins_encode(OpcP); - ins_pipe( pipe_slow ); %} // @@ -142,17 +79,4 @@ return 13; // movq r10,#addr; callq (r10) } -// emit an interrupt that is caught by the debugger -void emit_break(CodeBuffer &cbuf) { - cbuf.insts()->emit_int8((unsigned char) 0xcc); -} - -void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - emit_break(cbuf); -} - -uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - return 1; -} - %}
--- a/src/share/tools/hsdis/hsdis.c Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/tools/hsdis/hsdis.c Fri Feb 17 12:18:52 2012 -0800 @@ -356,7 +356,7 @@ if (plen > mach_size) plen = mach_size; strncpy(mach_option, p, plen); mach_option[plen] = '\0'; - } else if (plen > 6 && strncmp(p, "hsdis-", 6)) { + } else if (plen > 6 && strncmp(p, "hsdis-", 6) == 0) { // do not pass these to the next level } else { /* just copy it; {i386,sparc}-dis.c might like to see it */
--- a/src/share/vm/c1/c1_Canonicalizer.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/c1/c1_Canonicalizer.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -594,6 +594,13 @@ return false; } +static bool is_safepoint(BlockEnd* x, BlockBegin* sux) { + // An Instruction with multiple successors, x, is replaced by a Goto + // to a single successor, sux. Is a safepoint check needed = was the + // instruction being replaced a safepoint and the single remaining + // successor a back branch? + return x->is_safepoint() && (sux->bci() < x->state_before()->bci()); +} void Canonicalizer::do_If(If* x) { // move const to right @@ -614,7 +621,7 @@ case If::geq: sux = x->sux_for(true); break; } // If is a safepoint then the debug information should come from the state_before of the If. - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); return; } @@ -626,7 +633,7 @@ x->sux_for(false)); if (sux != NULL) { // If is a safepoint then the debug information should come from the state_before of the If. - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } } } else if (rt->as_IntConstant() != NULL) { @@ -694,10 +701,12 @@ } } else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) { if (x->cond() == Instruction::eql) { - set_canonical(new Goto(x->fsux(), x->state_before(), x->is_safepoint())); + BlockBegin* sux = x->fsux(); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } else { assert(x->cond() == Instruction::neq, "only other valid case"); - set_canonical(new Goto(x->tsux(), x->state_before(), x->is_safepoint())); + BlockBegin* sux = x->tsux(); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } } } @@ -710,7 +719,7 @@ if (v >= x->lo_key() && v <= x->hi_key()) { sux = x->sux_at(v - x->lo_key()); } - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } else if (x->number_of_sux() == 1) { // NOTE: Code permanently disabled for now since the switch statement's // tag expression may produce side-effects in which case it must @@ -741,7 +750,7 @@ sux = x->sux_at(i); } } - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } else if (x->number_of_sux() == 1) { // NOTE: Code permanently disabled for now since the switch statement's // tag expression may produce side-effects in which case it must
--- a/src/share/vm/c1/c1_GraphBuilder.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -1181,6 +1181,11 @@ bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci(); Instruction *i = append(new If(x, cond, false, y, tsux, fsux, is_bb ? state_before : NULL, is_bb)); + assert(i->as_Goto() == NULL || + (i->as_Goto()->sux_at(0) == tsux && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) || + (i->as_Goto()->sux_at(0) == fsux && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()), + "safepoint state of Goto returned by canonicalizer incorrect"); + if (is_profiling()) { If* if_node = i->as_If(); if (if_node != NULL) { @@ -1303,7 +1308,16 @@ // add default successor sux->at_put(i, block_at(bci() + sw.default_offset())); ValueStack* state_before = has_bb ? copy_state_before() : NULL; - append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb)); + Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb)); +#ifdef ASSERT + if (res->as_Goto()) { + for (i = 0; i < l; i++) { + if (sux->at(i) == res->as_Goto()->sux_at(0)) { + assert(res->as_Goto()->is_safepoint() == sw.dest_offset_at(i) < 0, "safepoint state of Goto returned by canonicalizer incorrect"); + } + } + } +#endif } } @@ -1338,7 +1352,16 @@ // add default successor sux->at_put(i, block_at(bci() + sw.default_offset())); ValueStack* state_before = has_bb ? copy_state_before() : NULL; - append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb)); + Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb)); +#ifdef ASSERT + if (res->as_Goto()) { + for (i = 0; i < l; i++) { + if (sux->at(i) == res->as_Goto()->sux_at(0)) { + assert(res->as_Goto()->is_safepoint() == sw.pair_at(i).offset() < 0, "safepoint state of Goto returned by canonicalizer incorrect"); + } + } + } +#endif } }
--- a/src/share/vm/c1/c1_LinearScan.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/c1/c1_LinearScan.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -2464,12 +2464,15 @@ // frequently used constants -ConstantOopWriteValue LinearScan::_oop_null_scope_value = ConstantOopWriteValue(NULL); -ConstantIntValue LinearScan::_int_m1_scope_value = ConstantIntValue(-1); -ConstantIntValue LinearScan::_int_0_scope_value = ConstantIntValue(0); -ConstantIntValue LinearScan::_int_1_scope_value = ConstantIntValue(1); -ConstantIntValue LinearScan::_int_2_scope_value = ConstantIntValue(2); -LocationValue _illegal_value = LocationValue(Location()); +// Allocate them with new so they are never destroyed (otherwise, a +// forced exit could destroy these objects while they are still in +// use). +ConstantOopWriteValue* LinearScan::_oop_null_scope_value = new (ResourceObj::C_HEAP) ConstantOopWriteValue(NULL); +ConstantIntValue* LinearScan::_int_m1_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(-1); +ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(0); +ConstantIntValue* LinearScan::_int_1_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(1); +ConstantIntValue* LinearScan::_int_2_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(2); +LocationValue* _illegal_value = new (ResourceObj::C_HEAP) LocationValue(Location()); void LinearScan::init_compute_debug_info() { // cache for frequently used scope values @@ -2508,7 +2511,7 @@ case T_OBJECT: { jobject value = c->as_jobject(); if (value == NULL) { - scope_values->append(&_oop_null_scope_value); + scope_values->append(_oop_null_scope_value); } else { scope_values->append(new ConstantOopWriteValue(c->as_jobject())); } @@ -2519,10 +2522,10 @@ case T_FLOAT: { int value = c->as_jint_bits(); switch (value) { - case -1: scope_values->append(&_int_m1_scope_value); break; - case 0: scope_values->append(&_int_0_scope_value); break; - case 1: scope_values->append(&_int_1_scope_value); break; - case 2: scope_values->append(&_int_2_scope_value); break; + case -1: scope_values->append(_int_m1_scope_value); break; + case 0: scope_values->append(_int_0_scope_value); break; + case 1: scope_values->append(_int_1_scope_value); break; + case 2: scope_values->append(_int_2_scope_value); break; default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break; } return 1; @@ -2531,7 +2534,7 @@ case T_LONG: // fall through case T_DOUBLE: { #ifdef _LP64 - scope_values->append(&_int_0_scope_value); + scope_values->append(_int_0_scope_value); scope_values->append(new ConstantLongValue(c->as_jlong_bits())); #else if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) { @@ -2657,7 +2660,7 @@ } // Does this reverse on x86 vs. sparc? first = new LocationValue(loc1); - second = &_int_0_scope_value; + second = _int_0_scope_value; #else Location loc1, loc2; if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) { @@ -2671,7 +2674,7 @@ #ifdef _LP64 VMReg rname_first = opr->as_register_lo()->as_VMReg(); first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first)); - second = &_int_0_scope_value; + second = _int_0_scope_value; #else VMReg rname_first = opr->as_register_lo()->as_VMReg(); VMReg rname_second = opr->as_register_hi()->as_VMReg(); @@ -2694,7 +2697,7 @@ VMReg rname_first = opr->as_xmm_double_reg()->as_VMReg(); # ifdef _LP64 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first)); - second = &_int_0_scope_value; + second = _int_0_scope_value; # else first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first)); // %%% This is probably a waste but we'll keep things as they were for now @@ -2741,7 +2744,7 @@ #ifdef _LP64 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first)); - second = &_int_0_scope_value; + second = _int_0_scope_value; #else first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first)); // %%% This is probably a waste but we'll keep things as they were for now @@ -2822,7 +2825,7 @@ } } else { // append a dummy value because real value not needed - scope_values->append(&_illegal_value); + scope_values->append(_illegal_value); return 1; } } @@ -2865,7 +2868,7 @@ nof_locals = cur_scope->method()->max_locals(); locals = new GrowableArray<ScopeValue*>(nof_locals); for(int i = 0; i < nof_locals; i++) { - locals->append(&_illegal_value); + locals->append(_illegal_value); } }
--- a/src/share/vm/c1/c1_LinearScan.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/c1/c1_LinearScan.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -160,11 +160,11 @@ // TODO: cached scope values for registers could be static ScopeValueArray _scope_value_cache; - static ConstantOopWriteValue _oop_null_scope_value; - static ConstantIntValue _int_m1_scope_value; - static ConstantIntValue _int_0_scope_value; - static ConstantIntValue _int_1_scope_value; - static ConstantIntValue _int_2_scope_value; + static ConstantOopWriteValue* _oop_null_scope_value; + static ConstantIntValue* _int_m1_scope_value; + static ConstantIntValue* _int_0_scope_value; + static ConstantIntValue* _int_1_scope_value; + static ConstantIntValue* _int_2_scope_value; // accessors IR* ir() const { return _ir; }
--- a/src/share/vm/compiler/compileBroker.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/compiler/compileBroker.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -204,7 +204,8 @@ } void log_nmethod(JavaThread* thread, nmethod* nm) { - log(thread, "nmethod " INTPTR_FORMAT " code ["INTPTR_FORMAT ", " INTPTR_FORMAT "]", + log(thread, "nmethod %d%s " INTPTR_FORMAT " code ["INTPTR_FORMAT ", " INTPTR_FORMAT "]", + nm->compile_id(), nm->is_osr_method() ? "%" : "", nm, nm->code_begin(), nm->code_end()); }
--- a/src/share/vm/gc_interface/collectedHeap.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -62,7 +62,7 @@ return; } - jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; + double timestamp = fetch_timestamp(); MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); int index = compute_log_index(); _records[index].thread = NULL; // Its the GC thread so it's not that interesting. @@ -70,9 +70,9 @@ _records[index].data.is_before = before; stringStream st(_records[index].data.buffer(), _records[index].data.size()); if (before) { - Universe::print_heap_before_gc(&st); + Universe::print_heap_before_gc(&st, true); } else { - Universe::print_heap_after_gc(&st); + Universe::print_heap_after_gc(&st, true); } }
--- a/src/share/vm/memory/gcLocker.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/memory/gcLocker.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -31,7 +31,6 @@ volatile jint GC_locker::_lock_count = 0; volatile bool GC_locker::_needs_gc = false; volatile bool GC_locker::_doing_gc = false; -jlong GC_locker::_wait_begin = 0; #ifdef ASSERT volatile jint GC_locker::_debug_jni_lock_count = 0; @@ -69,9 +68,8 @@ _needs_gc = true; if (PrintJNIGCStalls && PrintGCDetails) { ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 - _wait_begin = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; - gclog_or_tty->print_cr(INT64_FORMAT ": Setting _needs_gc. Thread \"%s\" %d locked.", - _wait_begin, Thread::current()->name(), _jni_lock_count); + gclog_or_tty->print_cr("%.3f: Setting _needs_gc. Thread \"%s\" %d locked.", + gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); } } @@ -85,8 +83,8 @@ if (needs_gc()) { if (PrintJNIGCStalls && PrintGCDetails) { ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 - gclog_or_tty->print_cr(INT64_FORMAT ": Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.", - (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - _wait_begin, Thread::current()->name(), _jni_lock_count); + gclog_or_tty->print_cr("%.3f: Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.", + gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); } } @@ -131,8 +129,8 @@ MutexUnlocker munlock(JNICritical_lock); if (PrintJNIGCStalls && PrintGCDetails) { ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 - gclog_or_tty->print_cr(INT64_FORMAT ": Thread \"%s\" is performing GC after exiting critical section, %d locked", - (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - _wait_begin, Thread::current()->name(), _jni_lock_count); + gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", + gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); } Universe::heap()->collect(GCCause::_gc_locker); }
--- a/src/share/vm/memory/gcLocker.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/memory/gcLocker.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -63,9 +63,6 @@ // note: bool is typedef'd as jint static volatile bool _doing_gc; // unlock_critical() is doing a GC - static jlong _wait_begin; // Timestamp for the setting of _needs_gc. - // Used only by printing code. - #ifdef ASSERT // This lock count is updated for all operations and is used to // validate the jni_lock_count that is computed during safepoints. @@ -86,13 +83,26 @@ static void jni_lock(JavaThread* thread); static void jni_unlock(JavaThread* thread); + static bool is_active_internal() { + verify_critical_count(); + return _lock_count > 0 || _jni_lock_count > 0; + } + public: // Accessors - static bool is_active(); + static bool is_active() { + assert(_needs_gc || SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); + return is_active_internal(); + } static bool needs_gc() { return _needs_gc; } // Shorthand - static bool is_active_and_needs_gc() { return needs_gc() && is_active(); } + static bool is_active_and_needs_gc() { + // Use is_active_internal since _needs_gc can change from true to + // false outside of a safepoint, triggering the assert in + // is_active. + return needs_gc() && is_active_internal(); + } // In debug mode track the locking state at all times static void increment_debug_jni_lock_count() {
--- a/src/share/vm/memory/gcLocker.inline.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/memory/gcLocker.inline.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -27,12 +27,6 @@ #include "memory/gcLocker.hpp" -inline bool GC_locker::is_active() { - assert(_needs_gc || SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); - verify_critical_count(); - return _lock_count > 0 || _jni_lock_count > 0; -} - inline void GC_locker::lock() { // cast away volatile Atomic::inc(&_lock_count);
--- a/src/share/vm/memory/universe.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/memory/universe.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -1303,22 +1303,22 @@ } } -void Universe::print_heap_before_gc(outputStream* st) { +void Universe::print_heap_before_gc(outputStream* st, bool ignore_extended) { st->print_cr("{Heap before GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections()); - if (!PrintHeapAtGCExtended) { + if (!PrintHeapAtGCExtended || ignore_extended) { heap()->print_on(st); } else { heap()->print_extended_on(st); } } -void Universe::print_heap_after_gc(outputStream* st) { +void Universe::print_heap_after_gc(outputStream* st, bool ignore_extended) { st->print_cr("Heap after GC invocations=%u (full %u):", heap()->total_collections(), heap()->total_full_collections()); - if (!PrintHeapAtGCExtended) { + if (!PrintHeapAtGCExtended || ignore_extended) { heap()->print_on(st); } else { heap()->print_extended_on(st);
--- a/src/share/vm/memory/universe.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/memory/universe.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -424,8 +424,8 @@ static void print_heap_at_SIGBREAK(); static void print_heap_before_gc() { print_heap_before_gc(gclog_or_tty); } static void print_heap_after_gc() { print_heap_after_gc(gclog_or_tty); } - static void print_heap_before_gc(outputStream* st); - static void print_heap_after_gc(outputStream* st); + static void print_heap_before_gc(outputStream* st, bool ignore_extended = false); + static void print_heap_after_gc(outputStream* st, bool ignore_extended = false); // Change the number of dummy objects kept reachable by the full gc dummy // array; this should trigger relocation in a sliding compaction collector.
--- a/src/share/vm/opto/chaitin.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/opto/chaitin.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1946,18 +1946,29 @@ reg2offset_unchecked(OptoReg::add(_matcher._old_SP,-1)) - reg2offset_unchecked(_matcher._new_SP)+jintSize); // Preserve area dump + int fixed_slots = C->fixed_slots(); + OptoReg::Name begin_in_preserve = OptoReg::add(_matcher._old_SP, -(int)C->in_preserve_stack_slots()); + OptoReg::Name return_addr = _matcher.return_addr(); + reg = OptoReg::add(reg, -1); - while( OptoReg::is_stack(reg)) { + while (OptoReg::is_stack(reg)) { tty->print("#r%3.3d %s+%2d: ",reg,fp,reg2offset_unchecked(reg)); - if( _matcher.return_addr() == reg ) + if (return_addr == reg) { tty->print_cr("return address"); - else if( _matcher.return_addr() == OptoReg::add(reg,1) && - VerifyStackAtCalls ) - tty->print_cr("0xBADB100D +VerifyStackAtCalls"); - else if ((int)OptoReg::reg2stack(reg) < C->fixed_slots()) + } else if (reg >= begin_in_preserve) { + // Preserved slots are present on x86 + if (return_addr == OptoReg::add(reg, VMRegImpl::slots_per_word)) + tty->print_cr("saved fp register"); + else if (return_addr == OptoReg::add(reg, 2*VMRegImpl::slots_per_word) && + VerifyStackAtCalls) + tty->print_cr("0xBADB100D +VerifyStackAtCalls"); + else + tty->print_cr("in_preserve"); + } else if ((int)OptoReg::reg2stack(reg) < fixed_slots) { tty->print_cr("Fixed slot %d", OptoReg::reg2stack(reg)); - else - tty->print_cr("pad2, in_preserve"); + } else { + tty->print_cr("pad2, stack alignment"); + } reg = OptoReg::add(reg, -1); }
--- a/src/share/vm/opto/escape.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/opto/escape.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1687,12 +1687,23 @@ // Observed 8 passes in jvm2008 compiler.compiler. // Set limit to 20 to catch situation when something // did go wrong and recompile the method without EA. + // Also limit build time to 30 sec (60 in debug VM). #define CG_BUILD_ITER_LIMIT 20 +#ifdef ASSERT +#define CG_BUILD_TIME_LIMIT 60.0 +#else +#define CG_BUILD_TIME_LIMIT 30.0 +#endif + uint length = worklist.length(); int iterations = 0; - while(_progress && (iterations++ < CG_BUILD_ITER_LIMIT)) { + elapsedTimer time; + while(_progress && + (iterations++ < CG_BUILD_ITER_LIMIT) && + (time.seconds() < CG_BUILD_TIME_LIMIT)) { + time.start(); _progress = false; for( uint next = 0; next < length; ++next ) { int ni = worklist.at(next); @@ -1701,18 +1712,19 @@ assert(n != NULL, "should be known node"); build_connection_graph(n, igvn); } + time.stop(); } - if (iterations >= CG_BUILD_ITER_LIMIT) { - assert(iterations < CG_BUILD_ITER_LIMIT, - err_msg("infinite EA connection graph build with %d nodes and worklist size %d", - nodes_size(), length)); + if ((iterations >= CG_BUILD_ITER_LIMIT) || + (time.seconds() >= CG_BUILD_TIME_LIMIT)) { + assert(false, err_msg("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d", + time.seconds(), iterations, nodes_size(), length)); // Possible infinite build_connection_graph loop, - // retry compilation without escape analysis. - C->record_failure(C2Compiler::retry_no_escape_analysis()); + // bailout (no changes to ideal graph were made). _collecting = false; return false; } #undef CG_BUILD_ITER_LIMIT +#undef CG_BUILD_TIME_LIMIT // 5. Propagate escaped states. worklist.clear(); @@ -2292,9 +2304,35 @@ PointsToNode::EscapeState arg_esc = ptnode_adr(arg->_idx)->escape_state(); if (!arg->is_top() && at->isa_ptr() && aat->isa_ptr() && (is_arraycopy || arg_esc < PointsToNode::ArgEscape)) { - +#ifdef ASSERT assert(aat == Type::TOP || aat == TypePtr::NULL_PTR || aat->isa_ptr() != NULL, "expecting an Ptr"); + if (!(is_arraycopy || + call->as_CallLeaf()->_name != NULL && + (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || + strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) + ) { + call->dump(); + assert(false, "EA: unexpected CallLeaf"); + } +#endif + if (arg_esc < PointsToNode::ArgEscape) { + set_escape_state(arg->_idx, PointsToNode::ArgEscape); + Node* arg_base = arg; + if (arg->is_AddP()) { + // + // The inline_native_clone() case when the arraycopy stub is called + // after the allocation before Initialize and CheckCastPP nodes. + // Or normal arraycopy for object arrays case. + // + // Set AddP's base (Allocate) as not scalar replaceable since + // pointer to the base (with offset) is passed as argument. + // + arg_base = get_addp_base(arg); + set_escape_state(arg_base->_idx, PointsToNode::ArgEscape); + } + } + bool arg_has_oops = aat->isa_oopptr() && (aat->isa_oopptr()->klass() == NULL || aat->isa_instptr() || (aat->isa_aryptr() && aat->isa_aryptr()->klass()->is_obj_array_klass())); @@ -2307,85 +2345,33 @@ // arraycopy(char[],0,Object*,0,size); // arraycopy(Object*,0,char[],0,size); // - // Don't add edges from dst's fields in such cases. + // Do nothing special in such cases. // - bool arg_is_arraycopy_dest = src_has_oops && is_arraycopy && - arg_has_oops && (i > TypeFunc::Parms); -#ifdef ASSERT - if (!(is_arraycopy || - call->as_CallLeaf()->_name != NULL && - (strcmp(call->as_CallLeaf()->_name, "g1_wb_pre") == 0 || - strcmp(call->as_CallLeaf()->_name, "g1_wb_post") == 0 )) - ) { - call->dump(); - assert(false, "EA: unexpected CallLeaf"); - } -#endif - // Always process arraycopy's destination object since - // we need to add all possible edges to references in - // source object. - if (arg_esc >= PointsToNode::ArgEscape && - !arg_is_arraycopy_dest) { - continue; - } - set_escape_state(arg->_idx, PointsToNode::ArgEscape); - Node* arg_base = arg; - if (arg->is_AddP()) { - // - // The inline_native_clone() case when the arraycopy stub is called - // after the allocation before Initialize and CheckCastPP nodes. - // Or normal arraycopy for object arrays case. - // - // Set AddP's base (Allocate) as not scalar replaceable since - // pointer to the base (with offset) is passed as argument. - // - arg_base = get_addp_base(arg); - } - VectorSet argset = *PointsTo(arg_base); // Clone set - for( VectorSetI j(&argset); j.test(); ++j ) { - uint pd = j.elem; // Destination object - set_escape_state(pd, PointsToNode::ArgEscape); - - if (arg_is_arraycopy_dest) { - PointsToNode* ptd = ptnode_adr(pd); - // Conservatively reference an unknown object since - // not all source's fields/elements may be known. - add_edge_from_fields(pd, _phantom_object, Type::OffsetBot); - - Node *src = call->in(TypeFunc::Parms)->uncast(); - Node* src_base = src; - if (src->is_AddP()) { - src_base = get_addp_base(src); - } - // Create edges from destination's fields to - // everything known source's fields could point to. - for( VectorSetI s(PointsTo(src_base)); s.test(); ++s ) { - uint ps = s.elem; - bool has_bottom_offset = false; - for (uint fd = 0; fd < ptd->edge_count(); fd++) { - assert(ptd->edge_type(fd) == PointsToNode::FieldEdge, "expecting a field edge"); - int fdi = ptd->edge_target(fd); - PointsToNode* pfd = ptnode_adr(fdi); - int offset = pfd->offset(); - if (offset == Type::OffsetBot) - has_bottom_offset = true; - assert(offset != -1, "offset should be set"); - add_deferred_edge_to_fields(fdi, ps, offset); - } - // Destination object may not have access (no field edge) - // to fields which are accessed in source object. - // As result no edges will be created to those source's - // fields and escape state of destination object will - // not be propagated to those fields. - // - // Mark source object as global escape except in - // the case with Type::OffsetBot field (which is - // common case for array elements access) when - // edges are created to all source's fields. - if (!has_bottom_offset) { - set_escape_state(ps, PointsToNode::GlobalEscape); - } - } + if (is_arraycopy && (i > TypeFunc::Parms) && + src_has_oops && arg_has_oops) { + // Destination object's fields reference an unknown object. + Node* arg_base = arg; + if (arg->is_AddP()) { + arg_base = get_addp_base(arg); + } + for (VectorSetI s(PointsTo(arg_base)); s.test(); ++s) { + uint ps = s.elem; + set_escape_state(ps, PointsToNode::ArgEscape); + add_edge_from_fields(ps, _phantom_object, Type::OffsetBot); + } + // Conservatively all values in source object fields globally escape + // since we don't know if values in destination object fields + // escape (it could be traced but it is too expensive). + Node* src = call->in(TypeFunc::Parms)->uncast(); + Node* src_base = src; + if (src->is_AddP()) { + src_base = get_addp_base(src); + } + for (VectorSetI s(PointsTo(src_base)); s.test(); ++s) { + uint ps = s.elem; + set_escape_state(ps, PointsToNode::ArgEscape); + // Use OffsetTop to indicate fields global escape. + add_edge_from_fields(ps, _phantom_object, Type::OffsetTop); } } }
--- a/src/share/vm/opto/output.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/opto/output.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -167,7 +167,7 @@ // Determine if we need to generate a stack overflow check. // Do it if the method is not a stub function and // has java calls or has frame size > vm_page_size/8. - return (stub_function() == NULL && + return (UseStackBanging && stub_function() == NULL && (has_java_calls() || frame_size_in_bytes > os::vm_page_size()>>3)); }
--- a/src/share/vm/runtime/arguments.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/runtime/arguments.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -102,8 +102,6 @@ char* Arguments::_meta_index_path = NULL; char* Arguments::_meta_index_dir = NULL; -static bool force_client_mode = false; - // Check if head of 'option' matches 'name', and sets 'tail' remaining part of option string static bool match_option(const JavaVMOption *option, const char* name, @@ -1345,7 +1343,7 @@ return; } - if (os::is_server_class_machine() && !force_client_mode ) { + if (os::is_server_class_machine()) { // If no other collector is requested explicitly, // let the VM select the collector based on // machine class and automatic selection policy. @@ -2937,11 +2935,6 @@ // Construct the path to the archive char jvm_path[JVM_MAXPATHLEN]; os::jvm_path(jvm_path, sizeof(jvm_path)); -#ifdef TIERED - if (strstr(jvm_path, "client") != NULL) { - force_client_mode = true; - } -#endif // TIERED char *end = strrchr(jvm_path, *os::file_separator()); if (end != NULL) *end = '\0'; char *shared_archive_path = NEW_C_HEAP_ARRAY(char, strlen(jvm_path) +
--- a/src/share/vm/runtime/globals.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/runtime/globals.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -3013,7 +3013,7 @@ product(intx, SafepointTimeoutDelay, 10000, \ "Delay in milliseconds for option SafepointTimeout") \ \ - product(intx, NmethodSweepFraction, 4, \ + product(intx, NmethodSweepFraction, 16, \ "Number of invocations of sweeper to cover all nmethods") \ \ product(intx, NmethodSweepCheckInterval, 5, \
--- a/src/share/vm/runtime/sharedRuntime.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/runtime/sharedRuntime.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -804,6 +804,7 @@ if (thread->deopt_mark() != NULL) { Deoptimization::cleanup_deopt_info(thread, NULL); } + Events::log_exception(thread, "StackOverflowError at " INTPTR_FORMAT, pc); return StubRoutines::throw_StackOverflowError_entry(); } @@ -820,8 +821,10 @@ if (vt_stub->is_abstract_method_error(pc)) { assert(!vt_stub->is_vtable_stub(), "should never see AbstractMethodErrors from vtable-type VtableStubs"); + Events::log_exception(thread, "AbstractMethodError at " INTPTR_FORMAT, pc); return StubRoutines::throw_AbstractMethodError_entry(); } else { + Events::log_exception(thread, "NullPointerException at vtable entry " INTPTR_FORMAT, pc); return StubRoutines::throw_NullPointerException_at_call_entry(); } } else { @@ -838,6 +841,7 @@ if (!cb->is_nmethod()) { guarantee(cb->is_adapter_blob() || cb->is_method_handles_adapter_blob(), "exception happened outside interpreter, nmethods and vtable stubs (1)"); + Events::log_exception(thread, "NullPointerException in code blob at " INTPTR_FORMAT, pc); // There is no handler here, so we will simply unwind. return StubRoutines::throw_NullPointerException_at_call_entry(); } @@ -849,6 +853,7 @@ // => the nmethod is not yet active (i.e., the frame // is not set up yet) => use return address pushed by // caller => don't push another return address + Events::log_exception(thread, "NullPointerException in IC check " INTPTR_FORMAT, pc); return StubRoutines::throw_NullPointerException_at_call_entry(); }
--- a/src/share/vm/runtime/sweeper.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/runtime/sweeper.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -266,7 +266,17 @@ // The last invocation iterates until there are no more nmethods for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) { + if (SafepointSynchronize::is_synchronizing()) { // Safepoint request + if (PrintMethodFlushing && Verbose) { + tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _invocations); + } + MutexUnlockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); + assert(Thread::current()->is_Java_thread(), "should be java thread"); + JavaThread* thread = (JavaThread*)Thread::current(); + ThreadBlockInVM tbivm(thread); + thread->java_suspend_self(); + } // Since we will give up the CodeCache_lock, always skip ahead // to the next nmethod. Other blobs can be deleted by other // threads but nmethods are only reclaimed by the sweeper.
--- a/src/share/vm/utilities/debug.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/utilities/debug.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -600,6 +600,10 @@ tty->flush(); } +extern "C" void events() { + Command c("events"); + Events::print(); +} // Given a heap address that was valid before the most recent GC, if // the oop that used to contain it is still live, prints the new @@ -759,7 +763,7 @@ tty->print_cr("misc."); tty->print_cr(" flush() - flushes the log file"); - tty->print_cr(" events() - dump last 50 events"); + tty->print_cr(" events() - dump events from ring buffers"); tty->print_cr("compiler debugging");
--- a/src/share/vm/utilities/events.cpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/utilities/events.cpp Fri Feb 17 12:18:52 2012 -0800 @@ -68,6 +68,10 @@ } } +void Events::print() { + print_all(tty); +} + void Events::init() { if (LogEvents) { _messages = new StringEventLog("Events");
--- a/src/share/vm/utilities/events.hpp Fri Feb 17 06:34:49 2012 -0800 +++ b/src/share/vm/utilities/events.hpp Fri Feb 17 12:18:52 2012 -0800 @@ -35,20 +35,12 @@ // This facility is extremly useful for post-mortem debugging. The eventlog // often provides crucial information about events leading up to the crash. // -// All arguments past the format string must be passed as an intptr_t. -// -// To log a single event use: -// Events::log("New nmethod has been created " INTPTR_FORMAT, nm); -// -// To log a block of events use: -// EventMark m("GarbageCollecting %d", (intptr_t)gc_number); -// -// The constructor to eventlog indents the eventlog until the -// destructor has been executed. -// -// IMPLEMENTATION RESTRICTION: -// Max 3 arguments are saved for each logged event. -// +// Abstractly the logs can record whatever they way but normally they +// would record at least a timestamp and the current Thread, along +// with whatever data they need in a ring buffer. Commonly fixed +// length text messages are recorded for simplicity but other +// strategies could be used. Several logs are provided by default but +// new instances can be created as needed. // The base event log dumping class that is registered for dumping at // crash time. This is a very generic interface that is mainly here @@ -79,7 +71,7 @@ template <class T> class EventLogBase : public EventLog { template <class X> class EventRecord { public: - jlong timestamp; + double timestamp; Thread* thread; X data; }; @@ -102,6 +94,10 @@ _records = new EventRecord<T>[length]; } + double fetch_timestamp() { + return os::elapsedTime(); + } + // move the ring buffer to next open slot and return the index of // the slot to use for the current message. Should only be called // while mutex is held. @@ -130,7 +126,7 @@ void print(outputStream* out, T& e); void print(outputStream* out, EventRecord<T>& e) { - out->print("Event: " INT64_FORMAT " ", e.timestamp); + out->print("Event: %.3f ", e.timestamp); if (e.thread != NULL) { out->print("Thread " INTPTR_FORMAT " ", e.thread); } @@ -155,7 +151,7 @@ void logv(Thread* thread, const char* format, va_list ap) { if (!should_log()) return; - jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; + double timestamp = fetch_timestamp(); MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); int index = compute_log_index(); _records[index].thread = thread; @@ -193,9 +189,8 @@ public: static void print_all(outputStream* out); - static void print() { - print_all(tty); - } + // Dump all events to the tty + static void print(); // Logs a generic message with timestamp and format as printf. static void log(Thread* thread, const char* format, ...); @@ -255,6 +250,7 @@ out->print_cr("%s (%d events):", _name, _count); if (_count == 0) { out->print_cr("No events"); + out->cr(); return; }