# HG changeset patch # User chegar # Date 1408352863 -3600 # Node ID 6a6c91ccc0bc2592e0096121f511e7b2da2c142f # Parent d06a6d3c66c08293b2a9650f3cc01fd55c620e65# Parent 41d12a329ec7c57e9dbfaa6331dc539319ec99fe Merge diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/agent/src/os/solaris/proc/saproc.cpp --- a/hotspot/agent/src/os/solaris/proc/saproc.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/agent/src/os/solaris/proc/saproc.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -661,30 +661,30 @@ // read FileMapHeader size_t n = read(fd, pheader, sizeof(struct FileMapHeader)); if (n != sizeof(struct FileMapHeader)) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check file magic if (pheader->_magic != 0xf00baba2) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2", classes_jsa, pheader->_magic); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check version if (pheader->_version != CURRENT_ARCHIVE_VERSION) { - free(pheader); - close(fd); char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d", classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION); + close(fd); + free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/make/jprt.properties --- a/hotspot/make/jprt.properties Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/make/jprt.properties Mon Aug 18 10:07:43 2014 +0100 @@ -356,14 +356,15 @@ ${jprt.my.windows.x64}-fastdebug-c2-internalvmtests jprt.make.rule.test.targets.standard.reg.group = \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.windows.i586}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-GROUP, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c1-GROUP, \ - ${jprt.my.windows.i586}-{product|fastdebug}-c1-GROUP + ${jprt.my.solaris.sparcv9}-fastdebug-c2-GROUP, \ + ${jprt.my.solaris.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.linux.i586}-fastdebug-c2-GROUP, \ + ${jprt.my.linux.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.macosx.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.windows.i586}-fastdebug-c2-GROUP, \ + ${jprt.my.windows.x64}-fastdebug-c2-GROUP, \ + ${jprt.my.linux.i586}-fastdebug-c1-GROUP, \ + ${jprt.my.windows.i586}-fastdebug-c1-GROUP jprt.make.rule.test.targets.standard = \ ${jprt.make.rule.test.targets.standard.client}, \ diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/make/solaris/makefiles/dtrace.make --- a/hotspot/make/solaris/makefiles/dtrace.make Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/make/solaris/makefiles/dtrace.make Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2014, 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 @@ -58,6 +58,8 @@ DTRACE_COMMON_SRCDIR = $(GAMMADIR)/src/os/posix/dtrace DTRACE = dtrace DTRACE.o = $(DTRACE).o +DTRACE_JHELPER = dtrace_jhelper +DTRACE_JHELPER.o = $(DTRACE_JHELPER).o # to remove '-g' option which causes link problems # also '-z nodefs' is used as workaround @@ -255,7 +257,10 @@ endif $(DTRACE).d: $(DTRACE_COMMON_SRCDIR)/hotspot.d $(DTRACE_COMMON_SRCDIR)/hotspot_jni.d \ - $(DTRACE_COMMON_SRCDIR)/hs_private.d $(DTRACE_SRCDIR)/jhelper.d + $(DTRACE_COMMON_SRCDIR)/hs_private.d + $(QUIETLY) cat $^ > $@ + +$(DTRACE_JHELPER).d: $(DTRACE_SRCDIR)/jhelper.d $(QUIETLY) cat $^ > $@ DTraced_Files = ciEnv.o \ @@ -280,7 +285,7 @@ vmGCOperations.o \ # Dtrace is available, so we build $(DTRACE.o) -$(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files) +$(DTRACE.o): $(DTRACE).d $(DTraced_Files) @echo Compiling $(DTRACE).d $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -xlazyload -o $@ -s $(DTRACE).d \ @@ -344,6 +349,11 @@ dtrace_gen_headers: $(DtraceOutDir)/hotspot.h $(DtraceOutDir)/hotspot_jni.h $(DtraceOutDir)/hs_private.h +# The jhelper.d and hotspot probes are separated into two different SUNW_dof sections. +# Now the jhelper.d is built without the -Xlazyload flag. +$(DTRACE_JHELPER.o) : $(DTRACE_JHELPER).d $(JVMOFFS).h $(JVMOFFS)Index.h + @echo Compiling $(DTRACE_JHELPER).d + $(QUIETLY) $(DTRACE_PROG) $(DTRACE_OPTS) -C -I. -G -o $@ -s $(DTRACE_JHELPER).d .PHONY: dtraceCheck @@ -372,7 +382,7 @@ ifneq ("${DTRACE_PROG}", "") ifeq ("${HOTSPOT_DISABLE_DTRACE_PROBES}", "") -DTRACE_OBJS = $(DTRACE.o) $(JVMOFFS.o) +DTRACE_OBJS = $(DTRACE.o) $(JVMOFFS.o) $(DTRACE_JHELPER.o) CFLAGS += $(DTRACE_INCL) -DDTRACE_ENABLED MAPFILE_DTRACE_OPT = $(MAPFILE_DTRACE) diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/assembler_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -298,6 +298,7 @@ LWZ_OPCODE = (32u << OPCODE_SHIFT), LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1), LWZU_OPCODE = (33u << OPCODE_SHIFT), + LWBRX_OPCODE = (31u << OPCODE_SHIFT | 534 << 1), LHA_OPCODE = (42u << OPCODE_SHIFT), LHAX_OPCODE = (31u << OPCODE_SHIFT | 343u << 1), @@ -306,6 +307,7 @@ LHZ_OPCODE = (40u << OPCODE_SHIFT), LHZX_OPCODE = (31u << OPCODE_SHIFT | 279u << 1), LHZU_OPCODE = (41u << OPCODE_SHIFT), + LHBRX_OPCODE = (31u << OPCODE_SHIFT | 790 << 1), LBZ_OPCODE = (34u << OPCODE_SHIFT), LBZX_OPCODE = (31u << OPCODE_SHIFT | 87u << 1), @@ -1364,11 +1366,17 @@ inline void lwax( Register d, Register s1, Register s2); inline void lwa( Register d, int si16, Register s1); + // 4 bytes reversed + inline void lwbrx( Register d, Register s1, Register s2); + // 2 bytes inline void lhzx( Register d, Register s1, Register s2); inline void lhz( Register d, int si16, Register s1); inline void lhzu( Register d, int si16, Register s1); + // 2 bytes reversed + inline void lhbrx( Register d, Register s1, Register s2); + // 2 bytes inline void lhax( Register d, Register s1, Register s2); inline void lha( Register d, int si16, Register s1); @@ -1858,10 +1866,12 @@ inline void lwz( Register d, int si16); inline void lwax( Register d, Register s2); inline void lwa( Register d, int si16); + inline void lwbrx(Register d, Register s2); inline void lhzx( Register d, Register s2); inline void lhz( Register d, int si16); inline void lhax( Register d, Register s2); inline void lha( Register d, int si16); + inline void lhbrx(Register d, Register s2); inline void lbzx( Register d, Register s2); inline void lbz( Register d, int si16); inline void ldx( Register d, Register s2); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -263,10 +263,14 @@ inline void Assembler::lwax( Register d, Register s1, Register s2) { emit_int32(LWAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::lwa( Register d, int si16, Register s1) { emit_int32(LWA_OPCODE | rt(d) | ds(si16) | ra0mem(s1));} +inline void Assembler::lwbrx( Register d, Register s1, Register s2) { emit_int32(LWBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} + inline void Assembler::lhzx( Register d, Register s1, Register s2) { emit_int32(LHZX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::lhz( Register d, int si16, Register s1) { emit_int32(LHZ_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} inline void Assembler::lhzu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHZU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} +inline void Assembler::lhbrx( Register d, Register s1, Register s2) { emit_int32(LHBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} + inline void Assembler::lhax( Register d, Register s1, Register s2) { emit_int32(LHAX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::lha( Register d, int si16, Register s1) { emit_int32(LHA_OPCODE | rt(d) | d1(si16) | ra0mem(s1));} inline void Assembler::lhau( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LHAU_OPCODE | rt(d) | d1(si16) | rta0mem(s1));} @@ -736,10 +740,12 @@ inline void Assembler::lwz( Register d, int si16 ) { emit_int32( LWZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::lwax( Register d, Register s2) { emit_int32( LWAX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lwa( Register d, int si16 ) { emit_int32( LWA_OPCODE | rt(d) | ds(si16));} +inline void Assembler::lwbrx(Register d, Register s2) { emit_int32( LWBRX_OPCODE| rt(d) | rb(s2));} inline void Assembler::lhzx( Register d, Register s2) { emit_int32( LHZX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lhz( Register d, int si16 ) { emit_int32( LHZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::lhax( Register d, Register s2) { emit_int32( LHAX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lha( Register d, int si16 ) { emit_int32( LHA_OPCODE | rt(d) | d1(si16));} +inline void Assembler::lhbrx(Register d, Register s2) { emit_int32( LHBRX_OPCODE| rt(d) | rb(s2));} inline void Assembler::lbzx( Register d, Register s2) { emit_int32( LBZX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lbz( Register d, int si16 ) { emit_int32( LBZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::ld( Register d, int si16 ) { emit_int32( LD_OPCODE | rt(d) | ds(si16));} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -119,9 +119,15 @@ // Call the Interpreter::remove_activation_preserving_args_entry() // func to get the address of the same-named entrypoint in the // generated interpreter code. +#if defined(ABI_ELFv2) + call_c(CAST_FROM_FN_PTR(address, + Interpreter::remove_activation_preserving_args_entry), + relocInfo::none); +#else call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, Interpreter::remove_activation_preserving_args_entry), relocInfo::none); +#endif // Jump to Interpreter::_remove_activation_preserving_args_entry. mtctr(R3_RET); @@ -331,29 +337,40 @@ void InterpreterMacroAssembler::get_2_byte_integer_at_bcp(int bcp_offset, Register Rdst, signedOrNot is_signed) { +#if defined(VM_LITTLE_ENDIAN) + if (bcp_offset) { + load_const_optimized(Rdst, bcp_offset); + lhbrx(Rdst, R14_bcp, Rdst); + } else { + lhbrx(Rdst, R14_bcp); + } + if (is_signed == Signed) { + extsh(Rdst, Rdst); + } +#else // Read Java big endian format. if (is_signed == Signed) { lha(Rdst, bcp_offset, R14_bcp); } else { lhz(Rdst, bcp_offset, R14_bcp); } -#if 0 - assert(Rtmp != Rdst, "need separate temp register"); - Register Rfirst = Rtmp; - lbz(Rfirst, bcp_offset, R14_bcp); // first byte - lbz(Rdst, bcp_offset+1, R14_bcp); // second byte - - // Rdst = ((Rfirst<<8) & 0xFF00) | (Rdst &~ 0xFF00) - rldimi(/*RA=*/Rdst, /*RS=*/Rfirst, /*sh=*/8, /*mb=*/48); - if (is_signed == Signed) { - extsh(Rdst, Rdst); - } #endif } void InterpreterMacroAssembler::get_4_byte_integer_at_bcp(int bcp_offset, Register Rdst, signedOrNot is_signed) { +#if defined(VM_LITTLE_ENDIAN) + if (bcp_offset) { + load_const_optimized(Rdst, bcp_offset); + lwbrx(Rdst, R14_bcp, Rdst); + } else { + lwbrx(Rdst, R14_bcp); + } + if (is_signed == Signed) { + extsw(Rdst, Rdst); + } +#else // Read Java big endian format. if (bcp_offset & 3) { // Offset unaligned? load_const_optimized(Rdst, bcp_offset); @@ -369,18 +386,26 @@ lwz(Rdst, bcp_offset, R14_bcp); } } +#endif } + // Load the constant pool cache index from the bytecode stream. // // Kills / writes: // - Rdst, Rscratch void InterpreterMacroAssembler::get_cache_index_at_bcp(Register Rdst, int bcp_offset, size_t index_size) { assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); + // Cache index is always in the native format, courtesy of Rewriter. if (index_size == sizeof(u2)) { - get_2_byte_integer_at_bcp(bcp_offset, Rdst, Unsigned); + lhz(Rdst, bcp_offset, R14_bcp); } else if (index_size == sizeof(u4)) { - get_4_byte_integer_at_bcp(bcp_offset, Rdst, Signed); + if (bcp_offset & 3) { + load_const_optimized(Rdst, bcp_offset); + lwax(Rdst, R14_bcp, Rdst); + } else { + lwa(Rdst, bcp_offset, R14_bcp); + } assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); nand(Rdst, Rdst, Rdst); // convert to plain index } else if (index_size == sizeof(u1)) { @@ -397,6 +422,29 @@ add(cache, R27_constPoolCache, cache); } +// Load 4-byte signed or unsigned integer in Java format (that is, big-endian format) +// from (Rsrc)+offset. +void InterpreterMacroAssembler::get_u4(Register Rdst, Register Rsrc, int offset, + signedOrNot is_signed) { +#if defined(VM_LITTLE_ENDIAN) + if (offset) { + load_const_optimized(Rdst, offset); + lwbrx(Rdst, Rdst, Rsrc); + } else { + lwbrx(Rdst, Rsrc); + } + if (is_signed == Signed) { + extsw(Rdst, Rdst); + } +#else + if (is_signed == Signed) { + lwa(Rdst, offset, Rsrc); + } else { + lwz(Rdst, offset, Rsrc); + } +#endif +} + // Load object from cpool->resolved_references(index). void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index) { assert_different_registers(result, index); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -130,6 +130,7 @@ void get_cache_and_index_at_bcp(Register cache, int bcp_offset, size_t index_size = sizeof(u2)); + void get_u4(Register Rdst, Register Rsrc, int offset, signedOrNot is_signed); // common code diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/ppc.ad --- a/hotspot/src/cpu/ppc/vm/ppc.ad Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/ppc.ad Mon Aug 18 10:07:43 2014 +0100 @@ -1283,8 +1283,6 @@ bool MachConstantBaseNode::requires_postalloc_expand() const { return true; } void MachConstantBaseNode::postalloc_expand(GrowableArray *nodes, PhaseRegAlloc *ra_) { - Compile *C = ra_->C; - iRegPdstOper *op_dst = new iRegPdstOper(); MachNode *m1 = new loadToc_hiNode(); MachNode *m2 = new loadToc_loNode(); @@ -2229,7 +2227,7 @@ } /* TODO: PPC port // Make a new machine dependent decode node (with its operands). -MachTypeNode *Matcher::make_decode_node(Compile *C) { +MachTypeNode *Matcher::make_decode_node() { assert(Universe::narrow_oop_base() == NULL && Universe::narrow_oop_shift() == 0, "This method is only implemented for unscaled cOops mode so far"); MachTypeNode *decode = new decodeN_unscaledNode(); @@ -2593,7 +2591,7 @@ MachNode *_last; } loadConLNodesTuple; -loadConLNodesTuple loadConLNodesTuple_create(Compile *C, PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc, +loadConLNodesTuple loadConLNodesTuple_create(PhaseRegAlloc *ra_, Node *toc, immLOper *immSrc, OptoReg::Name reg_second, OptoReg::Name reg_first) { loadConLNodesTuple nodes; @@ -2669,7 +2667,7 @@ enc_class postalloc_expand_load_long_constant(iRegLdst dst, immL src, iRegLdst toc) %{ // Create new nodes. loadConLNodesTuple loadConLNodes = - loadConLNodesTuple_create(C, ra_, n_toc, op_src, + loadConLNodesTuple_create(ra_, n_toc, op_src, ra_->get_reg_second(this), ra_->get_reg_first(this)); // Push new nodes. @@ -3391,7 +3389,7 @@ immLOper *op_repl = new immLOper((jlong)replicate_immF(op_src->constantF())); loadConLNodesTuple loadConLNodes = - loadConLNodesTuple_create(C, ra_, n_toc, op_repl, + loadConLNodesTuple_create(ra_, n_toc, op_repl, ra_->get_reg_second(this), ra_->get_reg_first(this)); // Push new nodes. @@ -3611,7 +3609,7 @@ // Create the nodes for loading the IC from the TOC. loadConLNodesTuple loadConLNodes_IC = - loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()), + loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong)Universe::non_oop_word()), OptoReg::Name(R19_H_num), OptoReg::Name(R19_num)); // Create the call node. @@ -3765,7 +3763,7 @@ #if defined(ABI_ELFv2) jlong entry_address = (jlong) this->entry_point(); assert(entry_address, "need address here"); - loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper(entry_address), + loadConLNodes_Entry = loadConLNodesTuple_create(ra_, n_toc, new immLOper(entry_address), OptoReg::Name(R12_H_num), OptoReg::Name(R12_num)); #else // Get the struct that describes the function we are about to call. @@ -3777,13 +3775,13 @@ loadConLNodesTuple loadConLNodes_Toc; // Create nodes and operands for loading the entry point. - loadConLNodes_Entry = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper(entry_address), + loadConLNodes_Entry = loadConLNodesTuple_create(ra_, n_toc, new immLOper(entry_address), OptoReg::Name(R12_H_num), OptoReg::Name(R12_num)); // Create nodes and operands for loading the env pointer. if (fd->env() != NULL) { - loadConLNodes_Env = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong) fd->env()), + loadConLNodes_Env = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->env()), OptoReg::Name(R11_H_num), OptoReg::Name(R11_num)); } else { loadConLNodes_Env._large_hi = NULL; @@ -3796,7 +3794,7 @@ } // Create nodes and operands for loading the Toc point. - loadConLNodes_Toc = loadConLNodesTuple_create(C, ra_, n_toc, new immLOper((jlong) fd->toc()), + loadConLNodes_Toc = loadConLNodesTuple_create(ra_, n_toc, new immLOper((jlong) fd->toc()), OptoReg::Name(R2_H_num), OptoReg::Name(R2_num)); #endif // ABI_ELFv2 // mtctr node diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -176,8 +176,12 @@ const Register size = R12_scratch2; __ get_cache_and_index_at_bcp(cache, 1, index_size); - // Big Endian (get least significant byte of 64 bit value): + // Get least significant byte of 64 bit value: +#if defined(VM_LITTLE_ENDIAN) + __ lbz(size, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()), cache); +#else __ lbz(size, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset()) + 7, cache); +#endif __ sldi(size, size, Interpreter::logStackElementSize); __ add(R15_esp, R15_esp, size); __ dispatch_next(state, step); @@ -858,7 +862,9 @@ // Our signature handlers copy required arguments to the C stack // (outgoing C args), R3_ARG1 to R10_ARG8, and FARG1 to FARG13. __ mr(R3_ARG1, R18_locals); +#if !defined(ABI_ELFv2) __ ld(signature_handler_fd, 0, signature_handler_fd); +#endif __ call_stub(signature_handler_fd); @@ -1020,8 +1026,13 @@ // native result across the call. No oop is present. __ mr(R3_ARG1, R16_thread); +#if defined(ABI_ELFv2) + __ call_c(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), + relocInfo::none); +#else __ call_c(CAST_FROM_FN_PTR(FunctionDescriptor*, JavaThread::check_special_condition_for_native_trans), relocInfo::none); +#endif __ bind(sync_check_done); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -189,8 +189,12 @@ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); assert(load_bc_into_bc_reg, "we use bc_reg as temp"); __ get_cache_and_index_at_bcp(Rtemp /* dst = cache */, 1); - // Big Endian: ((*(cache+indices))>>((1+byte_no)*8))&0xFF + // ((*(cache+indices))>>((1+byte_no)*8))&0xFF: +#if defined(VM_LITTLE_ENDIAN) + __ lbz(Rnew_bc, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 1 + byte_no, Rtemp); +#else __ lbz(Rnew_bc, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 7 - (1 + byte_no), Rtemp); +#endif __ cmpwi(CCR0, Rnew_bc, 0); __ li(Rnew_bc, (unsigned int)(unsigned char)new_bc); __ beq(CCR0, L_patch_done); @@ -1839,8 +1843,8 @@ __ clrrdi(Rdef_offset_addr, Rdef_offset_addr, log2_long((jlong)BytesPerInt)); // Load lo & hi. - __ lwz(Rlow_byte, BytesPerInt, Rdef_offset_addr); - __ lwz(Rhigh_byte, BytesPerInt * 2, Rdef_offset_addr); + __ get_u4(Rlow_byte, Rdef_offset_addr, BytesPerInt, InterpreterMacroAssembler::Unsigned); + __ get_u4(Rhigh_byte, Rdef_offset_addr, 2 *BytesPerInt, InterpreterMacroAssembler::Unsigned); // Check for default case (=index outside [low,high]). __ cmpw(CCR0, R17_tos, Rlow_byte); @@ -1854,12 +1858,17 @@ __ profile_switch_case(Rindex, Rhigh_byte /* scratch */, Rscratch1, Rscratch2); __ sldi(Rindex, Rindex, LogBytesPerInt); __ addi(Rindex, Rindex, 3 * BytesPerInt); +#if defined(VM_LITTLE_ENDIAN) + __ lwbrx(Roffset, Rdef_offset_addr, Rindex); + __ extsw(Roffset, Roffset); +#else __ lwax(Roffset, Rdef_offset_addr, Rindex); +#endif __ b(Ldispatch); __ bind(Ldefault_case); __ profile_switch_default(Rhigh_byte, Rscratch1); - __ lwa(Roffset, 0, Rdef_offset_addr); + __ get_u4(Roffset, Rdef_offset_addr, 0, InterpreterMacroAssembler::Signed); __ bind(Ldispatch); @@ -1875,12 +1884,11 @@ // Table switch using linear search through cases. // Bytecode stream format: // Bytecode (1) | 4-byte padding | default offset (4) | count (4) | value/offset pair1 (8) | value/offset pair2 (8) | ... -// Note: Everything is big-endian format here. So on little endian machines, we have to revers offset and count and cmp value. +// Note: Everything is big-endian format here. void TemplateTable::fast_linearswitch() { transition(itos, vtos); - Label Lloop_entry, Lsearch_loop, Lfound, Lcontinue_execution, Ldefault_case; - + Label Lloop_entry, Lsearch_loop, Lcontinue_execution, Ldefault_case; Register Rcount = R3_ARG1, Rcurrent_pair = R4_ARG2, Rdef_offset_addr = R5_ARG3, // Is going to contain address of default offset. @@ -1894,47 +1902,40 @@ __ clrrdi(Rdef_offset_addr, Rdef_offset_addr, log2_long((jlong)BytesPerInt)); // Setup loop counter and limit. - __ lwz(Rcount, BytesPerInt, Rdef_offset_addr); // Load count. + __ get_u4(Rcount, Rdef_offset_addr, BytesPerInt, InterpreterMacroAssembler::Unsigned); __ addi(Rcurrent_pair, Rdef_offset_addr, 2 * BytesPerInt); // Rcurrent_pair now points to first pair. - // Set up search loop. - __ cmpwi(CCR0, Rcount, 0); - __ beq(CCR0, Ldefault_case); - __ mtctr(Rcount); - - // linear table search - __ bind(Lsearch_loop); - - __ lwz(Rvalue, 0, Rcurrent_pair); - __ lwa(Roffset, 1 * BytesPerInt, Rcurrent_pair); - - __ cmpw(CCR0, Rvalue, Rcmp_value); - __ beq(CCR0, Lfound); - - __ addi(Rcurrent_pair, Rcurrent_pair, 2 * BytesPerInt); - __ bdnz(Lsearch_loop); - - // default case + __ cmpwi(CCR0, Rcount, 0); + __ bne(CCR0, Lloop_entry); + + // Default case __ bind(Ldefault_case); - - __ lwa(Roffset, 0, Rdef_offset_addr); + __ get_u4(Roffset, Rdef_offset_addr, 0, InterpreterMacroAssembler::Signed); if (ProfileInterpreter) { __ profile_switch_default(Rdef_offset_addr, Rcount/* scratch */); - __ b(Lcontinue_execution); } - - // Entry found, skip Roffset bytecodes and continue. - __ bind(Lfound); + __ b(Lcontinue_execution); + + // Next iteration + __ bind(Lsearch_loop); + __ bdz(Ldefault_case); + __ addi(Rcurrent_pair, Rcurrent_pair, 2 * BytesPerInt); + __ bind(Lloop_entry); + __ get_u4(Rvalue, Rcurrent_pair, 0, InterpreterMacroAssembler::Unsigned); + __ cmpw(CCR0, Rvalue, Rcmp_value); + __ bne(CCR0, Lsearch_loop); + + // Found, load offset. + __ get_u4(Roffset, Rcurrent_pair, BytesPerInt, InterpreterMacroAssembler::Signed); + // Calculate case index and profile + __ mfctr(Rcurrent_pair); if (ProfileInterpreter) { - // Calc the num of the pair we hit. Careful, Rcurrent_pair points 2 ints - // beyond the actual current pair due to the auto update load above! - __ sub(Rcurrent_pair, Rcurrent_pair, Rdef_offset_addr); - __ addi(Rcurrent_pair, Rcurrent_pair, - 2 * BytesPerInt); - __ srdi(Rcurrent_pair, Rcurrent_pair, LogBytesPerInt + 1); + __ sub(Rcurrent_pair, Rcount, Rcurrent_pair); __ profile_switch_case(Rcurrent_pair, Rcount /*scratch*/, Rdef_offset_addr/*scratch*/, Rscratch); - __ bind(Lcontinue_execution); } + + __ bind(Lcontinue_execution); __ add(R14_bcp, Roffset, R14_bcp); __ dispatch_next(vtos); } @@ -1990,7 +1991,7 @@ // initialize i & j __ li(Ri,0); - __ lwz(Rj, -BytesPerInt, Rarray); + __ get_u4(Rj, Rarray, -BytesPerInt, InterpreterMacroAssembler::Unsigned); // and start. Label entry; @@ -2007,7 +2008,11 @@ // i = h; // } __ sldi(Rscratch, Rh, log_entry_size); +#if defined(VM_LITTLE_ENDIAN) + __ lwbrx(Rscratch, Rscratch, Rarray); +#else __ lwzx(Rscratch, Rscratch, Rarray); +#endif // if (key < current value) // Rh = Rj @@ -2039,20 +2044,20 @@ // Ri = value offset __ sldi(Ri, Ri, log_entry_size); __ add(Ri, Ri, Rarray); - __ lwz(Rscratch, 0, Ri); + __ get_u4(Rscratch, Ri, 0, InterpreterMacroAssembler::Unsigned); Label not_found; // Ri = offset offset __ cmpw(CCR0, Rkey, Rscratch); __ beq(CCR0, not_found); // entry not found -> j = default offset - __ lwz(Rj, -2 * BytesPerInt, Rarray); + __ get_u4(Rj, Rarray, -2 * BytesPerInt, InterpreterMacroAssembler::Unsigned); __ b(default_case); __ bind(not_found); // entry found -> j = offset __ profile_switch_case(Rh, Rj, Rscratch, Rkey); - __ lwz(Rj, BytesPerInt, Ri); + __ get_u4(Rj, Ri, BytesPerInt, InterpreterMacroAssembler::Unsigned); if (ProfileInterpreter) { __ b(continue_execution); @@ -2147,8 +2152,11 @@ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); // We are resolved if the indices offset contains the current bytecode. - // Big Endian: +#if defined(VM_LITTLE_ENDIAN) + __ lbz(Rscratch, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + byte_no + 1, Rcache); +#else __ lbz(Rscratch, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset()) + 7 - (byte_no + 1), Rcache); +#endif // Acquire by cmp-br-isync (see below). __ cmpdi(CCR0, Rscratch, (int)bytecode()); __ beq(CCR0, Lresolved); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/sparc/vm/sparc.ad --- a/hotspot/src/cpu/sparc/vm/sparc.ad Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Mon Aug 18 10:07:43 2014 +0100 @@ -6184,7 +6184,11 @@ ins_cost(DEFAULT_COST * 3/2); format %{ "SET $con,$dst\t! non-oop ptr" %} ins_encode %{ - __ set($con$$constant, $dst$$Register); + if (_opnds[1]->constant_reloc() == relocInfo::metadata_type) { + __ set_metadata_constant((Metadata*)$con$$constant, $dst$$Register); + } else { + __ set($con$$constant, $dst$$Register); + } %} ins_pipe(loadConP); %} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/x86/vm/assembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -3854,6 +3854,15 @@ } // Carry-Less Multiplication Quadword +void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) { + assert(VM_Version::supports_clmul(), ""); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A); + emit_int8(0x44); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)mask); +} + +// Carry-Less Multiplication Quadword void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask) { assert(VM_Version::supports_avx() && VM_Version::supports_clmul(), ""); bool vector256 = false; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/x86/vm/assembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1837,6 +1837,7 @@ void vpbroadcastd(XMMRegister dst, XMMRegister src); // Carry-Less Multiplication Quadword + void pclmulqdq(XMMRegister dst, XMMRegister src, int mask); void vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask); // AVX instruction which is used to clear upper 128 bits of YMM registers and diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -7316,17 +7316,34 @@ * Fold 128-bit data chunk */ void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, int offset) { - vpclmulhdq(xtmp, xK, xcrc); // [123:64] - vpclmulldq(xcrc, xK, xcrc); // [63:0] - vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */); - pxor(xcrc, xtmp); + if (UseAVX > 0) { + vpclmulhdq(xtmp, xK, xcrc); // [123:64] + vpclmulldq(xcrc, xK, xcrc); // [63:0] + vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */); + pxor(xcrc, xtmp); + } else { + movdqa(xtmp, xcrc); + pclmulhdq(xtmp, xK); // [123:64] + pclmulldq(xcrc, xK); // [63:0] + pxor(xcrc, xtmp); + movdqu(xtmp, Address(buf, offset)); + pxor(xcrc, xtmp); + } } void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, XMMRegister xbuf) { - vpclmulhdq(xtmp, xK, xcrc); - vpclmulldq(xcrc, xK, xcrc); - pxor(xcrc, xbuf); - pxor(xcrc, xtmp); + if (UseAVX > 0) { + vpclmulhdq(xtmp, xK, xcrc); + vpclmulldq(xcrc, xK, xcrc); + pxor(xcrc, xbuf); + pxor(xcrc, xtmp); + } else { + movdqa(xtmp, xcrc); + pclmulhdq(xtmp, xK); + pclmulldq(xcrc, xK); + pxor(xcrc, xbuf); + pxor(xcrc, xtmp); + } } /** @@ -7444,9 +7461,17 @@ // Fold 128 bits in xmm1 down into 32 bits in crc register. BIND(L_fold_128b); movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr())); - vpclmulqdq(xmm2, xmm0, xmm1, 0x1); - vpand(xmm3, xmm0, xmm2, false /* vector256 */); - vpclmulqdq(xmm0, xmm0, xmm3, 0x1); + if (UseAVX > 0) { + vpclmulqdq(xmm2, xmm0, xmm1, 0x1); + vpand(xmm3, xmm0, xmm2, false /* vector256 */); + vpclmulqdq(xmm0, xmm0, xmm3, 0x1); + } else { + movdqa(xmm2, xmm0); + pclmulqdq(xmm2, xmm1, 0x1); + movdqa(xmm3, xmm0); + pand(xmm3, xmm2); + pclmulqdq(xmm0, xmm3, 0x1); + } psrldq(xmm1, 8); psrldq(xmm2, 4); pxor(xmm0, xmm1); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -966,6 +966,16 @@ void mulss(XMMRegister dst, Address src) { Assembler::mulss(dst, src); } void mulss(XMMRegister dst, AddressLiteral src); + // Carry-Less Multiplication Quadword + void pclmulldq(XMMRegister dst, XMMRegister src) { + // 0x00 - multiply lower 64 bits [0:63] + Assembler::pclmulqdq(dst, src, 0x00); + } + void pclmulhdq(XMMRegister dst, XMMRegister src) { + // 0x11 - multiply upper 64 bits [64:127] + Assembler::pclmulqdq(dst, src, 0x11); + } + void sqrtsd(XMMRegister dst, XMMRegister src) { Assembler::sqrtsd(dst, src); } void sqrtsd(XMMRegister dst, Address src) { Assembler::sqrtsd(dst, src); } void sqrtsd(XMMRegister dst, AddressLiteral src); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -559,7 +559,7 @@ FLAG_SET_DEFAULT(UseCLMUL, false); } - if (UseCLMUL && (UseAVX > 0) && (UseSSE > 2)) { + if (UseCLMUL && (UseSSE > 2)) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { UseCRC32Intrinsics = true; } @@ -805,6 +805,21 @@ } } } + if ((cpu_family() == 0x06) && + ((extended_cpu_model() == 0x36) || // Centerton + (extended_cpu_model() == 0x37) || // Silvermont + (extended_cpu_model() == 0x4D))) { +#ifdef COMPILER2 + if (FLAG_IS_DEFAULT(OptoScheduling)) { + OptoScheduling = true; + } +#endif + if (supports_sse4_2()) { // Silvermont + if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) { + UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus + } + } + } } // Use count leading zeros count instruction if available. @@ -892,23 +907,25 @@ AllocatePrefetchDistance = allocate_prefetch_distance(); AllocatePrefetchStyle = allocate_prefetch_style(); - if( is_intel() && cpu_family() == 6 && supports_sse3() ) { - if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core + if (is_intel() && cpu_family() == 6 && supports_sse3()) { + if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core #ifdef _LP64 AllocatePrefetchDistance = 384; #else AllocatePrefetchDistance = 320; #endif } - if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus + if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus AllocatePrefetchDistance = 192; AllocatePrefetchLines = 4; + } #ifdef COMPILER2 - if (AggressiveOpts && FLAG_IS_DEFAULT(UseFPUForSpilling)) { + if (supports_sse4_2()) { + if (FLAG_IS_DEFAULT(UseFPUForSpilling)) { FLAG_SET_DEFAULT(UseFPUForSpilling, true); } + } #endif - } } assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value"); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/os/solaris/vm/attachListener_solaris.cpp --- a/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/os/solaris/vm/attachListener_solaris.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -199,23 +199,29 @@ // Calls from the door function to check that the client credentials // match this process. Returns 0 if credentials okay, otherwise -1. static int check_credentials() { - door_cred_t cred_info; + ucred_t *cred_info = NULL; + int ret = -1; // deny by default // get client credentials - if (door_cred(&cred_info) == -1) { - return -1; // unable to get them + if (door_ucred(&cred_info) == -1) { + return -1; // unable to get them, deny } // get our euid/eguid (probably could cache these) uid_t euid = geteuid(); gid_t egid = getegid(); - // check that the effective uid/gid matches - discuss this with Jeff. - if (cred_info.dc_euid == euid && cred_info.dc_egid == egid) { - return 0; // okay - } else { - return -1; // denied + // get euid/egid from ucred_free + uid_t ucred_euid = ucred_geteuid(cred_info); + gid_t ucred_egid = ucred_getegid(cred_info); + + // check that the effective uid/gid matches + if (ucred_euid == euid && ucred_egid == egid) { + ret = 0; // allow } + + ucred_free(cred_info); + return ret; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/adlc/output_c.cpp --- a/hotspot/src/share/vm/adlc/output_c.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/adlc/output_c.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, 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 @@ -997,7 +997,7 @@ int nopcnt = 0; for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; nopcnt++ ); - fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d], Compile *C) {\n", nopcnt); + fprintf(fp_cpp, "void Bundle::initialize_nops(MachNode * nop_list[%d]) {\n", nopcnt); int i = 0; for ( _pipeline->_noplist.reset(); (nop = _pipeline->_noplist.iter()) != NULL; i++ ) { fprintf(fp_cpp, " nop_list[%d] = (MachNode *) new %sNode();\n", i, nop); @@ -1369,7 +1369,7 @@ fprintf(fp, " ra_->add_reference(root, inst%d);\n", inst_num); fprintf(fp, " ra_->set_oop (root, ra_->is_oop(inst%d));\n", inst_num); fprintf(fp, " ra_->set_pair(root->_idx, ra_->get_reg_second(inst%d), ra_->get_reg_first(inst%d));\n", inst_num, inst_num); - fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(C); // result\n", inst_num); + fprintf(fp, " root->_opnds[0] = inst%d->_opnds[0]->clone(); // result\n", inst_num); fprintf(fp, " // ----- Done with initial setup -----\n"); } else { if( (op_form == NULL) || (op_form->is_base_constant(globals) == Form::none) ) { @@ -1382,7 +1382,7 @@ } else { fprintf(fp, " // no ideal edge for constants after matching\n"); } - fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone(C);\n", + fprintf(fp, " root->_opnds[%d] = inst%d->_opnds[%d]->clone();\n", opnds_index, inst_num, inst_op_num ); } ++opnds_index; @@ -1402,7 +1402,7 @@ // Define the Peephole method for an instruction node void ArchDesc::definePeephole(FILE *fp, InstructForm *node) { // Generate Peephole function header - fprintf(fp, "MachNode *%sNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) {\n", node->_ident); + fprintf(fp, "MachNode *%sNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) {\n", node->_ident); fprintf(fp, " bool matches = true;\n"); // Identify the maximum instruction position, @@ -1593,7 +1593,7 @@ } const char *resultOper = new_inst->reduce_result(); - fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator( %s, C ));\n", + fprintf(fp," n%d->set_opnd_array(0, state->MachOperGenerator(%s));\n", cnt, machOperEnum(resultOper)); // get the formal operand NameList @@ -1634,7 +1634,7 @@ // If there is no use of the created operand, just skip it if (new_pos != NameList::Not_in_list) { //Copy the operand from the original made above - fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n", + fprintf(fp," n%d->set_opnd_array(%d, op%d->clone()); // %s\n", cnt, new_pos, exp_pos-node->num_opnds(), opid); // Check for who defines this operand & add edge if needed fprintf(fp," if(tmp%d != NULL)\n", exp_pos); @@ -1662,7 +1662,7 @@ new_pos = new_inst->operand_position(parameter,Component::USE); if (new_pos != -1) { // Copy the operand from the ExpandNode to the new node - fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n", + fprintf(fp," n%d->set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n", cnt, new_pos, exp_pos, opid); // For each operand add appropriate input edges by looking at tmp's fprintf(fp," if(tmp%d == this) {\n", exp_pos); @@ -1729,14 +1729,14 @@ declared_def = true; } if (op && op->_interface && op->_interface->is_RegInterface()) { - fprintf(fp," def = new MachTempNode(state->MachOperGenerator( %s, C ));\n", + fprintf(fp," def = new MachTempNode(state->MachOperGenerator(%s));\n", machOperEnum(op->_ident)); fprintf(fp," add_req(def);\n"); // The operand for TEMP is already constructed during // this mach node construction, see buildMachNode(). // // int idx = node->operand_position_format(comp->_name); - // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator( %s, C ));\n", + // fprintf(fp," set_opnd_array(%d, state->MachOperGenerator(%s));\n", // idx, machOperEnum(op->_ident)); } else { assert(false, "can't have temps which aren't registers"); @@ -1802,7 +1802,7 @@ uint j = node->unique_opnds_idx(i); // unique_opnds_idx(i) is unique if unique_opnds_idx(j) is not unique. if( j != node->unique_opnds_idx(j) ) { - fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone(C)); // %s\n", + fprintf(fp," set_opnd_array(%d, opnd_array(%d)->clone()); // %s\n", new_num_opnds, i, comp->_name); // delete not unique edges here fprintf(fp," for(unsigned i = 0; i < num%d; i++) {\n", i); @@ -2839,12 +2839,12 @@ // generate code to create a clone for a class derived from MachOper // -// (0) MachOper *MachOperXOper::clone(Compile* C) const { +// (0) MachOper *MachOperXOper::clone() const { // (1) return new MachXOper( _ccode, _c0, _c1, ..., _cn); // (2) } // static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) { - fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper._ident); + fprintf(fp,"MachOper *%sOper::clone() const {\n", oper._ident); // Check for constants that need to be copied over const int num_consts = oper.num_consts(globalNames); const bool is_ideal_bool = oper.is_ideal_bool(); @@ -3043,7 +3043,7 @@ static void define_fill_new_machnode(bool used, FILE *fp_cpp) { fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "// Copy _idx, inputs and operands to new node\n"); - fprintf(fp_cpp, "void MachNode::fill_new_machnode( MachNode* node, Compile* C) const {\n"); + fprintf(fp_cpp, "void MachNode::fill_new_machnode(MachNode* node) const {\n"); if( !used ) { fprintf(fp_cpp, " // This architecture does not have cisc or short branch instructions\n"); fprintf(fp_cpp, " ShouldNotCallThis();\n"); @@ -3064,7 +3064,7 @@ fprintf(fp_cpp, " MachOper **to = node->_opnds;\n"); fprintf(fp_cpp, " for( int i = 0; i < nopnds; i++ ) {\n"); fprintf(fp_cpp, " if( i != cisc_operand() ) \n"); - fprintf(fp_cpp, " to[i] = _opnds[i]->clone(C);\n"); + fprintf(fp_cpp, " to[i] = _opnds[i]->clone();\n"); fprintf(fp_cpp, " }\n"); fprintf(fp_cpp, "}\n"); } @@ -3105,7 +3105,7 @@ if ( strcmp(oper->_ident,"label") == 0 ) { defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); - fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident); + fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident); fprintf(fp," return new %sOper(_label, _block_num);\n", oper->_ident); fprintf(fp,"}\n"); @@ -3124,7 +3124,7 @@ if ( strcmp(oper->_ident,"method") == 0 ) { defineIn_RegMask(_CPP_MISC_file._fp, _globalNames, *oper); - fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper->_ident); + fprintf(fp,"MachOper *%sOper::clone() const {\n", oper->_ident); fprintf(fp," return new %sOper(_method);\n", oper->_ident); fprintf(fp,"}\n"); @@ -3845,7 +3845,7 @@ "// that invokes 'new' on the corresponding class constructor.\n"); fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "MachOper *State::MachOperGenerator"); - fprintf(fp_cpp, "(int opcode, Compile* C)"); + fprintf(fp_cpp, "(int opcode)"); fprintf(fp_cpp, "{\n"); fprintf(fp_cpp, "\n"); fprintf(fp_cpp, " switch(opcode) {\n"); @@ -3921,7 +3921,7 @@ int index = clist.operand_position(comp->_name, comp->_usedef, inst); const char *opcode = machOperEnum(comp->_type); fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index); - fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode); + fprintf(fp_cpp, "MachOperGenerator(%s));\n", opcode); } } else if ( inst->is_chain_of_constant(_globalNames, opType) ) { @@ -3978,7 +3978,7 @@ InstructForm *inst_cisc = cisc_spill_alternate(); if (inst_cisc != NULL) { fprintf(fp_hpp, " virtual int cisc_operand() const { return %d; }\n", cisc_spill_operand()); - fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset, Compile* C);\n"); + fprintf(fp_hpp, " virtual MachNode *cisc_version(int offset);\n"); fprintf(fp_hpp, " virtual void use_cisc_RegMask();\n"); fprintf(fp_hpp, " virtual const RegMask *cisc_RegMask() const { return _cisc_RegMask; }\n"); } @@ -4008,7 +4008,7 @@ // Construct CISC version of this instruction fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "// Build CISC version of this instruction\n"); - fprintf(fp_cpp, "MachNode *%sNode::cisc_version( int offset, Compile* C ) {\n", this->_ident); + fprintf(fp_cpp, "MachNode *%sNode::cisc_version(int offset) {\n", this->_ident); // Create the MachNode object fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); // Fill in the bottom_type where requested @@ -4023,7 +4023,7 @@ fprintf(fp_cpp, "\n"); fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); - fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); + fprintf(fp_cpp, " fill_new_machnode(node);\n"); // Construct operand to access [stack_pointer + offset] fprintf(fp_cpp, " // Construct operand to access [stack_pointer + offset]\n"); fprintf(fp_cpp, " node->set_opnd_array(cisc_operand(), new %sOper(offset));\n", cisc_oper_name); @@ -4042,7 +4042,7 @@ // Build prototypes for short branch methods void InstructForm::declare_short_branch_methods(FILE *fp_hpp) { if (has_short_branch_form()) { - fprintf(fp_hpp, " virtual MachNode *short_branch_version(Compile* C);\n"); + fprintf(fp_hpp, " virtual MachNode *short_branch_version();\n"); } } @@ -4055,7 +4055,7 @@ // Construct short_branch_version() method. fprintf(fp_cpp, "// Build short branch version of this instruction\n"); - fprintf(fp_cpp, "MachNode *%sNode::short_branch_version(Compile* C) {\n", this->_ident); + fprintf(fp_cpp, "MachNode *%sNode::short_branch_version() {\n", this->_ident); // Create the MachNode object fprintf(fp_cpp, " %sNode *node = new %sNode();\n", name, name); if( is_ideal_if() ) { @@ -4071,7 +4071,7 @@ // Short branch version must use same node index for access // through allocator's tables fprintf(fp_cpp, " // Copy _idx, inputs and operands to new node\n"); - fprintf(fp_cpp, " fill_new_machnode(node, C);\n"); + fprintf(fp_cpp, " fill_new_machnode(node);\n"); // Return result and exit scope fprintf(fp_cpp, " return node;\n"); @@ -4097,7 +4097,7 @@ "// that invokes 'new' on the corresponding class constructor.\n"); fprintf(fp_cpp, "\n"); fprintf(fp_cpp, "MachNode *State::MachNodeGenerator"); - fprintf(fp_cpp, "(int opcode, Compile* C)"); + fprintf(fp_cpp, "(int opcode)"); fprintf(fp_cpp, "{\n"); fprintf(fp_cpp, " switch(opcode) {\n"); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/adlc/output_h.cpp --- a/hotspot/src/share/vm/adlc/output_h.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/adlc/output_h.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1119,7 +1119,7 @@ fprintf(fp_hpp, " _nop_count = %d\n", _pipeline->_nopcnt); fprintf(fp_hpp, " };\n\n"); - fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n", + fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d]);\n\n", _pipeline->_nopcnt); fprintf(fp_hpp, "#ifndef PRODUCT\n"); fprintf(fp_hpp, " void dump(outputStream *st = tty) const;\n"); @@ -1240,7 +1240,7 @@ constant_type, _globalNames); // Clone function - fprintf(fp," virtual MachOper *clone(Compile* C) const;\n"); + fprintf(fp," virtual MachOper *clone() const;\n"); // Support setting a spill offset into a constant operand. // We only support setting an 'int' offset, while in the @@ -1718,7 +1718,7 @@ // If there is an explicit peephole rule, build it if ( instr->peepholes() != NULL ) { - fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile *C);\n"); + fprintf(fp," virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted);\n"); } // Output the declaration for number of relocation entries @@ -1863,7 +1863,7 @@ } if ( instr->num_post_match_opnds() != 0 || instr->is_chain_of_constant(_globalNames) ) { - fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode, Compile* C);\n"); + fprintf(fp," friend MachNode *State::MachNodeGenerator(int opcode);\n"); } if ( instr->rematerialize(_globalNames, get_registers()) ) { fprintf(fp," // Rematerialize %s\n", instr->_ident); @@ -2071,8 +2071,8 @@ fprintf(fp," DEBUG_ONLY( ~State(void); ) // Destructor\n"); fprintf(fp,"\n"); fprintf(fp," // Methods created by ADLC and invoked by Reduce\n"); - fprintf(fp," MachOper *MachOperGenerator( int opcode, Compile* C );\n"); - fprintf(fp," MachNode *MachNodeGenerator( int opcode, Compile* C );\n"); + fprintf(fp," MachOper *MachOperGenerator(int opcode);\n"); + fprintf(fp," MachNode *MachNodeGenerator(int opcode);\n"); fprintf(fp,"\n"); fprintf(fp," // Assign a state to a node, definition of method produced by ADLC\n"); fprintf(fp," bool DFA( int opcode, const Node *ideal );\n"); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/c1/c1_LinearScan.cpp --- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1613,25 +1613,22 @@ Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals; Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals; - create_unhandled_lists(&precolored_cpu_intervals, ¬_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval); - if (has_fpu_registers()) { - create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval); -#ifdef ASSERT - } else { - // fpu register allocation is omitted because no virtual fpu registers are present - // just check this again... - create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval); - assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval"); -#endif - } - // allocate cpu registers + create_unhandled_lists(&precolored_cpu_intervals, ¬_precolored_cpu_intervals, + is_precolored_cpu_interval, is_virtual_cpu_interval); + + // allocate fpu registers + create_unhandled_lists(&precolored_fpu_intervals, ¬_precolored_fpu_intervals, + is_precolored_fpu_interval, is_virtual_fpu_interval); + + // the fpu interval allocation cannot be moved down below with the fpu section as + // the cpu_lsw.walk() changes interval positions. + LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals); cpu_lsw.walk(); cpu_lsw.finish_allocation(); if (has_fpu_registers()) { - // allocate fpu registers LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals); fpu_lsw.walk(); fpu_lsw.finish_allocation(); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/classfile/stackMapFrame.cpp --- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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 @@ -54,21 +54,6 @@ return frame; } -bool StackMapFrame::has_new_object() const { - int32_t i; - for (i = 0; i < _max_locals; i++) { - if (_locals[i].is_uninitialized()) { - return true; - } - } - for (i = 0; i < _stack_size; i++) { - if (_stack[i].is_uninitialized()) { - return true; - } - } - return false; -} - void StackMapFrame::initialize_object( VerificationType old_object, VerificationType new_object) { int32_t i; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/classfile/stackMapFrame.hpp --- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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 @@ -155,10 +155,6 @@ const methodHandle m, VerificationType thisKlass, TRAPS); // Search local variable type array and stack type array. - // Return true if an uninitialized object is found. - bool has_new_object() const; - - // Search local variable type array and stack type array. // Set every element with type of old_object to new_object. void initialize_object( VerificationType old_object, VerificationType new_object); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/classfile/stackMapTable.cpp --- a/hotspot/src/share/vm/classfile/stackMapTable.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -70,24 +70,26 @@ bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, - bool match, bool update, ErrorContext* ctx, TRAPS) const { + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { int index = get_index_from_offset(target); - return match_stackmap(frame, target, index, match, update, ctx, THREAD); + return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD); } // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. +// handler is true if the frame in stackmap_table is for an exception handler. // -// The values of match and update are: _match__update_ +// The values of match and update are: _match__update__handler // -// checking a branch target/exception handler: true false +// checking a branch target: true false false +// checking an exception handler: true false true // linear bytecode verification following an -// unconditional branch: false true +// unconditional branch: false true false // linear bytecode verification not following an -// unconditional branch: true true +// unconditional branch: true true false bool StackMapTable::match_stackmap( StackMapFrame* frame, int32_t target, int32_t frame_index, - bool match, bool update, ErrorContext* ctx, TRAPS) const { + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { if (frame_index < 0 || frame_index >= _frame_count) { *ctx = ErrorContext::missing_stackmap(frame->offset()); frame->verifier()->verify_error( @@ -98,11 +100,9 @@ StackMapFrame *stackmap_frame = _frame_array[frame_index]; bool result = true; if (match) { - // when checking handler target, match == true && update == false - bool is_exception_handler = !update; // Has direct control flow from last instruction, need to match the two // frames. - result = frame->is_assignable_to(stackmap_frame, is_exception_handler, + result = frame->is_assignable_to(stackmap_frame, handler, ctx, CHECK_VERIFY_(frame->verifier(), result)); } if (update) { @@ -126,24 +126,10 @@ StackMapFrame* frame, int32_t target, TRAPS) const { ErrorContext ctx; bool match = match_stackmap( - frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); + frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { frame->verifier()->verify_error(ctx, "Inconsistent stackmap frames at branch target %d", target); - return; - } - // check if uninitialized objects exist on backward branches - check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); - frame->verifier()->update_furthest_jump(target); -} - -void StackMapTable::check_new_object( - const StackMapFrame* frame, int32_t target, TRAPS) const { - if (frame->offset() > target && frame->has_new_object()) { - frame->verifier()->verify_error( - ErrorContext::bad_code(frame->offset()), - "Uninitialized object exists on backward branch %d", target); - return; } } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/classfile/stackMapTable.hpp --- a/hotspot/src/share/vm/classfile/stackMapTable.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/classfile/stackMapTable.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -60,12 +60,12 @@ // specified offset. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, - bool match, bool update, ErrorContext* ctx, TRAPS) const; + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; // Match and/or update current_frame to the frame in stackmap table with // specified offset and frame index. Return true if the two frames match. bool match_stackmap( StackMapFrame* current_frame, int32_t offset, int32_t frame_index, - bool match, bool update, ErrorContext* ctx, TRAPS) const; + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. @@ -76,10 +76,6 @@ // Returns the frame array index where the frame with offset is stored. int get_index_from_offset(int32_t offset) const; - // Make sure that there's no uninitialized object exist on backward branch. - void check_new_object( - const StackMapFrame* frame, int32_t target, TRAPS) const; - void print_on(outputStream* str) const; }; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/classfile/verifier.cpp --- a/hotspot/src/share/vm/classfile/verifier.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/classfile/verifier.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -620,8 +620,6 @@ // flow from current instruction to the next // instruction in sequence - set_furthest_jump(0); - Bytecodes::Code opcode; while (!bcs.is_last_bytecode()) { // Check for recursive re-verification before each bytecode. @@ -1780,7 +1778,7 @@ // If matched, current_frame will be updated by this method. bool matches = stackmap_table->match_stackmap( current_frame, this_offset, stackmap_index, - !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); + !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0)); if (!matches) { // report type error verify_error(ctx, "Instruction type does not match stack map"); @@ -1827,7 +1825,7 @@ } ErrorContext ctx; bool matches = stackmap_table->match_stackmap( - new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); + new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this)); if (!matches) { verify_error(ctx, "Stack map does not match the one at " "exception handler %d", handler_pc); @@ -2238,13 +2236,6 @@ return; } - // Make sure that this call is not jumped over. - if (bci < furthest_jump()) { - verify_error(ErrorContext::bad_code(bci), - "Bad method call from inside of a branch"); - return; - } - // Make sure that this call is not done from within a TRY block because // that can result in returning an incomplete object. Simply checking // (bci >= start_pc) also ensures that this call is not done after a TRY diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/classfile/verifier.hpp --- a/hotspot/src/share/vm/classfile/verifier.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/classfile/verifier.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -258,9 +258,6 @@ ErrorContext _error_context; // contains information about an error - // Used to detect illegal jumps over calls to super() nd this() in ctors. - int32_t _furthest_jump; - void verify_method(methodHandle method, TRAPS); char* generate_code_data(methodHandle m, u4 code_length, TRAPS); void verify_exception_handler_table(u4 code_length, char* code_data, @@ -407,19 +404,6 @@ TypeOrigin ref_ctx(const char* str, TRAPS); - // Keep track of the furthest branch done in a method to make sure that - // there are no branches over calls to super() or this() from inside of - // a constructor. - int32_t furthest_jump() { return _furthest_jump; } - - void set_furthest_jump(int32_t target) { - _furthest_jump = target; - } - - void update_furthest_jump(int32_t target) { - if (target > _furthest_jump) _furthest_jump = target; - } - }; inline int ClassVerifier::change_sig_to_verificationType( diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/code/dependencies.cpp --- a/hotspot/src/share/vm/code/dependencies.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/code/dependencies.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -407,56 +407,66 @@ // for the sake of the compiler log, print out current dependencies: void Dependencies::log_all_dependencies() { if (log() == NULL) return; - ciBaseObject* args[max_arg_count]; + ResourceMark rm; for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) { DepType dept = (DepType)deptv; GrowableArray* deps = _deps[dept]; - if (deps->length() == 0) continue; + int deplen = deps->length(); + if (deplen == 0) { + continue; + } int stride = dep_args(dept); + GrowableArray* ciargs = new GrowableArray(stride); for (int i = 0; i < deps->length(); i += stride) { for (int j = 0; j < stride; j++) { // flush out the identities before printing - args[j] = deps->at(i+j); + ciargs->push(deps->at(i+j)); } - write_dependency_to(log(), dept, stride, args); + write_dependency_to(log(), dept, ciargs); + ciargs->clear(); } + guarantee(deplen == deps->length(), "deps array cannot grow inside nested ResoureMark scope"); } } void Dependencies::write_dependency_to(CompileLog* log, DepType dept, - int nargs, DepArgument args[], + GrowableArray* args, Klass* witness) { if (log == NULL) { return; } + ResourceMark rm; ciEnv* env = ciEnv::current(); - ciBaseObject* ciargs[max_arg_count]; - assert(nargs <= max_arg_count, "oob"); - for (int j = 0; j < nargs; j++) { - if (args[j].is_oop()) { - ciargs[j] = env->get_object(args[j].oop_value()); + GrowableArray* ciargs = new GrowableArray(args->length()); + for (GrowableArrayIterator it = args->begin(); it != args->end(); ++it) { + DepArgument arg = *it; + if (arg.is_oop()) { + ciargs->push(env->get_object(arg.oop_value())); } else { - ciargs[j] = env->get_metadata(args[j].metadata_value()); + ciargs->push(env->get_metadata(arg.metadata_value())); } } - Dependencies::write_dependency_to(log, dept, nargs, ciargs, witness); + int argslen = ciargs->length(); + Dependencies::write_dependency_to(log, dept, ciargs, witness); + guarantee(argslen == ciargs->length(), "ciargs array cannot grow inside nested ResoureMark scope"); } void Dependencies::write_dependency_to(CompileLog* log, DepType dept, - int nargs, ciBaseObject* args[], + GrowableArray* args, Klass* witness) { - if (log == NULL) return; - assert(nargs <= max_arg_count, "oob"); - int argids[max_arg_count]; - int ctxkj = dep_context_arg(dept); // -1 if no context arg - int j; - for (j = 0; j < nargs; j++) { - if (args[j]->is_object()) { - argids[j] = log->identify(args[j]->as_object()); + if (log == NULL) { + return; + } + ResourceMark rm; + GrowableArray* argids = new GrowableArray(args->length()); + for (GrowableArrayIterator it = args->begin(); it != args->end(); ++it) { + ciBaseObject* obj = *it; + if (obj->is_object()) { + argids->push(log->identify(obj->as_object())); } else { - argids[j] = log->identify(args[j]->as_metadata()); + argids->push(log->identify(obj->as_metadata())); } } if (witness != NULL) { @@ -465,16 +475,17 @@ log->begin_elem("dependency"); } log->print(" type='%s'", dep_name(dept)); - if (ctxkj >= 0) { - log->print(" ctxk='%d'", argids[ctxkj]); + const int ctxkj = dep_context_arg(dept); // -1 if no context arg + if (ctxkj >= 0 && ctxkj < argids->length()) { + log->print(" ctxk='%d'", argids->at(ctxkj)); } // write remaining arguments, if any. - for (j = 0; j < nargs; j++) { + for (int j = 0; j < argids->length(); j++) { if (j == ctxkj) continue; // already logged if (j == 1) { - log->print( " x='%d'", argids[j]); + log->print( " x='%d'", argids->at(j)); } else { - log->print(" x%d='%d'", j, argids[j]); + log->print(" x%d='%d'", j, argids->at(j)); } } if (witness != NULL) { @@ -486,9 +497,12 @@ void Dependencies::write_dependency_to(xmlStream* xtty, DepType dept, - int nargs, DepArgument args[], + GrowableArray* args, Klass* witness) { - if (xtty == NULL) return; + if (xtty == NULL) { + return; + } + ResourceMark rm; ttyLocker ttyl; int ctxkj = dep_context_arg(dept); // -1 if no context arg if (witness != NULL) { @@ -498,23 +512,24 @@ } xtty->print(" type='%s'", dep_name(dept)); if (ctxkj >= 0) { - xtty->object("ctxk", args[ctxkj].metadata_value()); + xtty->object("ctxk", args->at(ctxkj).metadata_value()); } // write remaining arguments, if any. - for (int j = 0; j < nargs; j++) { + for (int j = 0; j < args->length(); j++) { if (j == ctxkj) continue; // already logged + DepArgument arg = args->at(j); if (j == 1) { - if (args[j].is_oop()) { - xtty->object("x", args[j].oop_value()); + if (arg.is_oop()) { + xtty->object("x", arg.oop_value()); } else { - xtty->object("x", args[j].metadata_value()); + xtty->object("x", arg.metadata_value()); } } else { char xn[10]; sprintf(xn, "x%d", j); - if (args[j].is_oop()) { - xtty->object(xn, args[j].oop_value()); + if (arg.is_oop()) { + xtty->object(xn, arg.oop_value()); } else { - xtty->object(xn, args[j].metadata_value()); + xtty->object(xn, arg.metadata_value()); } } } @@ -525,7 +540,7 @@ xtty->end_elem(); } -void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[], +void Dependencies::print_dependency(DepType dept, GrowableArray* args, Klass* witness) { ResourceMark rm; ttyLocker ttyl; // keep the following output all in one block @@ -534,8 +549,8 @@ dep_name(dept)); // print arguments int ctxkj = dep_context_arg(dept); // -1 if no context arg - for (int j = 0; j < nargs; j++) { - DepArgument arg = args[j]; + for (int j = 0; j < args->length(); j++) { + DepArgument arg = args->at(j); bool put_star = false; if (arg.is_null()) continue; const char* what; @@ -571,31 +586,33 @@ void Dependencies::DepStream::log_dependency(Klass* witness) { if (_deps == NULL && xtty == NULL) return; // fast cutout for runtime ResourceMark rm; - int nargs = argument_count(); - DepArgument args[max_arg_count]; + const int nargs = argument_count(); + GrowableArray* args = new GrowableArray(nargs); for (int j = 0; j < nargs; j++) { if (type() == call_site_target_value) { - args[j] = argument_oop(j); + args->push(argument_oop(j)); } else { - args[j] = argument(j); + args->push(argument(j)); } } + int argslen = args->length(); if (_deps != NULL && _deps->log() != NULL) { - Dependencies::write_dependency_to(_deps->log(), - type(), nargs, args, witness); + Dependencies::write_dependency_to(_deps->log(), type(), args, witness); } else { - Dependencies::write_dependency_to(xtty, - type(), nargs, args, witness); + Dependencies::write_dependency_to(xtty, type(), args, witness); } + guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) { + ResourceMark rm; int nargs = argument_count(); - DepArgument args[max_arg_count]; + GrowableArray* args = new GrowableArray(nargs); for (int j = 0; j < nargs; j++) { - args[j] = argument(j); + args->push(argument(j)); } - Dependencies::print_dependency(type(), nargs, args, witness); + int argslen = args->length(); + Dependencies::print_dependency(type(), args, witness); if (verbose) { if (_code != NULL) { tty->print(" code: "); @@ -603,6 +620,7 @@ tty->cr(); } } + guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope"); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/code/dependencies.hpp --- a/hotspot/src/share/vm/code/dependencies.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/code/dependencies.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -369,20 +369,36 @@ void copy_to(nmethod* nm); void log_all_dependencies(); - void log_dependency(DepType dept, int nargs, ciBaseObject* args[]) { - write_dependency_to(log(), dept, nargs, args); + + void log_dependency(DepType dept, GrowableArray* args) { + ResourceMark rm; + int argslen = args->length(); + write_dependency_to(log(), dept, args); + guarantee(argslen == args->length(), + "args array cannot grow inside nested ResoureMark scope"); } + void log_dependency(DepType dept, ciBaseObject* x0, ciBaseObject* x1 = NULL, ciBaseObject* x2 = NULL) { - if (log() == NULL) return; - ciBaseObject* args[max_arg_count]; - args[0] = x0; - args[1] = x1; - args[2] = x2; - assert(2 < max_arg_count, ""); - log_dependency(dept, dep_args(dept), args); + if (log() == NULL) { + return; + } + ResourceMark rm; + GrowableArray* ciargs = + new GrowableArray(dep_args(dept)); + assert (x0 != NULL, "no log x0"); + ciargs->push(x0); + + if (x1 != NULL) { + ciargs->push(x1); + } + if (x2 != NULL) { + ciargs->push(x2); + } + assert(ciargs->length() == dep_args(dept), ""); + log_dependency(dept, ciargs); } class DepArgument : public ResourceObj { @@ -405,20 +421,8 @@ Metadata* metadata_value() const { assert(!_is_oop && _valid, "must be"); return (Metadata*) _value; } }; - static void write_dependency_to(CompileLog* log, - DepType dept, - int nargs, ciBaseObject* args[], - Klass* witness = NULL); - static void write_dependency_to(CompileLog* log, - DepType dept, - int nargs, DepArgument args[], - Klass* witness = NULL); - static void write_dependency_to(xmlStream* xtty, - DepType dept, - int nargs, DepArgument args[], - Klass* witness = NULL); static void print_dependency(DepType dept, - int nargs, DepArgument args[], + GrowableArray* args, Klass* witness = NULL); private: @@ -427,6 +431,18 @@ static Klass* ctxk_encoded_as_null(DepType dept, Metadata* x); + static void write_dependency_to(CompileLog* log, + DepType dept, + GrowableArray* args, + Klass* witness = NULL); + static void write_dependency_to(CompileLog* log, + DepType dept, + GrowableArray* args, + Klass* witness = NULL); + static void write_dependency_to(xmlStream* xtty, + DepType dept, + GrowableArray* args, + Klass* witness = NULL); public: // Use this to iterate over an nmethod's dependency set. // Works on new and old dependency sets. diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -5987,6 +5987,8 @@ }; void CMSRefProcTaskProxy::work(uint worker_id) { + ResourceMark rm; + HandleMark hm; assert(_collector->_span.equals(_span), "Inconsistency in _span"); CMSParKeepAliveClosure par_keep_alive(_collector, _span, _mark_bit_map, diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -2167,7 +2167,9 @@ g1h->increment_total_collections(); // Clean out dead classes and update Metaspace sizes. - ClassLoaderDataGraph::purge(); + if (ClassUnloadingWithConcurrentMark) { + ClassLoaderDataGraph::purge(); + } MetaspaceGC::compute_new_size(); // We reclaimed old regions so we should calculate the sizes to make @@ -2403,6 +2405,8 @@ } virtual void work(uint worker_id) { + ResourceMark rm; + HandleMark hm; CMTask* task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, task, false /* is_serial */); @@ -2595,24 +2599,27 @@ assert(_markStack.isEmpty(), "Marking should have completed"); // Unload Klasses, String, Symbols, Code Cache, etc. - - G1RemarkGCTraceTime trace("Unloading", G1Log::finer()); - - bool purged_classes; - { - G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest()); - purged_classes = SystemDictionary::do_unloading(&g1_is_alive); - } - - { - G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest()); - weakRefsWorkParallelPart(&g1_is_alive, purged_classes); - } - - if (G1StringDedup::is_enabled()) { - G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest()); - G1StringDedup::unlink(&g1_is_alive); + G1RemarkGCTraceTime trace("Unloading", G1Log::finer()); + + if (ClassUnloadingWithConcurrentMark) { + bool purged_classes; + + { + G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest()); + purged_classes = SystemDictionary::do_unloading(&g1_is_alive); + } + + { + G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest()); + weakRefsWorkParallelPart(&g1_is_alive, purged_classes); + } + } + + if (G1StringDedup::is_enabled()) { + G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest()); + G1StringDedup::unlink(&g1_is_alive); + } } } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1926,6 +1926,8 @@ _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()), _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()), _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()), + _humongous_is_live(), + _has_humongous_reclaim_candidates(false), _free_regions_coming(false), _young_list(new YoungList(this)), _gc_time_stamp(0), @@ -2082,6 +2084,7 @@ _g1h = this; _in_cset_fast_test.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); + _humongous_is_live.initialize(_g1_reserved.start(), _g1_reserved.end(), HeapRegion::GrainBytes); // Create the ConcurrentMark data structure and thread. // (Must do this late, so that "max_regions" is defined.) @@ -2177,6 +2180,11 @@ } } +void G1CollectedHeap::clear_humongous_is_live_table() { + guarantee(G1ReclaimDeadHumongousObjectsAtYoungGC, "Should only be called if true"); + _humongous_is_live.clear(); +} + size_t G1CollectedHeap::conservative_max_heap_alignment() { return HeapRegion::max_region_size(); } @@ -3771,6 +3779,61 @@ return g1_rem_set()->cardsScanned(); } +bool G1CollectedHeap::humongous_region_is_always_live(uint index) { + HeapRegion* region = region_at(index); + assert(region->startsHumongous(), "Must start a humongous object"); + return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty(); +} + +class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure { + private: + size_t _total_humongous; + size_t _candidate_humongous; + public: + RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) { + } + + virtual bool doHeapRegion(HeapRegion* r) { + if (!r->startsHumongous()) { + return false; + } + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + uint region_idx = r->hrs_index(); + bool is_candidate = !g1h->humongous_region_is_always_live(region_idx); + // Is_candidate already filters out humongous regions with some remembered set. + // This will not lead to humongous object that we mistakenly keep alive because + // during young collection the remembered sets will only be added to. + if (is_candidate) { + g1h->register_humongous_region_with_in_cset_fast_test(region_idx); + _candidate_humongous++; + } + _total_humongous++; + + return false; + } + + size_t total_humongous() const { return _total_humongous; } + size_t candidate_humongous() const { return _candidate_humongous; } +}; + +void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() { + if (!G1ReclaimDeadHumongousObjectsAtYoungGC) { + g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0); + return; + } + + RegisterHumongousWithInCSetFastTestClosure cl; + heap_region_iterate(&cl); + g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(), + cl.candidate_humongous()); + _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; + + if (_has_humongous_reclaim_candidates) { + clear_humongous_is_live_table(); + } +} + void G1CollectedHeap::setup_surviving_young_words() { assert(_surviving_young_words == NULL, "pre-condition"); @@ -4058,6 +4121,8 @@ g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info); + register_humongous_regions_with_in_cset_fast_test(); + _cm->note_start_of_gc(); // We should not verify the per-thread SATB buffers given that // we have not filtered them yet (we'll do so during the @@ -4108,6 +4173,9 @@ true /* verify_fingers */); free_collection_set(g1_policy()->collection_set(), evacuation_info); + + eagerly_reclaim_humongous_regions(); + g1_policy()->clear_collection_set(); cleanup_surviving_young_words(); @@ -4608,7 +4676,9 @@ assert(_worker_id == _par_scan_state->queue_num(), "sanity"); - if (_g1->in_cset_fast_test(obj)) { + G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj); + + if (state == G1CollectedHeap::InCSet) { oop forwardee; if (obj->is_forwarded()) { forwardee = obj->forwardee(); @@ -4627,6 +4697,9 @@ do_klass_barrier(p, forwardee); } } else { + if (state == G1CollectedHeap::IsHumongous) { + _g1->set_humongous_is_live(obj); + } // The object is not in collection set. If we're a root scanning // closure during an initial mark pause then attempt to mark the object. if (do_mark_object == G1MarkFromRoot) { @@ -4847,10 +4920,15 @@ if (_g1h->g1_policy()->during_initial_mark_pause()) { // We also need to mark copied objects. strong_root_cl = &scan_mark_root_cl; - weak_root_cl = &scan_mark_weak_root_cl; strong_cld_cl = &scan_mark_cld_cl; - weak_cld_cl = &scan_mark_weak_cld_cl; strong_code_cl = &scan_mark_code_cl; + if (ClassUnloadingWithConcurrentMark) { + weak_root_cl = &scan_mark_weak_root_cl; + weak_cld_cl = &scan_mark_weak_cld_cl; + } else { + weak_root_cl = &scan_mark_root_cl; + weak_cld_cl = &scan_mark_cld_cl; + } } else { strong_root_cl = &scan_only_root_cl; weak_root_cl = &scan_only_root_cl; @@ -4921,6 +4999,7 @@ double closure_app_time_sec = 0.0; bool during_im = _g1h->g1_policy()->during_initial_mark_pause(); + bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark; BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots); BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots); @@ -4930,8 +5009,8 @@ &buf_scan_non_heap_roots, &buf_scan_non_heap_weak_roots, scan_strong_clds, - // Initial Mark handles the weak CLDs separately. - (during_im ? NULL : scan_weak_clds), + // Unloading Initial Marks handle the weak CLDs separately. + (trace_metadata ? NULL : scan_weak_clds), scan_strong_code); // Now the CM ref_processor roots. @@ -4943,7 +5022,7 @@ ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots); } - if (during_im) { + if (trace_metadata) { // Barrier to make sure all workers passed // the strong CLD and strong nmethods phases. active_strong_roots_scope()->wait_until_all_workers_done_with_threads(n_par_threads()); @@ -5450,12 +5529,21 @@ public: G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } - void do_oop( oop* p) { + void do_oop(oop* p) { oop obj = *p; - if (_g1->obj_in_cs(obj)) { + G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj); + if (obj == NULL || cset_state == G1CollectedHeap::InNeither) { + return; + } + if (cset_state == G1CollectedHeap::InCSet) { assert( obj->is_forwarded(), "invariant" ); *p = obj->forwardee(); + } else { + assert(!obj->is_forwarded(), "invariant" ); + assert(cset_state == G1CollectedHeap::IsHumongous, + err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state)); + _g1->set_humongous_is_live(obj); } } }; @@ -5485,7 +5573,7 @@ template void do_oop_work(T* p) { oop obj = oopDesc::load_decode_heap_oop(p); - if (_g1h->obj_in_cs(obj)) { + if (_g1h->is_in_cset_or_humongous(obj)) { // If the referent object has been forwarded (either copied // to a new location or to itself in the event of an // evacuation failure) then we need to update the reference @@ -5510,10 +5598,10 @@ assert(!Metaspace::contains((const void*)p), err_msg("Unexpectedly found a pointer from metadata: " PTR_FORMAT, p)); - _copy_non_heap_obj_cl->do_oop(p); - } + _copy_non_heap_obj_cl->do_oop(p); } } + } }; // Serial drain queue closure. Called as the 'complete_gc' @@ -6435,6 +6523,154 @@ policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms); } +class G1FreeHumongousRegionClosure : public HeapRegionClosure { + private: + FreeRegionList* _free_region_list; + HeapRegionSet* _proxy_set; + HeapRegionSetCount _humongous_regions_removed; + size_t _freed_bytes; + public: + + G1FreeHumongousRegionClosure(FreeRegionList* free_region_list) : + _free_region_list(free_region_list), _humongous_regions_removed(), _freed_bytes(0) { + } + + virtual bool doHeapRegion(HeapRegion* r) { + if (!r->startsHumongous()) { + return false; + } + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + + oop obj = (oop)r->bottom(); + CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap(); + + // The following checks whether the humongous object is live are sufficient. + // The main additional check (in addition to having a reference from the roots + // or the young gen) is whether the humongous object has a remembered set entry. + // + // A humongous object cannot be live if there is no remembered set for it + // because: + // - there can be no references from within humongous starts regions referencing + // the object because we never allocate other objects into them. + // (I.e. there are no intra-region references that may be missed by the + // remembered set) + // - as soon there is a remembered set entry to the humongous starts region + // (i.e. it has "escaped" to an old object) this remembered set entry will stay + // until the end of a concurrent mark. + // + // It is not required to check whether the object has been found dead by marking + // or not, in fact it would prevent reclamation within a concurrent cycle, as + // all objects allocated during that time are considered live. + // SATB marking is even more conservative than the remembered set. + // So if at this point in the collection there is no remembered set entry, + // nobody has a reference to it. + // At the start of collection we flush all refinement logs, and remembered sets + // are completely up-to-date wrt to references to the humongous object. + // + // Other implementation considerations: + // - never consider object arrays: while they are a valid target, they have not + // been observed to be used as temporary objects. + // - they would also pose considerable effort for cleaning up the the remembered + // sets. + // While this cleanup is not strictly necessary to be done (or done instantly), + // given that their occurrence is very low, this saves us this additional + // complexity. + uint region_idx = r->hrs_index(); + if (g1h->humongous_is_live(region_idx) || + g1h->humongous_region_is_always_live(region_idx)) { + + if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { + gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", + r->isHumongous(), + region_idx, + r->rem_set()->occupied(), + r->rem_set()->strong_code_roots_list_length(), + next_bitmap->isMarked(r->bottom()), + g1h->humongous_is_live(region_idx), + obj->is_objArray() + ); + } + + return false; + } + + guarantee(!obj->is_objArray(), + err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.", + r->bottom())); + + if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { + gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", + r->isHumongous(), + r->bottom(), + region_idx, + r->region_num(), + r->rem_set()->occupied(), + r->rem_set()->strong_code_roots_list_length(), + next_bitmap->isMarked(r->bottom()), + g1h->humongous_is_live(region_idx), + obj->is_objArray() + ); + } + // Need to clear mark bit of the humongous object if already set. + if (next_bitmap->isMarked(r->bottom())) { + next_bitmap->clear(r->bottom()); + } + _freed_bytes += r->used(); + r->set_containing_set(NULL); + _humongous_regions_removed.increment(1u, r->capacity()); + g1h->free_humongous_region(r, _free_region_list, false); + + return false; + } + + HeapRegionSetCount& humongous_free_count() { + return _humongous_regions_removed; + } + + size_t bytes_freed() const { + return _freed_bytes; + } + + size_t humongous_reclaimed() const { + return _humongous_regions_removed.length(); + } +}; + +void G1CollectedHeap::eagerly_reclaim_humongous_regions() { + assert_at_safepoint(true); + + if (!G1ReclaimDeadHumongousObjectsAtYoungGC || !_has_humongous_reclaim_candidates) { + g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0); + return; + } + + double start_time = os::elapsedTime(); + + FreeRegionList local_cleanup_list("Local Humongous Cleanup List"); + + G1FreeHumongousRegionClosure cl(&local_cleanup_list); + heap_region_iterate(&cl); + + HeapRegionSetCount empty_set; + remove_from_old_sets(empty_set, cl.humongous_free_count()); + + G1HRPrinter* hr_printer = _g1h->hr_printer(); + if (hr_printer->is_active()) { + FreeRegionListIterator iter(&local_cleanup_list); + while (iter.more_available()) { + HeapRegion* hr = iter.get_next(); + hr_printer->cleanup(hr); + } + } + + prepend_to_freelist(&local_cleanup_list); + decrement_summary_bytes(cl.bytes_freed()); + + g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms((os::elapsedTime() - start_time) * 1000.0, + cl.humongous_reclaimed()); +} + // This routine is similar to the above but does not record // any policy statistics or update free lists; we are abandoning // the current incremental collection set in preparation of a diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -197,16 +197,6 @@ bool do_object_b(oop p); }; -// Instances of this class are used for quick tests on whether a reference points -// into the collection set. Each of the array's elements denotes whether the -// corresponding region is in the collection set. -class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray { - protected: - bool default_value() const { return false; } - public: - void clear() { G1BiasedMappedArray::clear(); } -}; - class RefineCardTableEntryClosure; class G1CollectedHeap : public SharedHeap { @@ -237,6 +227,7 @@ friend class EvacPopObjClosure; friend class G1ParCleanupCTTask; + friend class G1FreeHumongousRegionClosure; // Other related classes. friend class G1MarkSweep; @@ -267,6 +258,9 @@ // It keeps track of the humongous regions. HeapRegionSet _humongous_set; + void clear_humongous_is_live_table(); + void eagerly_reclaim_humongous_regions(); + // The number of regions we could create by expansion. uint _expansion_regions; @@ -367,10 +361,25 @@ // than the current allocation region. size_t _summary_bytes_used; - // This array is used for a quick test on whether a reference points into - // the collection set or not. Each of the array's elements denotes whether the - // corresponding region is in the collection set or not. - G1FastCSetBiasedMappedArray _in_cset_fast_test; + // Records whether the region at the given index is kept live by roots or + // references from the young generation. + class HumongousIsLiveBiasedMappedArray : public G1BiasedMappedArray { + protected: + bool default_value() const { return false; } + public: + void clear() { G1BiasedMappedArray::clear(); } + void set_live(uint region) { + set_by_index(region, true); + } + bool is_live(uint region) { + return get_by_index(region); + } + }; + + HumongousIsLiveBiasedMappedArray _humongous_is_live; + // Stores whether during humongous object registration we found candidate regions. + // If not, we can skip a few steps. + bool _has_humongous_reclaim_candidates; volatile unsigned _gc_time_stamp; @@ -690,10 +699,24 @@ virtual void gc_prologue(bool full); virtual void gc_epilogue(bool full); + inline void set_humongous_is_live(oop obj); + + bool humongous_is_live(uint region) { + return _humongous_is_live.is_live(region); + } + + // Returns whether the given region (which must be a humongous (start) region) + // is to be considered conservatively live regardless of any other conditions. + bool humongous_region_is_always_live(uint index); + // Register the given region to be part of the collection set. + inline void register_humongous_region_with_in_cset_fast_test(uint index); + // Register regions with humongous objects (actually on the start region) in + // the in_cset_fast_test table. + void register_humongous_regions_with_in_cset_fast_test(); // We register a region with the fast "in collection set" test. We // simply set to true the array slot corresponding to this region. void register_region_with_in_cset_fast_test(HeapRegion* r) { - _in_cset_fast_test.set_by_index(r->hrs_index(), true); + _in_cset_fast_test.set_in_cset(r->hrs_index()); } // This is a fast test on whether a reference points into the @@ -1283,9 +1306,61 @@ virtual bool is_in(const void* p) const; // Return "TRUE" iff the given object address is within the collection - // set. + // set. Slow implementation. inline bool obj_in_cs(oop obj); + inline bool is_in_cset(oop obj); + + inline bool is_in_cset_or_humongous(const oop obj); + + enum in_cset_state_t { + InNeither, // neither in collection set nor humongous + InCSet, // region is in collection set only + IsHumongous // region is a humongous start region + }; + private: + // Instances of this class are used for quick tests on whether a reference points + // into the collection set or is a humongous object (points into a humongous + // object). + // Each of the array's elements denotes whether the corresponding region is in + // the collection set or a humongous region. + // We use this to quickly reclaim humongous objects: by making a humongous region + // succeed this test, we sort-of add it to the collection set. During the reference + // iteration closures, when we see a humongous region, we simply mark it as + // referenced, i.e. live. + class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray { + protected: + char default_value() const { return G1CollectedHeap::InNeither; } + public: + void set_humongous(uintptr_t index) { + assert(get_by_index(index) != InCSet, "Should not overwrite InCSet values"); + set_by_index(index, G1CollectedHeap::IsHumongous); + } + + void clear_humongous(uintptr_t index) { + set_by_index(index, G1CollectedHeap::InNeither); + } + + void set_in_cset(uintptr_t index) { + assert(get_by_index(index) != G1CollectedHeap::IsHumongous, "Should not overwrite IsHumongous value"); + set_by_index(index, G1CollectedHeap::InCSet); + } + + bool is_in_cset_or_humongous(HeapWord* addr) const { return get_by_address(addr) != G1CollectedHeap::InNeither; } + bool is_in_cset(HeapWord* addr) const { return get_by_address(addr) == G1CollectedHeap::InCSet; } + G1CollectedHeap::in_cset_state_t at(HeapWord* addr) const { return (G1CollectedHeap::in_cset_state_t)get_by_address(addr); } + void clear() { G1BiasedMappedArray::clear(); } + }; + + // This array is used for a quick test on whether a reference points into + // the collection set or not. Each of the array's elements denotes whether the + // corresponding region is in the collection set or not. + G1FastCSetBiasedMappedArray _in_cset_fast_test; + + public: + + inline in_cset_state_t in_cset_state(const oop obj); + // Return "TRUE" iff the given object address is in the reserved // region of g1. bool is_in_g1_reserved(const void* p) const { @@ -1340,6 +1415,10 @@ // Return the region with the given index. It assumes the index is valid. inline HeapRegion* region_at(uint index) const; + // Calculate the region index of the given address. Given address must be + // within the heap. + inline uint addr_to_region(HeapWord* addr) const; + // Divide the heap region sequence into "chunks" of some size (the number // of regions divided by the number of parallel threads times some // overpartition factor, currently 4). Assumes that this will be called diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -40,6 +40,13 @@ // Return the region with the given index. It assumes the index is valid. inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrs.at(index); } +inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const { + assert(is_in_reserved(addr), + err_msg("Cannot calculate region index for address "PTR_FORMAT" that is outside of the heap ["PTR_FORMAT", "PTR_FORMAT")", + p2i(addr), p2i(_reserved.start()), p2i(_reserved.end()))); + return (uint)(pointer_delta(addr, _reserved.start(), sizeof(uint8_t)) >> HeapRegion::LogOfHRGrainBytes); +} + template inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const { @@ -172,12 +179,11 @@ return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj); } - // This is a fast test on whether a reference points into the // collection set or not. Assume that the reference // points into the heap. -inline bool G1CollectedHeap::in_cset_fast_test(oop obj) { - bool ret = _in_cset_fast_test.get_by_address((HeapWord*)obj); +inline bool G1CollectedHeap::is_in_cset(oop obj) { + bool ret = _in_cset_fast_test.is_in_cset((HeapWord*)obj); // let's make sure the result is consistent with what the slower // test returns assert( ret || !obj_in_cs(obj), "sanity"); @@ -185,6 +191,18 @@ return ret; } +bool G1CollectedHeap::is_in_cset_or_humongous(const oop obj) { + return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj); +} + +G1CollectedHeap::in_cset_state_t G1CollectedHeap::in_cset_state(const oop obj) { + return _in_cset_fast_test.at((HeapWord*)obj); +} + +void G1CollectedHeap::register_humongous_region_with_in_cset_fast_test(uint index) { + _in_cset_fast_test.set_humongous(index); +} + #ifndef PRODUCT // Support for G1EvacuationFailureALot @@ -288,4 +306,22 @@ return is_obj_ill(obj, heap_region_containing(obj)); } +inline void G1CollectedHeap::set_humongous_is_live(oop obj) { + uint region = addr_to_region((HeapWord*)obj); + // We not only set the "live" flag in the humongous_is_live table, but also + // reset the entry in the _in_cset_fast_test table so that subsequent references + // to the same humongous object do not go into the slow path again. + // This is racy, as multiple threads may at the same time enter here, but this + // is benign. + // During collection we only ever set the "live" flag, and only ever clear the + // entry in the in_cset_fast_table. + // We only ever evaluate the contents of these tables (in the VM thread) after + // having synchronized the worker threads with the VM thread, or in the same + // thread (i.e. within the VM thread). + if (!_humongous_is_live.is_live(region)) { + _humongous_is_live.set_live(region); + _in_cset_fast_test.clear_humongous(region); + } +} + #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -255,6 +255,10 @@ LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value); } +void G1GCPhaseTimes::print_stats(int level, const char* str, size_t value) { + LineBuffer(level).append_and_print_cr("[%s: "SIZE_FORMAT"]", str, value); +} + void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) { LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: %u]", str, value, workers); } @@ -357,6 +361,14 @@ _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards"); } } + if (G1ReclaimDeadHumongousObjectsAtYoungGC) { + print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); + if (G1Log::finest()) { + print_stats(3, "Humongous Total", _cur_fast_reclaim_humongous_total); + print_stats(3, "Humongous Candidate", _cur_fast_reclaim_humongous_candidates); + print_stats(3, "Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); + } + } print_stats(2, "Free CSet", (_recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms)); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -157,11 +157,17 @@ double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; + double _cur_fast_reclaim_humongous_time_ms; + size_t _cur_fast_reclaim_humongous_total; + size_t _cur_fast_reclaim_humongous_candidates; + size_t _cur_fast_reclaim_humongous_reclaimed; + double _cur_verify_before_time_ms; double _cur_verify_after_time_ms; // Helper methods for detailed logging void print_stats(int level, const char* str, double value); + void print_stats(int level, const char* str, size_t value); void print_stats(int level, const char* str, double value, uint workers); public: @@ -282,6 +288,16 @@ _recorded_non_young_free_cset_time_ms = time_ms; } + void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) { + _cur_fast_reclaim_humongous_total = total; + _cur_fast_reclaim_humongous_candidates = candidates; + } + + void record_fast_reclaim_humongous_time_ms(double value, size_t reclaimed) { + _cur_fast_reclaim_humongous_time_ms = value; + _cur_fast_reclaim_humongous_reclaimed = reclaimed; + } + void record_young_cset_choice_time_ms(double time_ms) { _recorded_young_cset_choice_time_ms = time_ms; } @@ -348,6 +364,10 @@ return _recorded_non_young_free_cset_time_ms; } + double fast_reclaim_humongous_time_ms() { + return _cur_fast_reclaim_humongous_time_ms; + } + double average_last_update_rs_time() { return _last_update_rs_times_ms.average(); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -44,7 +44,7 @@ inline void FilterIntoCSClosure::do_oop_nv(T* p) { T heap_oop = oopDesc::load_heap_oop(p); if (!oopDesc::is_null(heap_oop) && - _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) { + _g1->is_in_cset_or_humongous(oopDesc::decode_heap_oop_not_null(heap_oop))) { _oc->do_oop(p); } } @@ -67,7 +67,8 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if (_g1->in_cset_fast_test(obj)) { + G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj); + if (state == G1CollectedHeap::InCSet) { // We're not going to even bother checking whether the object is // already forwarded or not, as this usually causes an immediate // stall. We'll try to prefetch the object (for write, given that @@ -86,6 +87,9 @@ _par_scan_state->push_on_queue(p); } else { + if (state == G1CollectedHeap::IsHumongous) { + _g1->set_humongous_is_live(obj); + } _par_scan_state->update_rs(_from, p, _worker_id); } } @@ -97,12 +101,14 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - if (_g1->in_cset_fast_test(obj)) { + if (_g1->is_in_cset_or_humongous(obj)) { Prefetch::write(obj->mark_addr(), 0); Prefetch::read(obj->mark_addr(), (HeapWordSize*2)); // Place on the references queue _par_scan_state->push_on_queue(p); + } else { + assert(!_g1->obj_in_cs(obj), "checking"); } } } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -288,7 +288,12 @@ } HeapWord* G1ParScanThreadState::allocate(GCAllocPurpose purpose, size_t word_sz) { - HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz); + HeapWord* obj = NULL; + if (purpose == GCAllocForSurvived) { + obj = alloc_buffer(GCAllocForSurvived)->allocate_aligned(word_sz, SurvivorAlignmentInBytes); + } else { + obj = alloc_buffer(GCAllocForTenured)->allocate(word_sz); + } if (obj != NULL) { return obj; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -52,15 +52,20 @@ // set, due to (benign) races in the claim mechanism during RSet scanning more // than one thread might claim the same card. So the same card may be // processed multiple times. So redo this check. - if (_g1h->in_cset_fast_test(obj)) { + G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj); + if (in_cset_state == G1CollectedHeap::InCSet) { oop forwardee; if (obj->is_forwarded()) { forwardee = obj->forwardee(); } else { forwardee = copy_to_survivor_space(obj); } - assert(forwardee != NULL, "forwardee should not be NULL"); oopDesc::encode_store_heap_oop(p, forwardee); + } else if (in_cset_state == G1CollectedHeap::IsHumongous) { + _g1h->set_humongous_is_live(obj); + } else { + assert(in_cset_state == G1CollectedHeap::InNeither, + err_msg("In_cset_state must be InNeither here, but is %d", in_cset_state)); } assert(obj != NULL, "Must be"); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -349,23 +349,8 @@ assert((ParallelGCThreads > 0) || worker_i == 0, "invariant"); - // The two flags below were introduced temporarily to serialize - // the updating and scanning of remembered sets. There are some - // race conditions when these two operations are done in parallel - // and they are causing failures. When we resolve said race - // conditions, we'll revert back to parallel remembered set - // updating and scanning. See CRs 6677707 and 6677708. - if (G1UseParallelRSetUpdating || (worker_i == 0)) { - updateRS(&into_cset_dcq, worker_i); - } else { - _g1p->phase_times()->record_update_rs_processed_buffers(worker_i, 0); - _g1p->phase_times()->record_update_rs_time(worker_i, 0.0); - } - if (G1UseParallelRSetScanning || (worker_i == 0)) { - scanRS(oc, code_root_cl, worker_i); - } else { - _g1p->phase_times()->record_scan_rs_time(worker_i, 0.0); - } + updateRS(&into_cset_dcq, worker_i); + scanRS(oc, code_root_cl, worker_i); // We now clear the cached values of _cset_rs_update_cl for this worker _cset_rs_update_cl[worker_i] = NULL; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -220,14 +220,6 @@ product(uintx, G1HeapRegionSize, 0, \ "Size of the G1 regions.") \ \ - experimental(bool, G1UseParallelRSetUpdating, true, \ - "Enables the parallelization of remembered set updating " \ - "during evacuation pauses") \ - \ - experimental(bool, G1UseParallelRSetScanning, true, \ - "Enables the parallelization of remembered set scanning " \ - "during evacuation pauses") \ - \ product(uintx, G1ConcRefinementThreads, 0, \ "If non-0 is the number of parallel rem set update threads, " \ "otherwise the value is determined ergonomically.") \ @@ -289,6 +281,13 @@ "The amount of code root chunks that should be kept at most " \ "as percentage of already allocated.") \ \ + experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true, \ + "Try to reclaim dead large objects at every young GC.") \ + \ + experimental(bool, G1TraceReclaimDeadHumongousObjectsAtYoungGC, false, \ + "Print some information about large object liveness " \ + "at every young GC.") \ + \ experimental(uintx, G1OldCSetRegionThresholdPercent, 10, \ "An upper bound for the number of old CSet regions expressed " \ "as a percentage of the heap size.") \ diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -94,26 +94,37 @@ inline bool HeapRegion::block_is_obj(const HeapWord* p) const { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - return !g1h->is_obj_dead(oop(p), this); + if (ClassUnloadingWithConcurrentMark) { + return !g1h->is_obj_dead(oop(p), this); + } + return p < top(); } inline size_t HeapRegion::block_size(const HeapWord *addr) const { + if (addr == top()) { + return pointer_delta(end(), addr); + } + + if (block_is_obj(addr)) { + return oop(addr)->size(); + } + + assert(ClassUnloadingWithConcurrentMark, + err_msg("All blocks should be objects if G1 Class Unloading isn't used. " + "HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") " + "addr: " PTR_FORMAT, + p2i(bottom()), p2i(top()), p2i(end()), p2i(addr))); + // Old regions' dead objects may have dead classes // We need to find the next live object in some other // manner than getting the oop size G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (g1h->is_obj_dead(oop(addr), this)) { - HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()-> - getNextMarkedWordAddress(addr, prev_top_at_mark_start()); - - assert(next > addr, "must get the next live object"); + HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()-> + getNextMarkedWordAddress(addr, prev_top_at_mark_start()); - return pointer_delta(next, addr); - } else if (addr == top()) { - return pointer_delta(end(), addr); - } - return oop(addr)->size(); + assert(next > addr, "must get the next live object"); + return pointer_delta(next, addr); } inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t word_size) { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -695,6 +695,9 @@ clear_fcc(); } +bool OtherRegionsTable::is_empty() const { + return occ_sparse() == 0 && occ_coarse() == 0 && _first_all_fine_prts == NULL; +} size_t OtherRegionsTable::occupied() const { size_t sum = occ_fine(); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -185,6 +185,9 @@ // objects. void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); + // Returns whether this remembered set (and all sub-sets) contain no entries. + bool is_empty() const; + size_t occupied() const; size_t occ_fine() const; size_t occ_coarse() const; @@ -269,6 +272,10 @@ return _other_regions.hr(); } + bool is_empty() const { + return (strong_code_roots_list_length() == 0) && _other_regions.is_empty(); + } + size_t occupied() { MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); return occupied_locked(); @@ -371,7 +378,7 @@ void strong_code_roots_do(CodeBlobClosure* blk) const; // Returns the number of elements in the strong code roots list - size_t strong_code_roots_list_length() { + size_t strong_code_roots_list_length() const { return _code_roots.length(); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -28,12 +28,12 @@ #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/ageTable.hpp" -#include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "gc_implementation/shared/gcHeapSummary.hpp" #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcTraceTime.hpp" -#include "gc_implementation/shared/copyFailedInfo.hpp" +#include "gc_implementation/shared/parGCAllocBuffer.inline.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/defNewGeneration.inline.hpp" #include "memory/genCollectedHeap.hpp" @@ -252,7 +252,7 @@ plab->set_word_size(buf_size); plab->set_buf(buf_space); record_survivor_plab(buf_space, buf_size); - obj = plab->allocate(word_sz); + obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes); // Note that we cannot compare buf_size < word_sz below // because of AlignmentReserve (see ParGCAllocBuffer::allocate()). assert(obj != NULL || plab->words_remaining() < word_sz, diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp --- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -168,7 +168,7 @@ HeapWord* alloc_in_to_space_slow(size_t word_sz); HeapWord* alloc_in_to_space(size_t word_sz) { - HeapWord* obj = to_space_alloc_buffer()->allocate(word_sz); + HeapWord* obj = to_space_alloc_buffer()->allocate_aligned(word_sz, SurvivorAlignmentInBytes); if (obj != NULL) return obj; else return alloc_in_to_space_slow(word_sz); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_HPP #include "gc_implementation/parallelScavenge/objectStartArray.hpp" +#include "gc_interface/collectedHeap.inline.hpp" #include "memory/allocation.hpp" // @@ -94,23 +95,9 @@ PSYoungPromotionLAB() { } // Not MT safe - HeapWord* allocate(size_t size) { - // Can't assert this, when young fills, we keep the LAB around, but flushed. - // assert(_state != flushed, "Sanity"); - HeapWord* obj = top(); - HeapWord* new_top = obj + size; - // The 'new_top>obj' check is needed to detect overflow of obj+size. - if (new_top > obj && new_top <= end()) { - set_top(new_top); - assert(is_object_aligned((intptr_t)obj) && is_object_aligned((intptr_t)new_top), - "checking alignment"); - return obj; - } + inline HeapWord* allocate(size_t size); - return NULL; - } - - debug_only(virtual bool lab_is_valid(MemRegion lab)); + debug_only(virtual bool lab_is_valid(MemRegion lab);) }; class PSOldPromotionLAB : public PSPromotionLAB { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP + +#include "gc_implementation/parallelScavenge/psPromotionLAB.hpp" +#include "gc_interface/collectedHeap.inline.hpp" + +HeapWord* PSYoungPromotionLAB::allocate(size_t size) { + // Can't assert this, when young fills, we keep the LAB around, but flushed. + // assert(_state != flushed, "Sanity"); + HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end(), SurvivorAlignmentInBytes); + if (obj == NULL) { + return NULL; + } + + HeapWord* new_top = obj + size; + // The 'new_top>obj' check is needed to detect overflow of obj+size. + if (new_top > obj && new_top <= end()) { + set_top(new_top); + assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_object_aligned((intptr_t)new_top), + "checking alignment"); + return obj; + } else { + set_top(obj); + return NULL; + } +} + +#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -27,6 +27,7 @@ #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" +#include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "oops/oop.psgc.inline.hpp" diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp --- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -24,7 +24,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP - +#include "gc_interface/collectedHeap.hpp" #include "memory/allocation.hpp" #include "memory/blockOffsetTable.hpp" #include "memory/threadLocalAllocBuffer.hpp" @@ -84,6 +84,9 @@ } } + // Allocate the object aligned to "alignment_in_bytes". + HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes); + // Undo the last allocation in the buffer, which is required to be of the // "obj" of the given "word_sz". void undo_allocation(HeapWord* obj, size_t word_sz) { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP + +#include "gc_implementation/shared/parGCAllocBuffer.hpp" +#include "gc_interface/collectedHeap.inline.hpp" + +HeapWord* ParGCAllocBuffer::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) { + + HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes); + if (res == NULL) { + return NULL; + } + + // Set _top so that allocate(), which expects _top to be correctly set, + // can be used below. + _top = res; + return allocate(word_sz); +} + +#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -195,6 +195,7 @@ gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level); } +// Returns true iff concurrent GCs unloads metadata. bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() { #if INCLUDE_ALL_GCS if (UseConcMarkSweepGC && CMSClassUnloadingEnabled) { @@ -202,7 +203,7 @@ return true; } - if (UseG1GC) { + if (UseG1GC && ClassUnloadingWithConcurrentMark) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); g1h->g1_policy()->set_initiate_conc_mark_if_possible(); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_interface/collectedHeap.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -351,6 +351,12 @@ fill_with_object(start, pointer_delta(end, start), zap); } + // Return the address "addr" aligned by "alignment_in_bytes" if such + // an address is below "end". Return NULL otherwise. + inline static HeapWord* align_allocation_or_fail(HeapWord* addr, + HeapWord* end, + unsigned short alignment_in_bytes); + // Some heaps may offer a contiguous region for shared non-blocking // allocation, via inlined code (by exporting the address of the top and // end fields defining the extent of the contiguous allocation region.) diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -241,6 +241,44 @@ oop_iterate(&no_header_cl); } + +inline HeapWord* CollectedHeap::align_allocation_or_fail(HeapWord* addr, + HeapWord* end, + unsigned short alignment_in_bytes) { + if (alignment_in_bytes <= ObjectAlignmentInBytes) { + return addr; + } + + assert(is_ptr_aligned(addr, HeapWordSize), + err_msg("Address " PTR_FORMAT " is not properly aligned.", p2i(addr))); + assert(is_size_aligned(alignment_in_bytes, HeapWordSize), + err_msg("Alignment size %u is incorrect.", alignment_in_bytes)); + + HeapWord* new_addr = (HeapWord*) align_pointer_up(addr, alignment_in_bytes); + size_t padding = pointer_delta(new_addr, addr); + + if (padding == 0) { + return addr; + } + + if (padding < CollectedHeap::min_fill_size()) { + padding += alignment_in_bytes / HeapWordSize; + assert(padding >= CollectedHeap::min_fill_size(), + err_msg("alignment_in_bytes %u is expect to be larger " + "than the minimum object size", alignment_in_bytes)); + new_addr = addr + padding; + } + + assert(new_addr > addr, err_msg("Unexpected arithmetic overflow " + PTR_FORMAT " not greater than " PTR_FORMAT, p2i(new_addr), p2i(addr))); + if(new_addr < end) { + CollectedHeap::fill_with_object(addr, padding); + return new_addr; + } else { + return NULL; + } +} + #ifndef PRODUCT inline bool diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -987,17 +987,6 @@ int index = cp_entry->field_index(); if ((ik->field_access_flags(index) & JVM_ACC_FIELD_ACCESS_WATCHED) == 0) return; - switch(cp_entry->flag_state()) { - case btos: // fall through - case ctos: // fall through - case stos: // fall through - case itos: // fall through - case ftos: // fall through - case ltos: // fall through - case dtos: // fall through - case atos: break; - default: ShouldNotReachHere(); return; - } bool is_static = (obj == NULL); HandleMark hm(thread); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/memory/defNewGeneration.cpp --- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -790,7 +790,7 @@ // Try allocating obj in to-space (unless too old) if (old->age() < tenuring_threshold()) { - obj = (oop) to()->allocate(s); + obj = (oop) to()->allocate_aligned(s); } // Otherwise try allocating obj tenured diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/memory/sharedHeap.cpp --- a/hotspot/src/share/vm/memory/sharedHeap.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -159,9 +159,9 @@ Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false); void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers) { - // The Thread work barrier is only needed by G1. + // The Thread work barrier is only needed by G1 Class Unloading. // No need to use the barrier if this is single-threaded code. - if (UseG1GC && n_workers > 0) { + if (UseG1GC && ClassUnloadingWithConcurrentMark && n_workers > 0) { uint new_value = (uint)Atomic::add(1, &_n_workers_done_with_threads); if (new_value == n_workers) { // This thread is last. Notify the others. @@ -172,6 +172,9 @@ } void SharedHeap::StrongRootsScope::wait_until_all_workers_done_with_threads(uint n_workers) { + assert(UseG1GC, "Currently only used by G1"); + assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading"); + // No need to use the barrier if this is single-threaded code. if (n_workers > 0 && (uint)_n_workers_done_with_threads != n_workers) { MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/memory/space.cpp --- a/hotspot/src/share/vm/memory/space.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/memory/space.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -28,6 +28,7 @@ #include "gc_implementation/shared/liveRange.hpp" #include "gc_implementation/shared/markSweep.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" +#include "gc_interface/collectedHeap.inline.hpp" #include "memory/blockOffsetTable.inline.hpp" #include "memory/defNewGeneration.hpp" #include "memory/genCollectedHeap.hpp" @@ -720,6 +721,27 @@ } while (true); } +HeapWord* ContiguousSpace::allocate_aligned(size_t size) { + assert(Heap_lock->owned_by_self() || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()), "not locked"); + HeapWord* end_value = end(); + + HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end_value, SurvivorAlignmentInBytes); + if (obj == NULL) { + return NULL; + } + + if (pointer_delta(end_value, obj) >= size) { + HeapWord* new_top = obj + size; + set_top(new_top); + assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_aligned(new_top), + "checking alignment"); + return obj; + } else { + set_top(obj); + return NULL; + } +} + // Requires locking. HeapWord* ContiguousSpace::allocate(size_t size) { return allocate_impl(size, end()); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/memory/space.hpp --- a/hotspot/src/share/vm/memory/space.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/memory/space.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -526,6 +526,7 @@ // Allocation (return NULL if full) virtual HeapWord* allocate(size_t word_size); virtual HeapWord* par_allocate(size_t word_size); + HeapWord* allocate_aligned(size_t word_size); // Iteration void oop_iterate(ExtendedOopClosure* cl); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/oops/method.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -283,6 +283,13 @@ return bcp; } +address Method::bcp_from(address bcp) const { + if (is_native() && bcp == NULL) { + return code_base(); + } else { + return bcp; + } +} int Method::size(bool is_native) { // If native, then include pointers for native_function and signature_handler diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/oops/method.hpp --- a/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/oops/method.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -648,7 +648,8 @@ // Returns the byte code index from the byte code pointer int bci_from(address bcp) const; - address bcp_from(int bci) const; + address bcp_from(int bci) const; + address bcp_from(address bcp) const; int validate_bci_from_bcp(address bcp) const; int validate_bci(int bci) const; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/oops/oop.pcgc.inline.hpp --- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -55,8 +55,6 @@ klass()->oop_follow_contents(cm, this); } -// Used by parallel old GC. - inline oop oopDesc::forward_to_atomic(oop p) { assert(ParNewGeneration::is_legal_forward_ptr(p), "illegal forwarding pointer value."); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/callGenerator.cpp --- a/hotspot/src/share/vm/opto/callGenerator.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/callGenerator.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, 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 @@ -357,7 +357,7 @@ // Make sure the state is a MergeMem for parsing. if (!map->in(TypeFunc::Memory)->is_MergeMem()) { - Node* mem = MergeMemNode::make(C, map->in(TypeFunc::Memory)); + Node* mem = MergeMemNode::make(map->in(TypeFunc::Memory)); C->initial_gvn()->set_type_bottom(mem); map->set_req(TypeFunc::Memory, mem); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/callnode.cpp --- a/hotspot/src/share/vm/opto/callnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/callnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -688,7 +688,7 @@ return new MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); case TypeFunc::Parms+1: // For LONG & DOUBLE returns - assert(tf()->_range->field_at(TypeFunc::Parms+1) == Type::HALF, ""); + assert(tf()->range()->field_at(TypeFunc::Parms+1) == Type::HALF, ""); // 2nd half of doubles and longs return new MachProjNode(this,proj->_con, RegMask::Empty, (uint)OptoReg::Bad); @@ -778,7 +778,7 @@ } // Returns the unique CheckCastPP of a call -// or 'this' if there are several CheckCastPP +// or 'this' if there are several CheckCastPP or unexpected uses // or returns NULL if there is no one. Node *CallNode::result_cast() { Node *cast = NULL; @@ -794,6 +794,13 @@ return this; // more than 1 CheckCastPP } cast = use; + } else if (!use->is_Initialize() && + !use->is_AddP()) { + // Expected uses are restricted to a CheckCastPP, an Initialize + // node, and AddP nodes. If we encounter any other use (a Phi + // node can be seen in rare cases) return this to prevent + // incorrect optimizations. + return this; } } return cast; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/cfgnode.cpp --- a/hotspot/src/share/vm/opto/cfgnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/cfgnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -108,6 +108,7 @@ rreq++; // One more input to Region } // Found a region to merge into Region + igvn->_worklist.push(r); // Clobber pointer to the now dead 'r' region->set_req(i, phase->C->top()); } @@ -449,6 +450,7 @@ // Remove TOP or NULL input paths. If only 1 input path remains, this Region // degrades to a copy. bool add_to_worklist = false; + bool modified = false; int cnt = 0; // Count of values merging DEBUG_ONLY( int cnt_orig = req(); ) // Save original inputs count int del_it = 0; // The last input path we delete @@ -459,6 +461,7 @@ // Remove useless control copy inputs if( n->is_Region() && n->as_Region()->is_copy() ) { set_req(i, n->nonnull_req()); + modified = true; i--; continue; } @@ -466,12 +469,14 @@ Node *call = n->in(0); if (call->is_Call() && call->as_Call()->entry_point() == OptoRuntime::rethrow_stub()) { set_req(i, call->in(0)); + modified = true; i--; continue; } } if( phase->type(n) == Type::TOP ) { set_req(i, NULL); // Ignore TOP inputs + modified = true; i--; continue; } @@ -691,7 +696,7 @@ } } - return NULL; + return modified ? this : NULL; } @@ -1871,7 +1876,7 @@ igvn->register_new_node_with_optimizer(new_base); hook->add_req(new_base); } - MergeMemNode* result = MergeMemNode::make(phase->C, new_base); + MergeMemNode* result = MergeMemNode::make(new_base); for (uint i = 1; i < req(); ++i) { Node *ii = in(i); if (ii->is_MergeMem()) { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/chaitin.cpp --- a/hotspot/src/share/vm/opto/chaitin.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/chaitin.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1620,7 +1620,7 @@ C->check_node_count(0, "out of nodes fixing spills"); if (C->failing()) return; // Transform node - MachNode *cisc = mach->cisc_version(stk_offset, C)->as_Mach(); + MachNode *cisc = mach->cisc_version(stk_offset)->as_Mach(); cisc->set_req(inp,fp); // Base register is frame pointer if( cisc->oper_input_base() > 1 && mach->oper_input_base() <= 1 ) { assert( cisc->oper_input_base() == 2, "Only adding one edge"); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/compile.cpp --- a/hotspot/src/share/vm/opto/compile.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/compile.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1039,6 +1039,7 @@ _node_note_array = NULL; _default_node_notes = NULL; + DEBUG_ONLY( _modified_nodes = NULL; ) // Used in Optimize() _immutable_memory = NULL; // filled in at first inquiry @@ -1247,6 +1248,18 @@ } } } +void Compile::record_modified_node(Node* n) { + if (_modified_nodes != NULL && !_inlining_incrementally && + n->outcnt() != 0 && !n->is_Con()) { + _modified_nodes->push(n); + } +} + +void Compile::remove_modified_node(Node* n) { + if (_modified_nodes != NULL) { + _modified_nodes->remove(n); + } +} #endif #ifndef PRODUCT @@ -2035,6 +2048,9 @@ // Iterative Global Value Numbering, including ideal transforms // Initialize IterGVN with types and values from parse-time GVN PhaseIterGVN igvn(initial_gvn()); +#ifdef ASSERT + _modified_nodes = new (comp_arena()) Unique_Node_List(comp_arena()); +#endif { NOT_PRODUCT( TracePhase t2("iterGVN", &_t_iterGVN, TimeCompiler); ) igvn.optimize(); @@ -2197,6 +2213,7 @@ } } + DEBUG_ONLY( _modified_nodes = NULL; ) } // (End scope of igvn; run destructor if necessary for asserts.) process_print_inlining(); @@ -2825,7 +2842,7 @@ // oops implicit null check is not generated. // This will allow to generate normal oop implicit null check. if (Matcher::gen_narrow_oop_implicit_null_checks()) - new_in2 = ConNode::make(this, TypeNarrowOop::NULL_PTR); + new_in2 = ConNode::make(TypeNarrowOop::NULL_PTR); // // This transformation together with CastPP transformation above // will generated code for implicit NULL checks for compressed oops. @@ -2864,9 +2881,9 @@ // NullCheck base_reg // } else if (t->isa_oopptr()) { - new_in2 = ConNode::make(this, t->make_narrowoop()); + new_in2 = ConNode::make(t->make_narrowoop()); } else if (t->isa_klassptr()) { - new_in2 = ConNode::make(this, t->make_narrowklass()); + new_in2 = ConNode::make(t->make_narrowklass()); } } if (new_in2 != NULL) { @@ -2899,11 +2916,11 @@ const Type* t = in1->bottom_type(); if (t == TypePtr::NULL_PTR) { assert(t->isa_oopptr(), "null klass?"); - n->subsume_by(ConNode::make(this, TypeNarrowOop::NULL_PTR), this); + n->subsume_by(ConNode::make(TypeNarrowOop::NULL_PTR), this); } else if (t->isa_oopptr()) { - n->subsume_by(ConNode::make(this, t->make_narrowoop()), this); + n->subsume_by(ConNode::make(t->make_narrowoop()), this); } else if (t->isa_klassptr()) { - n->subsume_by(ConNode::make(this, t->make_narrowklass()), this); + n->subsume_by(ConNode::make(t->make_narrowklass()), this); } } if (in1->outcnt() == 0) { @@ -2964,7 +2981,7 @@ if (d) { // Replace them with a fused divmod if supported if (Matcher::has_match_rule(Op_DivModI)) { - DivModINode* divmod = DivModINode::make(this, n); + DivModINode* divmod = DivModINode::make(n); d->subsume_by(divmod->div_proj(), this); n->subsume_by(divmod->mod_proj(), this); } else { @@ -2984,7 +3001,7 @@ if (d) { // Replace them with a fused divmod if supported if (Matcher::has_match_rule(Op_DivModL)) { - DivModLNode* divmod = DivModLNode::make(this, n); + DivModLNode* divmod = DivModLNode::make(n); d->subsume_by(divmod->div_proj(), this); n->subsume_by(divmod->mod_proj(), this); } else { @@ -3010,7 +3027,7 @@ if (n->req()-1 > 2) { // Replace many operand PackNodes with a binary tree for matching PackNode* p = (PackNode*) n; - Node* btp = p->binary_tree_pack(this, 1, n->req()); + Node* btp = p->binary_tree_pack(1, n->req()); n->subsume_by(btp, this); } break; @@ -3035,11 +3052,11 @@ if (t != NULL && t->is_con()) { juint shift = t->get_con(); if (shift > mask) { // Unsigned cmp - n->set_req(2, ConNode::make(this, TypeInt::make(shift & mask))); + n->set_req(2, ConNode::make(TypeInt::make(shift & mask))); } } else { if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { - Node* shift = new AndINode(in2, ConNode::make(this, TypeInt::make(mask))); + Node* shift = new AndINode(in2, ConNode::make(TypeInt::make(mask))); n->set_req(2, shift); } } @@ -4031,6 +4048,7 @@ int j = 0; int identical = 0; int i = 0; + bool modified = false; for (; i < _expensive_nodes->length()-1; i++) { assert(j <= i, "can't write beyond current index"); if (_expensive_nodes->at(i)->Opcode() == _expensive_nodes->at(i+1)->Opcode()) { @@ -4043,20 +4061,23 @@ identical = 0; } else { Node* n = _expensive_nodes->at(i); - igvn.hash_delete(n); - n->set_req(0, NULL); + igvn.replace_input_of(n, 0, NULL); igvn.hash_insert(n); + modified = true; } } if (identical > 0) { _expensive_nodes->at_put(j++, _expensive_nodes->at(i)); } else if (_expensive_nodes->length() >= 1) { Node* n = _expensive_nodes->at(i); - igvn.hash_delete(n); - n->set_req(0, NULL); + igvn.replace_input_of(n, 0, NULL); igvn.hash_insert(n); + modified = true; } _expensive_nodes->trunc_to(j); + if (modified) { + igvn.optimize(); + } } void Compile::add_expensive_node(Node * n) { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/compile.hpp --- a/hotspot/src/share/vm/opto/compile.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/compile.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -344,6 +344,8 @@ VectorSet _dead_node_list; // Set of dead nodes uint _dead_node_count; // Number of dead nodes; VectorSet::Size() is O(N). // So use this to keep count and make the call O(1). + DEBUG_ONLY( Unique_Node_List* _modified_nodes; ) // List of nodes which inputs were modified + debug_only(static int _debug_idx;) // Monotonic counter (not reset), use -XX:BreakAtNode= Arena _node_arena; // Arena for new-space Nodes Arena _old_arena; // Arena for old-space Nodes, lifetime during xform @@ -766,6 +768,11 @@ void print_missing_nodes(); #endif + // Record modified nodes to check that they are put on IGVN worklist + void record_modified_node(Node* n) NOT_DEBUG_RETURN; + void remove_modified_node(Node* n) NOT_DEBUG_RETURN; + DEBUG_ONLY( Unique_Node_List* modified_nodes() const { return _modified_nodes; } ) + // Constant table ConstantTable& constant_table() { return _constant_table; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/connode.cpp --- a/hotspot/src/share/vm/opto/connode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/connode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -43,7 +43,7 @@ } //------------------------------make------------------------------------------- -ConNode *ConNode::make( Compile* C, const Type *t ) { +ConNode *ConNode::make(const Type *t) { switch( t->basic_type() ) { case T_INT: return new ConINode( t->is_int() ); case T_LONG: return new ConLNode( t->is_long() ); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/connode.hpp --- a/hotspot/src/share/vm/opto/connode.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/connode.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -46,7 +46,7 @@ virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; } // Polymorphic factory method: - static ConNode* make( Compile* C, const Type *t ); + static ConNode* make(const Type *t); }; //------------------------------ConINode--------------------------------------- @@ -57,7 +57,7 @@ virtual int Opcode() const; // Factory method: - static ConINode* make( Compile* C, int con ) { + static ConINode* make(int con) { return new ConINode( TypeInt::make(con) ); } @@ -71,7 +71,7 @@ virtual int Opcode() const; // Factory methods: - static ConPNode* make( Compile *C ,address con ) { + static ConPNode* make(address con) { if (con == NULL) return new ConPNode( TypePtr::NULL_PTR ) ; else @@ -105,7 +105,7 @@ virtual int Opcode() const; // Factory method: - static ConLNode* make( Compile *C ,jlong con ) { + static ConLNode* make(jlong con) { return new ConLNode( TypeLong::make(con) ); } @@ -119,7 +119,7 @@ virtual int Opcode() const; // Factory method: - static ConFNode* make( Compile *C, float con ) { + static ConFNode* make(float con) { return new ConFNode( TypeF::make(con) ); } @@ -133,7 +133,7 @@ virtual int Opcode() const; // Factory method: - static ConDNode* make( Compile *C, double con ) { + static ConDNode* make(double con) { return new ConDNode( TypeD::make(con) ); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/divnode.cpp --- a/hotspot/src/share/vm/opto/divnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/divnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -479,7 +479,10 @@ if (i == 0) return NULL; // Dividing by zero constant does not idealize - set_req(0,NULL); // Dividing by a not-zero constant; no faulting + if (in(0) != NULL) { + phase->igvn_rehash_node_delayed(this); + set_req(0, NULL); // Dividing by a not-zero constant; no faulting + } // Dividing by MININT does not optimize as a power-of-2 shift. if( i == min_jint ) return NULL; @@ -578,7 +581,10 @@ if (l == 0) return NULL; // Dividing by zero constant does not idealize - set_req(0,NULL); // Dividing by a not-zero constant; no faulting + if (in(0) != NULL) { + phase->igvn_rehash_node_delayed(this); + set_req(0, NULL); // Dividing by a not-zero constant; no faulting + } // Dividing by MINLONG does not optimize as a power-of-2 shift. if( l == min_jlong ) return NULL; @@ -1274,7 +1280,7 @@ } //------------------------------make------------------------------------------ -DivModINode* DivModINode::make(Compile* C, Node* div_or_mod) { +DivModINode* DivModINode::make(Node* div_or_mod) { Node* n = div_or_mod; assert(n->Opcode() == Op_DivI || n->Opcode() == Op_ModI, "only div or mod input pattern accepted"); @@ -1286,7 +1292,7 @@ } //------------------------------make------------------------------------------ -DivModLNode* DivModLNode::make(Compile* C, Node* div_or_mod) { +DivModLNode* DivModLNode::make(Node* div_or_mod) { Node* n = div_or_mod; assert(n->Opcode() == Op_DivL || n->Opcode() == Op_ModL, "only div or mod input pattern accepted"); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/divnode.hpp --- a/hotspot/src/share/vm/opto/divnode.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/divnode.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -168,7 +168,7 @@ virtual Node *match( const ProjNode *proj, const Matcher *m ); // Make a divmod and associated projections from a div or mod. - static DivModINode* make(Compile* C, Node* div_or_mod); + static DivModINode* make(Node* div_or_mod); }; //------------------------------DivModLNode--------------------------------------- @@ -181,7 +181,7 @@ virtual Node *match( const ProjNode *proj, const Matcher *m ); // Make a divmod and associated projections from a div or mod. - static DivModLNode* make(Compile* C, Node* div_or_mod); + static DivModLNode* make(Node* div_or_mod); }; #endif // SHARE_VM_OPTO_DIVNODE_HPP diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/escape.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1452,7 +1452,6 @@ return 0; InitializeNode* ini = alloc->as_Allocate()->initialization(); - Compile* C = _compile; bool visited_bottom_offset = false; GrowableArray offsets_worklist; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/graphKit.cpp --- a/hotspot/src/share/vm/opto/graphKit.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/graphKit.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2014, 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 @@ -591,7 +591,7 @@ C->log()->elem("hot_throw preallocated='1' reason='%s'", Deoptimization::trap_reason_name(reason)); const TypeInstPtr* ex_con = TypeInstPtr::make(ex_obj); - Node* ex_node = _gvn.transform( ConNode::make(C, ex_con) ); + Node* ex_node = _gvn.transform(ConNode::make(ex_con)); // Clear the detail message of the preallocated exception object. // Weblogic sometimes mutates the detail message of exceptions @@ -706,7 +706,7 @@ if (map() == NULL) return NULL; // Clone the memory edge first - Node* mem = MergeMemNode::make(C, map()->memory()); + Node* mem = MergeMemNode::make(map()->memory()); gvn().set_type_bottom(mem); SafePointNode *clonemap = (SafePointNode*)map()->clone(); @@ -1135,7 +1135,7 @@ return longcon((julong) offset_con); } Node* conv = _gvn.transform( new ConvI2LNode(offset)); - Node* mask = _gvn.transform( ConLNode::make(C, (julong) max_juint) ); + Node* mask = _gvn.transform(ConLNode::make((julong) max_juint)); return _gvn.transform( new AndLNode(conv, mask) ); } @@ -1435,7 +1435,7 @@ //------------------------------set_all_memory--------------------------------- void GraphKit::set_all_memory(Node* newmem) { - Node* mergemem = MergeMemNode::make(C, newmem); + Node* mergemem = MergeMemNode::make(newmem); gvn().set_type_bottom(mergemem); map()->set_memory(mergemem); } @@ -1464,9 +1464,9 @@ Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); + ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, mo); } else if (require_atomic_access && bt == T_DOUBLE) { - ld = LoadDNode::make_atomic(C, ctl, mem, adr, adr_type, t, mo); + ld = LoadDNode::make_atomic(ctl, mem, adr, adr_type, t, mo); } else { ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo); } @@ -1488,9 +1488,9 @@ Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); + st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else if (require_atomic_access && bt == T_DOUBLE) { - st = StoreDNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); + st = StoreDNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else { st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } @@ -2084,9 +2084,9 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) { // (Note: TypeFunc::make has a cache that makes this fast.) const TypeFunc* tf = TypeFunc::make(dest_method); - int nargs = tf->_domain->_cnt - TypeFunc::Parms; + int nargs = tf->domain()->cnt() - TypeFunc::Parms; for (int j = 0; j < nargs; j++) { - const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); + const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); if( targ->basic_type() == T_DOUBLE ) { // If any parameters are doubles, they must be rounded before // the call, dstore_rounding does gvn.transform @@ -2188,10 +2188,10 @@ return; } const TypeFunc* tf = TypeFunc::make(dest_method); - int nargs = tf->_domain->_cnt - TypeFunc::Parms; + int nargs = tf->domain()->cnt() - TypeFunc::Parms; int skip = Bytecodes::has_receiver(bc) ? 1 : 0; for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) { - const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); + const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms); if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) { bool maybe_null = true; ciKlass* better_type = NULL; @@ -3364,7 +3364,7 @@ // This will allow us to observe initializations when they occur, // and link them properly (as a group) to the InitializeNode. assert(init->in(InitializeNode::Memory) == malloc, ""); - MergeMemNode* minit_in = MergeMemNode::make(C, malloc); + MergeMemNode* minit_in = MergeMemNode::make(malloc); init->set_req(InitializeNode::Memory, minit_in); record_for_igvn(minit_in); // fold it up later, if possible Node* minit_out = memory(rawidx); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/idealKit.cpp --- a/hotspot/src/share/vm/opto/idealKit.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/idealKit.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -320,7 +320,7 @@ Node* ns = new_cvstate(); for (uint i = 0; i < ns->req(); i++) ns->init_req(i, _cvstate->in(i)); // We must clone memory since it will be updated as we do stores. - ns->set_req(TypeFunc::Memory, MergeMemNode::make(C, ns->in(TypeFunc::Memory))); + ns->set_req(TypeFunc::Memory, MergeMemNode::make(ns->in(TypeFunc::Memory))); return ns; } @@ -359,7 +359,7 @@ Node* mem = memory(adr_idx); Node* ld; if (require_atomic_access && bt == T_LONG) { - ld = LoadLNode::make_atomic(C, ctl, mem, adr, adr_type, t, MemNode::unordered); + ld = LoadLNode::make_atomic(ctl, mem, adr, adr_type, t, MemNode::unordered); } else { ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, MemNode::unordered); } @@ -375,7 +375,7 @@ Node *mem = memory(adr_idx); Node* st; if (require_atomic_access && bt == T_LONG) { - st = StoreLNode::make_atomic(C, ctl, mem, adr, adr_type, val, mo); + st = StoreLNode::make_atomic(ctl, mem, adr, adr_type, val, mo); } else { st = StoreNode::make(_gvn, ctl, mem, adr, adr_type, val, bt, mo); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/lcm.cpp --- a/hotspot/src/share/vm/opto/lcm.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/lcm.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -464,7 +464,9 @@ iop == Op_CreateEx || // Create-exception must start block iop == Op_CheckCastPP ) { - worklist.map(i,worklist.pop()); + // select the node n + // remove n from worklist and retain the order of remaining nodes + worklist.remove((uint)i); return n; } @@ -550,7 +552,9 @@ assert(idx >= 0, "index should be set"); Node *n = worklist[(uint)idx]; // Get the winner - worklist.map((uint)idx, worklist.pop()); // Compress worklist + // select the node n + // remove n from worklist and retain the order of remaining nodes + worklist.remove((uint)idx); return n; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1905,7 +1905,7 @@ Node *bolyplus1 = _gvn.transform(new BoolNode( cmpyplus1, BoolTest::eq )); Node* correctedsign = NULL; if (ConditionalMoveLimit != 0) { - correctedsign = _gvn.transform( CMoveNode::make(C, NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); + correctedsign = _gvn.transform(CMoveNode::make(NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); } else { IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN); RegionNode *r = new RegionNode(3); @@ -1934,7 +1934,7 @@ // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y) Node *signresult = NULL; if (ConditionalMoveLimit != 0) { - signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); + signresult = _gvn.transform(CMoveNode::make(NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); } else { IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN); RegionNode *r = new RegionNode(3); @@ -2268,7 +2268,7 @@ // which could hinder other optimizations. // Since Math.min/max is often used with arraycopy, we want // tightly_coupled_allocation to be able to see beyond min/max expressions. - Node* cmov = CMoveNode::make(C, NULL, best_bol, + Node* cmov = CMoveNode::make(NULL, best_bol, answer_if_false, answer_if_true, TypeInt::make(lo, hi, widen)); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/loopPredicate.cpp --- a/hotspot/src/share/vm/opto/loopPredicate.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopPredicate.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -107,8 +107,7 @@ rgn = new RegionNode(1); rgn->add_req(uncommon_proj); register_control(rgn, loop, uncommon_proj); - _igvn.hash_delete(call); - call->set_req(0, rgn); + _igvn.replace_input_of(call, 0, rgn); // When called from beautify_loops() idom is not constructed yet. if (_idom != NULL) { set_idom(call, rgn, dom_depth(rgn)); @@ -166,8 +165,7 @@ if (new_entry == NULL) { // Attach if_cont to iff - _igvn.hash_delete(iff); - iff->set_req(0, if_cont); + _igvn.replace_input_of(iff, 0, if_cont); if (_idom != NULL) { set_idom(iff, if_cont, dom_depth(iff)); } @@ -194,8 +192,7 @@ rgn = new RegionNode(1); register_new_node_with_optimizer(rgn); rgn->add_req(uncommon_proj); - hash_delete(call); - call->set_req(0, rgn); + replace_input_of(call, 0, rgn); } else { // Find region's edge corresponding to uncommon_proj for (; proj_index < rgn->req(); proj_index++) diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -924,15 +924,13 @@ if( bol->outcnt() != 1 ) { bol = bol->clone(); register_new_node(bol,main_end->in(CountedLoopEndNode::TestControl)); - _igvn.hash_delete(main_end); - main_end->set_req(CountedLoopEndNode::TestValue, bol); + _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, bol); } // Need only 1 user of 'cmp' because I will be hacking the loop bounds. if( cmp->outcnt() != 1 ) { cmp = cmp->clone(); register_new_node(cmp,main_end->in(CountedLoopEndNode::TestControl)); - _igvn.hash_delete(bol); - bol->set_req(1, cmp); + _igvn.replace_input_of(bol, 1, cmp); } //------------------------------ @@ -1118,8 +1116,7 @@ Node* pre_bol = pre_end->in(CountedLoopEndNode::TestValue)->as_Bool(); BoolNode* new_bol0 = new BoolNode(pre_bol->in(1), new_test); register_new_node( new_bol0, pre_head->in(0) ); - _igvn.hash_delete(pre_end); - pre_end->set_req(CountedLoopEndNode::TestValue, new_bol0); + _igvn.replace_input_of(pre_end, CountedLoopEndNode::TestValue, new_bol0); // Modify main loop guard condition assert(min_iff->in(CountedLoopEndNode::TestValue) == min_bol, "guard okay"); BoolNode* new_bol1 = new BoolNode(min_bol->in(1), new_test); @@ -1130,8 +1127,7 @@ BoolNode* main_bol = main_end->in(CountedLoopEndNode::TestValue)->as_Bool(); BoolNode* new_bol2 = new BoolNode(main_bol->in(1), new_test); register_new_node( new_bol2, main_end->in(CountedLoopEndNode::TestControl) ); - _igvn.hash_delete(main_end); - main_end->set_req(CountedLoopEndNode::TestValue, new_bol2); + _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, new_bol2); } // Flag main loop @@ -1346,8 +1342,7 @@ Node* bol2 = loop_end->in(1)->clone(); bol2->set_req(1, cmp2); register_new_node(bol2, ctrl2); - _igvn.hash_delete(loop_end); - loop_end->set_req(1, bol2); + _igvn.replace_input_of(loop_end, 1, bol2); } // Step 3: Find the min-trip test guaranteed before a 'main' loop. // Make it a 1-trip test (means at least 2 trips). @@ -1356,8 +1351,7 @@ // can edit it's inputs directly. Hammer in the new limit for the // minimum-trip guard. assert(opaq->outcnt() == 1, ""); - _igvn.hash_delete(opaq); - opaq->set_req(1, new_limit); + _igvn.replace_input_of(opaq, 1, new_limit); } // Adjust max trip count. The trip count is intentionally rounded @@ -1407,8 +1401,7 @@ register_new_node( cmp2, ctrl2 ); Node *bol2 = new BoolNode( cmp2, loop_end->test_trip() ); register_new_node( bol2, ctrl2 ); - _igvn.hash_delete(loop_end); - loop_end->set_req(CountedLoopEndNode::TestValue, bol2); + _igvn.replace_input_of(loop_end, CountedLoopEndNode::TestValue, bol2); // Step 3: Find the min-trip test guaranteed before a 'main' loop. // Make it a 1-trip test (means at least 2 trips). @@ -1997,8 +1990,7 @@ : (Node*)new MaxINode(pre_limit, orig_limit); register_new_node(pre_limit, pre_ctrl); } - _igvn.hash_delete(pre_opaq); - pre_opaq->set_req(1, pre_limit); + _igvn.replace_input_of(pre_opaq, 1, pre_limit); // Note:: we are making the main loop limit no longer precise; // need to round up based on stride. @@ -2027,10 +2019,9 @@ Node *main_bol = main_cle->in(1); // Hacking loop bounds; need private copies of exit test if( main_bol->outcnt() > 1 ) {// BoolNode shared? - _igvn.hash_delete(main_cle); main_bol = main_bol->clone();// Clone a private BoolNode register_new_node( main_bol, main_cle->in(0) ); - main_cle->set_req(1,main_bol); + _igvn.replace_input_of(main_cle, 1, main_bol); } Node *main_cmp = main_bol->in(1); if( main_cmp->outcnt() > 1 ) { // CmpNode shared? diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/loopnode.cpp --- a/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -133,7 +133,7 @@ // Return earliest legal location assert(early == find_non_split_ctrl(early), "unexpected early control"); - if (n->is_expensive()) { + if (n->is_expensive() && !_verify_only && !_verify_me) { assert(n->in(0), "should have control input"); early = get_early_ctrl_for_expensive(n, early); } @@ -226,8 +226,7 @@ } if (ctl != n->in(0)) { - _igvn.hash_delete(n); - n->set_req(0, ctl); + _igvn.replace_input_of(n, 0, ctl); _igvn.hash_insert(n); } @@ -521,8 +520,7 @@ assert(check_iff->in(1)->Opcode() == Op_Conv2B && check_iff->in(1)->in(1)->Opcode() == Op_Opaque1, ""); Node* opq = check_iff->in(1)->in(1); - _igvn.hash_delete(opq); - opq->set_req(1, bol); + _igvn.replace_input_of(opq, 1, bol); // Update ctrl. set_ctrl(opq, check_iff->in(0)); set_ctrl(check_iff->in(1), check_iff->in(0)); @@ -690,7 +688,7 @@ incr->set_req(2,stride); incr = _igvn.register_new_node_with_optimizer(incr); set_early_ctrl( incr ); - _igvn.hash_delete(phi); + _igvn.rehash_node_delayed(phi); phi->set_req_X( LoopNode::LoopBackControl, incr, &_igvn ); // If phi type is more restrictive than Int, raise to @@ -743,8 +741,8 @@ iffalse = iff2; iftrue = ift2; } else { - _igvn.hash_delete(iffalse); - _igvn.hash_delete(iftrue); + _igvn.rehash_node_delayed(iffalse); + _igvn.rehash_node_delayed(iftrue); iffalse->set_req_X( 0, le, &_igvn ); iftrue ->set_req_X( 0, le, &_igvn ); } @@ -1257,6 +1255,7 @@ _head->del_req(i); } } + igvn.rehash_node_delayed(_head); // Transform landing pad igvn.register_new_node_with_optimizer(landing_pad, _head); // Insert landing pad into the header @@ -1397,7 +1396,7 @@ igvn.register_new_node_with_optimizer(r, _head); // Plug region into end of loop _head, followed by hot_tail while( _head->req() > 3 ) _head->del_req( _head->req()-1 ); - _head->set_req(2, r); + igvn.replace_input_of(_head, 2, r); if( hot_idx ) _head->add_req(hot_tail); // Split all the Phis up between '_head' loop and the Region 'r' @@ -1419,7 +1418,7 @@ igvn.register_new_node_with_optimizer(phi, n); // Add the merge phi to the old Phi while( n->req() > 3 ) n->del_req( n->req()-1 ); - n->set_req(2, phi); + igvn.replace_input_of(n, 2, phi); if( hot_idx ) n->add_req(hot_phi); } } @@ -1495,13 +1494,14 @@ if( fall_in_cnt > 1 ) { // Since I am just swapping inputs I do not need to update def-use info Node *tmp = _head->in(1); + igvn.rehash_node_delayed(_head); _head->set_req( 1, _head->in(fall_in_cnt) ); _head->set_req( fall_in_cnt, tmp ); // Swap also all Phis for (DUIterator_Fast imax, i = _head->fast_outs(imax); i < imax; i++) { Node* phi = _head->fast_out(i); if( phi->is_Phi() ) { - igvn.hash_delete(phi); // Yank from hash before hacking edges + igvn.rehash_node_delayed(phi); // Yank from hash before hacking edges tmp = phi->in(1); phi->set_req( 1, phi->in(fall_in_cnt) ); phi->set_req( fall_in_cnt, tmp ); @@ -2905,6 +2905,7 @@ uint k = 0; // Probably cfg->in(0) while( cfg->in(k) != m ) k++; // But check incase cfg is a Region cfg->set_req( k, if_t ); // Now point to NeverBranch + _igvn._worklist.push(cfg); // Now create the never-taken loop exit Node *if_f = new CProjNode( iff, 1 ); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/loopopts.cpp --- a/hotspot/src/share/vm/opto/loopopts.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopopts.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, 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 @@ -625,7 +625,7 @@ set_ctrl(inp, cmov_ctrl); } } - Node *cmov = CMoveNode::make( C, cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi) ); + Node *cmov = CMoveNode::make(cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi)); register_new_node( cmov, cmov_ctrl ); _igvn.replace_node( phi, cmov ); #ifndef PRODUCT @@ -2574,7 +2574,7 @@ new_head->set_unswitch_count(head->unswitch_count()); // Preserve _igvn.register_new_node_with_optimizer(new_head); assert(first_not_peeled->in(0) == last_peel, "last_peel <- first_not_peeled"); - first_not_peeled->set_req(0, new_head); + _igvn.replace_input_of(first_not_peeled, 0, new_head); set_loop(new_head, loop); loop->_body.push(new_head); not_peel.set(new_head->_idx); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/machnode.cpp --- a/hotspot/src/share/vm/opto/machnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/machnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -178,7 +178,7 @@ } // Return an equivalent instruction using memory for cisc_operand position -MachNode *MachNode::cisc_version(int offset, Compile* C) { +MachNode *MachNode::cisc_version(int offset) { ShouldNotCallThis(); return NULL; } @@ -411,7 +411,7 @@ //------------------------------peephole--------------------------------------- // Apply peephole rule(s) to this instruction -MachNode *MachNode::peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ) { +MachNode *MachNode::peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted) { return NULL; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/machnode.hpp --- a/hotspot/src/share/vm/opto/machnode.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/machnode.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -152,7 +152,7 @@ virtual uint cmp( const MachOper &oper ) const; // Virtual clone, since I do not know how big the MachOper is. - virtual MachOper *clone(Compile* C) const = 0; + virtual MachOper *clone() const = 0; // Return ideal Type from simple operands. Fail for complex operands. virtual const Type *type() const; @@ -202,10 +202,10 @@ // Copy inputs and operands to new node of instruction. // Called from cisc_version() and short_branch_version(). // !!!! The method's body is defined in ad_.cpp file. - void fill_new_machnode(MachNode *n, Compile* C) const; + void fill_new_machnode(MachNode *n) const; // Return an equivalent instruction using memory for cisc_operand position - virtual MachNode *cisc_version(int offset, Compile* C); + virtual MachNode *cisc_version(int offset); // Modify this instruction's register mask to use stack version for cisc_operand virtual void use_cisc_RegMask(); @@ -317,7 +317,7 @@ virtual const class TypePtr *adr_type() const; // Apply peephole rule(s) to this instruction - virtual MachNode *peephole( Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted, Compile* C ); + virtual MachNode *peephole(Block *block, int block_index, PhaseRegAlloc *ra_, int &deleted); // Top-level ideal Opcode matched virtual int ideal_Opcode() const { return Op_Node; } @@ -627,7 +627,7 @@ virtual void save_label(Label** label, uint* block_num) = 0; // Support for short branches - virtual MachNode *short_branch_version(Compile* C) { return NULL; } + virtual MachNode *short_branch_version() { return NULL; } virtual bool pinned() const { return true; }; }; @@ -985,7 +985,7 @@ labelOper(labelOper* l) : _label(l->_label) , _block_num(l->_block_num) {} - virtual MachOper *clone(Compile* C) const; + virtual MachOper *clone() const; virtual Label *label() const { assert(_label != NULL, "need Label"); return _label; } @@ -1012,7 +1012,7 @@ methodOper() : _method(0) {} methodOper(intptr_t method) : _method(method) {} - virtual MachOper *clone(Compile* C) const; + virtual MachOper *clone() const; virtual intptr_t method() const { return _method; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/macro.cpp --- a/hotspot/src/share/vm/opto/macro.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/macro.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, 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 @@ -702,6 +702,7 @@ ciType* elem_type; Node* res = alloc->result_cast(); + assert(res == NULL || res->is_CheckCastPP(), "unexpected AllocateNode result"); const TypeOopPtr* res_type = NULL; if (res != NULL) { // Could be NULL when there are no users res_type = _igvn.type(res)->isa_oopptr(); @@ -791,6 +792,7 @@ for (int k = 0; k < j; k++) { sfpt->del_req(last--); } + _igvn._worklist.push(sfpt); // rollback processed safepoints while (safepoints_done.length() > 0) { SafePointNode* sfpt_done = safepoints_done.pop(); @@ -815,6 +817,7 @@ } } } + _igvn._worklist.push(sfpt_done); } #ifndef PRODUCT if (PrintEliminateAllocations) { @@ -855,6 +858,7 @@ int start = jvms->debug_start(); int end = jvms->debug_end(); sfpt->replace_edges_in_range(res, sobj, start, end); + _igvn._worklist.push(sfpt); safepoints_done.append_if_missing(sfpt); // keep it for rollback } return true; @@ -1034,6 +1038,8 @@ return false; } + assert(boxing->result_cast() == NULL, "unexpected boxing node result"); + extract_call_projections(boxing); const TypeTuple* r = boxing->tf()->range(); @@ -1775,6 +1781,7 @@ Node *pf_region = new RegionNode(3); Node *pf_phi_rawmem = new PhiNode( pf_region, Type::MEMORY, TypeRawPtr::BOTTOM ); + transform_later(pf_region); // Generate several prefetch instructions. uint lines = (length != NULL) ? AllocatePrefetchLines : AllocateInstancePrefetchLines; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/matcher.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -305,7 +305,7 @@ // to avoid false sharing if the corresponding mach node is not used. // The corresponding mach node is only used in rare cases for derived // pointers. - Node* new_ideal_null = ConNode::make(C, TypePtr::NULL_PTR); + Node* new_ideal_null = ConNode::make(TypePtr::NULL_PTR); // Swap out to old-space; emptying new-space Arena *old = C->node_arena()->move_contents(C->old_arena()); @@ -1643,8 +1643,8 @@ } // Build the object to represent this state & prepare for recursive calls - MachNode *mach = s->MachNodeGenerator( rule, C ); - mach->_opnds[0] = s->MachOperGenerator( _reduceOp[rule], C ); + MachNode *mach = s->MachNodeGenerator(rule); + mach->_opnds[0] = s->MachOperGenerator(_reduceOp[rule]); assert( mach->_opnds[0] != NULL, "Missing result operand" ); Node *leaf = s->_leaf; // Check for instruction or instruction chain rule @@ -1756,13 +1756,13 @@ assert( 0 <= opnd_class_instance && opnd_class_instance < NUM_OPERANDS, "Bad AD file: Instruction chain rule must chain from operand"); // Insert operand into array of operands for this instruction - mach->_opnds[1] = s->MachOperGenerator( opnd_class_instance, C ); + mach->_opnds[1] = s->MachOperGenerator(opnd_class_instance); ReduceOper( s, newrule, mem, mach ); } else { // Chain from the result of an instruction assert( newrule >= _LAST_MACH_OPER, "Do NOT chain from internal operand"); - mach->_opnds[1] = s->MachOperGenerator( _reduceOp[catch_op], C ); + mach->_opnds[1] = s->MachOperGenerator(_reduceOp[catch_op]); Node *mem1 = (Node*)1; debug_only(Node *save_mem_node = _mem_node;) mach->add_req( ReduceInst(s, newrule, mem1) ); @@ -1807,7 +1807,7 @@ if( newrule < NUM_OPERANDS ) { // Operand/operandClass or internalOp/instruction? // Operand/operandClass // Insert operand into array of operands for this instruction - mach->_opnds[num_opnds++] = newstate->MachOperGenerator( opnd_class_instance, C ); + mach->_opnds[num_opnds++] = newstate->MachOperGenerator(opnd_class_instance); ReduceOper( newstate, newrule, mem, mach ); } else { // Child is internal operand or new instruction @@ -1818,7 +1818,7 @@ } else { // instruction --> call build operand( ) to catch result // --> ReduceInst( newrule ) - mach->_opnds[num_opnds++] = s->MachOperGenerator( _reduceOp[catch_op], C ); + mach->_opnds[num_opnds++] = s->MachOperGenerator(_reduceOp[catch_op]); Node *mem1 = (Node*)1; debug_only(Node *save_mem_node = _mem_node;) mach->add_req( ReduceInst( newstate, newrule, mem1 ) ); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/mathexactnode.cpp --- a/hotspot/src/share/vm/opto/mathexactnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/mathexactnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, 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 @@ -191,7 +191,7 @@ NativeType val1 = TypeClass::as_self(type1)->get_con(); NativeType val2 = TypeClass::as_self(type2)->get_con(); if (node->will_overflow(val1, val2) == false) { - Node* con_result = ConINode::make(phase->C, 0); + Node* con_result = ConINode::make(0); return con_result; } return NULL; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/memnode.cpp --- a/hotspot/src/share/vm/opto/memnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/memnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -933,12 +933,12 @@ return (LoadNode*)NULL; } -LoadLNode* LoadLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { +LoadLNode* LoadLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { bool require_atomic = true; return new LoadLNode(ctl, mem, adr, adr_type, rt->is_long(), mo, require_atomic); } -LoadDNode* LoadDNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { +LoadDNode* LoadDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo) { bool require_atomic = true; return new LoadDNode(ctl, mem, adr, adr_type, rt, mo, require_atomic); } @@ -1471,6 +1471,7 @@ Node* ctrl = in(MemNode::Control); Node* address = in(MemNode::Address); + bool progress = false; // Skip up past a SafePoint control. Cannot do this for Stores because // pointer stores & cardmarks must stay on the same side of a SafePoint. @@ -1478,6 +1479,7 @@ phase->C->get_alias_index(phase->type(address)->is_ptr()) != Compile::AliasIdxRaw ) { ctrl = ctrl->in(0); set_req(MemNode::Control,ctrl); + progress = true; } intptr_t ignore = 0; @@ -1490,6 +1492,7 @@ && all_controls_dominate(base, phase->C->start())) { // A method-invariant, non-null address (constant or 'this' argument). set_req(MemNode::Control, NULL); + progress = true; } } @@ -1550,7 +1553,7 @@ } } - return NULL; // No further progress + return progress ? this : NULL; } // Helper to recognize certain Klass fields which are invariant across @@ -2014,7 +2017,6 @@ //----------------------------LoadKlassNode::make------------------------------ // Polymorphic factory method: Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* at, const TypeKlassPtr *tk ) { - Compile* C = gvn.C; Node *ctl = NULL; // sanity check the alias category against the created node type const TypePtr *adr_type = adr->bottom_type()->isa_ptr(); @@ -2379,12 +2381,12 @@ return (StoreNode*)NULL; } -StoreLNode* StoreLNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { +StoreLNode* StoreLNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { bool require_atomic = true; return new StoreLNode(ctl, mem, adr, adr_type, val, mo, require_atomic); } -StoreDNode* StoreDNode::make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { +StoreDNode* StoreDNode::make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo) { bool require_atomic = true; return new StoreDNode(ctl, mem, adr, adr_type, val, mo, require_atomic); } @@ -2460,7 +2462,7 @@ // and I need to disappear. if (moved != NULL) { // %%% hack to ensure that Ideal returns a new node: - mem = MergeMemNode::make(phase->C, mem); + mem = MergeMemNode::make(mem); return mem; // fold me away } } @@ -2820,7 +2822,6 @@ intptr_t start_offset, Node* end_offset, PhaseGVN* phase) { - Compile* C = phase->C; intptr_t offset = start_offset; int unit = BytesPerLong; @@ -2847,7 +2848,6 @@ return mem; } - Compile* C = phase->C; int unit = BytesPerLong; Node* zbase = start_offset; Node* zend = end_offset; @@ -2875,7 +2875,6 @@ return mem; } - Compile* C = phase->C; assert((end_offset % BytesPerInt) == 0, "odd end offset"); intptr_t done_offset = end_offset; if ((done_offset % BytesPerLong) != 0) { @@ -2944,6 +2943,7 @@ return NULL; } + bool progress = false; // Eliminate volatile MemBars for scalar replaced objects. if (can_reshape && req() == (Precedent+1)) { bool eliminate = false; @@ -2966,6 +2966,7 @@ phase->is_IterGVN()->_worklist.push(my_mem); // remove dead node later my_mem = NULL; } + progress = true; } if (my_mem != NULL && my_mem->is_Mem()) { const TypeOopPtr* t_oop = my_mem->in(MemNode::Address)->bottom_type()->isa_oopptr(); @@ -2995,7 +2996,7 @@ return new ConINode(TypeInt::ZERO); } } - return NULL; + return progress ? this : NULL; } //------------------------------Value------------------------------------------ @@ -3497,6 +3498,7 @@ // if it redundantly stored the same value (or zero to fresh memory). // In any case, wire it in: + phase->igvn_rehash_node_delayed(this); set_req(i, new_st); // The caller may now kill the old guy. @@ -4126,7 +4128,7 @@ // Make a new, untransformed MergeMem with the same base as 'mem'. // If mem is itself a MergeMem, populate the result with the same edges. -MergeMemNode* MergeMemNode::make(Compile* C, Node* mem) { +MergeMemNode* MergeMemNode::make(Node* mem) { return new MergeMemNode(mem); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/memnode.hpp --- a/hotspot/src/share/vm/opto/memnode.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/memnode.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -333,7 +333,7 @@ virtual int store_Opcode() const { return Op_StoreL; } virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } - static LoadLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, + static LoadLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { @@ -384,7 +384,7 @@ virtual int store_Opcode() const { return Op_StoreD; } virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } - static LoadDNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, + static LoadDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, const Type* rt, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { @@ -593,7 +593,7 @@ virtual int Opcode() const; virtual BasicType memory_type() const { return T_LONG; } bool require_atomic_access() const { return _require_atomic_access; } - static StoreLNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); + static StoreLNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); @@ -629,7 +629,7 @@ virtual int Opcode() const; virtual BasicType memory_type() const { return T_DOUBLE; } bool require_atomic_access() const { return _require_atomic_access; } - static StoreDNode* make_atomic(Compile *C, Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); + static StoreDNode* make_atomic(Node* ctl, Node* mem, Node* adr, const TypePtr* adr_type, Node* val, MemOrd mo); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const { StoreNode::dump_spec(st); @@ -1138,7 +1138,7 @@ // If the input is a whole memory state, clone it with all its slices intact. // Otherwise, make a new memory state with just that base memory input. // In either case, the result is a newly created MergeMem. - static MergeMemNode* make(Compile* C, Node* base_memory); + static MergeMemNode* make(Node* base_memory); virtual int Opcode() const; virtual Node *Identity( PhaseTransform *phase ); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/movenode.cpp --- a/hotspot/src/share/vm/opto/movenode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/movenode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -88,7 +88,7 @@ if( in(Condition)->is_Bool() ) { BoolNode* b = in(Condition)->as_Bool(); BoolNode* b2 = b->negate(phase); - return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type ); + return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type); } } return NULL; @@ -158,7 +158,7 @@ //------------------------------make------------------------------------------- // Make a correctly-flavored CMove. Since _type is directly determined // from the inputs we do not need to specify it here. -CMoveNode *CMoveNode::make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t ) { +CMoveNode *CMoveNode::make(Node *c, Node *bol, Node *left, Node *right, const Type *t) { switch( t->basic_type() ) { case T_INT: return new CMoveINode( bol, left, right, t->is_int() ); case T_FLOAT: return new CMoveFNode( bol, left, right, t ); @@ -196,7 +196,7 @@ if( in(Condition)->is_Bool() ) { BoolNode* b = in(Condition)->as_Bool(); BoolNode* b2 = b->negate(phase); - return make( phase->C, in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type ); + return make(in(Control), phase->transform(b2), in(IfTrue), in(IfFalse), _type); } } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/movenode.hpp --- a/hotspot/src/share/vm/opto/movenode.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/movenode.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -47,7 +47,7 @@ virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type *Value( PhaseTransform *phase ) const; virtual Node *Identity( PhaseTransform *phase ); - static CMoveNode *make( Compile *C, Node *c, Node *bol, Node *left, Node *right, const Type *t ); + static CMoveNode *make(Node *c, Node *bol, Node *left, Node *right, const Type *t); // Helper function to spot cmove graph shapes static Node *is_cmove_id( PhaseTransform *phase, Node *cmp, Node *t, Node *f, BoolNode *b ); }; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/node.cpp --- a/hotspot/src/share/vm/opto/node.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/node.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -507,7 +507,7 @@ (const void*)(&mthis->_opnds), 1)); mach->_opnds = to; for ( uint i = 0; i < nopnds; ++i ) { - to[i] = from[i]->clone(C); + to[i] = from[i]->clone(); } } // cloning CallNode may need to clone JVMState @@ -620,6 +620,7 @@ *(address*)this = badAddress; // smash the C++ vtbl, probably _in = _out = (Node**) badAddress; _max = _cnt = _outmax = _outcnt = 0; + compile->remove_modified_node(this); #endif } @@ -765,6 +766,7 @@ if (n != NULL) n->del_out((Node *)this); _in[idx] = in(--_cnt); // Compact the array _in[_cnt] = NULL; // NULL out emptied slot + Compile::current()->record_modified_node(this); } //------------------------------del_req_ordered-------------------------------- @@ -780,6 +782,7 @@ Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*))); } _in[--_cnt] = NULL; // NULL out emptied slot + Compile::current()->record_modified_node(this); } //------------------------------ins_req---------------------------------------- @@ -1297,6 +1300,7 @@ // Done with outputs. igvn->hash_delete(dead); igvn->_worklist.remove(dead); + igvn->C->remove_modified_node(dead); igvn->set_type(dead, Type::TOP); if (dead->is_macro()) { igvn->C->remove_macro_node(dead); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/node.hpp --- a/hotspot/src/share/vm/opto/node.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/node.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -398,6 +398,7 @@ if (*p != NULL) (*p)->del_out((Node *)this); (*p) = n; if (n != NULL) n->add_out((Node *)this); + Compile::current()->record_modified_node(this); } // Light version of set_req() to init inputs after node creation. void init_req( uint i, Node *n ) { @@ -409,6 +410,7 @@ assert( _in[i] == NULL, "sanity"); _in[i] = n; if (n != NULL) n->add_out((Node *)this); + Compile::current()->record_modified_node(this); } // Find first occurrence of n among my edges: int find_edge(Node* n); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/output.cpp --- a/hotspot/src/share/vm/opto/output.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/output.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -526,7 +526,7 @@ if (_matcher->is_short_branch_offset(mach->rule(), br_size, offset)) { // We've got a winner. Replace this branch. - MachNode* replacement = mach->as_MachBranch()->short_branch_version(this); + MachNode* replacement = mach->as_MachBranch()->short_branch_version(); // Update the jmp_size. int new_size = replacement->size(_regalloc); @@ -785,9 +785,10 @@ // grow downwards in all implementations. // (If, on some machine, the interpreter's Java locals or stack // were to grow upwards, the embedded doubles would be word-swapped.) - jint *dp = (jint*)&d; - array->append(new ConstantIntValue(dp[1])); - array->append(new ConstantIntValue(dp[0])); + jlong_accessor acc; + acc.long_value = jlong_cast(d); + array->append(new ConstantIntValue(acc.words[1])); + array->append(new ConstantIntValue(acc.words[0])); #endif break; } @@ -804,9 +805,10 @@ // grow downwards in all implementations. // (If, on some machine, the interpreter's Java locals or stack // were to grow upwards, the embedded doubles would be word-swapped.) - jint *dp = (jint*)&d; - array->append(new ConstantIntValue(dp[1])); - array->append(new ConstantIntValue(dp[0])); + jlong_accessor acc; + acc.long_value = d; + array->append(new ConstantIntValue(acc.words[1])); + array->append(new ConstantIntValue(acc.words[0])); #endif break; } @@ -1174,7 +1176,7 @@ // fill in the nop array for bundling computations MachNode *_nop_list[Bundle::_nop_count]; - Bundle::initialize_nops(_nop_list, this); + Bundle::initialize_nops(_nop_list); return cb; } @@ -1408,7 +1410,7 @@ if (_matcher->is_short_branch_offset(mach->rule(), br_size, offset)) { // We've got a winner. Replace this branch. - MachNode* replacement = mach->as_MachBranch()->short_branch_version(this); + MachNode* replacement = mach->as_MachBranch()->short_branch_version(); // Update the jmp_size. int new_size = replacement->size(_regalloc); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/parse1.cpp --- a/hotspot/src/share/vm/opto/parse1.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/parse1.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -575,12 +575,13 @@ decrement_age(); } } - if (depth() == 1) { + + if (depth() == 1 && !failing()) { // Add check to deoptimize the nmethod if RTM state was changed rtm_deopt(); } - // Check for bailouts during method entry. + // Check for bailouts during method entry or RTM state check setup. if (failing()) { if (log) log->done("parse"); C->set_default_node_notes(caller_nn); @@ -1756,7 +1757,7 @@ if (remerge == NULL) { assert(base != NULL, ""); assert(base->in(0) != NULL, "should not be xformed away"); - remerge = MergeMemNode::make(C, base->in(pnum)); + remerge = MergeMemNode::make(base->in(pnum)); gvn().set_type(remerge, Type::MEMORY); base->set_req(pnum, remerge); } @@ -2199,7 +2200,7 @@ // down below a SafePoint. // Clone the current memory state - Node* mem = MergeMemNode::make(C, map()->memory()); + Node* mem = MergeMemNode::make(map()->memory()); mem = _gvn.transform(mem); @@ -2213,7 +2214,7 @@ // Create a node for the polling address if( add_poll_param ) { - Node *polladr = ConPNode::make(C, (address)os::get_polling_page()); + Node *polladr = ConPNode::make((address)os::get_polling_page()); sfpnt->init_req(TypeFunc::Parms+0, _gvn.transform(polladr)); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/parseHelper.cpp --- a/hotspot/src/share/vm/opto/parseHelper.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/parseHelper.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, 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 @@ -47,7 +47,7 @@ // Get method const TypePtr* method_type = TypeMetadataPtr::make(method); - Node *method_node = _gvn.transform( ConNode::make(C, method_type) ); + Node *method_node = _gvn.transform(ConNode::make(method_type)); kill_dead_locals(); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/phaseX.cpp --- a/hotspot/src/share/vm/opto/phaseX.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/phaseX.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -615,7 +615,7 @@ // Make an idealized constant - one of ConINode, ConPNode, etc. ConNode* PhaseValues::uncached_makecon(const Type *t) { assert(t->singleton(), "must be a constant"); - ConNode* x = ConNode::make(C, t); + ConNode* x = ConNode::make(t); ConNode* k = (ConNode*)hash_find_insert(x); // Value numbering if (k == NULL) { set_type(x, t); // Missed, provide type mapping @@ -933,9 +933,32 @@ for (int i = 0; i < _verify_window_size; i++) { _verify_window[i] = NULL; } +#ifdef ASSERT + // Verify that all modified nodes are on _worklist + Unique_Node_List* modified_list = C->modified_nodes(); + while (modified_list != NULL && modified_list->size()) { + Node* n = modified_list->pop(); + if (n->outcnt() != 0 && !n->is_Con() && !_worklist.member(n)) { + n->dump(); + assert(false, "modified node is not on IGVN._worklist"); + } + } +#endif } void PhaseIterGVN::verify_PhaseIterGVN() { +#ifdef ASSERT + // Verify nodes with changed inputs. + Unique_Node_List* modified_list = C->modified_nodes(); + while (modified_list != NULL && modified_list->size()) { + Node* n = modified_list->pop(); + if (n->outcnt() != 0 && !n->is_Con()) { // skip dead and Con nodes + n->dump(); + assert(false, "modified node was not processed by IGVN.transform_old()"); + } + } +#endif + C->verify_graph_edges(); if( VerifyOpto && allow_progress() ) { // Must turn off allow_progress to enable assert and break recursion @@ -964,6 +987,14 @@ (int) _verify_counter, (int) _verify_full_passes); } } + +#ifdef ASSERT + while (modified_list->size()) { + Node* n = modified_list->pop(); + n->dump(); + assert(false, "VerifyIterativeGVN: new modified node was added"); + } +#endif } #endif /* PRODUCT */ @@ -1066,6 +1097,7 @@ Node* k = n; DEBUG_ONLY(dead_loop_check(k);) DEBUG_ONLY(bool is_new = (k->outcnt() == 0);) + C->remove_modified_node(k); Node* i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || i->outcnt() > 0, "don't return dead nodes"); #ifndef PRODUCT @@ -1107,6 +1139,7 @@ DEBUG_ONLY(dead_loop_check(k);) // Try idealizing again DEBUG_ONLY(is_new = (k->outcnt() == 0);) + C->remove_modified_node(k); i = k->Ideal(this, /*can_reshape=*/true); assert(i != k || is_new || (i->outcnt() > 0), "don't return dead nodes"); #ifndef PRODUCT @@ -1259,6 +1292,7 @@ _stack.pop(); // Remove dead node from iterative worklist _worklist.remove(dead); + C->remove_modified_node(dead); // Constant node that has no out-edges and has only one in-edge from // root is usually dead. However, sometimes reshaping walk makes // it reachable by adding use edges. So, we will NOT count Con nodes @@ -1288,7 +1322,7 @@ for (DUIterator_Last imin, i = old->last_outs(imin); i >= imin; ) { Node* use = old->last_out(i); // for each use... // use might need re-hashing (but it won't if it's a new node) - bool is_in_table = _table.hash_delete( use ); + rehash_node_delayed(use); // Update use-def info as well // We remove all occurrences of old within use->in, // so as to avoid rehashing any node more than once. @@ -1300,11 +1334,6 @@ ++num_edges; } } - // Insert into GVN hash table if unique - // If a duplicate, 'use' will be cleaned up when pulled off worklist - if( is_in_table ) { - hash_find_insert(use); - } i -= num_edges; // we deleted 1 or more copies of this edge } @@ -1599,7 +1628,7 @@ if( t == Type::TOP ) { // cache my top node on the Compile instance if( C->cached_top_node() == NULL || C->cached_top_node()->in(0) == NULL ) { - C->set_cached_top_node( ConNode::make(C, Type::TOP) ); + C->set_cached_top_node(ConNode::make(Type::TOP)); set_type(C->top(), Type::TOP); } nn = C->top(); @@ -1725,7 +1754,7 @@ MachNode *m = n->as_Mach(); int deleted_count = 0; // check for peephole opportunities - MachNode *m2 = m->peephole( block, instruction_index, _regalloc, deleted_count, C ); + MachNode *m2 = m->peephole(block, instruction_index, _regalloc, deleted_count); if( m2 != NULL ) { #ifndef PRODUCT if( PrintOptoPeephole ) { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/phaseX.hpp --- a/hotspot/src/share/vm/opto/phaseX.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/phaseX.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -311,6 +311,9 @@ const Type* limit_type) const { ShouldNotCallThis(); return NULL; } + // Delayed node rehash if this is an IGVN phase + virtual void igvn_rehash_node_delayed(Node* n) {} + #ifndef PRODUCT void dump_old2new_map() const; void dump_new( uint new_lidx ) const; @@ -488,6 +491,10 @@ _worklist.push(n); } + void igvn_rehash_node_delayed(Node* n) { + rehash_node_delayed(n); + } + // Replace ith edge of "n" with "in" void replace_input_of(Node* n, int i, Node* in) { rehash_node_delayed(n); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/rootnode.cpp --- a/hotspot/src/share/vm/opto/rootnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/rootnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -35,10 +35,12 @@ //------------------------------Ideal------------------------------------------ // Remove dead inputs Node *RootNode::Ideal(PhaseGVN *phase, bool can_reshape) { + bool modified = false; for( uint i = 1; i < req(); i++ ) { // For all inputs // Check for and remove dead inputs if( phase->type(in(i)) == Type::TOP ) { del_req(i--); // Delete TOP inputs + modified = true; } } @@ -56,7 +58,7 @@ // If we want to get the rest of the win later, we should pattern match // simple recursive call trees to closed-form solutions. - return NULL; // No further opportunities exposed + return modified ? this : NULL; } //============================================================================= diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/stringopts.cpp --- a/hotspot/src/share/vm/opto/stringopts.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/stringopts.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -1438,7 +1438,7 @@ } // Make sure the memory state is a MergeMem for parsing. if (!map->in(TypeFunc::Memory)->is_MergeMem()) { - map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory))); + map->set_req(TypeFunc::Memory, MergeMemNode::make(map->in(TypeFunc::Memory))); } jvms->set_map(map); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/subnode.cpp --- a/hotspot/src/share/vm/opto/subnode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/subnode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1168,7 +1168,6 @@ Node* BoolNode::make_predicate(Node* test_value, PhaseGVN* phase) { if (test_value->is_Con()) return test_value; if (test_value->is_Bool()) return test_value; - Compile* C = phase->C; if (test_value->is_CMove() && test_value->in(CMoveNode::Condition)->is_Bool()) { BoolNode* bol = test_value->in(CMoveNode::Condition)->as_Bool(); @@ -1191,7 +1190,7 @@ //--------------------------------as_int_value--------------------------------- Node* BoolNode::as_int_value(PhaseGVN* phase) { // Inverse to make_predicate. The CMove probably boils down to a Conv2B. - Node* cmov = CMoveNode::make(phase->C, NULL, this, + Node* cmov = CMoveNode::make(NULL, this, phase->intcon(0), phase->intcon(1), TypeInt::BOOL); return phase->transform(cmov); @@ -1199,7 +1198,6 @@ //----------------------------------negate------------------------------------- BoolNode* BoolNode::negate(PhaseGVN* phase) { - Compile* C = phase->C; return new BoolNode(in(1), _test.negate()); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/superword.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, 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 @@ -1378,9 +1378,23 @@ if (n->is_Load()) { Node* ctl = n->in(MemNode::Control); Node* mem = first->in(MemNode::Memory); + SWPointer p1(n->as_Mem(), this); + // Identify the memory dependency for the new loadVector node by + // walking up through memory chain. + // This is done to give flexibility to the new loadVector node so that + // it can move above independent storeVector nodes. + while (mem->is_StoreVector()) { + SWPointer p2(mem->as_Mem(), this); + int cmp = p1.cmp(p2); + if (SWPointer::not_equal(cmp) || !SWPointer::comparable(cmp)) { + mem = mem->in(MemNode::Memory); + } else { + break; // dependent memory + } + } Node* adr = low_adr->in(MemNode::Address); const TypePtr* atyp = n->adr_type(); - vn = LoadVectorNode::make(C, opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n)); + vn = LoadVectorNode::make(opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n)); vlen_in_bytes = vn->as_LoadVector()->memory_size(); } else if (n->is_Store()) { // Promote value to be stored to vector @@ -1389,7 +1403,7 @@ Node* mem = first->in(MemNode::Memory); Node* adr = low_adr->in(MemNode::Address); const TypePtr* atyp = n->adr_type(); - vn = StoreVectorNode::make(C, opc, ctl, mem, adr, atyp, val, vlen); + vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen); vlen_in_bytes = vn->as_StoreVector()->memory_size(); } else if (n->req() == 3) { // Promote operands to vector @@ -1401,7 +1415,7 @@ in1 = in2; in2 = tmp; } - vn = VectorNode::make(C, opc, in1, in2, vlen, velt_basic_type(n)); + vn = VectorNode::make(opc, in1, in2, vlen, velt_basic_type(n)); vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } else { ShouldNotReachHere(); @@ -1450,11 +1464,11 @@ if (t != NULL && t->is_con()) { juint shift = t->get_con(); if (shift > mask) { // Unsigned cmp - cnt = ConNode::make(C, TypeInt::make(shift & mask)); + cnt = ConNode::make(TypeInt::make(shift & mask)); } } else { if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { - cnt = ConNode::make(C, TypeInt::make(mask)); + cnt = ConNode::make(TypeInt::make(mask)); _igvn.register_new_node_with_optimizer(cnt); cnt = new AndINode(opd, cnt); _igvn.register_new_node_with_optimizer(cnt); @@ -1462,7 +1476,7 @@ } assert(opd->bottom_type()->isa_int(), "int type only"); // Move non constant shift count into vector register. - cnt = VectorNode::shift_count(C, p0, cnt, vlen, velt_basic_type(p0)); + cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0)); } if (cnt != opd) { _igvn.register_new_node_with_optimizer(cnt); @@ -1475,7 +1489,7 @@ // p0's vector. Use p0's type because size of operand's container in // vector should match p0's size regardless operand's size. const Type* p0_t = velt_type(p0); - VectorNode* vn = VectorNode::scalar2vector(_phase->C, opd, vlen, p0_t); + VectorNode* vn = VectorNode::scalar2vector(opd, vlen, p0_t); _igvn.register_new_node_with_optimizer(vn); _phase->set_ctrl(vn, _phase->get_ctrl(opd)); @@ -1490,7 +1504,7 @@ // Insert pack operation BasicType bt = velt_basic_type(p0); - PackNode* pk = PackNode::make(_phase->C, opd, vlen, bt); + PackNode* pk = PackNode::make(opd, vlen, bt); DEBUG_ONLY( const BasicType opd_bt = opd->bottom_type()->basic_type(); ) for (uint i = 1; i < vlen; i++) { @@ -1546,7 +1560,7 @@ _igvn.hash_delete(def); int def_pos = alignment(def) / data_size(def); - Node* ex = ExtractNode::make(_phase->C, def, def_pos, velt_basic_type(def)); + Node* ex = ExtractNode::make(def, def_pos, velt_basic_type(def)); _igvn.register_new_node_with_optimizer(ex); _phase->set_ctrl(ex, _phase->get_ctrl(def)); _igvn.replace_input_of(use, idx, ex); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/type.cpp --- a/hotspot/src/share/vm/opto/type.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/type.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -5087,11 +5087,11 @@ // Dump Function Type #ifndef PRODUCT void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const { - if( _range->_cnt <= Parms ) + if( _range->cnt() <= Parms ) st->print("void"); else { uint i; - for (i = Parms; i < _range->_cnt-1; i++) { + for (i = Parms; i < _range->cnt()-1; i++) { _range->field_at(i)->dump2(d,depth,st); st->print("/"); } @@ -5104,9 +5104,9 @@ return; } d.Insert((void*)this,(void*)this); // Stop recursion - if (Parms < _domain->_cnt) + if (Parms < _domain->cnt()) _domain->field_at(Parms)->dump2(d,depth-1,st); - for (uint i = Parms+1; i < _domain->_cnt; i++) { + for (uint i = Parms+1; i < _domain->cnt(); i++) { st->print(", "); _domain->field_at(i)->dump2(d,depth-1,st); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/type.hpp --- a/hotspot/src/share/vm/opto/type.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/type.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -609,16 +609,16 @@ // signature types. class TypeTuple : public Type { TypeTuple( uint cnt, const Type **fields ) : Type(Tuple), _cnt(cnt), _fields(fields) { } + + const uint _cnt; // Count of fields + const Type ** const _fields; // Array of field types + public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous -public: - const uint _cnt; // Count of fields - const Type ** const _fields; // Array of field types - // Accessors: uint cnt() const { return _cnt; } const Type* field_at(uint i) const { @@ -1447,6 +1447,10 @@ virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous + + const TypeTuple* const _domain; // Domain of inputs + const TypeTuple* const _range; // Range of results + public: // Constants are shared among ADLC and VM enum { Control = AdlcVMDeps::Control, @@ -1457,8 +1461,6 @@ Parms = AdlcVMDeps::Parms }; - const TypeTuple* const _domain; // Domain of inputs - const TypeTuple* const _range; // Range of results // Accessors: const TypeTuple* domain() const { return _domain; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/vectornode.cpp --- a/hotspot/src/share/vm/opto/vectornode.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/vectornode.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, 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 @@ -245,7 +245,7 @@ } // Return the vector version of a scalar operation node. -VectorNode* VectorNode::make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt) { +VectorNode* VectorNode::make(int opc, Node* n1, Node* n2, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); int vopc = VectorNode::opcode(opc, bt); // This method should not be called for unimplemented vectors. @@ -299,7 +299,7 @@ } // Scalar promotion -VectorNode* VectorNode::scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t) { +VectorNode* VectorNode::scalar2vector(Node* s, uint vlen, const Type* opd_t) { BasicType bt = opd_t->array_element_basic_type(); const TypeVect* vt = opd_t->singleton() ? TypeVect::make(opd_t, vlen) : TypeVect::make(bt, vlen); @@ -323,7 +323,7 @@ return NULL; } -VectorNode* VectorNode::shift_count(Compile* C, Node* shift, Node* cnt, uint vlen, BasicType bt) { +VectorNode* VectorNode::shift_count(Node* shift, Node* cnt, uint vlen, BasicType bt) { assert(VectorNode::is_shift(shift) && !cnt->is_Con(), "only variable shift count"); // Match shift count type with shift vector type. const TypeVect* vt = TypeVect::make(bt, vlen); @@ -342,7 +342,7 @@ } // Return initial Pack node. Additional operands added with add_opd() calls. -PackNode* PackNode::make(Compile* C, Node* s, uint vlen, BasicType bt) { +PackNode* PackNode::make(Node* s, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); switch (bt) { case T_BOOLEAN: @@ -365,18 +365,18 @@ } // Create a binary tree form for Packs. [lo, hi) (half-open) range -PackNode* PackNode::binary_tree_pack(Compile* C, int lo, int hi) { +PackNode* PackNode::binary_tree_pack(int lo, int hi) { int ct = hi - lo; assert(is_power_of_2(ct), "power of 2"); if (ct == 2) { - PackNode* pk = PackNode::make(C, in(lo), 2, vect_type()->element_basic_type()); + PackNode* pk = PackNode::make(in(lo), 2, vect_type()->element_basic_type()); pk->add_opd(in(lo+1)); return pk; } else { int mid = lo + ct/2; - PackNode* n1 = binary_tree_pack(C, lo, mid); - PackNode* n2 = binary_tree_pack(C, mid, hi ); + PackNode* n1 = binary_tree_pack(lo, mid); + PackNode* n2 = binary_tree_pack(mid, hi ); BasicType bt = n1->vect_type()->element_basic_type(); assert(bt == n2->vect_type()->element_basic_type(), "should be the same"); @@ -402,23 +402,23 @@ } // Return the vector version of a scalar load node. -LoadVectorNode* LoadVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem, +LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, uint vlen, BasicType bt) { const TypeVect* vt = TypeVect::make(bt, vlen); return new LoadVectorNode(ctl, mem, adr, atyp, vt); } // Return the vector version of a scalar store node. -StoreVectorNode* StoreVectorNode::make(Compile* C, int opc, Node* ctl, Node* mem, +StoreVectorNode* StoreVectorNode::make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, Node* val, uint vlen) { return new StoreVectorNode(ctl, mem, adr, atyp, val); } // Extract a scalar element of vector. -Node* ExtractNode::make(Compile* C, Node* v, uint position, BasicType bt) { +Node* ExtractNode::make(Node* v, uint position, BasicType bt) { assert((int)position < Matcher::max_vector_size(bt), "pos in range"); - ConINode* pos = ConINode::make(C, (int)position); + ConINode* pos = ConINode::make((int)position); switch (bt) { case T_BOOLEAN: return new ExtractUBNode(v, pos); diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/opto/vectornode.hpp --- a/hotspot/src/share/vm/opto/vectornode.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/opto/vectornode.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, 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 @@ -52,9 +52,9 @@ virtual uint ideal_reg() const { return Matcher::vector_ideal_reg(vect_type()->length_in_bytes()); } - static VectorNode* scalar2vector(Compile* C, Node* s, uint vlen, const Type* opd_t); - static VectorNode* shift_count(Compile* C, Node* shift, Node* cnt, uint vlen, BasicType bt); - static VectorNode* make(Compile* C, int opc, Node* n1, Node* n2, uint vlen, BasicType bt); + static VectorNode* scalar2vector(Node* s, uint vlen, const Type* opd_t); + static VectorNode* shift_count(Node* shift, Node* cnt, uint vlen, BasicType bt); + static VectorNode* make(int opc, Node* n1, Node* n2, uint vlen, BasicType bt); static int opcode(int opc, BasicType bt); static bool implemented(int opc, uint vlen, BasicType bt); @@ -371,7 +371,7 @@ virtual int store_Opcode() const { return Op_StoreVector; } - static LoadVectorNode* make(Compile* C, int opc, Node* ctl, Node* mem, + static LoadVectorNode* make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, uint vlen, BasicType bt); }; @@ -394,7 +394,7 @@ virtual BasicType memory_type() const { return T_VOID; } virtual int memory_size() const { return vect_type()->length_in_bytes(); } - static StoreVectorNode* make(Compile* C, int opc, Node* ctl, Node* mem, + static StoreVectorNode* make(int opc, Node* ctl, Node* mem, Node* adr, const TypePtr* atyp, Node* val, uint vlen); }; @@ -465,9 +465,9 @@ } // Create a binary tree form for Packs. [lo, hi) (half-open) range - PackNode* binary_tree_pack(Compile* C, int lo, int hi); + PackNode* binary_tree_pack(int lo, int hi); - static PackNode* make(Compile* C, Node* s, uint vlen, BasicType bt); + static PackNode* make(Node* s, uint vlen, BasicType bt); }; //------------------------------PackBNode-------------------------------------- @@ -552,7 +552,7 @@ virtual int Opcode() const; uint pos() const { return in(2)->get_int(); } - static Node* make(Compile* C, Node* v, uint position, BasicType bt); + static Node* make(Node* v, uint position, BasicType bt); }; //------------------------------ExtractBNode----------------------------------- diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -1431,6 +1431,22 @@ (int)ObjectAlignmentInBytes, os::vm_page_size()); return false; } + if(SurvivorAlignmentInBytes == 0) { + SurvivorAlignmentInBytes = ObjectAlignmentInBytes; + } else { + if (!is_power_of_2(SurvivorAlignmentInBytes)) { + jio_fprintf(defaultStream::error_stream(), + "error: SurvivorAlignmentInBytes=%d must be power of 2\n", + (int)SurvivorAlignmentInBytes); + return false; + } + if (SurvivorAlignmentInBytes < ObjectAlignmentInBytes) { + jio_fprintf(defaultStream::error_stream(), + "error: SurvivorAlignmentInBytes=%d must be greater than ObjectAlignmentInBytes=%d \n", + (int)SurvivorAlignmentInBytes, (int)ObjectAlignmentInBytes); + return false; + } + } return true; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/deoptimization.cpp --- a/hotspot/src/share/vm/runtime/deoptimization.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -661,7 +661,7 @@ (iframe->interpreter_frame_expression_stack_size() == (next_mask_expression_stack_size - top_frame_expression_stack_adjustment))) || (is_top_frame && (exec_mode == Unpack_exception) && iframe->interpreter_frame_expression_stack_size() == 0) || - (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute) && + (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute || el->should_reexecute()) && (iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size)) )) { ttyLocker ttyl; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/frame.cpp --- a/hotspot/src/share/vm/runtime/frame.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/frame.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -407,7 +407,8 @@ address frame::interpreter_frame_bcp() const { assert(is_interpreted_frame(), "interpreted frame expected"); - return (address)*interpreter_frame_bcp_addr(); + address bcp = (address)*interpreter_frame_bcp_addr(); + return interpreter_frame_method()->bcp_from(bcp); } void frame::interpreter_frame_set_bcp(address bcp) { diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -1078,6 +1078,9 @@ product(bool, ClassUnloading, true, \ "Do unloading of classes") \ \ + product(bool, ClassUnloadingWithConcurrentMark, true, \ + "Do unloading of classes with a concurrent marking cycle") \ + \ develop(bool, DisableStartThread, false, \ "Disable starting of additional Java threads " \ "(for debugging only)") \ @@ -3871,6 +3874,9 @@ product(bool, PrintGCCause, true, \ "Include GC cause in GC logging") \ \ + experimental(intx, SurvivorAlignmentInBytes, 0, \ + "Default survivor space alignment in bytes") \ + \ product(bool , AllowNonVirtualCalls, false, \ "Obey the ACC_SUPER flag and allow invokenonvirtual calls") \ \ diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -27,20 +27,51 @@ #include -// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles -// [jk] this is not 100% correct because the float word order may different -// from the byte order (e.g. on ARM FPA) +// Used to access the lower/higher 32 bits of a double +typedef union { + double d; + struct { #ifdef VM_LITTLE_ENDIAN -# define __HI(x) *(1+(int*)&x) -# define __LO(x) *(int*)&x + int lo; + int hi; #else -# define __HI(x) *(int*)&x -# define __LO(x) *(1+(int*)&x) + int hi; + int lo; #endif + } split; +} DoubleIntConv; + +static inline int high(double d) { + DoubleIntConv x; + x.d = d; + return x.split.hi; +} + +static inline int low(double d) { + DoubleIntConv x; + x.d = d; + return x.split.lo; +} + +static inline void set_high(double* d, int high) { + DoubleIntConv conv; + conv.d = *d; + conv.split.hi = high; + *d = conv.d; +} + +static inline void set_low(double* d, int low) { + DoubleIntConv conv; + conv.d = *d; + conv.split.lo = low; + *d = conv.d; +} static double copysignA(double x, double y) { - __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000); - return x; + DoubleIntConv convX; + convX.d = x; + convX.split.hi = (convX.split.hi & 0x7fffffff) | (high(y) & 0x80000000); + return convX.d; } /* @@ -67,30 +98,32 @@ hugeX = 1.0e+300, tiny = 1.0e-300; -static double scalbnA (double x, int n) { +static double scalbnA(double x, int n) { int k,hx,lx; - hx = __HI(x); - lx = __LO(x); + hx = high(x); + lx = low(x); k = (hx&0x7ff00000)>>20; /* extract exponent */ if (k==0) { /* 0 or subnormal x */ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */ x *= two54; - hx = __HI(x); + hx = high(x); k = ((hx&0x7ff00000)>>20) - 54; if (n< -50000) return tiny*x; /*underflow*/ } if (k==0x7ff) return x+x; /* NaN or Inf */ k = k+n; - if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ - if (k > 0) /* normal result */ - {__HI(x) = (hx&0x800fffff)|(k<<20); return x;} + if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow */ + if (k > 0) { /* normal result */ + set_high(&x, (hx&0x800fffff)|(k<<20)); + return x; + } if (k <= -54) { if (n > 50000) /* in case integer overflow in n+k */ return hugeX*copysignA(hugeX,x); /*overflow*/ else return tiny*copysignA(tiny,x); /*underflow*/ } k += 54; /* subnormal result */ - __HI(x) = (hx&0x800fffff)|(k<<20); + set_high(&x, (hx&0x800fffff)|(k<<20)); return x*twom54; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -40,6 +40,7 @@ // generated; can not figure out how to turn down optimization for one // file in the IDE on Windows #ifdef WIN32 +# pragma warning( disable: 4748 ) // /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function # pragma optimize ( "", off ) #endif @@ -114,8 +115,8 @@ int k,hx,i,j; unsigned lx; - hx = __HI(x); /* high word of x */ - lx = __LO(x); /* low word of x */ + hx = high(x); /* high word of x */ + lx = low(x); /* low word of x */ k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ @@ -123,13 +124,13 @@ return -two54/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; hx &= 0x000fffff; i = (hx+0x95f64)&0x100000; - __HI(x) = hx|(i^0x3ff00000); /* normalize x or x/2 */ + set_high(&x, hx|(i^0x3ff00000)); /* normalize x or x/2 */ k += (i>>20); f = x-1.0; if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ @@ -208,8 +209,8 @@ int i,k,hx; unsigned lx; - hx = __HI(x); /* high word of x */ - lx = __LO(x); /* low word of x */ + hx = high(x); /* high word of x */ + lx = low(x); /* low word of x */ k=0; if (hx < 0x00100000) { /* x < 2**-1022 */ @@ -217,14 +218,14 @@ return -two54/zero; /* log(+-0)=-inf */ if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ k -= 54; x *= two54; /* subnormal number, scale up x */ - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ } if (hx >= 0x7ff00000) return x+x; k += (hx>>20)-1023; i = ((unsigned)k&0x80000000)>>31; hx = (hx&0x000fffff)|((0x3ff-i)<<20); y = (double)(k+i); - __HI(x) = hx; + set_high(&x, hx); z = y*log10_2lo + ivln10*__ieee754_log(x); return z+y*log10_2hi; } @@ -319,14 +320,14 @@ int k=0,xsb; unsigned hx; - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ xsb = (hx>>31)&1; /* sign bit of x */ hx &= 0x7fffffff; /* high word of |x| */ /* filter out non-finite argument */ if(hx >= 0x40862E42) { /* if |x|>=709.78... */ if(hx>=0x7ff00000) { - if(((hx&0xfffff)|__LO(x))!=0) + if(((hx&0xfffff)|low(x))!=0) return x+x; /* NaN */ else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ } @@ -357,10 +358,10 @@ if(k==0) return one-((x*c)/(c-2.0)-x); else y = one-((lo-(x*c)/(2.0-c))-hi); if(k >= -1021) { - __HI(y) += (k<<20); /* add k to y's exponent */ + set_high(&y, high(y) + (k<<20)); /* add k to y's exponent */ return y; } else { - __HI(y) += ((k+1000)<<20);/* add k to y's exponent */ + set_high(&y, high(y) + ((k+1000)<<20)); /* add k to y's exponent */ return y*twom1000; } } @@ -447,8 +448,8 @@ unsigned lx,ly; i0 = ((*(int*)&one)>>29)^1; i1=1-i0; - hx = __HI(x); lx = __LO(x); - hy = __HI(y); ly = __LO(y); + hx = high(x); lx = low(x); + hy = high(y); ly = low(y); ix = hx&0x7fffffff; iy = hy&0x7fffffff; /* y==zero: x**0 = 1 */ @@ -548,14 +549,14 @@ u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ v = t*ivln2_l-w*ivln2; t1 = u+v; - __LO(t1) = 0; + set_low(&t1, 0); t2 = v-(t1-u); } else { double ss,s2,s_h,s_l,t_h,t_l; n = 0; /* take care subnormal number */ if(ix<0x00100000) - {ax *= two53; n -= 53; ix = __HI(ax); } + {ax *= two53; n -= 53; ix = high(ax); } n += ((ix)>>20)-0x3ff; j = ix&0x000fffff; /* determine interval */ @@ -563,17 +564,17 @@ if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18); + set_high(&t_h, ((ix>>1)|0x20000000)+0x00080000+(k<<18)); t_l = ax - (t_h-bp[k]); s_l = v*((u-s_h*t_h)-s_h*t_l); /* compute log(ax) */ @@ -582,32 +583,32 @@ r += s_l*(s_h+ss); s2 = s_h*s_h; t_h = 3.0+s2+r; - __LO(t_h) = 0; + set_low(&t_h, 0); t_l = r-((t_h-3.0)-s2); /* u+v = ss*(1+...) */ u = s_h*t_h; v = s_l*t_h+t_l*ss; /* 2/(3log2)*(ss+...) */ p_h = u+v; - __LO(p_h) = 0; + set_low(&p_h, 0); p_l = v-(p_h-u); z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ z_l = cp_l*p_h+p_l*cp+dp_l[k]; /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ t = (double)n; t1 = (((z_h+z_l)+dp_h[k])+t); - __LO(t1) = 0; + set_low(&t1, 0); t2 = z_l-(((t1-t)-dp_h[k])-z_h); } /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ y1 = y; - __LO(y1) = 0; + set_low(&y1, 0); p_l = (y-y1)*t1+y*t2; p_h = y1*t1; z = p_l+p_h; - j = __HI(z); - i = __LO(z); + j = high(z); + i = low(z); if (j>=0x40900000) { /* z >= 1024 */ if(((j-0x40900000)|i)!=0) /* if z > 1024 */ return s*hugeX*hugeX; /* overflow */ @@ -631,13 +632,13 @@ n = j+(0x00100000>>(k+1)); k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ t = zeroX; - __HI(t) = (n&~(0x000fffff>>k)); + set_high(&t, (n&~(0x000fffff>>k))); n = ((n&0x000fffff)|0x00100000)>>(20-k); if(j<0) n = -n; p_h -= t; } t = p_l+p_h; - __LO(t) = 0; + set_low(&t, 0); u = t*lg2_h; v = (p_l-(t-p_h))*lg2+t*lg2_l; z = u+v; @@ -646,10 +647,10 @@ t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); r = (z*t1)/(t1-two)-(w+z*w); z = one-(r-z); - j = __HI(z); + j = high(z); j += (n<<20); if((j>>20)<=0) z = scalbnA(z,n); /* subnormal output */ - else __HI(z) += (n<<20); + else set_high(&z, high(z) + (n<<20)); return s*z; } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp Mon Aug 18 10:07:43 2014 +0100 @@ -519,7 +519,7 @@ { double z,r,v; int ix; - ix = __HI(x)&0x7fffffff; /* high word of x */ + ix = high(x)&0x7fffffff; /* high word of x */ if(ix<0x3e400000) /* |x| < 2**-27 */ {if((int)x==0) return x;} /* generate inexact */ z = x*x; @@ -574,9 +574,9 @@ static double __kernel_cos(double x, double y) { - double a,h,z,r,qx; + double a,h,z,r,qx=0; int ix; - ix = __HI(x)&0x7fffffff; /* ix = |x|'s high word*/ + ix = high(x)&0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x3e400000) { /* if x < 2**27 */ if(((int)x)==0) return one; /* generate inexact */ } @@ -588,8 +588,8 @@ if(ix > 0x3fe90000) { /* x > 0.78125 */ qx = 0.28125; } else { - __HI(qx) = ix-0x00200000; /* x/4 */ - __LO(qx) = 0; + set_high(&qx, ix-0x00200000); /* x/4 */ + set_low(&qx, 0); } h = 0.5*z-qx; a = one-qx; @@ -654,11 +654,11 @@ { double z,r,v,w,s; int ix,hx; - hx = __HI(x); /* high word of x */ + hx = high(x); /* high word of x */ ix = hx&0x7fffffff; /* high word of |x| */ if(ix<0x3e300000) { /* x < 2**-28 */ if((int)x==0) { /* generate inexact */ - if (((ix | __LO(x)) | (iy + 1)) == 0) + if (((ix | low(x)) | (iy + 1)) == 0) return one / fabsd(x); else { if (iy == 1) @@ -667,10 +667,10 @@ double a, t; z = w = x + y; - __LO(z) = 0; + set_low(&z, 0); v = y - (z - x); t = a = -one / w; - __LO(t) = 0; + set_low(&t, 0); s = one + t * z; return t + a * (s + t * v); } @@ -705,10 +705,10 @@ /* compute -1.0/(x+r) accurately */ double a,t; z = w; - __LO(z) = 0; + set_low(&z, 0); v = r-(z - x); /* z+v = r+x */ t = a = -1.0/w; /* a = -1.0/w */ - __LO(t) = 0; + set_low(&t, 0); s = 1.0+t*z; return t+a*(s+t*v); } @@ -757,7 +757,7 @@ int n, ix; /* High word of x. */ - ix = __HI(x); + ix = high(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; @@ -815,7 +815,7 @@ int n, ix; /* High word of x. */ - ix = __HI(x); + ix = high(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; @@ -872,7 +872,7 @@ int n, ix; /* High word of x. */ - ix = __HI(x); + ix = high(x); /* |x| ~< pi/4 */ ix &= 0x7fffffff; diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -558,6 +558,27 @@ return fabs(value); } +//---------------------------------------------------------------------------------------------------- +// Special casts +// Cast floats into same-size integers and vice-versa w/o changing bit-pattern +typedef union { + jfloat f; + jint i; +} FloatIntConv; + +typedef union { + jdouble d; + jlong l; + julong ul; +} DoubleLongConv; + +inline jint jint_cast (jfloat x) { return ((FloatIntConv*)&x)->i; } +inline jfloat jfloat_cast (jint x) { return ((FloatIntConv*)&x)->f; } + +inline jlong jlong_cast (jdouble x) { return ((DoubleLongConv*)&x)->l; } +inline julong julong_cast (jdouble x) { return ((DoubleLongConv*)&x)->ul; } +inline jdouble jdouble_cast (jlong x) { return ((DoubleLongConv*)&x)->d; } + inline jint low (jlong value) { return jint(value); } inline jint high(jlong value) { return jint(value >> 32); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -167,17 +167,6 @@ typedef uint32_t juint; typedef uint64_t julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern -// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } -inline julong julong_cast (jdouble x) { return *(julong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Constant for jlong (specifying an long long canstant is C++ compiler specific) diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -183,15 +183,6 @@ typedef unsigned int juint; typedef unsigned long long julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Constant for jlong (specifying an long long constant is C++ compiler specific) diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -116,16 +116,6 @@ typedef unsigned int juint; typedef unsigned __int64 julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } - //---------------------------------------------------------------------------------------------------- // Non-standard stdlib-like stuff: diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp Mon Aug 18 10:07:43 2014 +0100 @@ -114,16 +114,6 @@ typedef uint32_t juint; typedef uint64_t julong; -//---------------------------------------------------------------------------------------------------- -// Special (possibly not-portable) casts -// Cast floats into same-size integers and vice-versa w/o changing bit-pattern -// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar - -inline jint jint_cast (jfloat x) { return *(jint* )&x; } -inline jlong jlong_cast (jdouble x) { return *(jlong* )&x; } - -inline jfloat jfloat_cast (jint x) { return *(jfloat* )&x; } -inline jdouble jdouble_cast(jlong x) { return *(jdouble*)&x; } //---------------------------------------------------------------------------------------------------- // Constant for jlong (specifying an long long canstant is C++ compiler specific) diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/TEST.groups Mon Aug 18 10:07:43 2014 +0100 @@ -217,6 +217,7 @@ gc/arguments/TestMaxHeapSizeTools.java \ gc/arguments/TestMaxNewSize.java \ gc/arguments/TestUseCompressedOopsErgo.java \ + gc/class_unloading/TestG1ClassUnloadingHWM.java \ gc/g1/ \ gc/metaspace/G1AddMetaspaceDependency.java \ gc/metaspace/TestMetaspacePerfCounters.java \ @@ -257,7 +258,7 @@ gc/arguments/TestCMSHeapSizeFlags.java \ gc/arguments/TestMaxNewSize.java \ gc/arguments/TestUseCompressedOopsErgo.java \ - gc/class_unloading/TestCMSClassUnloadingDisabledHWM.java \ + gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java \ gc/concurrentMarkSweep/ \ gc/startup_warnings/TestCMS.java \ gc/startup_warnings/TestCMSIncrementalMode.java \ diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/5091921/Test7005594.sh --- a/hotspot/test/compiler/5091921/Test7005594.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/5091921/Test7005594.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, 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 @@ -78,7 +78,7 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7005594.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTOPTS} -Xmx1600m -Xms1600m -XX:+IgnoreUnrecognizedVMOptions -XX:-ZapUnusedHeapArea -Xcomp -XX:CompileOnly=Test7005594.test Test7005594 > test.out 2>&1 result=$? diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/6857159/Test6857159.sh --- a/hotspot/test/compiler/6857159/Test6857159.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/6857159/Test6857159.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2014, 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 @@ -39,7 +39,7 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test6857159.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTOPTS} -Xbatch -XX:+PrintCompilation -XX:CompileOnly=Test6857159\$ct.run Test6857159 > test.out 2>&1 grep "COMPILE SKIPPED" test.out diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/6894807/IsInstanceTest.java --- a/hotspot/test/compiler/6894807/IsInstanceTest.java Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/6894807/IsInstanceTest.java Mon Aug 18 10:07:43 2014 +0100 @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2012, 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* * @test * @bug 6894807 diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/6894807/Test6894807.sh --- a/hotspot/test/compiler/6894807/Test6894807.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/6894807/Test6894807.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,55 +1,38 @@ #!/bin/sh +# +# Copyright (c) 2012, 2014, 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# if [ "${TESTSRC}" = "" ] -then TESTSRC=. +then + TESTSRC=${PWD} + echo "TESTSRC not set. Using "${TESTSRC}" as default" fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi +echo "TESTSRC=${TESTSRC}" -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - NULL=/dev/null - PS=":" - FS="/" - ;; - Windows_* ) - NULL=NUL - PS=";" - FS="\\" - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac +## Adding common setup Variables for running shell tests. +. ${TESTSRC}/../../test_env.sh -JEMMYPATH=${CPAPPEND} -CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH - -THIS_DIR=`pwd` - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} IsInstanceTest > test.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} IsInstanceTest > test.out 2>&1 cat test.out diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/6932496/Test6932496.java --- a/hotspot/test/compiler/6932496/Test6932496.java Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/6932496/Test6932496.java Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, 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 @@ -26,26 +26,162 @@ * @test * @bug 6932496 * @summary incorrect deopt of jsr subroutine on 64 bit c1 - * - * @compile -source 1.5 -target 1.5 -XDjsrlimit=0 Test6932496.java - * @run main/othervm -Xcomp -XX:CompileOnly=Test6932496.m Test6932496 + * @run main/othervm -Xcomp -XX:CompileOnly=Test.test Test6932496 */ +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.io.IOException; -public class Test6932496 { - static class A { - volatile boolean flag = false; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.Type; +import jdk.internal.org.objectweb.asm.Label; + +public class Test6932496 extends ClassLoader { + private static final int CLASS_FILE_VERSION = 49; + private static final String CLASS_TEST = "Test"; + private static final String CLASS_OBJECT = "java/lang/Object"; + private static final String METHOD_INIT = ""; + private static final String METHOD_TEST = "test"; + private static final String DESC_VOID_METHOD = "()V"; + private static final String FIELD_FLAG = "flag"; + + public static void main(String[] args) { + Test6932496 test = new Test6932496(); + test.execute(); } - static void m() { + private void execute() { + byte[] bytecode = Test6932496.generateTestClass(); + try { - } finally { - A a = new A(); - a.flag = true; + Files.write(Paths.get("Test.class.dump"), bytecode); + } catch (IOException e) { + System.err.println("classfile dump failed : " + e.getMessage()); + e.printStackTrace(); + } + try { + Class aClass = defineClass(CLASS_TEST, bytecode, 0, bytecode.length); + Method test = aClass.getDeclaredMethod(METHOD_TEST); + test.invoke(null); + } catch (ClassFormatError | IllegalArgumentException + | ReflectiveOperationException e) { + throw new RuntimeException("TESTBUG : generated class is invalid", e); } } + /* + public class Test { + volatile boolean flag = false; + public static void m() { + try { + } finally { + Test test = new Test(); + test.flag = true; + } + } + } + */ + private static byte[] generateTestClass() { + ClassWriter cw = new ClassWriter(0); + cw.visit(CLASS_FILE_VERSION, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, + CLASS_TEST, null, CLASS_OBJECT, null); + // volatile boolean flag; + { + FieldVisitor fv = cw.visitField(Opcodes.ACC_VOLATILE, FIELD_FLAG, + Type.BOOLEAN_TYPE.getDescriptor(), + /* signature = */ null, /* value = */ null); + } - static public void main(String[] args) { - m(); + /* + public Test() { + flag = false; + } + */ + { + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, + METHOD_INIT, DESC_VOID_METHOD, + /* signature = */ null, /* exceptions = */ null); + + mv.visitCode(); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_OBJECT, METHOD_INIT, + DESC_VOID_METHOD, false); + + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitFieldInsn(Opcodes.PUTFIELD, CLASS_TEST, FIELD_FLAG, + Type.BOOLEAN_TYPE.getDescriptor()); + + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(/* stack = */ 2, /* locals = */ 1); + mv.visitEnd(); + } + + /* + public static void m() { + try { + } finally { + Test test = new Test(); + test.flag = true; + } + } + */ + { + MethodVisitor mv = cw.visitMethod( + Opcodes.ACC_STATIC + Opcodes.ACC_PUBLIC, + METHOD_TEST, DESC_VOID_METHOD, + /* signature = */ null, /* exceptions = */ null); + Label beginLabel = new Label(); + Label block1EndLabel = new Label(); + Label handlerLabel = new Label(); + Label block2EndLabel = new Label(); + Label label = new Label(); + Label endLabel = new Label(); + + mv.visitCode(); + mv.visitTryCatchBlock(beginLabel, block1EndLabel, handlerLabel, + /* type = */ null); + mv.visitTryCatchBlock(handlerLabel, block2EndLabel, handlerLabel, + /* type = */ null); + + mv.visitLabel(beginLabel); + mv.visitJumpInsn(Opcodes.JSR, label); + mv.visitLabel(block1EndLabel); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + + mv.visitLabel(handlerLabel); + mv.visitVarInsn(Opcodes.ASTORE, 0); + mv.visitJumpInsn(Opcodes.JSR, label); + mv.visitLabel(block2EndLabel); + mv.visitVarInsn(Opcodes.ALOAD, 0); + mv.visitInsn(Opcodes.ATHROW); + + mv.visitLabel(label); + mv.visitVarInsn(Opcodes.ASTORE, 1); + mv.visitTypeInsn(Opcodes.NEW, CLASS_TEST); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, CLASS_TEST, METHOD_INIT, + DESC_VOID_METHOD); + mv.visitVarInsn(Opcodes.ASTORE, 2); + + mv.visitVarInsn(Opcodes.ALOAD, 2); + mv.visitInsn(Opcodes.ICONST_1); + mv.visitFieldInsn(Opcodes.PUTFIELD, CLASS_TEST, FIELD_FLAG, + Type.BOOLEAN_TYPE.getDescriptor()); + + mv.visitVarInsn(Opcodes.RET, 1); + + mv.visitLabel(endLabel); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(/* stack = */ 2, /* locals = */ 3); + mv.visitEnd(); + } + + cw.visitEnd(); + return cw.toByteArray(); } } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/7068051/Test7068051.sh --- a/hotspot/test/compiler/7068051/Test7068051.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/7068051/Test7068051.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, 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 @@ -41,5 +41,5 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Test7068051.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -showversion -Xbatch Test7068051 foo.jar +${TESTJAVA}/bin/java ${TESTOPTS} -showversion -Xbatch Test7068051 foo.jar diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/7070134/Test7070134.sh --- a/hotspot/test/compiler/7070134/Test7070134.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/7070134/Test7070134.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2014, 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 @@ -39,7 +39,7 @@ ${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} -d . Stemmer.java -${TESTJAVA}/bin/java ${TESTVMOPTS} -Xbatch Stemmer words > test.out 2>&1 +${TESTJAVA}/bin/java ${TESTOPTS} -Xbatch Stemmer words > test.out 2>&1 exit $? diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/7200264/Test7200264.sh --- a/hotspot/test/compiler/7200264/Test7200264.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/7200264/Test7200264.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2014, 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 @@ -33,7 +33,7 @@ ## Adding common setup Variables for running shell tests. . ${TESTSRC}/../../test_env.sh -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion | sed 's/amd64/x86/' | grep "x86" | grep "Server VM" | grep "debug" +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xinternalversion | sed 's/amd64/x86/' | grep "x86" | grep "Server VM" | grep "debug" # Only test fastdebug Server VM on x86 if [ $? != 0 ] @@ -43,7 +43,7 @@ fi # grep for support integer multiply vectors (cpu with SSE4.1) -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -XX:+PrintMiscellaneous -XX:+Verbose -version | grep "cores per cpu" | grep "sse4.1" +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -XX:+PrintMiscellaneous -XX:+Verbose -version | grep "cores per cpu" | grep "sse4.1" if [ $? != 0 ] then @@ -55,7 +55,7 @@ cp ${TESTSRC}${FS}TestIntVect.java . ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} -d . TestIntVect.java -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+PrintCompilation -XX:+TraceNewVectors TestIntVect > test.out 2>&1 COUNT=`grep AddVI test.out | wc -l | awk '{print $1}'` if [ $COUNT -lt 4 ] diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/ciReplay/TestSA.sh --- a/hotspot/test/compiler/ciReplay/TestSA.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/ciReplay/TestSA.sh Mon Aug 18 10:07:43 2014 +0100 @@ -68,7 +68,7 @@ fi echo "dumpreplaydata -a > ${replay_data}" | \ - ${JAVA} ${TESTVMOPTS} \ + ${JAVA} ${TESTOPTS} \ -cp ${TESTJAVA}${FS}lib${FS}sa-jdi.jar \ sun.jvm.hotspot.CLHSDB ${JAVA} ${core_file} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/ciReplay/common.sh --- a/hotspot/test/compiler/ciReplay/common.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/compiler/ciReplay/common.sh Mon Aug 18 10:07:43 2014 +0100 @@ -22,6 +22,7 @@ # questions. # # +set -x # $1 - error code # $2 - test name @@ -56,7 +57,7 @@ shift name=$1 shift - VMOPTS="${TESTVMOPTS} $@" + VMOPTS="${TESTOPTS} $@" echo "POSITIVE TEST [$name]" start_test ${VMOPTS} exit_code=$? @@ -75,7 +76,7 @@ shift name=$1 shift - VMOPTS="${TESTVMOPTS} $@" + VMOPTS="${TESTOPTS} $@" echo "NEGATIVE TEST [$name]" start_test ${VMOPTS} exit_code=$? @@ -149,7 +150,7 @@ replay_data=test_replay.txt -${JAVA} ${TESTVMOPTS} -Xinternalversion 2>&1 | grep debug +${JAVA} ${TESTOPTS} -Xinternalversion 2>&1 | grep debug # Only test fastdebug if [ $? -ne 0 ] @@ -158,7 +159,7 @@ exit 0 fi -is_int=`${JAVA} ${TESTVMOPTS} -version 2>&1 | grep -c "interpreted mode"` +is_int=`${JAVA} ${TESTOPTS} -version 2>&1 | grep -c "interpreted mode"` # Not applicable for Xint if [ $is_int -ne 0 ] then @@ -168,14 +169,14 @@ cleanup -client_available=`${JAVA} ${TESTVMOPTS} -client -Xinternalversion 2>&1 | \ +client_available=`${JAVA} ${TESTOPTS} -client -Xinternalversion 2>&1 | \ grep -c Client` -server_available=`${JAVA} ${TESTVMOPTS} -server -Xinternalversion 2>&1 | \ +server_available=`${JAVA} ${TESTOPTS} -server -Xinternalversion 2>&1 | \ grep -c Server` -tiered_available=`${JAVA} ${TESTVMOPTS} -XX:+TieredCompilation -XX:+PrintFlagsFinal -version | \ +tiered_available=`${JAVA} ${TESTOPTS} -XX:+TieredCompilation -XX:+PrintFlagsFinal -version | \ grep TieredCompilation | \ grep -c true` -is_tiered=`${JAVA} ${TESTVMOPTS} -XX:+PrintFlagsFinal -version | \ +is_tiered=`${JAVA} ${TESTOPTS} -XX:+PrintFlagsFinal -version | \ grep TieredCompilation | \ grep -c true` # CompLevel_simple -- C1 @@ -207,7 +208,7 @@ fi fi - cmd="${JAVA} ${TESTVMOPTS} $@ \ + cmd="${JAVA} ${TESTOPTS} $@ \ -Xms8m \ -Xmx32m \ -XX:MetaspaceSize=4m \ diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.hotspot.WhiteBox; + +import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + +/* + * @test MethodUnloadingTest + * @bug 8029443 + * @summary "Tests the unloading of methods to to class unloading" + * @library /testlibrary /testlibrary/whitebox + * @build TestMethodUnloading + * @build WorkerClass + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseCompressedOops -XX:+UseParallelGC -XX:CompileOnly=TestMethodUnloading::doWork TestMethodUnloading + */ +public class TestMethodUnloading { + private static final String workerClassName = "WorkerClass"; + private static int work = -1; + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static int COMP_LEVEL_SIMPLE = 1; + private static int COMP_LEVEL_FULL_OPTIMIZATION = 4; + + /** + * Does some work by either using the workerClass or locally producing values. + * @param workerClass Class performing some work (will be unloaded) + * @param useWorker If true the workerClass is used + */ + static private void doWork(Class workerClass, boolean useWorker) throws InstantiationException, IllegalAccessException { + if (useWorker) { + // Create a new instance + Object worker = workerClass.newInstance(); + // We would like to call a method of WorkerClass here but we cannot cast to WorkerClass + // because the class was loaded by a different class loader. One solution would be to use + // reflection but since we want C2 to implement the call as an optimized IC we call + // Object::hashCode() here which actually calls WorkerClass::hashCode(). + // C2 will then implement this call as an optimized IC that points to a to-interpreter stub + // referencing the Method* for WorkerClass::hashCode(). + work = worker.hashCode(); + if (work != 42) { + new RuntimeException("Work not done"); + } + } else { + // Do some important work here + work = 1; + } + } + + /** + * Makes sure that method is compiled by forcing compilation if not yet compiled. + * @param m Method to be checked + */ + static private void makeSureIsCompiled(Method m) { + // Make sure background compilation is disabled + if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) { + throw new RuntimeException("Background compilation enabled"); + } + + // Check if already compiled + if (!WHITE_BOX.isMethodCompiled(m)) { + // If not, try to compile it with C2 + if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) { + // C2 compiler not available, try to compile with C1 + WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE); + } + // Because background compilation is disabled, method should now be compiled + if(!WHITE_BOX.isMethodCompiled(m)) { + throw new RuntimeException(m + " not compiled"); + } + } + } + + /** + * This test creates stale Method* metadata in a to-interpreter stub of an optimized IC. + * + * The following steps are performed: + * (1) A workerClass is loaded by a custom class loader + * (2) The method doWork that calls a method of the workerClass is compiled. The call + * is implemented as an optimized IC calling a to-interpreted stub. The to-interpreter + * stub contains a Method* to a workerClass method. + * (3) Unloading of the workerClass is enforced. The to-interpreter stub now contains a dead Method*. + * (4) Depending on the implementation of the IC, the compiled version of doWork should still be + * valid. We call it again without using the workerClass. + */ + static public void main(String[] args) throws Exception { + // (1) Create a custom class loader with no parent class loader + URL url = TestMethodUnloading.class.getProtectionDomain().getCodeSource().getLocation(); + URLClassLoader loader = new URLClassLoader(new URL[] {url}, null); + + // Load worker class with custom class loader + Class workerClass = Class.forName(workerClassName, true, loader); + + // (2) Make sure all paths of doWork are profiled and compiled + for (int i = 0; i < 100000; ++i) { + doWork(workerClass, true); + doWork(workerClass, false); + } + + // Make sure doWork is compiled now + Method doWork = TestMethodUnloading.class.getDeclaredMethod("doWork", Class.class, boolean.class); + makeSureIsCompiled(doWork); + + // (3) Throw away class loader and reference to workerClass to allow unloading + loader.close(); + loader = null; + workerClass = null; + + // Force garbage collection to trigger unloading of workerClass + // Dead reference to WorkerClass::hashCode triggers JDK-8029443 + WHITE_BOX.fullGC(); + + // (4) Depending on the implementation of the IC, the compiled version of doWork + // may still be valid here. Execute it without a workerClass. + doWork(null, false); + if (work != 1) { + throw new RuntimeException("Work not done"); + } + + doWork(Object.class, false); + } +} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Worker class that is dynamically loaded/unloaded by TestMethodUnloading. + */ +public class WorkerClass { + /** + * We override hashCode here to be able to access this implementation + * via an Object reference (we cannot cast to WorkerClass). + */ + @Override + public int hashCode() { + return 42; + } +} + diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/macronodes/TestEliminateAllocationPhi.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/macronodes/TestEliminateAllocationPhi.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8046698 + * @summary PhiNode inserted between AllocateNode and Initialization node confuses allocation elimination + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestEliminateAllocationPhi + * + */ + +public class TestEliminateAllocationPhi { + + // This will return I when called from m(0 and once optimized will + // go away but this will confuse escape analysis in m(): it will + // find I as non escaping but non scalar replaceable. In its own + // method so that we can make the profile of the if() branch look + // like it's taken sometimes. + static Integer m2(Integer I, int i) { + for (; i < 10; i=(i+2)*(i+2)) { + } + if (i == 121) { + return II; + } + return I; + } + + static Integer II = new Integer(42); + + static int m(int[] integers, boolean flag) { + int j = 0; + while(true) { + try { + int k = integers[j++]; + // A branch that will cause loop unswitching + if (flag) { + k += 42; + } + if (k < 1000) { + throw new Exception(); + } + // Because of the try/catch the Allocate node for this + // new will be in the loop while the Initialization + // node will be outside the loop. When loop + // unswitching happens, the Allocate node will be + // cloned and the results of both will be inputs to a + // Phi that will be between the Allocate nodes and the + // Initialization nodes. + Integer I = new Integer(k); + + I = m2(I, 0); + + int i = I.intValue(); + return i; + } catch(Exception e) { + } + } + } + + static public void main(String[] args) { + for (int i = 0; i < 5000; i++) { + m2(null, 1); + } + + int[] integers = { 2000 }; + for (int i = 0; i < 6000; i++) { + m(integers, (i%2) == 0); + } + int[] integers2 = { 1, 2, 3, 4, 5, 2000 }; + for (int i = 0; i < 10000; i++) { + m(integers2, (i%2) == 0); + } + } +} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.Label; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import static jdk.internal.org.objectweb.asm.Opcodes.*; + +/** + * @test + * @bug 8051344 + * @summary Force OSR compilation with non-empty stack at the OSR entry point. + * @compile -XDignore.symbol.file TestOSRWithNonEmptyStack.java + * @run main/othervm -XX:CompileOnly=TestCase.test TestOSRWithNonEmptyStack + */ +public class TestOSRWithNonEmptyStack extends ClassLoader { + private static final int CLASS_FILE_VERSION = 52; + private static final String CLASS_NAME = "TestCase"; + private static final String METHOD_NAME = "test"; + private static final int ITERATIONS = 1_000_000; + + private static byte[] generateTestClass() { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + + cw.visit(TestOSRWithNonEmptyStack.CLASS_FILE_VERSION, ACC_PUBLIC, + TestOSRWithNonEmptyStack.CLASS_NAME, null, "java/lang/Object", + null); + + TestOSRWithNonEmptyStack.generateConstructor(cw); + TestOSRWithNonEmptyStack.generateTestMethod(cw); + + cw.visitEnd(); + return cw.toByteArray(); + } + + private static void generateConstructor(ClassWriter classWriter) { + MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, "", "()V", + null, null); + + mv.visitCode(); + + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", + false); + mv.visitInsn(RETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private static void generateTestMethod(ClassWriter classWriter) { + MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, + TestOSRWithNonEmptyStack.METHOD_NAME, "()V", null, null); + Label osrEntryPoint = new Label(); + + mv.visitCode(); + // Push 'this' into stack before OSR entry point to bail out compilation + mv.visitVarInsn(ALOAD, 0); + // Setup loop counter + mv.visitInsn(ICONST_0); + mv.visitVarInsn(ISTORE, 1); + // Begin loop + mv.visitLabel(osrEntryPoint); + // Increment loop counter + mv.visitVarInsn(ILOAD, 1); + mv.visitInsn(ICONST_1); + mv.visitInsn(IADD); + // Duplicate it for loop condition check + mv.visitInsn(DUP); + mv.visitVarInsn(ISTORE, 1); + // Check loop condition + mv.visitLdcInsn(TestOSRWithNonEmptyStack.ITERATIONS); + mv.visitJumpInsn(IF_ICMPLT, osrEntryPoint); + // Pop 'this'. + mv.visitInsn(POP); + mv.visitInsn(RETURN); + + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + private void run() { + byte[] bytecode = TestOSRWithNonEmptyStack.generateTestClass(); + + try { + Class klass = defineClass(TestOSRWithNonEmptyStack.CLASS_NAME, + bytecode, 0, bytecode.length); + + Constructor ctor = klass.getConstructor(); + Method method = klass.getDeclaredMethod( + TestOSRWithNonEmptyStack.METHOD_NAME); + + Object testCase = ctor.newInstance(); + method.invoke(testCase); + } catch (Exception e) { + throw new RuntimeException( + "Test bug: generated class should be valid.", e); + } + } + + public static void main(String args[]) { + new TestOSRWithNonEmptyStack().run(); + } +} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.hotspot.WhiteBox; + +class AllocateBeyondMetaspaceSize { + public static Object dummy; + + public static void main(String [] args) { + if (args.length != 2) { + throw new IllegalArgumentException("Usage: "); + } + + long metaspaceSize = Long.parseLong(args[0]); + long youngGenSize = Long.parseLong(args[1]); + + run(metaspaceSize, youngGenSize); + } + + private static void run(long metaspaceSize, long youngGenSize) { + WhiteBox wb = WhiteBox.getWhiteBox(); + + long allocationBeyondMetaspaceSize = metaspaceSize * 2; + long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); + + triggerYoungGC(youngGenSize); + + wb.freeMetaspace(null, metaspace, metaspace); + } + + private static void triggerYoungGC(long youngGenSize) { + long approxAllocSize = 32 * 1024; + long numAllocations = 2 * youngGenSize / approxAllocSize; + + for (long i = 0; i < numAllocations; i++) { + dummy = new byte[(int)approxAllocSize]; + } + } +} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key gc + * @bug 8049831 + * @library /testlibrary /testlibrary/whitebox + * @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver TestCMSClassUnloadingEnabledHWM + * @summary Test that -XX:-CMSClassUnloadingEnabled will trigger a Full GC when more than MetaspaceSize metadata is allocated. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.util.ArrayList; +import java.util.Arrays; + +public class TestCMSClassUnloadingEnabledHWM { + private static long MetaspaceSize = 32 * 1024 * 1024; + private static long YoungGenSize = 32 * 1024 * 1024; + + private static OutputAnalyzer run(boolean enableUnloading) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+WhiteBoxAPI", + "-XX:MetaspaceSize=" + MetaspaceSize, + "-Xmn" + YoungGenSize, + "-XX:+UseConcMarkSweepGC", + "-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled", + "-XX:+PrintHeapAtGC", + "-XX:+PrintGCDetails", + "AllocateBeyondMetaspaceSize", + "" + MetaspaceSize, + "" + YoungGenSize); + return new OutputAnalyzer(pb.start()); + } + + public static OutputAnalyzer runWithCMSClassUnloading() throws Exception { + return run(true); + } + + public static OutputAnalyzer runWithoutCMSClassUnloading() throws Exception { + return run(false); + } + + public static void testWithoutCMSClassUnloading() throws Exception { + // -XX:-CMSClassUnloadingEnabled is used, so we expect a full GC instead of a concurrent cycle. + OutputAnalyzer out = runWithoutCMSClassUnloading(); + + out.shouldMatch(".*Full GC.*"); + out.shouldNotMatch(".*CMS Initial Mark.*"); + } + + public static void testWithCMSClassUnloading() throws Exception { + // -XX:+CMSClassUnloadingEnabled is used, so we expect a concurrent cycle instead of a full GC. + OutputAnalyzer out = runWithCMSClassUnloading(); + + out.shouldMatch(".*CMS Initial Mark.*"); + out.shouldNotMatch(".*Full GC.*"); + } + + public static void main(String args[]) throws Exception { + testWithCMSClassUnloading(); + testWithoutCMSClassUnloading(); + } +} + diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key gc + * @bug 8049831 + * @library /testlibrary /testlibrary/whitebox + * @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver TestG1ClassUnloadingHWM + * @summary Test that -XX:-ClassUnloadingWithConcurrentMark will trigger a Full GC when more than MetaspaceSize metadata is allocated. + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.util.ArrayList; +import java.util.Arrays; + +public class TestG1ClassUnloadingHWM { + private static long MetaspaceSize = 32 * 1024 * 1024; + private static long YoungGenSize = 32 * 1024 * 1024; + + private static OutputAnalyzer run(boolean enableUnloading) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+WhiteBoxAPI", + "-XX:MetaspaceSize=" + MetaspaceSize, + "-Xmn" + YoungGenSize, + "-XX:+UseG1GC", + "-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark", + "-XX:+PrintHeapAtGC", + "-XX:+PrintGCDetails", + "AllocateBeyondMetaspaceSize", + "" + MetaspaceSize, + "" + YoungGenSize); + return new OutputAnalyzer(pb.start()); + } + + public static OutputAnalyzer runWithG1ClassUnloading() throws Exception { + return run(true); + } + + public static OutputAnalyzer runWithoutG1ClassUnloading() throws Exception { + return run(false); + } + + public static void testWithoutG1ClassUnloading() throws Exception { + // -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC instead of a concurrent cycle. + OutputAnalyzer out = runWithoutG1ClassUnloading(); + + out.shouldMatch(".*Full GC.*"); + out.shouldNotMatch(".*initial-mark.*"); + } + + public static void testWithG1ClassUnloading() throws Exception { + // -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle instead of a full GC. + OutputAnalyzer out = runWithG1ClassUnloading(); + + out.shouldMatch(".*initial-mark.*"); + out.shouldNotMatch(".*Full GC.*"); + } + + public static void main(String args[]) throws Exception { + testWithG1ClassUnloading(); + testWithoutG1ClassUnloading(); + } +} + diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestEagerReclaimHumongousRegions + * @bug 8027959 + * @summary Test to make sure that eager reclaim of humongous objects work. We simply try to fill + * up the heap with humongous objects that should be eagerly reclaimable to avoid Full GC. + * @key gc + * @library /testlibrary + */ + +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.LinkedList; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Asserts; + +class ReclaimRegionFast { + public static final int M = 1024*1024; + + public static LinkedList garbageList = new LinkedList(); + + public static void genGarbage() { + for (int i = 0; i < 32*1024; i++) { + garbageList.add(new int[100]); + } + garbageList.clear(); + } + + // A large object referenced by a static. + static int[] filler = new int[10 * M]; + + public static void main(String[] args) { + + int[] large = new int[M]; + + Object ref_from_stack = large; + + for (int i = 0; i < 100; i++) { + // A large object that will be reclaimed eagerly. + large = new int[6*M]; + genGarbage(); + // Make sure that the compiler cannot completely remove + // the allocation of the large object until here. + System.out.println(large); + } + + // Keep the reference to the first object alive. + System.out.println(ref_from_stack); + } +} + +public class TestEagerReclaimHumongousRegions { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn16M", + "-XX:+PrintGC", + ReclaimRegionFast.class.getName()); + + Pattern p = Pattern.compile("Full GC"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + int found = 0; + Matcher m = p.matcher(output.getStdout()); + while (m.find()) { found++; } + System.out.println("Issued " + found + " Full GCs"); + Asserts.assertLT(found, 10, "Found that " + found + " Full GCs were issued. This is larger than the bound. Eager reclaim seems to not work at all"); + + output.shouldHaveExitValue(0); + } +} diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java Mon Aug 18 10:07:43 2014 +0100 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestEagerReclaimHumongousRegions2 + * @bug 8051973 + * @summary Test to make sure that eager reclaim of humongous objects correctly clears + * mark bitmaps at reclaim. + * @key gc + * @library /testlibrary + */ + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.Random; + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +// An object that has a few references to other instances to slow down marking. +class ObjectWithSomeRefs { + public ObjectWithSomeRefs other1; + public ObjectWithSomeRefs other2; + public ObjectWithSomeRefs other3; + public ObjectWithSomeRefs other4; +} + +class ReclaimRegionFast { + public static final int M = 1024*1024; + + public static LinkedList garbageList = new LinkedList(); + + public static void genGarbage(Object large) { + for (int i = 0; i < 64*1024; i++) { + Object[] garbage = new Object[50]; + garbage[0] = large; + garbageList.add(garbage); + } + garbageList.clear(); + } + + public static ArrayList longList = new ArrayList(); + + public static void main(String[] args) { + + for (int i = 0; i < 16*1024; i++) { + longList.add(new ObjectWithSomeRefs()); + } + + Random rnd = new Random(); + for (int i = 0; i < longList.size(); i++) { + int len = longList.size(); + longList.get(i).other1 = longList.get(rnd.nextInt(len)); + longList.get(i).other2 = longList.get(rnd.nextInt(len)); + longList.get(i).other3 = longList.get(rnd.nextInt(len)); + longList.get(i).other4 = longList.get(rnd.nextInt(len)); + } + + int[] large1 = new int[M]; + int[] large2 = null; + int[] large3 = null; + int[] large4 = null; + + Object ref_from_stack = large1; + + for (int i = 0; i < 20; i++) { + // A set of large objects that will be reclaimed eagerly - and hopefully marked. + large1 = new int[M - 20]; + large2 = new int[M - 20]; + large3 = new int[M - 20]; + large4 = new int[M - 20]; + genGarbage(large1); + // Make sure that the compiler cannot completely remove + // the allocation of the large object until here. + System.out.println(large1 + " " + large2 + " " + large3 + " " + large4); + } + + // Keep the reference to the first object alive. + System.out.println(ref_from_stack); + } +} + +public class TestEagerReclaimHumongousRegions2 { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn2M", + "-XX:G1HeapRegionSize=1M", + "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks. + "-XX:+PrintGC", + "-XX:+VerifyAfterGC", + "-XX:ConcGCThreads=1", // Want to make marking as slow as possible. + "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only. + "-XX:+G1VerifyBitmaps", + ReclaimRegionFast.class.getName()); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } +} + diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/gc/g1/TestGCLogMessages.java --- a/hotspot/test/gc/g1/TestGCLogMessages.java Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/gc/g1/TestGCLogMessages.java Mon Aug 18 10:07:43 2014 +0100 @@ -23,7 +23,7 @@ /* * @test TestGCLogMessages - * @bug 8035406 8027295 8035398 8019342 + * @bug 8035406 8027295 8035398 8019342 8027959 * @summary Ensure that the PrintGCDetails output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -54,6 +54,7 @@ output.shouldNotContain("[String Dedup Fixup"); output.shouldNotContain("[Young Free CSet"); output.shouldNotContain("[Non-Young Free CSet"); + output.shouldNotContain("[Humongous Reclaim"); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", @@ -71,6 +72,10 @@ output.shouldContain("[String Dedup Fixup"); output.shouldNotContain("[Young Free CSet"); output.shouldNotContain("[Non-Young Free CSet"); + output.shouldContain("[Humongous Reclaim"); + output.shouldNotContain("[Humongous Total"); + output.shouldNotContain("[Humongous Candidate"); + output.shouldNotContain("[Humongous Reclaimed"); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", @@ -90,6 +95,10 @@ output.shouldContain("[String Dedup Fixup"); output.shouldContain("[Young Free CSet"); output.shouldContain("[Non-Young Free CSet"); + output.shouldContain("[Humongous Reclaim"); + output.shouldContain("[Humongous Total"); + output.shouldContain("[Humongous Candidate"); + output.shouldContain("[Humongous Reclaimed"); output.shouldHaveExitValue(0); } diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/6626217/Test6626217.sh --- a/hotspot/test/runtime/6626217/Test6626217.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/6626217/Test6626217.sh Mon Aug 18 10:07:43 2014 +0100 @@ -69,7 +69,7 @@ ${MV} many_loader.impl1 many_loader.class ${RM} many_loader.java -${JAVA} ${TESTVMOPTS} -Xverify -Xint -cp . bug_21227 >test.out 2>&1 +${JAVA} ${TESTOPTS} -Xverify -Xint -cp . bug_21227 >test.out 2>&1 grep "loader constraint" test.out exit $? diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/6888954/vmerrors.sh --- a/hotspot/test/runtime/6888954/vmerrors.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/6888954/vmerrors.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,4 +1,4 @@ -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2014, 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 @@ -44,6 +44,16 @@ # export TESTJAVA TESTVMOPTS # sh test/runtime/6888954/vmerrors.sh +if [ "${TESTSRC}" = "" ] +then + TESTSRC=${PWD} + echo "TESTSRC not set. Using "${TESTSRC}" as default" +fi +echo "TESTSRC=${TESTSRC}" + +## Adding common setup Variables for running shell tests. +. ${TESTSRC}/../../test_env.sh + ulimit -c 0 # no core files i=1 @@ -84,7 +94,7 @@ i2=$i [ $i -lt 10 ] && i2=0$i - "$TESTJAVA/bin/java" $TESTVMOPTS -XX:+IgnoreUnrecognizedVMOptions \ + "$TESTJAVA/bin/java" $TESTOPTS -XX:+IgnoreUnrecognizedVMOptions \ -XX:-TransmitErrorReport -XX:-CreateMinidumpOnCrash \ -XX:ErrorHandlerTest=${i} -version > ${i2}.out 2>&1 diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/7107135/Test7107135.sh --- a/hotspot/test/runtime/7107135/Test7107135.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/7107135/Test7107135.sh Mon Aug 18 10:07:43 2014 +0100 @@ -25,7 +25,6 @@ # ## -## @ignore 8025519 ## @test Test7107135.sh ## @bug 7107135 ## @bug 8021296 diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/7116786/Test7116786.java --- a/hotspot/test/runtime/7116786/Test7116786.java Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/7116786/Test7116786.java Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, 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 @@ -147,7 +147,8 @@ "no stackmap frame at jump location or bad jump", "Inconsistent stackmap frames at branch target "), - new Case("case15", "stackMapTable.cpp", true, "check_new_object", + /* Backward jump with uninit is allowed starting with JDK 8 */ + new Case("case15", "stackMapTable.cpp", false, "check_new_object", "backward jump with uninit", "Uninitialized object exists on backward branch "), diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/7162488/Test7162488.sh --- a/hotspot/test/runtime/7162488/Test7162488.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/7162488/Test7162488.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2014, 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 @@ -45,14 +45,14 @@ # OPTION=this_is_not_an_option -${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep "Unrecognized VM option" +${JAVA} -showversion -XX:${OPTION} 2>&1 | grep "Unrecognized VM option" if [ "$?" != "0" ] then printf "FAILED: option not flagged as unrecognized.\n" exit 1 fi -${JAVA} ${TESTVMOPTS} -showversion -XX:${OPTION} 2>&1 | grep ${OPTION} +${JAVA} -showversion -XX:${OPTION} 2>&1 | grep ${OPTION} if [ "$?" != "0" ] then printf "FAILED: bad option not named as being bad.\n" diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java --- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java Mon Aug 18 10:07:43 2014 +0100 @@ -21,8 +21,7 @@ * questions. */ -/* @ignore JDK-8043896 - * @test LimitSharedSizes +/* @test LimitSharedSizes * @summary Test handling of limits on shared space size * @library /testlibrary * @run main LimitSharedSizes diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/runtime/jsig/Test8017498.sh --- a/hotspot/test/runtime/jsig/Test8017498.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/runtime/jsig/Test8017498.sh Mon Aug 18 10:07:43 2014 +0100 @@ -24,7 +24,6 @@ # ## -## @ignore 8028806 ## @test Test8017498.sh ## @bug 8017498 ## @bug 8020791 diff -r d06a6d3c66c0 -r 6a6c91ccc0bc hotspot/test/test_env.sh --- a/hotspot/test/test_env.sh Wed Jul 05 19:56:33 2017 +0200 +++ b/hotspot/test/test_env.sh Mon Aug 18 10:07:43 2014 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2014, 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 @@ -50,6 +50,9 @@ fi echo "TESTCLASSES=${TESTCLASSES}" +TESTOPTS="${TESTVMOPTS} ${TESTJAVAOPTS}" +echo "TESTOPTS=${TESTOPTS}" + # set platform-dependent variables OS=`uname -s` case "$OS" in @@ -101,14 +104,14 @@ echo "THIS_DIR=${THIS_DIR}" # Check to ensure the java defined actually works -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -version if [ $? != 0 ]; then - echo "Wrong TESTJAVA or TESTVMOPTS:" - echo $TESTJAVA TESTVMOPTS + echo "Wrong TESTJAVA or TESTJAVAOPTS or TESTVMOPTS:" + echo ''$TESTJAVA'' ''$TESTJAVAOPTS'' ''$TESTVMOPTS'' exit 1 fi -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Xinternalversion > vm_version.out 2>&1 +${TESTJAVA}${FS}bin${FS}java ${TESTOPTS} -Xinternalversion > vm_version.out 2>&1 VM_TYPE="unknown" grep "Server" vm_version.out > ${NULL}