OpenJDK / jdk / hs
changeset 8805:1a56a0bf5840
Merge
author | lana |
---|---|
date | Fri, 18 Mar 2011 10:59:12 -0700 |
parents | 2d69a944f4da 2173b8120b13 |
children | c81d4e10ffb7 |
files | jdk/make/common/shared/Platform.gmk langtools/test/tools/javac/T6900037.java langtools/test/tools/javac/T6900037.out langtools/test/tools/javac/diags/examples/DiamondInvalidArg.java langtools/test/tools/javac/diags/examples/DiamondInvalidArgs.java langtools/test/tools/javac/generics/diamond/neg/Neg12.java langtools/test/tools/javac/generics/diamond/neg/Neg12.out langtools/test/tools/javac/multicatch/Neg05.java langtools/test/tools/javac/multicatch/Neg05.out |
diffstat | 248 files changed, 6685 insertions(+), 2185 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -107,3 +107,4 @@ a36beda9b9de91231d92a2c529f21cc218fcf8d5 jdk7-b130 d8af56da89bc0fc02a6b6ad78f51157a46d665ab jdk7-b131 d61280d36755d1941fb487f554e8b7a6d0bca6a1 jdk7-b132 +fd444c61e7ed3d92b2a730da7c737b02191b682f jdk7-b133
--- a/.hgtags-top-repo Fri Mar 18 07:17:24 2011 -0700 +++ b/.hgtags-top-repo Fri Mar 18 10:59:12 2011 -0700 @@ -107,3 +107,4 @@ cc58c11af15411042719e9c82707fdbef60a9e0f jdk7-b130 5d86d951426aaf340b1ba84ae2d5ab5da65a71e2 jdk7-b131 0f62a65fb666b337caa585015ab6ea2e60e709ca jdk7-b132 +c6f380693342feadccc5fe2c5adf500e861361aa jdk7-b133
--- a/corba/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/corba/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -107,3 +107,4 @@ 563a8f8b5be3940e9346cffac4eff9ed02b3c69f jdk7-b130 9d6dd2cdfcb92612dbd836ecded87770d52b49db jdk7-b131 1b1e75e8f476e5c07f0d2b035993895e2603e1f0 jdk7-b132 +671fe2e623ffefb4b7c312be919fc71eb48c1df1 jdk7-b133
--- a/hotspot/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -153,3 +153,4 @@ e9aa2ca89ad6c53420623d579765f9706ec523d7 hs21-b02 0e531ab5ba04967a0e9aa6aef65e6eb3a0dcf632 jdk7-b132 a8d643a4db47c7b58e0bcb49c77b5c3610de86a8 hs21-b03 +1b3a350709e4325d759bb453ff3fb6a463270488 jdk7-b133
--- a/hotspot/make/hotspot_version Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/make/hotspot_version Fri Mar 18 10:59:12 2011 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=21 HS_MINOR_VER=0 -HS_BUILD_NUMBER=03 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=7
--- a/hotspot/make/windows/makefiles/compile.make Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/make/windows/makefiles/compile.make Fri Mar 18 10:59:12 2011 -0700 @@ -207,6 +207,9 @@ # Manifest Tool - used in VS2005 and later to adjust manifests stored # as resources inside build artifacts. MT=mt.exe +!if "$(BUILDARCH)" == "i486" +LINK_FLAGS = /SAFESEH $(LINK_FLAGS) +!endif !endif # Compile for space above time.
--- a/hotspot/make/windows/makefiles/launcher.make Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/make/windows/makefiles/launcher.make Fri Mar 18 10:59:12 2011 -0700 @@ -1,71 +1,73 @@ -# -# Copyright (c) 2010, 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. -# -# - - -LAUNCHER_FLAGS=$(CPP_FLAGS) $(ARCHFLAG) \ - /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ - /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ - /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ - /D GAMMA \ - /D LAUNCHER_TYPE=\"gamma\" \ - /D _CRT_SECURE_NO_WARNINGS \ - /D _CRT_SECURE_NO_DEPRECATE \ - /D LINK_INTO_LIBJVM \ - /I $(WorkSpace)\src\os\windows\launcher \ - /I $(WorkSpace)\src\share\tools\launcher \ - /I $(WorkSpace)\src\share\vm\prims \ - /I $(WorkSpace)\src\share\vm \ - /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \ - /I $(WorkSpace)\src\os\windows\vm - -LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console - -!if "$(COMPILER_NAME)" == "VS2005" -# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib -# on the link command line, otherwise we get missing __security_check_cookie -# externals at link time. Even with /GS-, you need bufferoverflowU.lib. -BUFFEROVERFLOWLIB = bufferoverflowU.lib -LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) -!endif - -LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher -LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher - -OUTDIR = launcher - -{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) 2>NUL >NUL - $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< - -{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: - -mkdir $(OUTDIR) 2>NUL >NUL - $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< - -$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h - -launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj - echo $(JAVA_HOME) > jdkpath.txt - $(LINK) $(LINK_FLAGS) /out:hotspot.exe $** - - +# +# Copyright (c) 2010, 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. +# +# + + +LAUNCHER_FLAGS=$(CPP_FLAGS) $(ARCHFLAG) \ + /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ + /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ + /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ + /D GAMMA \ + /D LAUNCHER_TYPE=\"gamma\" \ + /D _CRT_SECURE_NO_WARNINGS \ + /D _CRT_SECURE_NO_DEPRECATE \ + /D LINK_INTO_LIBJVM \ + /I $(WorkSpace)\src\os\windows\launcher \ + /I $(WorkSpace)\src\share\tools\launcher \ + /I $(WorkSpace)\src\share\vm\prims \ + /I $(WorkSpace)\src\share\vm \ + /I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \ + /I $(WorkSpace)\src\os\windows\vm + +LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console + +!if "$(COMPILER_NAME)" == "VS2005" +# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib +# on the link command line, otherwise we get missing __security_check_cookie +# externals at link time. Even with /GS-, you need bufferoverflowU.lib. +BUFFEROVERFLOWLIB = bufferoverflowU.lib +LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) +!endif + +!if "$(COMPILER_NAME)" == "VS2010" && "$(BUILDARCH)" == "i486" +LINK_FLAGS = /SAFESEH $(LINK_FLAGS) +!endif + +LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher +LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher + +OUTDIR = launcher + +{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: + -mkdir $(OUTDIR) 2>NUL >NUL + $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< + +{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: + -mkdir $(OUTDIR) 2>NUL >NUL + $(CPP) $(LAUNCHER_FLAGS) /c /Fo$@ $< + +$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h + +launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj + echo $(JAVA_HOME) > jdkpath.txt + $(LINK) $(LINK_FLAGS) /out:hotspot.exe $**
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -395,9 +395,9 @@ int offset = code_offset(); - __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type); + __ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id), relocInfo::runtime_call_type); __ delayed()->nop(); - debug_only(__ stop("should have gone to the caller");) + __ should_not_reach_here(); assert(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub();
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -148,7 +148,7 @@ static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) { assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), - " mismatch in calculation"); + "mismatch in calculation"); sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); OopMap* oop_map = new OopMap(frame_size_in_slots, 0); @@ -176,9 +176,8 @@ static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) { assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words), - " mismatch in calculation"); + "mismatch in calculation"); __ save_frame_c1(frame_size_in_bytes); - sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); // Record volatile registers as callee-save values in an OopMap so their save locations will be // propagated to the caller frame's RegisterMap during StackFrameStream construction (needed for @@ -367,23 +366,7 @@ switch (id) { case forward_exception_id: { - // we're handling an exception in the context of a compiled - // frame. The registers have been saved in the standard - // places. Perform an exception lookup in the caller and - // dispatch to the handler if found. Otherwise unwind and - // dispatch to the callers exception handler. - - oop_maps = new OopMapSet(); - OopMap* oop_map = generate_oop_map(sasm, true); - - // transfer the pending exception to the exception_oop - __ ld_ptr(G2_thread, in_bytes(JavaThread::pending_exception_offset()), Oexception); - __ ld_ptr(Oexception, 0, G0); - __ st_ptr(G0, G2_thread, in_bytes(JavaThread::pending_exception_offset())); - __ add(I7, frame::pc_return_offset, Oissuing_pc); - - generate_handle_exception(sasm, oop_maps, oop_map); - __ should_not_reach_here(); + oop_maps = generate_handle_exception(id, sasm); } break; @@ -671,15 +654,14 @@ break; case handle_exception_id: - { - __ set_info("handle_exception", dont_gc_arguments); - // make a frame and preserve the caller's caller-save registers + { __ set_info("handle_exception", dont_gc_arguments); + oop_maps = generate_handle_exception(id, sasm); + } + break; - oop_maps = new OopMapSet(); - OopMap* oop_map = save_live_registers(sasm); - __ mov(Oexception->after_save(), Oexception); - __ mov(Oissuing_pc->after_save(), Oissuing_pc); - generate_handle_exception(sasm, oop_maps, oop_map); + case handle_exception_from_callee_id: + { __ set_info("handle_exception_from_callee", dont_gc_arguments); + oop_maps = generate_handle_exception(id, sasm); } break; @@ -696,7 +678,7 @@ G2_thread, Oissuing_pc->after_save()); __ verify_not_null_oop(Oexception->after_save()); - // Restore SP from L7 if the exception PC is a MethodHandle call site. + // Restore SP from L7 if the exception PC is a method handle call site. __ mov(O0, G5); // Save the target address. __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); __ tst(L0); // Condition codes are preserved over the restore. @@ -1006,48 +988,89 @@ } -void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_maps, OopMap* oop_map, bool) { - Label no_deopt; +OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler* sasm) { + __ block_comment("generate_handle_exception"); + + // Save registers, if required. + OopMapSet* oop_maps = new OopMapSet(); + OopMap* oop_map = NULL; + switch (id) { + case forward_exception_id: + // We're handling an exception in the context of a compiled frame. + // The registers have been saved in the standard places. Perform + // an exception lookup in the caller and dispatch to the handler + // if found. Otherwise unwind and dispatch to the callers + // exception handler. + oop_map = generate_oop_map(sasm, true); + + // transfer the pending exception to the exception_oop + __ ld_ptr(G2_thread, in_bytes(JavaThread::pending_exception_offset()), Oexception); + __ ld_ptr(Oexception, 0, G0); + __ st_ptr(G0, G2_thread, in_bytes(JavaThread::pending_exception_offset())); + __ add(I7, frame::pc_return_offset, Oissuing_pc); + break; + case handle_exception_id: + // At this point all registers MAY be live. + oop_map = save_live_registers(sasm); + __ mov(Oexception->after_save(), Oexception); + __ mov(Oissuing_pc->after_save(), Oissuing_pc); + break; + case handle_exception_from_callee_id: + // At this point all registers except exception oop (Oexception) + // and exception pc (Oissuing_pc) are dead. + oop_map = new OopMap(frame_size_in_bytes / sizeof(jint), 0); + sasm->set_frame_size(frame_size_in_bytes / BytesPerWord); + __ save_frame_c1(frame_size_in_bytes); + __ mov(Oexception->after_save(), Oexception); + __ mov(Oissuing_pc->after_save(), Oissuing_pc); + break; + default: ShouldNotReachHere(); + } __ verify_not_null_oop(Oexception); // save the exception and issuing pc in the thread - __ st_ptr(Oexception, G2_thread, in_bytes(JavaThread::exception_oop_offset())); + __ st_ptr(Oexception, G2_thread, in_bytes(JavaThread::exception_oop_offset())); __ st_ptr(Oissuing_pc, G2_thread, in_bytes(JavaThread::exception_pc_offset())); - // save the real return address and use the throwing pc as the return address to lookup (has bci & oop map) - __ mov(I7, L0); + // use the throwing pc as the return address to lookup (has bci & oop map) __ mov(Oissuing_pc, I7); __ sub(I7, frame::pc_return_offset, I7); int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); + oop_maps->add_gc_map(call_offset, oop_map); // Note: if nmethod has been deoptimized then regardless of // whether it had a handler or not we will deoptimize // by entering the deopt blob with a pending exception. -#ifdef ASSERT - Label done; - __ tst(O0); - __ br(Assembler::notZero, false, Assembler::pn, done); - __ delayed()->nop(); - __ stop("should have found address"); - __ bind(done); -#endif + // Restore the registers that were saved at the beginning, remove + // the frame and jump to the exception handler. + switch (id) { + case forward_exception_id: + case handle_exception_id: + restore_live_registers(sasm); + __ jmp(O0, 0); + __ delayed()->restore(); + break; + case handle_exception_from_callee_id: + // Restore SP from L7 if the exception PC is a method handle call site. + __ mov(O0, G5); // Save the target address. + __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); + __ tst(L0); // Condition codes are preserved over the restore. + __ restore(); - // restore the registers that were saved at the beginning and jump to the exception handler. - restore_live_registers(sasm); + __ jmp(G5, 0); // jump to the exception handler + __ delayed()->movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP); // Restore SP if required. + break; + default: ShouldNotReachHere(); + } - __ jmp(O0, 0); - __ delayed()->restore(); - - oop_maps->add_gc_map(call_offset, oop_map); + return oop_maps; } #undef __ -#define __ masm-> - const char *Runtime1::pd_name_for_address(address entry) { return "<unknown function>"; }
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -417,6 +417,7 @@ // Some handy addresses: Address G5_method_fie( G5_method, in_bytes(methodOopDesc::from_interpreted_offset())); + Address G5_method_fce( G5_method, in_bytes(methodOopDesc::from_compiled_offset())); Address G3_mh_vmtarget( G3_method_handle, java_dyn_MethodHandle::vmtarget_offset_in_bytes()); @@ -444,12 +445,10 @@ case _raise_exception: { // Not a real MH entry, but rather shared code for raising an - // exception. Since we use a C2I adapter to set up the - // interpreter state, arguments are expected in compiler - // argument registers. + // exception. Since we use the compiled entry, arguments are + // expected in compiler argument registers. assert(raise_exception_method(), "must be set"); - address c2i_entry = raise_exception_method()->get_c2i_entry(); - assert(c2i_entry, "method must be linked"); + assert(raise_exception_method()->from_compiled_entry(), "method must be linked"); __ mov(O5_savedSP, SP); // Cut the stack back to where the caller started. @@ -468,10 +467,9 @@ __ delayed()->nop(); __ verify_oop(G5_method); - __ jump_to(AddressLiteral(c2i_entry), O3_scratch); + __ jump_indirect_to(G5_method_fce, O3_scratch); // jump to compiled entry __ delayed()->nop(); - // If we get here, the Java runtime did not do its job of creating the exception. // Do something that is at least causes a valid throw from the interpreter. __ bind(L_no_method); __ unimplemented("call throw_WrongMethodType_entry");
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -968,19 +968,6 @@ return start; } - static address disjoint_byte_copy_entry; - static address disjoint_short_copy_entry; - static address disjoint_int_copy_entry; - static address disjoint_long_copy_entry; - static address disjoint_oop_copy_entry; - - static address byte_copy_entry; - static address short_copy_entry; - static address int_copy_entry; - static address long_copy_entry; - static address oop_copy_entry; - - static address checkcast_copy_entry; // // Verify that a register contains clean 32-bits positive value @@ -1046,31 +1033,40 @@ // // The input registers are overwritten. // - void gen_write_ref_array_pre_barrier(Register addr, Register count) { + void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) { BarrierSet* bs = Universe::heap()->barrier_set(); - if (bs->has_write_ref_pre_barrier()) { - assert(bs->has_write_ref_array_pre_opt(), - "Else unsupported barrier set."); - - __ save_frame(0); - // Save the necessary global regs... will be used after. - if (addr->is_global()) { - __ mov(addr, L0); - } - if (count->is_global()) { - __ mov(count, L1); - } - __ mov(addr->after_save(), O0); - // Get the count into O1 - __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre)); - __ delayed()->mov(count->after_save(), O1); - if (addr->is_global()) { - __ mov(L0, addr); - } - if (count->is_global()) { - __ mov(L1, count); - } - __ restore(); + switch (bs->kind()) { + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: + // With G1, don't generate the call if we statically know that the target in uninitialized + if (!dest_uninitialized) { + __ save_frame(0); + // Save the necessary global regs... will be used after. + if (addr->is_global()) { + __ mov(addr, L0); + } + if (count->is_global()) { + __ mov(count, L1); + } + __ mov(addr->after_save(), O0); + // Get the count into O1 + __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre)); + __ delayed()->mov(count->after_save(), O1); + if (addr->is_global()) { + __ mov(L0, addr); + } + if (count->is_global()) { + __ mov(L1, count); + } + __ restore(); + } + break; + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + case BarrierSet::ModRef: + break; + default: + ShouldNotReachHere(); } } // @@ -1084,7 +1080,7 @@ // The input registers are overwritten. // void gen_write_ref_array_post_barrier(Register addr, Register count, - Register tmp) { + Register tmp) { BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { @@ -1283,7 +1279,7 @@ // to: O1 // count: O2 treated as signed // - address generate_disjoint_byte_copy(bool aligned, const char * name) { + address generate_disjoint_byte_copy(bool aligned, address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1299,9 +1295,11 @@ assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) disjoint_byte_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } // for short arrays, just do single element copy __ cmp(count, 23); // 16 + 7 @@ -1391,15 +1389,13 @@ // to: O1 // count: O2 treated as signed // - address generate_conjoint_byte_copy(bool aligned, const char * name) { + address generate_conjoint_byte_copy(bool aligned, address nooverlap_target, + address *entry, const char *name) { // Do reverse copy. __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - address nooverlap_target = aligned ? - StubRoutines::arrayof_jbyte_disjoint_arraycopy() : - disjoint_byte_copy_entry; Label L_skip_alignment, L_align, L_aligned_copy; Label L_copy_byte, L_copy_byte_loop, L_exit; @@ -1412,9 +1408,11 @@ assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) byte_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } array_overlap_test(nooverlap_target, 0); @@ -1504,7 +1502,7 @@ // to: O1 // count: O2 treated as signed // - address generate_disjoint_short_copy(bool aligned, const char * name) { + address generate_disjoint_short_copy(bool aligned, address *entry, const char * name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1520,9 +1518,11 @@ assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) disjoint_short_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } // for short arrays, just do single element copy __ cmp(count, 11); // 8 + 3 (22 bytes) @@ -1842,15 +1842,13 @@ // to: O1 // count: O2 treated as signed // - address generate_conjoint_short_copy(bool aligned, const char * name) { + address generate_conjoint_short_copy(bool aligned, address nooverlap_target, + address *entry, const char *name) { // Do reverse copy. __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - address nooverlap_target = aligned ? - StubRoutines::arrayof_jshort_disjoint_arraycopy() : - disjoint_short_copy_entry; Label L_skip_alignment, L_skip_alignment2, L_aligned_copy; Label L_copy_2_bytes, L_copy_2_bytes_loop, L_exit; @@ -1865,9 +1863,11 @@ assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) short_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } array_overlap_test(nooverlap_target, 1); @@ -2072,7 +2072,7 @@ // to: O1 // count: O2 treated as signed // - address generate_disjoint_int_copy(bool aligned, const char * name) { + address generate_disjoint_int_copy(bool aligned, address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -2080,9 +2080,11 @@ const Register count = O2; assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) disjoint_int_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } generate_disjoint_int_copy_core(aligned); @@ -2204,20 +2206,19 @@ // to: O1 // count: O2 treated as signed // - address generate_conjoint_int_copy(bool aligned, const char * name) { + address generate_conjoint_int_copy(bool aligned, address nooverlap_target, + address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - address nooverlap_target = aligned ? - StubRoutines::arrayof_jint_disjoint_arraycopy() : - disjoint_int_copy_entry; - assert_clean_int(O2, O3); // Make sure 'count' is clean int. - if (!aligned) int_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } array_overlap_test(nooverlap_target, 2); @@ -2336,16 +2337,18 @@ // to: O1 // count: O2 treated as signed // - address generate_disjoint_long_copy(bool aligned, const char * name) { + address generate_disjoint_long_copy(bool aligned, address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); assert_clean_int(O2, O3); // Make sure 'count' is clean int. - if (!aligned) disjoint_long_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } generate_disjoint_long_copy_core(aligned); @@ -2406,19 +2409,21 @@ // to: O1 // count: O2 treated as signed // - address generate_conjoint_long_copy(bool aligned, const char * name) { + address generate_conjoint_long_copy(bool aligned, address nooverlap_target, + address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - assert(!aligned, "usage"); - address nooverlap_target = disjoint_long_copy_entry; + assert(aligned, "Should always be aligned"); assert_clean_int(O2, O3); // Make sure 'count' is clean int. - if (!aligned) long_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } array_overlap_test(nooverlap_target, 3); @@ -2439,7 +2444,8 @@ // to: O1 // count: O2 treated as signed // - address generate_disjoint_oop_copy(bool aligned, const char * name) { + address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name, + bool dest_uninitialized = false) { const Register from = O0; // source array address const Register to = O1; // destination array address @@ -2451,14 +2457,16 @@ assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) disjoint_oop_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here + BLOCK_COMMENT("Entry:"); + } // save arguments for barrier generation __ mov(to, G1); __ mov(count, G5); - gen_write_ref_array_pre_barrier(G1, G5); + gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized); #ifdef _LP64 assert_clean_int(count, O3); // Make sure 'count' is clean int. if (UseCompressedOops) { @@ -2487,7 +2495,9 @@ // to: O1 // count: O2 treated as signed // - address generate_conjoint_oop_copy(bool aligned, const char * name) { + address generate_conjoint_oop_copy(bool aligned, address nooverlap_target, + address *entry, const char *name, + bool dest_uninitialized = false) { const Register from = O0; // source array address const Register to = O1; // destination array address @@ -2499,21 +2509,18 @@ assert_clean_int(count, O3); // Make sure 'count' is clean int. - if (!aligned) oop_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here - if (!aligned) BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here + BLOCK_COMMENT("Entry:"); + } + + array_overlap_test(nooverlap_target, LogBytesPerHeapOop); // save arguments for barrier generation __ mov(to, G1); __ mov(count, G5); - - gen_write_ref_array_pre_barrier(G1, G5); - - address nooverlap_target = aligned ? - StubRoutines::arrayof_oop_disjoint_arraycopy() : - disjoint_oop_copy_entry; - - array_overlap_test(nooverlap_target, LogBytesPerHeapOop); + gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized); #ifdef _LP64 if (UseCompressedOops) { @@ -2582,7 +2589,7 @@ // ckval: O4 (super_klass) // ret: O0 zero for success; (-1^K) where K is partial transfer count // - address generate_checkcast_copy(const char* name) { + address generate_checkcast_copy(const char *name, address *entry, bool dest_uninitialized = false) { const Register O0_from = O0; // source array address const Register O1_to = O1; // destination array address @@ -2600,8 +2607,6 @@ StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); - gen_write_ref_array_pre_barrier(O1, O2); - #ifdef ASSERT // We sometimes save a frame (see generate_type_check below). // If this will cause trouble, let's fail now instead of later. @@ -2625,9 +2630,12 @@ } #endif //ASSERT - checkcast_copy_entry = __ pc(); - // caller can pass a 64-bit byte count here (from generic stub) - BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from generic stub) + BLOCK_COMMENT("Entry:"); + } + gen_write_ref_array_pre_barrier(O1_to, O2_count, dest_uninitialized); Label load_element, store_element, do_card_marks, fail, done; __ addcc(O2_count, 0, G1_remain); // initialize loop index, and test it @@ -2700,7 +2708,11 @@ // Examines the alignment of the operands and dispatches // to a long, int, short, or byte copy loop. // - address generate_unsafe_copy(const char* name) { + address generate_unsafe_copy(const char* name, + address byte_copy_entry, + address short_copy_entry, + address int_copy_entry, + address long_copy_entry) { const Register O0_from = O0; // source array address const Register O1_to = O1; // destination array address @@ -2796,8 +2808,13 @@ // O0 == 0 - success // O0 == -1 - need to call System.arraycopy // - address generate_generic_copy(const char *name) { - + address generate_generic_copy(const char *name, + address entry_jbyte_arraycopy, + address entry_jshort_arraycopy, + address entry_jint_arraycopy, + address entry_oop_arraycopy, + address entry_jlong_arraycopy, + address entry_checkcast_arraycopy) { Label L_failed, L_objArray; // Input registers @@ -2970,15 +2987,15 @@ BLOCK_COMMENT("choose copy loop based on element size"); __ cmp(G3_elsize, 0); - __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jbyte_arraycopy); + __ br(Assembler::equal, true, Assembler::pt, entry_jbyte_arraycopy); __ delayed()->signx(length, count); // length __ cmp(G3_elsize, LogBytesPerShort); - __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jshort_arraycopy); + __ br(Assembler::equal, true, Assembler::pt, entry_jshort_arraycopy); __ delayed()->signx(length, count); // length __ cmp(G3_elsize, LogBytesPerInt); - __ br(Assembler::equal,true,Assembler::pt,StubRoutines::_jint_arraycopy); + __ br(Assembler::equal, true, Assembler::pt, entry_jint_arraycopy); __ delayed()->signx(length, count); // length #ifdef ASSERT { Label L; @@ -2989,7 +3006,7 @@ __ bind(L); } #endif - __ br(Assembler::always,false,Assembler::pt,StubRoutines::_jlong_arraycopy); + __ br(Assembler::always, false, Assembler::pt, entry_jlong_arraycopy); __ delayed()->signx(length, count); // length // objArrayKlass @@ -3013,7 +3030,7 @@ __ add(src, src_pos, from); // src_addr __ add(dst, dst_pos, to); // dst_addr __ BIND(L_plain_copy); - __ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy); + __ br(Assembler::always, false, Assembler::pt, entry_oop_arraycopy); __ delayed()->signx(length, count); // length __ BIND(L_checkcast_copy); @@ -3057,7 +3074,7 @@ __ ld_ptr(G4_dst_klass, ek_offset, O4); // dest elem klass // lduw(O4, sco_offset, O3); // sco of elem klass - __ br(Assembler::always, false, Assembler::pt, checkcast_copy_entry); + __ br(Assembler::always, false, Assembler::pt, entry_checkcast_arraycopy); __ delayed()->lduw(O4, sco_offset, O3); } @@ -3068,39 +3085,124 @@ } void generate_arraycopy_stubs() { - - // Note: the disjoint stubs must be generated first, some of - // the conjoint stubs use them. - StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy"); - StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy"); - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, "jint_disjoint_arraycopy"); - StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(false, "jlong_disjoint_arraycopy"); - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, "oop_disjoint_arraycopy"); - StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, "arrayof_jbyte_disjoint_arraycopy"); - StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, "arrayof_jshort_disjoint_arraycopy"); - StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, "arrayof_jint_disjoint_arraycopy"); - StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, "arrayof_jlong_disjoint_arraycopy"); - StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, "arrayof_oop_disjoint_arraycopy"); - - StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy"); - StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy"); - StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, "jint_arraycopy"); - StubRoutines::_jlong_arraycopy = generate_conjoint_long_copy(false, "jlong_arraycopy"); - StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, "oop_arraycopy"); - StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, "arrayof_jbyte_arraycopy"); - StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, "arrayof_jshort_arraycopy"); + address entry; + address entry_jbyte_arraycopy; + address entry_jshort_arraycopy; + address entry_jint_arraycopy; + address entry_oop_arraycopy; + address entry_jlong_arraycopy; + address entry_checkcast_arraycopy; + + //*** jbyte + // Always need aligned and unaligned versions + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry, + "jbyte_disjoint_arraycopy"); + StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, + &entry_jbyte_arraycopy, + "jbyte_arraycopy"); + StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, &entry, + "arrayof_jbyte_disjoint_arraycopy"); + StubRoutines::_arrayof_jbyte_arraycopy = generate_conjoint_byte_copy(true, entry, NULL, + "arrayof_jbyte_arraycopy"); + + //*** jshort + // Always need aligned and unaligned versions + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry, + "jshort_disjoint_arraycopy"); + StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, + &entry_jshort_arraycopy, + "jshort_arraycopy"); + StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, &entry, + "arrayof_jshort_disjoint_arraycopy"); + StubRoutines::_arrayof_jshort_arraycopy = generate_conjoint_short_copy(true, entry, NULL, + "arrayof_jshort_arraycopy"); + + //*** jint + // Aligned versions + StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, &entry, + "arrayof_jint_disjoint_arraycopy"); + StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, &entry_jint_arraycopy, + "arrayof_jint_arraycopy"); #ifdef _LP64 - // since sizeof(jint) < sizeof(HeapWord), there's a different flavor: - StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, "arrayof_jint_arraycopy"); - #else - StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; + // In 64 bit we need both aligned and unaligned versions of jint arraycopy. + // entry_jint_arraycopy always points to the unaligned version (notice that we overwrite it). + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry, + "jint_disjoint_arraycopy"); + StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry, + &entry_jint_arraycopy, + "jint_arraycopy"); +#else + // In 32 bit jints are always HeapWordSize aligned, so always use the aligned version + // (in fact in 32bit we always have a pre-loop part even in the aligned version, + // because it uses 64-bit loads/stores, so the aligned flag is actually ignored). + StubRoutines::_jint_disjoint_arraycopy = StubRoutines::_arrayof_jint_disjoint_arraycopy; + StubRoutines::_jint_arraycopy = StubRoutines::_arrayof_jint_arraycopy; #endif - StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; - StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; - - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy"); - StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy"); - StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy"); + + + //*** jlong + // It is always aligned + StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, &entry, + "arrayof_jlong_disjoint_arraycopy"); + StubRoutines::_arrayof_jlong_arraycopy = generate_conjoint_long_copy(true, entry, &entry_jlong_arraycopy, + "arrayof_jlong_arraycopy"); + StubRoutines::_jlong_disjoint_arraycopy = StubRoutines::_arrayof_jlong_disjoint_arraycopy; + StubRoutines::_jlong_arraycopy = StubRoutines::_arrayof_jlong_arraycopy; + + + //*** oops + // Aligned versions + StubRoutines::_arrayof_oop_disjoint_arraycopy = generate_disjoint_oop_copy(true, &entry, + "arrayof_oop_disjoint_arraycopy"); + StubRoutines::_arrayof_oop_arraycopy = generate_conjoint_oop_copy(true, entry, &entry_oop_arraycopy, + "arrayof_oop_arraycopy"); + // Aligned versions without pre-barriers + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(true, &entry, + "arrayof_oop_disjoint_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, entry, NULL, + "arrayof_oop_arraycopy_uninit", + /*dest_uninitialized*/true); +#ifdef _LP64 + if (UseCompressedOops) { + // With compressed oops we need unaligned versions, notice that we overwrite entry_oop_arraycopy. + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, &entry, + "oop_disjoint_arraycopy"); + StubRoutines::_oop_arraycopy = generate_conjoint_oop_copy(false, entry, &entry_oop_arraycopy, + "oop_arraycopy"); + // Unaligned versions without pre-barriers + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(false, &entry, + "oop_disjoint_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(false, entry, NULL, + "oop_arraycopy_uninit", + /*dest_uninitialized*/true); + } else +#endif + { + // oop arraycopy is always aligned on 32bit and 64bit without compressed oops + StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy; + StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy; + StubRoutines::_oop_disjoint_arraycopy_uninit = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit; + StubRoutines::_oop_arraycopy_uninit = StubRoutines::_arrayof_oop_arraycopy_uninit; + } + + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, + /*dest_uninitialized*/true); + + StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", + entry_jbyte_arraycopy, + entry_jshort_arraycopy, + entry_jint_arraycopy, + entry_jlong_arraycopy); + StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", + entry_jbyte_arraycopy, + entry_jshort_arraycopy, + entry_jint_arraycopy, + entry_oop_arraycopy, + entry_jlong_arraycopy, + entry_checkcast_arraycopy); StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); @@ -3224,21 +3326,6 @@ }; // end class declaration - -address StubGenerator::disjoint_byte_copy_entry = NULL; -address StubGenerator::disjoint_short_copy_entry = NULL; -address StubGenerator::disjoint_int_copy_entry = NULL; -address StubGenerator::disjoint_long_copy_entry = NULL; -address StubGenerator::disjoint_oop_copy_entry = NULL; - -address StubGenerator::byte_copy_entry = NULL; -address StubGenerator::short_copy_entry = NULL; -address StubGenerator::int_copy_entry = NULL; -address StubGenerator::long_copy_entry = NULL; -address StubGenerator::oop_copy_entry = NULL; - -address StubGenerator::checkcast_copy_entry = NULL; - void StubGenerator_generate(CodeBuffer* code, bool all) { StubGenerator g(code, all); }
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1601,6 +1601,17 @@ emit_byte(0xC0 | encode); } +void Assembler::movdl(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + emit_byte(0x66); + prefix(src, dst); + emit_byte(0x0F); + emit_byte(0x6E); + emit_operand(dst, src); +} + + void Assembler::movdqa(XMMRegister dst, Address src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionMark im(this); @@ -2412,7 +2423,10 @@ } void Assembler::psrlq(XMMRegister dst, int shift) { - // HMM Table D-1 says sse2 or mmx + // Shift 64 bit value logically right by specified number of bits. + // HMM Table D-1 says sse2 or mmx. + // Do not confuse it with psrldq SSE2 instruction which + // shifts 128 bit value in xmm register by number of bytes. NOT_LP64(assert(VM_Version::supports_sse(), "")); int encode = prefixq_and_encode(xmm2->encoding(), dst->encoding()); @@ -2423,6 +2437,18 @@ emit_byte(shift); } +void Assembler::psrldq(XMMRegister dst, int shift) { + // Shift 128 bit value in xmm register by number of bytes. + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + + int encode = prefixq_and_encode(xmm3->encoding(), dst->encoding()); + emit_byte(0x66); + emit_byte(0x0F); + emit_byte(0x73); + emit_byte(0xC0 | encode); + emit_byte(shift); +} + void Assembler::ptest(XMMRegister dst, Address src) { assert(VM_Version::supports_sse4_1(), ""); @@ -8567,101 +8593,418 @@ } #endif // _LP64 -// IndexOf substring. -void MacroAssembler::string_indexof(Register str1, Register str2, - Register cnt1, Register cnt2, Register result, - XMMRegister vec, Register tmp) { +// IndexOf for constant substrings with size >= 8 chars +// which don't need to be loaded through stack. +void MacroAssembler::string_indexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp) { assert(UseSSE42Intrinsics, "SSE4.2 is required"); - Label RELOAD_SUBSTR, PREP_FOR_SCAN, SCAN_TO_SUBSTR, - SCAN_SUBSTR, RET_NOT_FOUND, CLEANUP; - - push(str1); // string addr - push(str2); // substr addr - push(cnt2); // substr count - jmpb(PREP_FOR_SCAN); - - // Substr count saved at sp - // Substr saved at sp+1*wordSize - // String saved at sp+2*wordSize - - // Reload substr for rescan - bind(RELOAD_SUBSTR); - movl(cnt2, Address(rsp, 0)); - movptr(str2, Address(rsp, wordSize)); - // We came here after the beginninig of the substring was - // matched but the rest of it was not so we need to search - // again. Start from the next element after the previous match. - subptr(str1, result); // Restore counter - shrl(str1, 1); - addl(cnt1, str1); - decrementl(cnt1); - lea(str1, Address(result, 2)); // Reload string - - // Load substr - bind(PREP_FOR_SCAN); - movdqu(vec, Address(str2, 0)); - addl(cnt1, 8); // prime the loop - subptr(str1, 16); - - // Scan string for substr in 16-byte vectors - bind(SCAN_TO_SUBSTR); - subl(cnt1, 8); - addptr(str1, 16); - - // pcmpestri + // This method uses pcmpestri inxtruction with bound registers // inputs: // xmm - substring // rax - substring length (elements count) - // mem - scaned string + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + + Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, + RET_FOUND, RET_NOT_FOUND, EXIT, FOUND_SUBSTR, + MATCH_SUBSTR_HEAD, RELOAD_STR, FOUND_CANDIDATE; + + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + assert(int_cnt2 >= 8, "this code isused only for cnt2 >= 8 chars"); + + // Load substring. + movdqu(vec, Address(str2, 0)); + movl(cnt2, int_cnt2); + movptr(result, str1); // string addr + + if (int_cnt2 > 8) { + jmpb(SCAN_TO_SUBSTR); + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(RELOAD_SUBSTR); + movdqu(vec, Address(str2, 0)); + negptr(cnt2); // Jumped here with negative cnt2, convert to positive + + bind(RELOAD_STR); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + + // cnt2 is number of substring reminding elements and + // cnt1 is number of string reminding elements when cmp failed. + // Restored cnt1 = cnt1 - cnt2 + int_cnt2 + subl(cnt1, cnt2); + addl(cnt1, int_cnt2); + movl(cnt2, int_cnt2); // Now restore cnt2 + + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + + addptr(result, 2); + + } // (int_cnt2 > 8) + + // Scan string for start of substr in 16-byte vectors + bind(SCAN_TO_SUBSTR); + pcmpestri(vec, Address(result, 0), 0x0d); + jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 + subl(cnt1, 8); + jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + addptr(result, 16); + jmpb(SCAN_TO_SUBSTR); + + // Found a potential substr + bind(FOUND_CANDIDATE); + // Matched whole vector if first element matched (tmp(rcx) == 0). + if (int_cnt2 == 8) { + jccb(Assembler::overflow, RET_FOUND); // OF == 1 + } else { // int_cnt2 > 8 + jccb(Assembler::overflow, FOUND_SUBSTR); + } + // After pcmpestri tmp(rcx) contains matched element index + // Compute start addr of substr + lea(result, Address(result, tmp, Address::times_2)); + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + if (int_cnt2 == 8) { + jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); + } else { // int_cnt2 > 8 + jccb(Assembler::greaterEqual, MATCH_SUBSTR_HEAD); + } + // Left less then substring. + + bind(RET_NOT_FOUND); + movl(result, -1); + jmpb(EXIT); + + if (int_cnt2 > 8) { + // This code is optimized for the case when whole substring + // is matched if its head is matched. + bind(MATCH_SUBSTR_HEAD); + pcmpestri(vec, Address(result, 0), 0x0d); + // Reload only string if does not match + jccb(Assembler::noOverflow, RELOAD_STR); // OF == 0 + + Label CONT_SCAN_SUBSTR; + // Compare the rest of substring (> 8 chars). + bind(FOUND_SUBSTR); + // First 8 chars are already matched. + negptr(cnt2); + addptr(cnt2, 8); + + bind(SCAN_SUBSTR); + subl(cnt1, 8); + cmpl(cnt2, -8); // Do not read beyond substring + jccb(Assembler::lessEqual, CONT_SCAN_SUBSTR); + // Back-up strings to avoid reading beyond substring: + // cnt1 = cnt1 - cnt2 + 8 + addl(cnt1, cnt2); // cnt2 is negative + addl(cnt1, 8); + movl(cnt2, 8); negptr(cnt2); + bind(CONT_SCAN_SUBSTR); + if (int_cnt2 < (int)G) { + movdqu(vec, Address(str2, cnt2, Address::times_2, int_cnt2*2)); + pcmpestri(vec, Address(result, cnt2, Address::times_2, int_cnt2*2), 0x0d); + } else { + // calculate index in register to avoid integer overflow (int_cnt2*2) + movl(tmp, int_cnt2); + addptr(tmp, cnt2); + movdqu(vec, Address(str2, tmp, Address::times_2, 0)); + pcmpestri(vec, Address(result, tmp, Address::times_2, 0), 0x0d); + } + // Need to reload strings pointers if not matched whole vector + jccb(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 + addptr(cnt2, 8); + jccb(Assembler::negative, SCAN_SUBSTR); + // Fall through if found full substring + + } // (int_cnt2 > 8) + + bind(RET_FOUND); + // Found result if we matched full small substring. + // Compute substr offset + subptr(result, str1); + shrl(result, 1); // index + bind(EXIT); + +} // string_indexofC8 + +// Small strings are loaded through stack if they cross page boundary. +void MacroAssembler::string_indexof(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp) { + assert(UseSSE42Intrinsics, "SSE4.2 is required"); + // + // int_cnt2 is length of small (< 8 chars) constant substring + // or (-1) for non constant substring in which case its length + // is in cnt2 register. + // + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + // + assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0"); + + // This method uses pcmpestri inxtruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string // rdx - string length (elements count) // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) // outputs: // rcx - matched index in string assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); - pcmpestri(vec, Address(str1, 0), 0x0d); - jcc(Assembler::above, SCAN_TO_SUBSTR); // CF == 0 && ZF == 0 - jccb(Assembler::aboveEqual, RET_NOT_FOUND); // CF == 0 - - // Fallthrough: found a potential substr + Label RELOAD_SUBSTR, SCAN_TO_SUBSTR, SCAN_SUBSTR, ADJUST_STR, + RET_FOUND, RET_NOT_FOUND, CLEANUP, FOUND_SUBSTR, + FOUND_CANDIDATE; + + { //======================================================== + // We don't know where these strings are located + // and we can't read beyond them. Load them through stack. + Label BIG_STRINGS, CHECK_STR, COPY_SUBSTR, COPY_STR; + + movptr(tmp, rsp); // save old SP + + if (int_cnt2 > 0) { // small (< 8 chars) constant substring + if (int_cnt2 == 1) { // One char + load_unsigned_short(result, Address(str2, 0)); + movdl(vec, result); // move 32 bits + } else if (int_cnt2 == 2) { // Two chars + movdl(vec, Address(str2, 0)); // move 32 bits + } else if (int_cnt2 == 4) { // Four chars + movq(vec, Address(str2, 0)); // move 64 bits + } else { // cnt2 = { 3, 5, 6, 7 } + // Array header size is 12 bytes in 32-bit VM + // + 6 bytes for 3 chars == 18 bytes, + // enough space to load vec and shift. + assert(HeapWordSize*typeArrayKlass::header_size() >= 12,"sanity"); + movdqu(vec, Address(str2, (int_cnt2*2)-16)); + psrldq(vec, 16-(int_cnt2*2)); + } + } else { // not constant substring + cmpl(cnt2, 8); + jccb(Assembler::aboveEqual, BIG_STRINGS); // Both strings are big enough + + // We can read beyond string if srt+16 does not cross page boundary + // since heaps are aligned and mapped by pages. + assert(os::vm_page_size() < (int)G, "default page should be small"); + movl(result, str2); // We need only low 32 bits + andl(result, (os::vm_page_size()-1)); + cmpl(result, (os::vm_page_size()-16)); + jccb(Assembler::belowEqual, CHECK_STR); + + // Move small strings to stack to allow load 16 bytes into vec. + subptr(rsp, 16); + int stk_offset = wordSize-2; + push(cnt2); + + bind(COPY_SUBSTR); + load_unsigned_short(result, Address(str2, cnt2, Address::times_2, -2)); + movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); + decrement(cnt2); + jccb(Assembler::notZero, COPY_SUBSTR); + + pop(cnt2); + movptr(str2, rsp); // New substring address + } // non constant + + bind(CHECK_STR); + cmpl(cnt1, 8); + jccb(Assembler::aboveEqual, BIG_STRINGS); + + // Check cross page boundary. + movl(result, str1); // We need only low 32 bits + andl(result, (os::vm_page_size()-1)); + cmpl(result, (os::vm_page_size()-16)); + jccb(Assembler::belowEqual, BIG_STRINGS); + + subptr(rsp, 16); + int stk_offset = -2; + if (int_cnt2 < 0) { // not constant + push(cnt2); + stk_offset += wordSize; + } + movl(cnt2, cnt1); + + bind(COPY_STR); + load_unsigned_short(result, Address(str1, cnt2, Address::times_2, -2)); + movw(Address(rsp, cnt2, Address::times_2, stk_offset), result); + decrement(cnt2); + jccb(Assembler::notZero, COPY_STR); + + if (int_cnt2 < 0) { // not constant + pop(cnt2); + } + movptr(str1, rsp); // New string address + + bind(BIG_STRINGS); + // Load substring. + if (int_cnt2 < 0) { // -1 + movdqu(vec, Address(str2, 0)); + push(cnt2); // substr count + push(str2); // substr addr + push(str1); // string addr + } else { + // Small (< 8 chars) constant substrings are loaded already. + movl(cnt2, int_cnt2); + } + push(tmp); // original SP + + } // Finished loading + + //======================================================== + // Start search + // + + movptr(result, str1); // string addr + + if (int_cnt2 < 0) { // Only for non constant substring + jmpb(SCAN_TO_SUBSTR); + + // SP saved at sp+0 + // String saved at sp+1*wordSize + // Substr saved at sp+2*wordSize + // Substr count saved at sp+3*wordSize + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(RELOAD_SUBSTR); + movptr(str2, Address(rsp, 2*wordSize)); + movl(cnt2, Address(rsp, 3*wordSize)); + movdqu(vec, Address(str2, 0)); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + subptr(str1, result); // Restore counter + shrl(str1, 1); + addl(cnt1, str1); + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + + addptr(result, 2); + } // non constant + + // Scan string for start of substr in 16-byte vectors + bind(SCAN_TO_SUBSTR); + assert(cnt1 == rdx && cnt2 == rax && tmp == rcx, "pcmpestri"); + pcmpestri(vec, Address(result, 0), 0x0d); + jccb(Assembler::below, FOUND_CANDIDATE); // CF == 1 + subl(cnt1, 8); + jccb(Assembler::lessEqual, RET_NOT_FOUND); // Scanned full string + cmpl(cnt1, cnt2); + jccb(Assembler::negative, RET_NOT_FOUND); // Left less then substring + addptr(result, 16); + + bind(ADJUST_STR); + cmpl(cnt1, 8); // Do not read beyond string + jccb(Assembler::greaterEqual, SCAN_TO_SUBSTR); + // Back-up string to avoid reading beyond string. + lea(result, Address(result, cnt1, Address::times_2, -16)); + movl(cnt1, 8); + jmpb(SCAN_TO_SUBSTR); + + // Found a potential substr + bind(FOUND_CANDIDATE); + // After pcmpestri tmp(rcx) contains matched element index // Make sure string is still long enough subl(cnt1, tmp); cmpl(cnt1, cnt2); - jccb(Assembler::negative, RET_NOT_FOUND); - // Compute start addr of substr - lea(str1, Address(str1, tmp, Address::times_2)); - movptr(result, str1); // save - - // Compare potential substr - addl(cnt1, 8); // prime the loop - addl(cnt2, 8); - subptr(str1, 16); - subptr(str2, 16); - - // Scan 16-byte vectors of string and substr - bind(SCAN_SUBSTR); - subl(cnt1, 8); - subl(cnt2, 8); - addptr(str1, 16); - addptr(str2, 16); - movdqu(vec, Address(str2, 0)); - pcmpestri(vec, Address(str1, 0), 0x0d); - jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 - jcc(Assembler::positive, SCAN_SUBSTR); // SF == 0 - - // Compute substr offset - subptr(result, Address(rsp, 2*wordSize)); - shrl(result, 1); // index - jmpb(CLEANUP); + jccb(Assembler::greaterEqual, FOUND_SUBSTR); + // Left less then substring. bind(RET_NOT_FOUND); movl(result, -1); + jmpb(CLEANUP); + + bind(FOUND_SUBSTR); + // Compute start addr of substr + lea(result, Address(result, tmp, Address::times_2)); + + if (int_cnt2 > 0) { // Constant substring + // Repeat search for small substring (< 8 chars) + // from new point without reloading substring. + // Have to check that we don't read beyond string. + cmpl(tmp, 8-int_cnt2); + jccb(Assembler::greater, ADJUST_STR); + // Fall through if matched whole substring. + } else { // non constant + assert(int_cnt2 == -1, "should be != 0"); + + addl(tmp, cnt2); + // Found result if we matched whole substring. + cmpl(tmp, 8); + jccb(Assembler::lessEqual, RET_FOUND); + + // Repeat search for small substring (<= 8 chars) + // from new point 'str1' without reloading substring. + cmpl(cnt2, 8); + // Have to check that we don't read beyond string. + jccb(Assembler::lessEqual, ADJUST_STR); + + Label CHECK_NEXT, CONT_SCAN_SUBSTR, RET_FOUND_LONG; + // Compare the rest of substring (> 8 chars). + movptr(str1, result); + + cmpl(tmp, cnt2); + // First 8 chars are already matched. + jccb(Assembler::equal, CHECK_NEXT); + + bind(SCAN_SUBSTR); + pcmpestri(vec, Address(str1, 0), 0x0d); + // Need to reload strings pointers if not matched whole vector + jcc(Assembler::noOverflow, RELOAD_SUBSTR); // OF == 0 + + bind(CHECK_NEXT); + subl(cnt2, 8); + jccb(Assembler::lessEqual, RET_FOUND_LONG); // Found full substring + addptr(str1, 16); + addptr(str2, 16); + subl(cnt1, 8); + cmpl(cnt2, 8); // Do not read beyond substring + jccb(Assembler::greaterEqual, CONT_SCAN_SUBSTR); + // Back-up strings to avoid reading beyond substring. + lea(str2, Address(str2, cnt2, Address::times_2, -16)); + lea(str1, Address(str1, cnt2, Address::times_2, -16)); + subl(cnt1, cnt2); + movl(cnt2, 8); + addl(cnt1, 8); + bind(CONT_SCAN_SUBSTR); + movdqu(vec, Address(str2, 0)); + jmpb(SCAN_SUBSTR); + + bind(RET_FOUND_LONG); + movptr(str1, Address(rsp, wordSize)); + } // non constant + + bind(RET_FOUND); + // Compute substr offset + subptr(result, str1); + shrl(result, 1); // index bind(CLEANUP); - addptr(rsp, 3*wordSize); -} + pop(rsp); // restore SP + +} // string_indexof // Compare strings. void MacroAssembler::string_compare(Register str1, Register str2,
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -1121,6 +1121,7 @@ void movdl(XMMRegister dst, Register src); void movdl(Register dst, XMMRegister src); + void movdl(XMMRegister dst, Address src); // Move Double Quadword void movdq(XMMRegister dst, Register src); @@ -1288,9 +1289,12 @@ void pshuflw(XMMRegister dst, XMMRegister src, int mode); void pshuflw(XMMRegister dst, Address src, int mode); - // Shift Right Logical Quadword Immediate + // Shift Right by bits Logical Quadword Immediate void psrlq(XMMRegister dst, int shift); + // Shift Right by bytes Logical DoubleQuadword Immediate + void psrldq(XMMRegister dst, int shift); + // Logical Compare Double Quadword void ptest(XMMRegister dst, XMMRegister src); void ptest(XMMRegister dst, Address src); @@ -2290,10 +2294,22 @@ void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } // IndexOf strings. + // Small strings are loaded through stack if they cross page boundary. void string_indexof(Register str1, Register str2, - Register cnt1, Register cnt2, Register result, + Register cnt1, Register cnt2, + int int_cnt2, Register result, XMMRegister vec, Register tmp); + // IndexOf for constant substrings with size >= 8 elements + // which don't need to be loaded through stack. + void string_indexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int int_cnt2, Register result, + XMMRegister vec, Register tmp); + + // Smallest code: we don't need to load through stack, + // check string tail. + // Compare strings. void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result,
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -456,10 +456,8 @@ __ verify_not_null_oop(rax); // search an exception handler (rax: exception oop, rdx: throwing pc) - __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); - - __ stop("should not reach here"); - + __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id))); + __ should_not_reach_here(); assert(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub();
--- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -248,11 +248,14 @@ #ifdef _LP64 align_dummy_0, align_dummy_1, #endif // _LP64 - dummy1, SLOT2(dummy1H) // 0, 4 - dummy2, SLOT2(dummy2H) // 8, 12 - // Two temps to be used as needed by users of save/restore callee registers - temp_2_off, SLOT2(temp_2H_off) // 16, 20 - temp_1_off, SLOT2(temp_1H_off) // 24, 28 +#ifdef _WIN64 + // Windows always allocates space for it's argument registers (see + // frame::arg_reg_save_area_bytes). + arg_reg_save_1, arg_reg_save_1H, // 0, 4 + arg_reg_save_2, arg_reg_save_2H, // 8, 12 + arg_reg_save_3, arg_reg_save_3H, // 16, 20 + arg_reg_save_4, arg_reg_save_4H, // 24, 28 +#endif // _WIN64 xmm_regs_as_doubles_off, // 32 float_regs_as_doubles_off = xmm_regs_as_doubles_off + xmm_regs_as_doubles_size_in_slots, // 160 fpu_state_off = float_regs_as_doubles_off + float_regs_as_doubles_size_in_slots, // 224 @@ -282,24 +285,7 @@ rax_off, SLOT2(raxH_off) // 480, 484 saved_rbp_off, SLOT2(saved_rbpH_off) // 488, 492 return_off, SLOT2(returnH_off) // 496, 500 - reg_save_frame_size, // As noted: neglects any parameters to runtime // 504 - -#ifdef _WIN64 - c_rarg0_off = rcx_off, -#else - c_rarg0_off = rdi_off, -#endif // WIN64 - - // equates - - // illegal instruction handler - continue_dest_off = temp_1_off, - - // deoptimization equates - fp0_off = float_regs_as_doubles_off, // slot for java float/double return value - xmm0_off = xmm_regs_as_doubles_off, // slot for java float/double return value - deopt_type = temp_2_off, // slot for type of deopt in progress - ret_type = temp_1_off // slot for return type + reg_save_frame_size // As noted: neglects any parameters to runtime // 504 }; @@ -405,11 +391,6 @@ bool save_fpu_registers = true) { __ block_comment("save_live_registers"); - // 64bit passes the args in regs to the c++ runtime - int frame_size_in_slots = reg_save_frame_size NOT_LP64(+ num_rt_args); // args + thread - // frame_size = round_to(frame_size, 4); - sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word ); - __ pusha(); // integer registers // assert(float_regs_as_doubles_off % 2 == 0, "misaligned offset"); @@ -642,19 +623,58 @@ } -void Runtime1::generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map, bool save_fpu_registers) { +OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { + __ block_comment("generate_handle_exception"); + // incoming parameters const Register exception_oop = rax; - const Register exception_pc = rdx; + const Register exception_pc = rdx; // other registers used in this stub - const Register real_return_addr = rbx; const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); - __ block_comment("generate_handle_exception"); + // Save registers, if required. + OopMapSet* oop_maps = new OopMapSet(); + OopMap* oop_map = NULL; + switch (id) { + case forward_exception_id: + // We're handling an exception in the context of a compiled frame. + // The registers have been saved in the standard places. Perform + // an exception lookup in the caller and dispatch to the handler + // if found. Otherwise unwind and dispatch to the callers + // exception handler. + oop_map = generate_oop_map(sasm, 1 /*thread*/); + + // load and clear pending exception oop into RAX + __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); + __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); + + // load issuing PC (the return address for this stub) into rdx + __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); + + // make sure that the vm_results are cleared (may be unnecessary) + __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); + __ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); + break; + case handle_exception_nofpu_id: + case handle_exception_id: + // At this point all registers MAY be live. + oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id); + break; + case handle_exception_from_callee_id: { + // At this point all registers except exception oop (RAX) and + // exception pc (RDX) are dead. + const int frame_size = 2 /*BP, return address*/ NOT_LP64(+ 1 /*thread*/) WIN64_ONLY(+ frame::arg_reg_save_area_bytes / BytesPerWord); + oop_map = new OopMap(frame_size * VMRegImpl::slots_per_word, 0); + sasm->set_frame_size(frame_size); + WIN64_ONLY(__ subq(rsp, frame::arg_reg_save_area_bytes)); + break; + } + default: ShouldNotReachHere(); + } #ifdef TIERED // C2 can leave the fpu stack dirty - if (UseSSE < 2 ) { + if (UseSSE < 2) { __ empty_FPU_stack(); } #endif // TIERED @@ -686,11 +706,7 @@ // save exception oop and issuing pc into JavaThread // (exception handler will load it from here) __ movptr(Address(thread, JavaThread::exception_oop_offset()), exception_oop); - __ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc); - - // save real return address (pc that called this stub) - __ movptr(real_return_addr, Address(rbp, 1*BytesPerWord)); - __ movptr(Address(rsp, temp_1_off * VMRegImpl::stack_slot_size), real_return_addr); + __ movptr(Address(thread, JavaThread::exception_pc_offset()), exception_pc); // patch throwing pc into return address (has bci & oop map) __ movptr(Address(rbp, 1*BytesPerWord), exception_pc); @@ -700,33 +716,41 @@ int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, exception_handler_for_pc)); oop_maps->add_gc_map(call_offset, oop_map); - // rax,: handler address + // rax: handler address // will be the deopt blob if nmethod was deoptimized while we looked up // handler regardless of whether handler existed in the nmethod. // only rax, is valid at this time, all other registers have been destroyed by the runtime call __ invalidate_registers(false, true, true, true, true, true); -#ifdef ASSERT - // Do we have an exception handler in the nmethod? - Label done; - __ testptr(rax, rax); - __ jcc(Assembler::notZero, done); - __ stop("no handler found"); - __ bind(done); -#endif - - // exception handler found - // patch the return address -> the stub will directly return to the exception handler + // patch the return address, this stub will directly return to the exception handler __ movptr(Address(rbp, 1*BytesPerWord), rax); - // restore registers - restore_live_registers(sasm, save_fpu_registers); + switch (id) { + case forward_exception_id: + case handle_exception_nofpu_id: + case handle_exception_id: + // Restore the registers that were saved at the beginning. + restore_live_registers(sasm, id == handle_exception_nofpu_id); + break; + case handle_exception_from_callee_id: + // WIN64_ONLY: No need to add frame::arg_reg_save_area_bytes to SP + // since we do a leave anyway. - // return to exception handler - __ leave(); - __ ret(0); + // Pop the return address since we are possibly changing SP (restoring from BP). + __ leave(); + __ pop(rcx); + // Restore SP from BP if the exception PC is a method handle call site. + NOT_LP64(__ get_thread(thread);) + __ cmpl(Address(thread, JavaThread::is_method_handle_return_offset()), 0); + __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save); + __ jmp(rcx); // jump to exception handler + break; + default: ShouldNotReachHere(); + } + + return oop_maps; } @@ -791,7 +815,7 @@ // the pop is also necessary to simulate the effect of a ret(0) __ pop(exception_pc); - // Restore SP from BP if the exception PC is a MethodHandle call site. + // Restore SP from BP if the exception PC is a method handle call site. NOT_LP64(__ get_thread(thread);) __ cmpl(Address(thread, JavaThread::is_method_handle_return_offset()), 0); __ cmovptr(Assembler::notEqual, rsp, rbp_mh_SP_save); @@ -934,7 +958,6 @@ __ ret(0); return oop_maps; - } @@ -952,35 +975,9 @@ switch (id) { case forward_exception_id: { - // we're handling an exception in the context of a compiled - // frame. The registers have been saved in the standard - // places. Perform an exception lookup in the caller and - // dispatch to the handler if found. Otherwise unwind and - // dispatch to the callers exception handler. - - const Register thread = NOT_LP64(rdi) LP64_ONLY(r15_thread); - const Register exception_oop = rax; - const Register exception_pc = rdx; - - // load pending exception oop into rax, - __ movptr(exception_oop, Address(thread, Thread::pending_exception_offset())); - // clear pending exception - __ movptr(Address(thread, Thread::pending_exception_offset()), NULL_WORD); - - // load issuing PC (the return address for this stub) into rdx - __ movptr(exception_pc, Address(rbp, 1*BytesPerWord)); - - // make sure that the vm_results are cleared (may be unnecessary) - __ movptr(Address(thread, JavaThread::vm_result_offset()), NULL_WORD); - __ movptr(Address(thread, JavaThread::vm_result_2_offset()), NULL_WORD); - - // verify that that there is really a valid exception in rax, - __ verify_not_null_oop(exception_oop); - - oop_maps = new OopMapSet(); - OopMap* oop_map = generate_oop_map(sasm, 1); - generate_handle_exception(sasm, oop_maps, oop_map); - __ stop("should not reach here"); + oop_maps = generate_handle_exception(id, sasm); + __ leave(); + __ ret(0); } break; @@ -1315,13 +1312,15 @@ break; case handle_exception_nofpu_id: - save_fpu_registers = false; - // fall through case handle_exception_id: { StubFrame f(sasm, "handle_exception", dont_gc_arguments); - oop_maps = new OopMapSet(); - OopMap* oop_map = save_live_registers(sasm, 1, save_fpu_registers); - generate_handle_exception(sasm, oop_maps, oop_map, save_fpu_registers); + oop_maps = generate_handle_exception(id, sasm); + } + break; + + case handle_exception_from_callee_id: + { StubFrame f(sasm, "handle_exception_from_callee", dont_gc_arguments); + oop_maps = generate_handle_exception(id, sasm); } break;
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -419,6 +419,7 @@ // some handy addresses Address rbx_method_fie( rbx, methodOopDesc::from_interpreted_offset() ); + Address rbx_method_fce( rbx, methodOopDesc::from_compiled_offset() ); Address rcx_mh_vmtarget( rcx_recv, java_dyn_MethodHandle::vmtarget_offset_in_bytes() ); Address rcx_dmh_vmindex( rcx_recv, sun_dyn_DirectMethodHandle::vmindex_offset_in_bytes() ); @@ -448,12 +449,10 @@ case _raise_exception: { // Not a real MH entry, but rather shared code for raising an - // exception. Since we use a C2I adapter to set up the - // interpreter state, arguments are expected in compiler - // argument registers. + // exception. Since we use the compiled entry, arguments are + // expected in compiler argument registers. assert(raise_exception_method(), "must be set"); - address c2i_entry = raise_exception_method()->get_c2i_entry(); - assert(c2i_entry, "method must be linked"); + assert(raise_exception_method()->from_compiled_entry(), "method must be linked"); const Register rdi_pc = rax; __ pop(rdi_pc); // caller PC @@ -472,13 +471,10 @@ __ jccb(Assembler::zero, L_no_method); __ verify_oop(rbx_method); - // 32-bit: push remaining arguments as if coming from the compiler. NOT_LP64(__ push(rarg2_required)); + __ push(rdi_pc); // restore caller PC + __ jmp(rbx_method_fce); // jump to compiled entry - __ push(rdi_pc); // restore caller PC - __ jump(ExternalAddress(c2i_entry)); // do C2I transition - - // If we get here, the Java runtime did not do its job of creating the exception. // Do something that is at least causes a valid throw from the interpreter. __ bind(L_no_method); __ push(rarg2_required);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -439,10 +439,6 @@ // Verify that there is really a valid exception in RAX. __ verify_oop(exception_oop); - // Restore SP from BP if the exception PC is a MethodHandle call site. - __ cmpl(Address(thread, JavaThread::is_method_handle_return_offset()), 0); - __ cmovptr(Assembler::notEqual, rsp, rbp); - // continue at exception handler (return address removed) // rax: exception // rbx: exception handler @@ -733,18 +729,19 @@ // Input: // start - starting address // count - element count - void gen_write_ref_array_pre_barrier(Register start, Register count) { + void gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) { assert_different_registers(start, count); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: - { - __ pusha(); // push registers - __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), - start, count); - __ popa(); - } + // With G1, don't generate the call if we statically know that the target in uninitialized + if (!uninitialized_target) { + __ pusha(); // push registers + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), + start, count); + __ popa(); + } break; case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: @@ -923,7 +920,8 @@ address generate_disjoint_copy(BasicType t, bool aligned, Address::ScaleFactor sf, - address* entry, const char *name) { + address* entry, const char *name, + bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -945,16 +943,19 @@ __ movptr(from , Address(rsp, 12+ 4)); __ movptr(to , Address(rsp, 12+ 8)); __ movl(count, Address(rsp, 12+ 12)); + + if (entry != NULL) { + *entry = __ pc(); // Entry point from conjoint arraycopy stub. + BLOCK_COMMENT("Entry:"); + } + if (t == T_OBJECT) { __ testl(count, count); __ jcc(Assembler::zero, L_0_count); - gen_write_ref_array_pre_barrier(to, count); + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); __ mov(saved_to, to); // save 'to' } - *entry = __ pc(); // Entry point from conjoint arraycopy stub. - BLOCK_COMMENT("Entry:"); - __ subptr(to, from); // to --> to_from __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp @@ -1085,7 +1086,8 @@ address generate_conjoint_copy(BasicType t, bool aligned, Address::ScaleFactor sf, address nooverlap_target, - address* entry, const char *name) { + address* entry, const char *name, + bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1108,23 +1110,17 @@ __ movptr(src , Address(rsp, 12+ 4)); // from __ movptr(dst , Address(rsp, 12+ 8)); // to __ movl2ptr(count, Address(rsp, 12+12)); // count - if (t == T_OBJECT) { - gen_write_ref_array_pre_barrier(dst, count); - } if (entry != NULL) { *entry = __ pc(); // Entry point from generic arraycopy stub. BLOCK_COMMENT("Entry:"); } - if (t == T_OBJECT) { - __ testl(count, count); - __ jcc(Assembler::zero, L_0_count); - } + // nooverlap_target expects arguments in rsi and rdi. __ mov(from, src); __ mov(to , dst); - // arrays overlap test + // arrays overlap test: dispatch to disjoint stub if necessary. RuntimeAddress nooverlap(nooverlap_target); __ cmpptr(dst, src); __ lea(end, Address(src, count, sf, 0)); // src + count * elem_size @@ -1132,6 +1128,12 @@ __ cmpptr(dst, end); __ jump_cc(Assembler::aboveEqual, nooverlap); + if (t == T_OBJECT) { + __ testl(count, count); + __ jcc(Assembler::zero, L_0_count); + gen_write_ref_array_pre_barrier(dst, count, dest_uninitialized); + } + // copy from high to low __ cmpl(count, 2<<shift); // Short arrays (< 8 bytes) copy by element __ jcc(Assembler::below, L_copy_4_bytes); // use unsigned cmp @@ -1416,7 +1418,7 @@ // rax, == 0 - success // rax, == -1^K - failure, where K is partial transfer count // - address generate_checkcast_copy(const char *name, address* entry) { + address generate_checkcast_copy(const char *name, address* entry, bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1451,8 +1453,10 @@ __ movptr(to, to_arg); __ movl2ptr(length, length_arg); - *entry = __ pc(); // Entry point from generic arraycopy stub. - BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); // Entry point from generic arraycopy stub. + BLOCK_COMMENT("Entry:"); + } //--------------------------------------------------------------- // Assembler stub will be used for this call to arraycopy @@ -1475,7 +1479,7 @@ Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes()); // Copy from low to high addresses, indexed from the end of each array. - gen_write_ref_array_pre_barrier(to, count); + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); __ lea(end_from, end_from_addr); __ lea(end_to, end_to_addr); assert(length == count, ""); // else fix next line: @@ -2038,6 +2042,15 @@ generate_conjoint_copy(T_OBJECT, true, Address::times_ptr, entry, &entry_oop_arraycopy, "oop_arraycopy"); + StubRoutines::_oop_disjoint_arraycopy_uninit = + generate_disjoint_copy(T_OBJECT, true, Address::times_ptr, &entry, + "oop_disjoint_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_oop_arraycopy_uninit = + generate_conjoint_copy(T_OBJECT, true, Address::times_ptr, entry, + NULL, "oop_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_copy(&entry, "jlong_disjoint_arraycopy"); StubRoutines::_jlong_arraycopy = @@ -2051,20 +2064,20 @@ StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); - StubRoutines::_arrayof_jint_disjoint_arraycopy = - StubRoutines::_jint_disjoint_arraycopy; - StubRoutines::_arrayof_oop_disjoint_arraycopy = - StubRoutines::_oop_disjoint_arraycopy; - StubRoutines::_arrayof_jlong_disjoint_arraycopy = - StubRoutines::_jlong_disjoint_arraycopy; + StubRoutines::_arrayof_jint_disjoint_arraycopy = StubRoutines::_jint_disjoint_arraycopy; + StubRoutines::_arrayof_oop_disjoint_arraycopy = StubRoutines::_oop_disjoint_arraycopy; + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = StubRoutines::_oop_disjoint_arraycopy_uninit; + StubRoutines::_arrayof_jlong_disjoint_arraycopy = StubRoutines::_jlong_disjoint_arraycopy; - StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; - StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; - StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; + StubRoutines::_arrayof_jint_arraycopy = StubRoutines::_jint_arraycopy; + StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; + StubRoutines::_arrayof_oop_arraycopy_uninit = StubRoutines::_oop_arraycopy_uninit; + StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy; StubRoutines::_checkcast_arraycopy = - generate_checkcast_copy("checkcast_arraycopy", - &entry_checkcast_arraycopy); + generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = + generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, /*dest_uninitialized*/true); StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy",
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -1057,20 +1057,6 @@ return start; } - static address disjoint_byte_copy_entry; - static address disjoint_short_copy_entry; - static address disjoint_int_copy_entry; - static address disjoint_long_copy_entry; - static address disjoint_oop_copy_entry; - - static address byte_copy_entry; - static address short_copy_entry; - static address int_copy_entry; - static address long_copy_entry; - static address oop_copy_entry; - - static address checkcast_copy_entry; - // // Verify that a register contains clean 32-bits positive value // (high 32-bits are 0) so it could be used in 64-bits shifts. @@ -1173,34 +1159,35 @@ // Generate code for an array write pre barrier // // addr - starting address - // count - element count + // count - element count + // tmp - scratch register // // Destroy no registers! // - void gen_write_ref_array_pre_barrier(Register addr, Register count) { + void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) { BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: - { - __ pusha(); // push registers - if (count == c_rarg0) { - if (addr == c_rarg1) { - // exactly backwards!! - __ xchgptr(c_rarg1, c_rarg0); - } else { - __ movptr(c_rarg1, count); - __ movptr(c_rarg0, addr); - } - - } else { - __ movptr(c_rarg0, addr); - __ movptr(c_rarg1, count); - } - __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); - __ popa(); + // With G1, don't generate the call if we statically know that the target in uninitialized + if (!dest_uninitialized) { + __ pusha(); // push registers + if (count == c_rarg0) { + if (addr == c_rarg1) { + // exactly backwards!! + __ xchgptr(c_rarg1, c_rarg0); + } else { + __ movptr(c_rarg1, count); + __ movptr(c_rarg0, addr); + } + } else { + __ movptr(c_rarg0, addr); + __ movptr(c_rarg1, count); + } + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); + __ popa(); } - break; + break; case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: @@ -1379,7 +1366,7 @@ // disjoint_byte_copy_entry is set to the no-overlap entry point // used by generate_conjoint_byte_copy(). // - address generate_disjoint_byte_copy(bool aligned, const char *name) { + address generate_disjoint_byte_copy(bool aligned, address* entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1399,9 +1386,11 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - disjoint_byte_copy_entry = __ pc(); - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers @@ -1479,7 +1468,8 @@ // dwords or qwords that span cache line boundaries will still be loaded // and stored atomically. // - address generate_conjoint_byte_copy(bool aligned, const char *name) { + address generate_conjoint_byte_copy(bool aligned, address nooverlap_target, + address* entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1494,11 +1484,13 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - byte_copy_entry = __ pc(); - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - - array_overlap_test(disjoint_byte_copy_entry, Address::times_1); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } + + array_overlap_test(nooverlap_target, Address::times_1); setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers @@ -1574,7 +1566,7 @@ // disjoint_short_copy_entry is set to the no-overlap entry point // used by generate_conjoint_short_copy(). // - address generate_disjoint_short_copy(bool aligned, const char *name) { + address generate_disjoint_short_copy(bool aligned, address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1593,9 +1585,11 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - disjoint_short_copy_entry = __ pc(); - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers @@ -1686,7 +1680,8 @@ // or qwords that span cache line boundaries will still be loaded // and stored atomically. // - address generate_conjoint_short_copy(bool aligned, const char *name) { + address generate_conjoint_short_copy(bool aligned, address nooverlap_target, + address *entry, const char *name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1701,11 +1696,13 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - short_copy_entry = __ pc(); - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - - array_overlap_test(disjoint_short_copy_entry, Address::times_2); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } + + array_overlap_test(nooverlap_target, Address::times_2); setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers @@ -1773,7 +1770,8 @@ // disjoint_int_copy_entry is set to the no-overlap entry point // used by generate_conjoint_int_oop_copy(). // - address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) { + address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, + const char *name, bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1793,21 +1791,17 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - (is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry) = __ pc(); - - if (is_oop) { - // no registers are destroyed by this call - gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); } - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers - if (is_oop) { __ movq(saved_to, to); + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); } // 'from', 'to' and 'count' are now valid @@ -1867,7 +1861,9 @@ // the hardware handle it. The two dwords within qwords that span // cache line boundaries will still be loaded and stored atomicly. // - address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) { + address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, address nooverlap_target, + address *entry, const char *name, + bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1882,20 +1878,21 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); + } + + array_overlap_test(nooverlap_target, Address::times_4); + setup_arg_regs(); // from => rdi, to => rsi, count => rdx + // r9 and r10 may be used to save non-volatile registers + if (is_oop) { // no registers are destroyed by this call - gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); } - (is_oop ? oop_copy_entry : int_copy_entry) = __ pc(); - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - - array_overlap_test(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry, - Address::times_4); - setup_arg_regs(); // from => rdi, to => rsi, count => rdx - // r9 and r10 may be used to save non-volatile registers - assert_clean_int(count, rax); // Make sure 'count' is clean int. // 'from', 'to' and 'count' are now valid __ movptr(dword_count, count); @@ -1959,7 +1956,8 @@ // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the // no-overlap entry point used by generate_conjoint_long_oop_copy(). // - address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, const char *name) { + address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, + const char *name, bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1978,20 +1976,19 @@ // Save no-overlap entry point for generate_conjoint_long_oop_copy() assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - if (is_oop) { - disjoint_oop_copy_entry = __ pc(); - // no registers are destroyed by this call - gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2); - } else { - disjoint_long_copy_entry = __ pc(); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); } - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers - // 'from', 'to' and 'qword_count' are now valid + if (is_oop) { + // no registers are destroyed by this call + gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized); + } // Copy from low to high addresses. Use 'to' as scratch. __ lea(end_from, Address(from, qword_count, Address::times_8, -8)); @@ -2045,7 +2042,9 @@ // c_rarg1 - destination array address // c_rarg2 - element count, treated as ssize_t, can be zero // - address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, const char *name) { + address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, + address nooverlap_target, address *entry, + const char *name, bool dest_uninitialized = false) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -2059,31 +2058,21 @@ __ enter(); // required for proper stackwalking of RuntimeStub frame assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int. - address disjoint_copy_entry = NULL; - if (is_oop) { - assert(!UseCompressedOops, "shouldn't be called for compressed oops"); - disjoint_copy_entry = disjoint_oop_copy_entry; - oop_copy_entry = __ pc(); - array_overlap_test(disjoint_oop_copy_entry, Address::times_8); - } else { - disjoint_copy_entry = disjoint_long_copy_entry; - long_copy_entry = __ pc(); - array_overlap_test(disjoint_long_copy_entry, Address::times_8); + if (entry != NULL) { + *entry = __ pc(); + // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) + BLOCK_COMMENT("Entry:"); } - BLOCK_COMMENT("Entry:"); - // caller can pass a 64-bit byte count here (from Unsafe.copyMemory) - - array_overlap_test(disjoint_copy_entry, Address::times_8); + + array_overlap_test(nooverlap_target, Address::times_8); setup_arg_regs(); // from => rdi, to => rsi, count => rdx // r9 and r10 may be used to save non-volatile registers - // 'from', 'to' and 'qword_count' are now valid - if (is_oop) { // Save to and count for store barrier __ movptr(saved_count, qword_count); // No registers are destroyed by this call - gen_write_ref_array_pre_barrier(to, saved_count); + gen_write_ref_array_pre_barrier(to, saved_count, dest_uninitialized); } __ jmp(L_copy_32_bytes); @@ -2162,7 +2151,8 @@ // rax == 0 - success // rax == -1^K - failure, where K is partial transfer count // - address generate_checkcast_copy(const char *name) { + address generate_checkcast_copy(const char *name, address *entry, + bool dest_uninitialized = false) { Label L_load_element, L_store_element, L_do_card_marks, L_done; @@ -2216,8 +2206,10 @@ #endif // Caller of this entry point must set up the argument registers. - checkcast_copy_entry = __ pc(); - BLOCK_COMMENT("Entry:"); + if (entry != NULL) { + *entry = __ pc(); + BLOCK_COMMENT("Entry:"); + } // allocate spill slots for r13, r14 enum { @@ -2254,7 +2246,7 @@ Address from_element_addr(end_from, count, TIMES_OOP, 0); Address to_element_addr(end_to, count, TIMES_OOP, 0); - gen_write_ref_array_pre_barrier(to, count); + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); // Copy from low to high addresses, indexed from the end of each array. __ lea(end_from, end_from_addr); @@ -2334,7 +2326,9 @@ // Examines the alignment of the operands and dispatches // to a long, int, short, or byte copy loop. // - address generate_unsafe_copy(const char *name) { + address generate_unsafe_copy(const char *name, + address byte_copy_entry, address short_copy_entry, + address int_copy_entry, address long_copy_entry) { Label L_long_aligned, L_int_aligned, L_short_aligned; @@ -2432,7 +2426,10 @@ // rax == 0 - success // rax == -1^K - failure, where K is partial transfer count // - address generate_generic_copy(const char *name) { + address generate_generic_copy(const char *name, + address byte_copy_entry, address short_copy_entry, + address int_copy_entry, address long_copy_entry, + address oop_copy_entry, address checkcast_copy_entry) { Label L_failed, L_failed_0, L_objArray; Label L_copy_bytes, L_copy_shorts, L_copy_ints, L_copy_longs; @@ -2725,33 +2722,75 @@ } void generate_arraycopy_stubs() { - // Call the conjoint generation methods immediately after - // the disjoint ones so that short branches from the former - // to the latter can be generated. - StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, "jbyte_disjoint_arraycopy"); - StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, "jbyte_arraycopy"); - - StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy"); - StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy"); - - StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, "jint_disjoint_arraycopy"); - StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, "jint_arraycopy"); - - StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, "jlong_disjoint_arraycopy"); - StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, "jlong_arraycopy"); + address entry; + address entry_jbyte_arraycopy; + address entry_jshort_arraycopy; + address entry_jint_arraycopy; + address entry_oop_arraycopy; + address entry_jlong_arraycopy; + address entry_checkcast_arraycopy; + + StubRoutines::_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(false, &entry, + "jbyte_disjoint_arraycopy"); + StubRoutines::_jbyte_arraycopy = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy, + "jbyte_arraycopy"); + + StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry, + "jshort_disjoint_arraycopy"); + StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy, + "jshort_arraycopy"); + + StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, &entry, + "jint_disjoint_arraycopy"); + StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, entry, + &entry_jint_arraycopy, "jint_arraycopy"); + + StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, &entry, + "jlong_disjoint_arraycopy"); + StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, entry, + &entry_jlong_arraycopy, "jlong_arraycopy"); if (UseCompressedOops) { - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, "oop_disjoint_arraycopy"); - StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, "oop_arraycopy"); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, &entry, + "oop_disjoint_arraycopy"); + StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, entry, + &entry_oop_arraycopy, "oop_arraycopy"); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_int_oop_copy(false, true, &entry, + "oop_disjoint_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_int_oop_copy(false, true, entry, + NULL, "oop_arraycopy_uninit", + /*dest_uninitialized*/true); } else { - StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy"); - StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy"); + StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, &entry, + "oop_disjoint_arraycopy"); + StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, entry, + &entry_oop_arraycopy, "oop_arraycopy"); + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_long_oop_copy(false, true, &entry, + "oop_disjoint_arraycopy_uninit", + /*dest_uninitialized*/true); + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_long_oop_copy(false, true, entry, + NULL, "oop_arraycopy_uninit", + /*dest_uninitialized*/true); } - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy"); - StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy"); - StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy"); + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, + /*dest_uninitialized*/true); + + StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", + entry_jbyte_arraycopy, + entry_jshort_arraycopy, + entry_jint_arraycopy, + entry_jlong_arraycopy); + StubRoutines::_generic_arraycopy = generate_generic_copy("generic_arraycopy", + entry_jbyte_arraycopy, + entry_jshort_arraycopy, + entry_jint_arraycopy, + entry_oop_arraycopy, + entry_jlong_arraycopy, + entry_checkcast_arraycopy); StubRoutines::_jbyte_fill = generate_fill(T_BYTE, false, "jbyte_fill"); StubRoutines::_jshort_fill = generate_fill(T_SHORT, false, "jshort_fill"); @@ -2776,6 +2815,9 @@ StubRoutines::_arrayof_oop_disjoint_arraycopy = StubRoutines::_oop_disjoint_arraycopy; StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; + + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = StubRoutines::_oop_disjoint_arraycopy_uninit; + StubRoutines::_arrayof_oop_arraycopy_uninit = StubRoutines::_oop_arraycopy_uninit; } void generate_math_stubs() { @@ -3069,20 +3111,6 @@ } }; // end class declaration -address StubGenerator::disjoint_byte_copy_entry = NULL; -address StubGenerator::disjoint_short_copy_entry = NULL; -address StubGenerator::disjoint_int_copy_entry = NULL; -address StubGenerator::disjoint_long_copy_entry = NULL; -address StubGenerator::disjoint_oop_copy_entry = NULL; - -address StubGenerator::byte_copy_entry = NULL; -address StubGenerator::short_copy_entry = NULL; -address StubGenerator::int_copy_entry = NULL; -address StubGenerator::long_copy_entry = NULL; -address StubGenerator::oop_copy_entry = NULL; - -address StubGenerator::checkcast_copy_entry = NULL; - void StubGenerator_generate(CodeBuffer* code, bool all) { StubGenerator g(code, all); }
--- a/hotspot/src/cpu/x86/vm/x86_32.ad Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_32.ad Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 2011, 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 @@ -12658,17 +12658,46 @@ ins_pipe( pipe_slow ); %} +// fast search of substring with known size. +instruct string_indexof_con(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2, + eBXRegI result, regXD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{ + predicate(UseSSE42Intrinsics); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + if (icnt2 >= 8) { + // IndexOf for constant substrings with size >= 8 elements + // which don't need to be loaded through stack. + __ string_indexofC8($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register); + } else { + // Small strings are loaded through stack if they cross page boundary. + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register); + } + %} + ins_pipe( pipe_slow ); +%} + instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2, - eBXRegI result, regXD tmp1, eCXRegI tmp2, eFlagsReg cr) %{ + eBXRegI result, regXD vec, eCXRegI tmp, eFlagsReg cr) %{ predicate(UseSSE42Intrinsics); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr); - - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp2, $tmp1" %} + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, - $cnt1$$Register, $cnt2$$Register, $result$$Register, - $tmp1$$XMMRegister, $tmp2$$Register); + $cnt1$$Register, $cnt2$$Register, + (-1), $result$$Register, + $vec$$XMMRegister, $tmp$$Register); %} ins_pipe( pipe_slow ); %}
--- a/hotspot/src/cpu/x86/vm/x86_64.ad Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2011, 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 @@ -11598,18 +11598,48 @@ ins_pipe( pipe_slow ); %} +// fast search of substring with known size. +instruct string_indexof_con(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2, + rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr) +%{ + predicate(UseSSE42Intrinsics); + match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2))); + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %} + ins_encode %{ + int icnt2 = (int)$int_cnt2$$constant; + if (icnt2 >= 8) { + // IndexOf for constant substrings with size >= 8 elements + // which don't need to be loaded through stack. + __ string_indexofC8($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register); + } else { + // Small strings are loaded through stack if they cross page boundary. + __ string_indexof($str1$$Register, $str2$$Register, + $cnt1$$Register, $cnt2$$Register, + icnt2, $result$$Register, + $vec$$XMMRegister, $tmp$$Register); + } + %} + ins_pipe( pipe_slow ); +%} + instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2, - rbx_RegI result, regD tmp1, rcx_RegI tmp2, rFlagsReg cr) + rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr) %{ predicate(UseSSE42Intrinsics); match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2))); - effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp2, KILL cr); - - format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1, $tmp2" %} + effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr); + + format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %} ins_encode %{ __ string_indexof($str1$$Register, $str2$$Register, - $cnt1$$Register, $cnt2$$Register, $result$$Register, - $tmp1$$XMMRegister, $tmp2$$Register); + $cnt1$$Register, $cnt2$$Register, + (-1), $result$$Register, + $vec$$XMMRegister, $tmp$$Register); %} ins_pipe( pipe_slow ); %}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -2213,7 +2213,7 @@ if (rp == NULL) return; - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is // "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and
--- a/hotspot/src/os/posix/vm/os_posix.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/os/posix/vm/os_posix.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -59,3 +59,12 @@ VMError::report_coredump_status(buffer, success); } +bool os::is_debugger_attached() { + // not implemented + return false; +} + +void os::wait_for_keypress_at_exit(void) { + // don't do anything on posix platforms + return; +}
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -2511,7 +2511,7 @@ assert(ret != 0, "cannot locate libjvm"); realpath((char *)dlinfo.dli_fname, buf); - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is // "<JAVA_HOME>/jre/lib/<arch>/<vmtype>/libjvm.so". If "/jre/lib/" appears at // the right place in the string, then assume we are installed in a JDK and
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -22,10 +22,8 @@ * */ -#ifdef _WIN64 -// Must be at least Windows 2000 or XP to use VectoredExceptions +// Must be at least Windows 2000 or XP to use VectoredExceptions and IsDebuggerPresent #define _WIN32_WINNT 0x500 -#endif // no precompiled headers #include "classfile/classLoader.hpp" @@ -1788,7 +1786,7 @@ } buf[0] = '\0'; - if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Check for an // JAVA_HOME environment variable // and fix up the path so it looks like @@ -3418,6 +3416,19 @@ } +bool os::is_debugger_attached() { + return IsDebuggerPresent() ? true : false; +} + + +void os::wait_for_keypress_at_exit(void) { + if (PauseAtExit) { + fprintf(stderr, "Press any key to continue...\n"); + fgetc(stdin); + } +} + + int os::message_box(const char* title, const char* message) { int result = MessageBox(NULL, message, title, MB_YESNO | MB_ICONERROR | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);
--- a/hotspot/src/share/tools/hsdis/hsdis-demo.c Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/tools/hsdis/hsdis-demo.c Fri Mar 18 10:59:12 2011 -0700 @@ -22,8 +22,6 @@ * */ -#include "precompiled.hpp" - /* hsdis-demo.c -- dump a range of addresses as native instructions This demonstrates the protocol required by the HotSpot PrintAssembly option. */
--- a/hotspot/src/share/tools/hsdis/hsdis.c Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/tools/hsdis/hsdis.c Fri Mar 18 10:59:12 2011 -0700 @@ -22,8 +22,6 @@ * */ -#include "precompiled.hpp" - /* hsdis.c -- dump a range of addresses as native instructions This implements the plugin protocol required by the HotSpot PrintAssembly option.
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -3308,22 +3308,23 @@ Value exception = append_with_bci(new ExceptionObject(), SynchronizationEntryBCI); assert(exception->is_pinned(), "must be"); + int bci = SynchronizationEntryBCI; if (compilation()->env()->dtrace_method_probes()) { - // Report exit from inline methods + // Report exit from inline methods. We don't have a stream here + // so pass an explicit bci of SynchronizationEntryBCI. Values* args = new Values(1); - args->push(append(new Constant(new ObjectConstant(method())))); - append(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args)); + args->push(append_with_bci(new Constant(new ObjectConstant(method())), bci)); + append_with_bci(new RuntimeCall(voidType, "dtrace_method_exit", CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), args), bci); } - int bci = SynchronizationEntryBCI; if (lock) { assert(state()->locks_size() > 0 && state()->lock_at(state()->locks_size() - 1) == lock, "lock is missing"); if (!lock->is_linked()) { - lock = append_with_bci(lock, -1); + lock = append_with_bci(lock, bci); } // exit the monitor in the context of the synchronized method - monitorexit(lock, SynchronizationEntryBCI); + monitorexit(lock, bci); // exit the context of the synchronized method if (!default_handler) {
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -426,10 +426,9 @@ // been deoptimized. If that is the case we return the deopt blob // unpack_with_exception entry instead. This makes life for the exception blob easier // because making that same check and diverting is painful from assembly language. -// - - JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* thread, oopDesc* ex, address pc, nmethod*& nm)) + // Reset method handle flag. + thread->set_is_method_handle_return(false); Handle exception(thread, ex); nm = CodeCache::find_nmethod(pc); @@ -480,11 +479,12 @@ return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); } - // ExceptionCache is used only for exceptions at call and not for implicit exceptions + // ExceptionCache is used only for exceptions at call sites and not for implicit exceptions if (guard_pages_enabled) { address fast_continuation = nm->handler_for_exception_and_pc(exception, pc); if (fast_continuation != NULL) { - if (fast_continuation == ExceptionCache::unwind_handler()) fast_continuation = NULL; + // Set flag if return address is a method handle call site. + thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); return fast_continuation; } } @@ -522,14 +522,14 @@ thread->set_exception_pc(pc); // the exception cache is used only by non-implicit exceptions - if (continuation == NULL) { - nm->add_handler_for_exception_and_pc(exception, pc, ExceptionCache::unwind_handler()); - } else { + if (continuation != NULL) { nm->add_handler_for_exception_and_pc(exception, pc, continuation); } } thread->set_vm_result(exception()); + // Set flag if return address is a method handle call site. + thread->set_is_method_handle_return(nm->is_method_handle_return(pc)); if (TraceExceptions) { ttyLocker ttyl; @@ -542,20 +542,19 @@ JRT_END // Enter this method from compiled code only if there is a Java exception handler -// in the method handling the exception +// in the method handling the exception. // We are entering here from exception stub. We don't do a normal VM transition here. // We do it in a helper. This is so we can check to see if the nmethod we have just // searched for an exception handler has been deoptimized in the meantime. -address Runtime1::exception_handler_for_pc(JavaThread* thread) { +address Runtime1::exception_handler_for_pc(JavaThread* thread) { oop exception = thread->exception_oop(); address pc = thread->exception_pc(); // Still in Java mode - debug_only(ResetNoHandleMark rnhm); + DEBUG_ONLY(ResetNoHandleMark rnhm); nmethod* nm = NULL; address continuation = NULL; { // Enter VM mode by calling the helper - ResetNoHandleMark rnhm; continuation = exception_handler_for_pc_helper(thread, exception, pc, nm); } @@ -563,11 +562,11 @@ // Now check to see if the nmethod we were called from is now deoptimized. // If so we must return to the deopt blob and deoptimize the nmethod - if (nm != NULL && caller_is_deopted()) { continuation = SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); } + assert(continuation != NULL, "no handler found"); return continuation; }
--- a/hotspot/src/share/vm/c1/c1_Runtime1.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -54,6 +54,7 @@ stub(new_multi_array) \ stub(handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \ stub(handle_exception) \ + stub(handle_exception_from_callee) \ stub(throw_array_store_exception) \ stub(throw_class_cast_exception) \ stub(throw_incompatible_class_change_error) \ @@ -116,11 +117,11 @@ static const char* _blob_names[]; // stub generation - static void generate_blob_for(BufferBlob* blob, StubID id); - static OopMapSet* generate_code_for(StubID id, StubAssembler* masm); + static void generate_blob_for(BufferBlob* blob, StubID id); + static OopMapSet* generate_code_for(StubID id, StubAssembler* sasm); static OopMapSet* generate_exception_throw(StubAssembler* sasm, address target, bool has_argument); - static void generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map, bool ignore_fpu_registers = false); - static void generate_unwind_exception(StubAssembler *sasm); + static OopMapSet* generate_handle_exception(StubID id, StubAssembler* sasm); + static void generate_unwind_exception(StubAssembler *sasm); static OopMapSet* generate_patching(StubAssembler* sasm, address target); static OopMapSet* generate_stub_call(StubAssembler* sasm, Register result, address entry,
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1332,7 +1332,7 @@ } if (_compile_the_world_counter >= CompileTheWorldStartAt) { - if (k.is_null() || (exception_occurred && !CompileTheWorldIgnoreInitErrors)) { + if (k.is_null() || exception_occurred) { // If something went wrong (e.g. ExceptionInInitializerError) we skip this class tty->print_cr("CompileTheWorld (%d) : Skipping %s", _compile_the_world_counter, buffer); } else {
--- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -170,6 +170,44 @@ return true; } +bool StackMapFrame::has_flag_match_exception( + const StackMapFrame* target) const { + // We allow flags of {UninitThis} to assign to {} if-and-only-if the + // target frame does not depend upon the current type. + // This is slightly too strict, as we need only enforce that the + // slots that were initialized by the <init> (the things that were + // UninitializedThis before initialize_object() converted them) are unused. + // However we didn't save that information so we'll enforce this upon + // anything that might have been initialized. This is a rare situation + // and javac never generates code that would end up here, but some profilers + // (such as NetBeans) might, when adding exception handlers in <init> + // methods to cover the invokespecial instruction. See 7020118. + + assert(max_locals() == target->max_locals() && + stack_size() == target->stack_size(), "StackMap sizes must match"); + + VerificationType top = VerificationType::top_type(); + VerificationType this_type = verifier()->current_type(); + + if (!flag_this_uninit() || target->flags() != 0) { + return false; + } + + for (int i = 0; i < target->locals_size(); ++i) { + if (locals()[i] == this_type && target->locals()[i] != top) { + return false; + } + } + + for (int i = 0; i < target->stack_size(); ++i) { + if (stack()[i] == this_type && target->stack()[i] != top) { + return false; + } + } + + return true; +} + bool StackMapFrame::is_assignable_to(const StackMapFrame* target, TRAPS) const { if (_max_locals != target->max_locals() || _stack_size != target->stack_size()) { return false; @@ -182,7 +220,9 @@ bool match_stack = is_assignable_to( _stack, target->stack(), _stack_size, CHECK_false); bool match_flags = (_flags | target->flags()) == target->flags(); - return (match_locals && match_stack && match_flags); + + return match_locals && match_stack && + (match_flags || has_flag_match_exception(target)); } VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) {
--- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -228,6 +228,8 @@ bool is_assignable_to( VerificationType* src, VerificationType* target, int32_t len, TRAPS) const; + bool has_flag_match_exception(const StackMapFrame* target) const; + // Debugging void print() const PRODUCT_RETURN; };
--- a/hotspot/src/share/vm/classfile/verificationType.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/classfile/verificationType.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -128,6 +128,7 @@ // Create verification types static VerificationType bogus_type() { return VerificationType(Bogus); } + static VerificationType top_type() { return bogus_type(); } // alias static VerificationType null_type() { return VerificationType(Null); } static VerificationType integer_type() { return VerificationType(Integer); } static VerificationType float_type() { return VerificationType(Float); }
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -190,15 +190,10 @@ } nmethod_stats; #endif //PRODUCT + //--------------------------------------------------------------------------------- -// The _unwind_handler is a special marker address, which says that -// for given exception oop and address, the frame should be removed -// as the tuple cannot be caught in the nmethod -address ExceptionCache::_unwind_handler = (address) -1; - - ExceptionCache::ExceptionCache(Handle exception, address pc, address handler) { assert(pc != NULL, "Must be non null"); assert(exception.not_null(), "Must be non null");
--- a/hotspot/src/share/vm/code/nmethod.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/code/nmethod.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -34,7 +34,6 @@ class ExceptionCache : public CHeapObj { friend class VMStructs; private: - static address _unwind_handler; enum { cache_size = 16 }; klassOop _exception_type; address _pc[cache_size]; @@ -62,8 +61,6 @@ bool match_exception_with_space(Handle exception) ; address test_address(address addr); bool add_address_and_handler(address addr, address handler) ; - - static address unwind_handler() { return _unwind_handler; } };
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -5474,8 +5474,6 @@ _refine_cte_cl->set_concurrent(concurrent); } -#ifdef ASSERT - bool G1CollectedHeap::is_in_closed_subset(const void* p) const { HeapRegion* hr = heap_region_containing(p); if (hr == NULL) { @@ -5484,7 +5482,6 @@ return hr->is_in(p); } } -#endif // ASSERT class VerifyRegionListsClosure : public HeapRegionClosure { private:
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -1134,7 +1134,7 @@ return _g1_committed; } - NOT_PRODUCT(bool is_in_closed_subset(const void* p) const;) + virtual bool is_in_closed_subset(const void* p) const; // Dirty card table entries covering a list of young regions. void dirtyCardsForYoungRegions(CardTableModRefBS* ct_bs, HeapRegion* list);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -83,11 +83,15 @@ } template <class T> void write_ref_array_pre_work(T* dst, int count); - virtual void write_ref_array_pre(oop* dst, int count) { - write_ref_array_pre_work(dst, count); + virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) { + if (!dest_uninitialized) { + write_ref_array_pre_work(dst, count); + } } - virtual void write_ref_array_pre(narrowOop* dst, int count) { - write_ref_array_pre_work(dst, count); + virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) { + if (!dest_uninitialized) { + write_ref_array_pre_work(dst, count); + } } };
--- a/hotspot/src/share/vm/memory/allocation.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/memory/allocation.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -422,6 +422,9 @@ return sum; // Return total consumed space. } +void Arena::signal_out_of_memory(size_t sz, const char* whence) const { + vm_exit_out_of_memory(sz, whence); +} // Grow a new Chunk void* Arena::grow( size_t x ) { @@ -431,8 +434,9 @@ Chunk *k = _chunk; // Get filled-up chunk address _chunk = new (len) Chunk(len); - if (_chunk == NULL) - vm_exit_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow"); + if (_chunk == NULL) { + signal_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow"); + } if (k) k->set_next(_chunk); // Append new chunk to end of linked list else _first = _chunk; @@ -529,6 +533,7 @@ // for debugging with UseMallocOnly void* Arena::internal_malloc_4(size_t x) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); + check_for_overflow(x, "Arena::internal_malloc_4"); if (_hwm + x > _max) { return grow(x); } else {
--- a/hotspot/src/share/vm/memory/allocation.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/memory/allocation.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -207,6 +207,15 @@ debug_only(void* malloc(size_t size);) debug_only(void* internal_malloc_4(size_t x);) NOT_PRODUCT(void inc_bytes_allocated(size_t x);) + + void signal_out_of_memory(size_t request, const char* whence) const; + + void check_for_overflow(size_t request, const char* whence) const { + if (UINTPTR_MAX - request < (uintptr_t)_hwm) { + signal_out_of_memory(request, whence); + } + } + public: Arena(); Arena(size_t init_size); @@ -220,6 +229,7 @@ assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2"); x = ARENA_ALIGN(x); debug_only(if (UseMallocOnly) return malloc(x);) + check_for_overflow(x, "Arena::Amalloc"); NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); @@ -233,6 +243,7 @@ void *Amalloc_4(size_t x) { assert( (x&(sizeof(char*)-1)) == 0, "misaligned size" ); debug_only(if (UseMallocOnly) return malloc(x);) + check_for_overflow(x, "Arena::Amalloc_4"); NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); @@ -253,6 +264,7 @@ size_t delta = (((size_t)_hwm + DALIGN_M1) & ~DALIGN_M1) - (size_t)_hwm; x += delta; #endif + check_for_overflow(x, "Arena::Amalloc_D"); NOT_PRODUCT(inc_bytes_allocated(x);) if (_hwm + x > _max) { return grow(x); // grow() returns a result aligned >= 8 bytes.
--- a/hotspot/src/share/vm/memory/barrierSet.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/memory/barrierSet.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -35,9 +35,9 @@ start, count); #endif if (UseCompressedOops) { - Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count); + Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count, false); } else { - Universe::heap()->barrier_set()->write_ref_array_pre( (oop*)start, (int)count); + Universe::heap()->barrier_set()->write_ref_array_pre( (oop*)start, (int)count, false); } }
--- a/hotspot/src/share/vm/memory/barrierSet.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/memory/barrierSet.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, 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,10 @@ Uninit }; + enum Flags { + None = 0, + TargetUninitialized = 1 + }; protected: int _max_covered_regions; Name _kind; @@ -128,8 +132,10 @@ virtual void read_prim_array(MemRegion mr) = 0; // Below length is the # array elements being written - virtual void write_ref_array_pre( oop* dst, int length) {} - virtual void write_ref_array_pre(narrowOop* dst, int length) {} + virtual void write_ref_array_pre(oop* dst, int length, + bool dest_uninitialized = false) {} + virtual void write_ref_array_pre(narrowOop* dst, int length, + bool dest_uninitialized = false) {} // Below count is the # array elements being written, starting // at the address "start", which may not necessarily be HeapWord-aligned inline void write_ref_array(HeapWord* start, size_t count);
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/opto/library_call.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -97,7 +97,7 @@ RegionNode* region); Node* generate_current_thread(Node* &tls_output); address basictype2arraycopy(BasicType t, Node *src_offset, Node *dest_offset, - bool disjoint_bases, const char* &name); + bool disjoint_bases, const char* &name, bool dest_uninitialized); Node* load_mirror_from_klass(Node* klass); Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null, int nargs, @@ -212,26 +212,26 @@ AllocateNode* alloc, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* dest_size); + Node* dest_size, bool dest_uninitialized); void generate_slow_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length); + Node* copy_length, bool dest_uninitialized); Node* generate_checkcast_arraycopy(const TypePtr* adr_type, Node* dest_elem_klass, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length); + Node* copy_length, bool dest_uninitialized); Node* generate_generic_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length); + Node* copy_length, bool dest_uninitialized); void generate_unchecked_arraycopy(const TypePtr* adr_type, BasicType basic_elem_type, bool disjoint_bases, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length); + Node* copy_length, bool dest_uninitialized); bool inline_unsafe_CAS(BasicType type); bool inline_unsafe_ordered_store(BasicType type); bool inline_fp_conversions(vmIntrinsics::ID id); @@ -1193,7 +1193,7 @@ Node* result; // Disable the use of pcmpestri until it can be guaranteed that // the load doesn't cross into the uncommited space. - if (false && Matcher::has_match_rule(Op_StrIndexOf) && + if (Matcher::has_match_rule(Op_StrIndexOf) && UseSSE42Intrinsics) { // Generate SSE4.2 version of indexOf // We currently only have match rules that use SSE4.2 @@ -1211,14 +1211,14 @@ return true; } + ciInstanceKlass* str_klass = env()->String_klass(); + const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(str_klass); + // Make the merge point - RegionNode* result_rgn = new (C, 3) RegionNode(3); - Node* result_phi = new (C, 3) PhiNode(result_rgn, TypeInt::INT); + RegionNode* result_rgn = new (C, 4) RegionNode(4); + Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT); Node* no_ctrl = NULL; - ciInstanceKlass* klass = env()->String_klass(); - const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass); - // Get counts for string and substr Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset); Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset)); @@ -1236,6 +1236,17 @@ } if (!stopped()) { + // Check for substr count == 0 + cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, intcon(0)) ); + bol = _gvn.transform( new(C, 2) BoolNode(cmp, BoolTest::eq) ); + Node* if_zero = generate_slow_guard(bol, NULL); + if (if_zero != NULL) { + result_phi->init_req(3, intcon(0)); + result_rgn->init_req(3, if_zero); + } + } + + if (!stopped()) { result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt); result_phi->init_req(1, result); result_rgn->init_req(1, control()); @@ -1244,8 +1255,8 @@ record_for_igvn(result_rgn); result = _gvn.transform(result_phi); - } else { //Use LibraryCallKit::string_indexOf - // don't intrinsify is argument isn't a constant string. + } else { // Use LibraryCallKit::string_indexOf + // don't intrinsify if argument isn't a constant string. if (!argument->is_Con()) { return false; } @@ -1281,7 +1292,7 @@ // No null check on the argument is needed since it's a constant String oop. _sp -= 2; if (stopped()) { - return true; + return true; } // The null string as a pattern always returns 0 (match at beginning of string) @@ -4081,7 +4092,8 @@ const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; bool disjoint_bases = true; generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases, - src, NULL, dest, NULL, countx); + src, NULL, dest, NULL, countx, + /*dest_uninitialized*/true); // If necessary, emit some card marks afterwards. (Non-arrays only.) if (card_mark) { @@ -4295,7 +4307,7 @@ // Note: The condition "disjoint" applies also for overlapping copies // where an descending copy is permitted (i.e., dest_offset <= src_offset). static address -select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name) { +select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name, bool dest_uninitialized) { int selector = (aligned ? COPYFUNC_ALIGNED : COPYFUNC_UNALIGNED) + (disjoint ? COPYFUNC_DISJOINT : COPYFUNC_CONJOINT); @@ -4304,6 +4316,10 @@ name = #xxx_arraycopy; \ return StubRoutines::xxx_arraycopy(); } +#define RETURN_STUB_PARM(xxx_arraycopy, parm) { \ + name = #xxx_arraycopy; \ + return StubRoutines::xxx_arraycopy(parm); } + switch (t) { case T_BYTE: case T_BOOLEAN: @@ -4340,10 +4356,10 @@ case T_ARRAY: case T_OBJECT: switch (selector) { - case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED: RETURN_STUB(oop_arraycopy); - case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED: RETURN_STUB(arrayof_oop_arraycopy); - case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED: RETURN_STUB(oop_disjoint_arraycopy); - case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED: RETURN_STUB(arrayof_oop_disjoint_arraycopy); + case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED: RETURN_STUB_PARM(oop_arraycopy, dest_uninitialized); + case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED: RETURN_STUB_PARM(arrayof_oop_arraycopy, dest_uninitialized); + case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED: RETURN_STUB_PARM(oop_disjoint_arraycopy, dest_uninitialized); + case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED: RETURN_STUB_PARM(arrayof_oop_disjoint_arraycopy, dest_uninitialized); } default: ShouldNotReachHere(); @@ -4351,6 +4367,7 @@ } #undef RETURN_STUB +#undef RETURN_STUB_PARM } //------------------------------basictype2arraycopy---------------------------- @@ -4358,7 +4375,8 @@ Node* src_offset, Node* dest_offset, bool disjoint_bases, - const char* &name) { + const char* &name, + bool dest_uninitialized) { const TypeInt* src_offset_inttype = gvn().find_int_type(src_offset);; const TypeInt* dest_offset_inttype = gvn().find_int_type(dest_offset);; @@ -4384,7 +4402,7 @@ disjoint = true; } - return select_arraycopy_function(t, aligned, disjoint, name); + return select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized); } @@ -4440,7 +4458,8 @@ // The component types are not the same or are not recognized. Punt. // (But, avoid the native method wrapper to JVM_ArrayCopy.) generate_slow_arraycopy(TypePtr::BOTTOM, - src, src_offset, dest, dest_offset, length); + src, src_offset, dest, dest_offset, length, + /*dest_uninitialized*/false); return true; } @@ -4553,7 +4572,7 @@ Node* original_dest = dest; AllocateArrayNode* alloc = NULL; // used for zeroing, if needed - bool must_clear_dest = false; + bool dest_uninitialized = false; // See if this is the initialization of a newly-allocated array. // If so, we will take responsibility here for initializing it to zero. @@ -4576,12 +4595,14 @@ adr_type = TypeRawPtr::BOTTOM; // all initializations are into raw memory // From this point on, every exit path is responsible for // initializing any non-copied parts of the object to zero. - must_clear_dest = true; + // Also, if this flag is set we make sure that arraycopy interacts properly + // with G1, eliding pre-barriers. See CR 6627983. + dest_uninitialized = true; } else { // No zeroing elimination here. alloc = NULL; //original_dest = dest; - //must_clear_dest = false; + //dest_uninitialized = false; } // Results are placed here: @@ -4613,10 +4634,10 @@ Node* checked_value = NULL; if (basic_elem_type == T_CONFLICT) { - assert(!must_clear_dest, ""); + assert(!dest_uninitialized, ""); Node* cv = generate_generic_arraycopy(adr_type, src, src_offset, dest, dest_offset, - copy_length); + copy_length, dest_uninitialized); if (cv == NULL) cv = intcon(-1); // failure (no stub available) checked_control = control(); checked_i_o = i_o(); @@ -4636,7 +4657,7 @@ } // copy_length is 0. - if (!stopped() && must_clear_dest) { + if (!stopped() && dest_uninitialized) { Node* dest_length = alloc->in(AllocateNode::ALength); if (_gvn.eqv_uncast(copy_length, dest_length) || _gvn.find_int_con(dest_length, 1) <= 0) { @@ -4662,7 +4683,7 @@ result_memory->init_req(zero_path, memory(adr_type)); } - if (!stopped() && must_clear_dest) { + if (!stopped() && dest_uninitialized) { // We have to initialize the *uncopied* part of the array to zero. // The copy destination is the slice dest[off..off+len]. The other slices // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length]. @@ -4698,7 +4719,7 @@ { PreserveJVMState pjvms(this); didit = generate_block_arraycopy(adr_type, basic_elem_type, alloc, src, src_offset, dest, dest_offset, - dest_size); + dest_size, dest_uninitialized); if (didit) { // Present the results of the block-copying fast call. result_region->init_req(bcopy_path, control()); @@ -4774,7 +4795,7 @@ Node* cv = generate_checkcast_arraycopy(adr_type, dest_elem_klass, src, src_offset, dest, dest_offset, - ConvI2X(copy_length)); + ConvI2X(copy_length), dest_uninitialized); if (cv == NULL) cv = intcon(-1); // failure (no stub available) checked_control = control(); checked_i_o = i_o(); @@ -4797,7 +4818,7 @@ PreserveJVMState pjvms(this); generate_unchecked_arraycopy(adr_type, copy_type, disjoint_bases, src, src_offset, dest, dest_offset, - ConvI2X(copy_length)); + ConvI2X(copy_length), dest_uninitialized); // Present the results of the fast call. result_region->init_req(fast_path, control()); @@ -4876,7 +4897,7 @@ set_memory(slow_mem, adr_type); set_i_o(slow_i_o); - if (must_clear_dest) { + if (dest_uninitialized) { generate_clear_array(adr_type, dest, basic_elem_type, intcon(0), NULL, alloc->in(AllocateNode::AllocSize)); @@ -4884,7 +4905,7 @@ generate_slow_arraycopy(adr_type, src, src_offset, dest, dest_offset, - copy_length); + copy_length, /*dest_uninitialized*/false); result_region->init_req(slow_call_path, control()); result_i_o ->init_req(slow_call_path, i_o()); @@ -5128,7 +5149,7 @@ AllocateNode* alloc, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* dest_size) { + Node* dest_size, bool dest_uninitialized) { // See if there is an advantage from block transfer. int scale = exact_log2(type2aelembytes(basic_elem_type)); if (scale >= LogBytesPerLong) @@ -5173,7 +5194,7 @@ bool disjoint_bases = true; // since alloc != NULL generate_unchecked_arraycopy(adr_type, T_LONG, disjoint_bases, - sptr, NULL, dptr, NULL, countx); + sptr, NULL, dptr, NULL, countx, dest_uninitialized); return true; } @@ -5186,7 +5207,8 @@ LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length) { + Node* copy_length, bool dest_uninitialized) { + assert(!dest_uninitialized, "Invariant"); Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON, OptoRuntime::slow_arraycopy_Type(), OptoRuntime::slow_arraycopy_Java(), @@ -5204,10 +5226,10 @@ Node* dest_elem_klass, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length) { + Node* copy_length, bool dest_uninitialized) { if (stopped()) return NULL; - address copyfunc_addr = StubRoutines::checkcast_arraycopy(); + address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized); if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. return NULL; } @@ -5245,9 +5267,9 @@ LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length) { + Node* copy_length, bool dest_uninitialized) { + assert(!dest_uninitialized, "Invariant"); if (stopped()) return NULL; - address copyfunc_addr = StubRoutines::generic_arraycopy(); if (copyfunc_addr == NULL) { // Stub was not generated, go slow path. return NULL; @@ -5268,7 +5290,7 @@ bool disjoint_bases, Node* src, Node* src_offset, Node* dest, Node* dest_offset, - Node* copy_length) { + Node* copy_length, bool dest_uninitialized) { if (stopped()) return; // nothing to do Node* src_start = src; @@ -5283,7 +5305,7 @@ const char* copyfunc_name = "arraycopy"; address copyfunc_addr = basictype2arraycopy(basic_elem_type, src_offset, dest_offset, - disjoint_bases, copyfunc_name); + disjoint_bases, copyfunc_name, dest_uninitialized); // Call it. Note that the count_ix value is not scaled to a byte-size. make_runtime_call(RC_LEAF|RC_NO_FP,
--- a/hotspot/src/share/vm/opto/memnode.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/opto/memnode.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -1559,21 +1559,24 @@ phase->C->has_unsafe_access(), "Field accesses must be precise" ); // For oop loads, we expect the _type to be precise - if (OptimizeStringConcat && klass == phase->C->env()->String_klass() && + if (klass == phase->C->env()->String_klass() && adr->is_AddP() && off != Type::OffsetBot) { - // For constant Strings treat the fields as compile time constants. + // For constant Strings treat the final fields as compile time constants. Node* base = adr->in(AddPNode::Base); const TypeOopPtr* t = phase->type(base)->isa_oopptr(); if (t != NULL && t->singleton()) { - ciObject* string = t->const_oop(); - ciConstant constant = string->as_instance()->field_value_by_offset(off); - if (constant.basic_type() == T_INT) { - return TypeInt::make(constant.as_int()); - } else if (constant.basic_type() == T_ARRAY) { - if (adr->bottom_type()->is_ptr_to_narrowoop()) { - return TypeNarrowOop::make_from_constant(constant.as_object()); - } else { - return TypeOopPtr::make_from_constant(constant.as_object()); + ciField* field = phase->C->env()->String_klass()->get_field_by_offset(off, false); + if (field != NULL && field->is_final()) { + ciObject* string = t->const_oop(); + ciConstant constant = string->as_instance()->field_value(field); + if (constant.basic_type() == T_INT) { + return TypeInt::make(constant.as_int()); + } else if (constant.basic_type() == T_ARRAY) { + if (adr->bottom_type()->is_ptr_to_narrowoop()) { + return TypeNarrowOop::make_from_constant(constant.as_object()); + } else { + return TypeOopPtr::make_from_constant(constant.as_object()); + } } } } @@ -4077,6 +4080,7 @@ n = base_memory(); assert(Node::in_dump() || n == NULL || n->bottom_type() == Type::TOP + || n->adr_type() == NULL // address is TOP || n->adr_type() == TypePtr::BOTTOM || n->adr_type() == TypeRawPtr::BOTTOM || Compile::current()->AliasLevel() == 0,
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1805,6 +1805,10 @@ void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) { JavaThread* thread = JavaThread::current(); + // In theory everyone coming thru here is in_vm but we need to be certain + // because a callee will do a vm->native transition + ThreadInVMfromUnknown __tiv; + EVT_TRIG_TRACE(JVMTI_EVENT_DYNAMIC_CODE_GENERATED, ("JVMTI [%s] method dynamic code generated event triggered", JvmtiTrace::safe_get_thread_name(thread))); @@ -1826,19 +1830,18 @@ } void JvmtiExport::post_dynamic_code_generated(const char *name, const void *code_begin, const void *code_end) { - // In theory everyone coming thru here is in_vm but we need to be certain - // because a callee will do a vm->native transition - ThreadInVMfromUnknown __tiv; jvmtiPhase phase = JvmtiEnv::get_phase(); if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) { post_dynamic_code_generated_internal(name, code_begin, code_end); - return; + } else { + // It may not be safe to post the event from this thread. Defer all + // postings to the service thread so that it can perform them in a safe + // context and in-order. + MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); + JvmtiDeferredEvent event = JvmtiDeferredEvent::dynamic_code_generated_event( + name, code_begin, code_end); + JvmtiDeferredEventQueue::enqueue(event); } - - // Blocks until everything now in the queue has been posted - JvmtiDeferredEventQueue::flush_queue(Thread::current()); - - post_dynamic_code_generated_internal(name, code_begin, code_end); }
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -140,12 +140,12 @@ char sig_type, jvalue *value); - private: // posts a DynamicCodeGenerated event (internal/private implementation). // The public post_dynamic_code_generated* functions make use of the - // internal implementation. + // internal implementation. Also called from JvmtiDeferredEvent::post() static void post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) KERNEL_RETURN; + private: // GenerateEvents support to allow posting of CompiledMethodLoad and // DynamicCodeGenerated events for a given environment.
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -918,7 +918,7 @@ JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); - event.set_compiled_method_load(nm); + event._event_data.compiled_method_load = nm; nmethodLocker::lock_nmethod(nm); // will be unlocked when posted return event; } @@ -926,23 +926,39 @@ JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event( jmethodID id, const void* code) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD); - event.set_compiled_method_unload(id, code); + event._event_data.compiled_method_unload.method_id = id; + event._event_data.compiled_method_unload.code_begin = code; + return event; +} +JvmtiDeferredEvent JvmtiDeferredEvent::dynamic_code_generated_event( + const char* name, const void* code_begin, const void* code_end) { + JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_DYNAMIC_CODE_GENERATED); + event._event_data.dynamic_code_generated.name = name; + event._event_data.dynamic_code_generated.code_begin = code_begin; + event._event_data.dynamic_code_generated.code_end = code_end; return event; } void JvmtiDeferredEvent::post() { + assert(ServiceThread::is_service_thread(Thread::current()), + "Service thread must post enqueued events"); switch(_type) { - case TYPE_COMPILED_METHOD_LOAD: - JvmtiExport::post_compiled_method_load(compiled_method_load()); - nmethodLocker::unlock_nmethod(compiled_method_load()); + case TYPE_COMPILED_METHOD_LOAD: { + nmethod* nm = _event_data.compiled_method_load; + JvmtiExport::post_compiled_method_load(nm); + nmethodLocker::unlock_nmethod(nm); break; + } case TYPE_COMPILED_METHOD_UNLOAD: JvmtiExport::post_compiled_method_unload( - compiled_method_unload_method_id(), - compiled_method_unload_code_begin()); + _event_data.compiled_method_unload.method_id, + _event_data.compiled_method_unload.code_begin); break; - case TYPE_FLUSH: - JvmtiDeferredEventQueue::flush_complete(flush_state_addr()); + case TYPE_DYNAMIC_CODE_GENERATED: + JvmtiExport::post_dynamic_code_generated_internal( + _event_data.dynamic_code_generated.name, + _event_data.dynamic_code_generated.code_begin, + _event_data.dynamic_code_generated.code_end); break; default: ShouldNotReachHere(); @@ -1065,54 +1081,4 @@ } } -enum { - // Random - used for debugging - FLUSHING = 0x50403020, - FLUSHED = 0x09080706 -}; - -void JvmtiDeferredEventQueue::flush_queue(Thread* thread) { - - volatile int flush_state = FLUSHING; - - JvmtiDeferredEvent flush(JvmtiDeferredEvent::TYPE_FLUSH); - flush.set_flush_state_addr((int*)&flush_state); - - if (ServiceThread::is_service_thread(thread)) { - // If we are the service thread we have to post all preceding events - // Use the flush event as a token to indicate when we can stop - JvmtiDeferredEvent event; - { - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - enqueue(flush); - event = dequeue(); - } - while (!event.is_flush_event() || - event.flush_state_addr() != &flush_state) { - event.post(); - { - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - event = dequeue(); - } - } - } else { - // Wake up the service thread so it will process events. When it gets - // to the flush event it will set 'flush_complete' and notify us. - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - enqueue(flush); - while (flush_state != FLUSHED) { - assert(flush_state == FLUSHING || flush_state == FLUSHED, - "only valid values for this"); - Service_lock->wait(Mutex::_no_safepoint_check_flag); - } - } -} - -void JvmtiDeferredEventQueue::flush_complete(int* state_addr) { - assert(state_addr != NULL && *state_addr == FLUSHING, "must be"); - MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag); - *state_addr = FLUSHED; - Service_lock->notify_all(); -} - #endif // ndef KERNEL
--- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -451,7 +451,7 @@ TYPE_NONE, TYPE_COMPILED_METHOD_LOAD, TYPE_COMPILED_METHOD_UNLOAD, - TYPE_FLUSH // pseudo-event used to implement flush_queue() + TYPE_DYNAMIC_CODE_GENERATED } Type; Type _type; @@ -461,49 +461,15 @@ jmethodID method_id; const void* code_begin; } compiled_method_unload; - int* flush_state_addr; + struct { + const char* name; + const void* code_begin; + const void* code_end; + } dynamic_code_generated; } _event_data; JvmtiDeferredEvent(Type t) : _type(t) {} - void set_compiled_method_load(nmethod* nm) { - assert(_type == TYPE_COMPILED_METHOD_LOAD, "must be"); - _event_data.compiled_method_load = nm; - } - - nmethod* compiled_method_load() const { - assert(_type == TYPE_COMPILED_METHOD_LOAD, "must be"); - return _event_data.compiled_method_load; - } - - void set_compiled_method_unload(jmethodID id, const void* code) { - assert(_type == TYPE_COMPILED_METHOD_UNLOAD, "must be"); - _event_data.compiled_method_unload.method_id = id; - _event_data.compiled_method_unload.code_begin = code; - } - - jmethodID compiled_method_unload_method_id() const { - assert(_type == TYPE_COMPILED_METHOD_UNLOAD, "must be"); - return _event_data.compiled_method_unload.method_id; - } - - const void* compiled_method_unload_code_begin() const { - assert(_type == TYPE_COMPILED_METHOD_UNLOAD, "must be"); - return _event_data.compiled_method_unload.code_begin; - } - - bool is_flush_event() const { return _type == TYPE_FLUSH; } - - int* flush_state_addr() const { - assert(is_flush_event(), "must be"); - return _event_data.flush_state_addr; - } - - void set_flush_state_addr(int* flag) { - assert(is_flush_event(), "must be"); - _event_data.flush_state_addr = flag; - } - public: JvmtiDeferredEvent() : _type(TYPE_NONE) {} @@ -513,6 +479,9 @@ KERNEL_RETURN_(JvmtiDeferredEvent()); static JvmtiDeferredEvent compiled_method_unload_event( jmethodID id, const void* code) KERNEL_RETURN_(JvmtiDeferredEvent()); + static JvmtiDeferredEvent dynamic_code_generated_event( + const char* name, const void* begin, const void* end) + KERNEL_RETURN_(JvmtiDeferredEvent()); // Actually posts the event. void post() KERNEL_RETURN; @@ -548,25 +517,12 @@ // Transfers events from the _pending_list to the _queue. static void process_pending_events() KERNEL_RETURN; - static void flush_complete(int* flush_state) KERNEL_RETURN; - public: // Must be holding Service_lock when calling these static bool has_events() KERNEL_RETURN_(false); static void enqueue(const JvmtiDeferredEvent& event) KERNEL_RETURN; static JvmtiDeferredEvent dequeue() KERNEL_RETURN_(JvmtiDeferredEvent()); - // This call blocks until all events enqueued prior to this call - // have been posted. The Service_lock is acquired and waited upon. - // - // Implemented by creating a "flush" event and placing it in the queue. - // When the flush event is "posted" it will call flush_complete(), which - // will release the caller. - // - // Can be called by any thread (maybe even the service thread itself). - // Not necessary for the caller to be a JavaThread. - static void flush_queue(Thread* current) KERNEL_RETURN; - // Used to enqueue events without using a lock, for times (such as during // safepoint) when we can't or don't want to lock the Service_lock. //
--- a/hotspot/src/share/vm/prims/unsafe.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/prims/unsafe.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -110,6 +110,8 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { jlong byte_offset = field_offset_to_byte_offset(field_offset); + // Don't allow unsafe to be used to read or write the header word of oops + assert(p == NULL || field_offset >= oopDesc::header_size(), "offset must be outside of header"); #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -78,6 +78,7 @@ const char* Arguments::_java_vendor_url_bug = DEFAULT_VENDOR_URL_BUG; const char* Arguments::_sun_java_launcher = DEFAULT_JAVA_LAUNCHER; int Arguments::_sun_java_launcher_pid = -1; +bool Arguments::_created_by_gamma_launcher = false; // These parameters are reset in method parse_vm_init_args(JavaVMInitArgs*) bool Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods; @@ -1656,6 +1657,9 @@ void Arguments::process_java_launcher_argument(const char* launcher, void* extra_info) { _sun_java_launcher = strdup(launcher); + if (strcmp("gamma", _sun_java_launcher) == 0) { + _created_by_gamma_launcher = true; + } } bool Arguments::created_by_java_launcher() { @@ -1663,6 +1667,10 @@ return strcmp(DEFAULT_JAVA_LAUNCHER, _sun_java_launcher) != 0; } +bool Arguments::created_by_gamma_launcher() { + return _created_by_gamma_launcher; +} + //=========================================================================================================== // Parsing of main arguments @@ -2790,10 +2798,6 @@ if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) { FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1); } - // Temporary disable bulk zeroing reduction with G1. See CR 6627983. - if (UseG1GC) { - FLAG_SET_DEFAULT(ReduceBulkZeroing, false); - } #endif // If we are running in a headless jre, force java.awt.headless property @@ -3155,6 +3159,16 @@ } } + // set PauseAtExit if the gamma launcher was used and a debugger is attached + // but only if not already set on the commandline + if (Arguments::created_by_gamma_launcher() && os::is_debugger_attached()) { + bool set = false; + CommandLineFlags::wasSetOnCmdline("PauseAtExit", &set); + if (!set) { + FLAG_SET_DEFAULT(PauseAtExit, true); + } + } + return JNI_OK; }
--- a/hotspot/src/share/vm/runtime/arguments.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/arguments.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -257,6 +257,9 @@ // sun.java.launcher.pid, private property static int _sun_java_launcher_pid; + // was this VM created by the gamma launcher + static bool _created_by_gamma_launcher; + // Option flags static bool _has_profile; static bool _has_alloc_profile; @@ -444,6 +447,8 @@ static const char* sun_java_launcher() { return _sun_java_launcher; } // Was VM created by a Java launcher? static bool created_by_java_launcher(); + // Was VM created by the gamma Java launcher? + static bool created_by_gamma_launcher(); // -Dsun.java.launcher.pid static int sun_java_launcher_pid() { return _sun_java_launcher_pid; }
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -2610,9 +2610,6 @@ develop(bool, CompileTheWorldPreloadClasses, true, \ "Preload all classes used by a class before start loading") \ \ - notproduct(bool, CompileTheWorldIgnoreInitErrors, false, \ - "Compile all methods although class initializer failed") \ - \ notproduct(intx, CompileTheWorldSafepointInterval, 100, \ "Force a safepoint every n compiles so sweeper can keep up") \ \ @@ -3733,6 +3730,9 @@ "The file to create and for whose removal to await when pausing " \ "at startup. (default: ./vm.paused.<pid>)") \ \ + diagnostic(bool, PauseAtExit, false, \ + "Pause and wait for keypress on exit if a debugger is attached") \ + \ product(bool, ExtendedDTraceProbes, false, \ "Enable performance-impacting dtrace probes") \ \
--- a/hotspot/src/share/vm/runtime/java.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/java.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -551,6 +551,7 @@ void vm_direct_exit(int code) { notify_vm_shutdown(); + os::wait_for_keypress_at_exit(); ::exit(code); } @@ -577,11 +578,13 @@ void vm_shutdown() { vm_perform_shutdown_actions(); + os::wait_for_keypress_at_exit(); os::shutdown(); } void vm_abort(bool dump_core) { vm_perform_shutdown_actions(); + os::wait_for_keypress_at_exit(); os::abort(dump_core); ShouldNotReachHere(); }
--- a/hotspot/src/share/vm/runtime/os.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/os.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -492,6 +492,12 @@ static void print_location(outputStream* st, intptr_t x, bool verbose = false); static size_t lasterror(char *buf, size_t len); + // Determines whether the calling process is being debugged by a user-mode debugger. + static bool is_debugger_attached(); + + // wait for a key press if PauseAtExit is set + static void wait_for_keypress_at_exit(void); + // The following two functions are used by fatal error handler to trace // native (C) frames. They are not part of frame.hpp/frame.cpp because // frame.hpp/cpp assume thread is JavaThread, and also because different
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -431,25 +431,24 @@ // previous frame depending on the return address. address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) { - assert(frame::verify_return_pc(return_address), "must be a return pc"); - - // Reset MethodHandle flag. + assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address)); + + // Reset method handle flag. thread->set_is_method_handle_return(false); - // the fastest case first + // The fastest case first CodeBlob* blob = CodeCache::find_blob(return_address); - if (blob != NULL && blob->is_nmethod()) { - nmethod* code = (nmethod*)blob; - assert(code != NULL, "nmethod must be present"); - // Check if the return address is a MethodHandle call site. - thread->set_is_method_handle_return(code->is_method_handle_return(return_address)); + nmethod* nm = (blob != NULL) ? blob->as_nmethod_or_null() : NULL; + if (nm != NULL) { + // Set flag if return address is a method handle call site. + thread->set_is_method_handle_return(nm->is_method_handle_return(return_address)); // native nmethods don't have exception handlers - assert(!code->is_native_method(), "no exception handler"); - assert(code->header_begin() != code->exception_begin(), "no exception handler"); - if (code->is_deopt_pc(return_address)) { + assert(!nm->is_native_method(), "no exception handler"); + assert(nm->header_begin() != nm->exception_begin(), "no exception handler"); + if (nm->is_deopt_pc(return_address)) { return SharedRuntime::deopt_blob()->unpack_with_exception(); } else { - return code->exception_begin(); + return nm->exception_begin(); } } @@ -462,22 +461,9 @@ return Interpreter::rethrow_exception_entry(); } - // Compiled code - if (CodeCache::contains(return_address)) { - CodeBlob* blob = CodeCache::find_blob(return_address); - if (blob->is_nmethod()) { - nmethod* code = (nmethod*)blob; - assert(code != NULL, "nmethod must be present"); - // Check if the return address is a MethodHandle call site. - thread->set_is_method_handle_return(code->is_method_handle_return(return_address)); - assert(code->header_begin() != code->exception_begin(), "no exception handler"); - return code->exception_begin(); - } - if (blob->is_runtime_stub()) { - ShouldNotReachHere(); // callers are responsible for skipping runtime stub frames - } - } + guarantee(blob == NULL || !blob->is_runtime_stub(), "caller should have skipped stub"); guarantee(!VtableStubs::contains(return_address), "NULL exceptions in vtables should have been handled already!"); + #ifndef PRODUCT { ResourceMark rm; tty->print_cr("No exception handler found for exception at " INTPTR_FORMAT " - potential problems:", return_address); @@ -485,6 +471,7 @@ tty->print_cr("b) other problem"); } #endif // PRODUCT + ShouldNotReachHere(); return NULL; }
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -80,30 +80,36 @@ jint StubRoutines::_fpu_subnormal_bias2[3] = { 0, 0, 0 }; // Compiled code entry points default values -// The dafault functions don't have separate disjoint versions. +// The default functions don't have separate disjoint versions. address StubRoutines::_jbyte_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jbyte_copy); address StubRoutines::_jshort_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jshort_copy); address StubRoutines::_jint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jint_copy); address StubRoutines::_jlong_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jlong_copy); address StubRoutines::_oop_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy); +address StubRoutines::_oop_arraycopy_uninit = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy_uninit); address StubRoutines::_jbyte_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jbyte_copy); address StubRoutines::_jshort_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jshort_copy); address StubRoutines::_jint_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jint_copy); address StubRoutines::_jlong_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::jlong_copy); address StubRoutines::_oop_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy); +address StubRoutines::_oop_disjoint_arraycopy_uninit = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy_uninit); address StubRoutines::_arrayof_jbyte_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jbyte_copy); address StubRoutines::_arrayof_jshort_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jshort_copy); address StubRoutines::_arrayof_jint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jint_copy); address StubRoutines::_arrayof_jlong_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jlong_copy); address StubRoutines::_arrayof_oop_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy); +address StubRoutines::_arrayof_oop_arraycopy_uninit = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit); address StubRoutines::_arrayof_jbyte_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jbyte_copy); address StubRoutines::_arrayof_jshort_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jshort_copy); address StubRoutines::_arrayof_jint_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jint_copy); address StubRoutines::_arrayof_jlong_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jlong_copy); -address StubRoutines::_arrayof_oop_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy); +address StubRoutines::_arrayof_oop_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy); +address StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit); + address StubRoutines::_checkcast_arraycopy = NULL; +address StubRoutines::_checkcast_arraycopy_uninit = NULL; address StubRoutines::_unsafe_arraycopy = NULL; address StubRoutines::_generic_arraycopy = NULL; @@ -282,12 +288,12 @@ // Default versions of arraycopy functions // -static void gen_arraycopy_barrier_pre(oop* dest, size_t count) { +static void gen_arraycopy_barrier_pre(oop* dest, size_t count, bool dest_uninitialized) { assert(count != 0, "count should be non-zero"); assert(count <= (size_t)max_intx, "count too large"); BarrierSet* bs = Universe::heap()->barrier_set(); assert(bs->has_write_ref_array_pre_opt(), "Must have pre-barrier opt"); - bs->write_ref_array_pre(dest, (int)count); + bs->write_ref_array_pre(dest, (int)count, dest_uninitialized); } static void gen_arraycopy_barrier(oop* dest, size_t count) { @@ -330,7 +336,17 @@ SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); - gen_arraycopy_barrier_pre(dest, count); + gen_arraycopy_barrier_pre(dest, count, /*dest_uninitialized*/false); + Copy::conjoint_oops_atomic(src, dest, count); + gen_arraycopy_barrier(dest, count); +JRT_END + +JRT_LEAF(void, StubRoutines::oop_copy_uninit(oop* src, oop* dest, size_t count)) +#ifndef PRODUCT + SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy +#endif // !PRODUCT + assert(count != 0, "count should be non-zero"); + gen_arraycopy_barrier_pre(dest, count, /*dest_uninitialized*/true); Copy::conjoint_oops_atomic(src, dest, count); gen_arraycopy_barrier(dest, count); JRT_END @@ -368,11 +384,20 @@ SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy #endif // !PRODUCT assert(count != 0, "count should be non-zero"); - gen_arraycopy_barrier_pre((oop *) dest, count); + gen_arraycopy_barrier_pre((oop *) dest, count, /*dest_uninitialized*/false); Copy::arrayof_conjoint_oops(src, dest, count); gen_arraycopy_barrier((oop *) dest, count); JRT_END +JRT_LEAF(void, StubRoutines::arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count)) +#ifndef PRODUCT + SharedRuntime::_oop_array_copy_ctr++; // Slow-path oop array copy +#endif // !PRODUCT + assert(count != 0, "count should be non-zero"); + gen_arraycopy_barrier_pre((oop *) dest, count, /*dest_uninitialized*/true); + Copy::arrayof_conjoint_oops(src, dest, count); + gen_arraycopy_barrier((oop *) dest, count); +JRT_END address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) { #define RETURN_STUB(xxx_fill) { \
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -164,12 +164,12 @@ static address _jshort_arraycopy; static address _jint_arraycopy; static address _jlong_arraycopy; - static address _oop_arraycopy; + static address _oop_arraycopy, _oop_arraycopy_uninit; static address _jbyte_disjoint_arraycopy; static address _jshort_disjoint_arraycopy; static address _jint_disjoint_arraycopy; static address _jlong_disjoint_arraycopy; - static address _oop_disjoint_arraycopy; + static address _oop_disjoint_arraycopy, _oop_disjoint_arraycopy_uninit; // arraycopy operands aligned on zero'th element boundary // These are identical to the ones aligned aligned on an @@ -179,15 +179,15 @@ static address _arrayof_jshort_arraycopy; static address _arrayof_jint_arraycopy; static address _arrayof_jlong_arraycopy; - static address _arrayof_oop_arraycopy; + static address _arrayof_oop_arraycopy, _arrayof_oop_arraycopy_uninit; static address _arrayof_jbyte_disjoint_arraycopy; static address _arrayof_jshort_disjoint_arraycopy; static address _arrayof_jint_disjoint_arraycopy; static address _arrayof_jlong_disjoint_arraycopy; - static address _arrayof_oop_disjoint_arraycopy; + static address _arrayof_oop_disjoint_arraycopy, _arrayof_oop_disjoint_arraycopy_uninit; // these are recommended but optional: - static address _checkcast_arraycopy; + static address _checkcast_arraycopy, _checkcast_arraycopy_uninit; static address _unsafe_arraycopy; static address _generic_arraycopy; @@ -286,26 +286,36 @@ static address jshort_arraycopy() { return _jshort_arraycopy; } static address jint_arraycopy() { return _jint_arraycopy; } static address jlong_arraycopy() { return _jlong_arraycopy; } - static address oop_arraycopy() { return _oop_arraycopy; } + static address oop_arraycopy(bool dest_uninitialized = false) { + return dest_uninitialized ? _oop_arraycopy_uninit : _oop_arraycopy; + } static address jbyte_disjoint_arraycopy() { return _jbyte_disjoint_arraycopy; } static address jshort_disjoint_arraycopy() { return _jshort_disjoint_arraycopy; } static address jint_disjoint_arraycopy() { return _jint_disjoint_arraycopy; } static address jlong_disjoint_arraycopy() { return _jlong_disjoint_arraycopy; } - static address oop_disjoint_arraycopy() { return _oop_disjoint_arraycopy; } + static address oop_disjoint_arraycopy(bool dest_uninitialized = false) { + return dest_uninitialized ? _oop_disjoint_arraycopy_uninit : _oop_disjoint_arraycopy; + } static address arrayof_jbyte_arraycopy() { return _arrayof_jbyte_arraycopy; } static address arrayof_jshort_arraycopy() { return _arrayof_jshort_arraycopy; } static address arrayof_jint_arraycopy() { return _arrayof_jint_arraycopy; } static address arrayof_jlong_arraycopy() { return _arrayof_jlong_arraycopy; } - static address arrayof_oop_arraycopy() { return _arrayof_oop_arraycopy; } + static address arrayof_oop_arraycopy(bool dest_uninitialized = false) { + return dest_uninitialized ? _arrayof_oop_arraycopy_uninit : _arrayof_oop_arraycopy; + } static address arrayof_jbyte_disjoint_arraycopy() { return _arrayof_jbyte_disjoint_arraycopy; } static address arrayof_jshort_disjoint_arraycopy() { return _arrayof_jshort_disjoint_arraycopy; } static address arrayof_jint_disjoint_arraycopy() { return _arrayof_jint_disjoint_arraycopy; } static address arrayof_jlong_disjoint_arraycopy() { return _arrayof_jlong_disjoint_arraycopy; } - static address arrayof_oop_disjoint_arraycopy() { return _arrayof_oop_disjoint_arraycopy; } + static address arrayof_oop_disjoint_arraycopy(bool dest_uninitialized = false) { + return dest_uninitialized ? _arrayof_oop_disjoint_arraycopy_uninit : _arrayof_oop_disjoint_arraycopy; + } - static address checkcast_arraycopy() { return _checkcast_arraycopy; } + static address checkcast_arraycopy(bool dest_uninitialized = false) { + return dest_uninitialized ? _checkcast_arraycopy_uninit : _checkcast_arraycopy; + } static address unsafe_arraycopy() { return _unsafe_arraycopy; } static address generic_arraycopy() { return _generic_arraycopy; } @@ -352,17 +362,19 @@ // Default versions of the above arraycopy functions for platforms which do // not have specialized versions // - static void jbyte_copy (jbyte* src, jbyte* dest, size_t count); - static void jshort_copy(jshort* src, jshort* dest, size_t count); - static void jint_copy (jint* src, jint* dest, size_t count); - static void jlong_copy (jlong* src, jlong* dest, size_t count); - static void oop_copy (oop* src, oop* dest, size_t count); + static void jbyte_copy (jbyte* src, jbyte* dest, size_t count); + static void jshort_copy (jshort* src, jshort* dest, size_t count); + static void jint_copy (jint* src, jint* dest, size_t count); + static void jlong_copy (jlong* src, jlong* dest, size_t count); + static void oop_copy (oop* src, oop* dest, size_t count); + static void oop_copy_uninit(oop* src, oop* dest, size_t count); - static void arrayof_jbyte_copy (HeapWord* src, HeapWord* dest, size_t count); - static void arrayof_jshort_copy(HeapWord* src, HeapWord* dest, size_t count); - static void arrayof_jint_copy (HeapWord* src, HeapWord* dest, size_t count); - static void arrayof_jlong_copy (HeapWord* src, HeapWord* dest, size_t count); - static void arrayof_oop_copy (HeapWord* src, HeapWord* dest, size_t count); + static void arrayof_jbyte_copy (HeapWord* src, HeapWord* dest, size_t count); + static void arrayof_jshort_copy (HeapWord* src, HeapWord* dest, size_t count); + static void arrayof_jint_copy (HeapWord* src, HeapWord* dest, size_t count); + static void arrayof_jlong_copy (HeapWord* src, HeapWord* dest, size_t count); + static void arrayof_oop_copy (HeapWord* src, HeapWord* dest, size_t count); + static void arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count); }; #endif // SHARE_VM_RUNTIME_STUBROUTINES_HPP
--- a/hotspot/src/share/vm/runtime/thread.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -3644,6 +3644,7 @@ if (ShowMessageBoxOnError && is_error_reported()) { os::infinite_sleep(); } + os::wait_for_keypress_at_exit(); if (JDK_Version::is_jdk12x_version()) { // We are the last thread running, so check if finalizers should be run.
--- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -77,6 +77,7 @@ # endif #ifdef LINUX +#define __STDC_LIMIT_MACROS #include <inttypes.h> #include <signal.h> #include <ucontext.h>
--- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -148,6 +148,17 @@ #endif #endif +// On solaris 8, UINTPTR_MAX is defined as empty. +// Everywhere else it's an actual value. +#if UINTPTR_MAX - 1 == -1 +#undef UINTPTR_MAX +#ifdef _LP64 +#define UINTPTR_MAX UINT64_MAX +#else +#define UINTPTR_MAX UINT32_MAX +#endif /* ifdef _LP64 */ +#endif + // Additional Java basic types typedef unsigned char jubyte;
--- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -41,6 +41,7 @@ # include <stdio.h> // for va_list # include <time.h> # include <fcntl.h> +# include <limits.h> // Need this on windows to get the math constants (e.g., M_PI). #define _USE_MATH_DEFINES # include <math.h> @@ -99,6 +100,14 @@ typedef signed int ssize_t; #endif +#ifndef UINTPTR_MAX +#ifdef _WIN64 +#define UINTPTR_MAX _UI64_MAX +#else +#define UINTPTR_MAX _UI32_MAX +#endif +#endif + //---------------------------------------------------------------------------------------------------- // Additional Java basic types
--- a/hotspot/src/share/vm/utilities/macros.hpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/utilities/macros.hpp Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -161,6 +161,14 @@ #define NOT_WINDOWS(code) code #endif +#ifdef _WIN64 +#define WIN64_ONLY(code) code +#define NOT_WIN64(code) +#else +#define WIN64_ONLY(code) +#define NOT_WIN64(code) code +#endif + #if defined(IA32) || defined(AMD64) #define X86 #define X86_ONLY(code) code
--- a/hotspot/src/share/vm/utilities/vmError.cpp Fri Mar 18 07:17:24 2011 -0700 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Mar 18 10:59:12 2011 -0700 @@ -802,7 +802,7 @@ first_error_tid = mytid; set_error_reported(); - if (ShowMessageBoxOnError) { + if (ShowMessageBoxOnError || PauseAtExit) { show_message_box(buffer, sizeof(buffer)); // User has asked JVM to abort. Reset ShowMessageBoxOnError so the
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/6942326/Test.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2011, 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 6942326 + * @summary x86 code in string_indexof() could read beyond reserved heap space + * + * @run main/othervm/timeout=300 -Xmx32m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:CompileCommand=exclude,Test,main -XX:CompileCommand=exclude,Test,test_varsub_indexof -XX:CompileCommand=exclude,Test,test_varstr_indexof -XX:CompileCommand=exclude,Test,test_missub_indexof -XX:CompileCommand=exclude,Test,test_consub_indexof -XX:CompileCommand=exclude,Test,test_conmis_indexof -XX:CompileCommand=exclude,Test,test_subcon Test + * + */ + +public class Test { + + static String[] strings = new String[1024]; + private static final int ITERATIONS = 100000; + + public static void main(String[] args) { + + long start_total = System.currentTimeMillis(); + + // search variable size substring in string (33 chars). + String a = " 1111111111111xx1111111111111xx11y"; // +1 to execute a.substring(1) first + String b = "1111111111111xx1111111111111xx11y"; + test_varsub_indexof(a, b); + + // search variable size substring in string (32 chars). + a = " 1111111111111xx1111111111111xx1y"; + b = "1111111111111xx1111111111111xx1y"; + test_varsub_indexof(a, b); + + // search variable size substring in string (17 chars). + a = " 1111111111111xx1y"; + b = "1111111111111xx1y"; + test_varsub_indexof(a, b); + + // search variable size substring in string (16 chars). + a = " 111111111111xx1y"; + b = "111111111111xx1y"; + test_varsub_indexof(a, b); + + // search variable size substring in string (8 chars). + a = " 1111xx1y"; + b = "1111xx1y"; + test_varsub_indexof(a, b); + + // search variable size substring in string (7 chars). + a = " 111xx1y"; + b = "111xx1y"; + test_varsub_indexof(a, b); + + + + // search substring (17 chars) in variable size string. + a = "1111111111111xx1x"; + b = " 1111111111111xx1111111111111xx1x"; // +1 to execute b.substring(1) first + test_varstr_indexof(a, b); + + // search substring (16 chars) in variable size string. + a = "111111111111xx1x"; + b = " 1111111111111xx1111111111111xx1x"; + test_varstr_indexof(a, b); + + // search substring (9 chars) in variable size string. + a = "11111xx1x"; + b = " 1111111111111xx1111111111111xx1x"; + test_varstr_indexof(a, b); + + // search substring (8 chars) in variable size string. + a = "1111xx1x"; + b = " 1111111111111xx1111111111111xx1x"; + test_varstr_indexof(a, b); + + // search substring (4 chars) in variable size string. + a = "xx1x"; + b = " 1111111111111xx1111111111111xx1x"; + test_varstr_indexof(a, b); + + // search substring (3 chars) in variable size string. + a = "x1x"; + b = " 1111111111111xx1111111111111xx1x"; + test_varstr_indexof(a, b); + + // search substring (2 chars) in variable size string. + a = "1y"; + b = " 1111111111111xx1111111111111xx1y"; + test_varstr_indexof(a, b); + + + + // search non matching variable size substring in string (33 chars). + a = " 1111111111111xx1111111111111xx11z"; // +1 to execute a.substring(1) first + b = "1111111111111xx1111111111111xx11y"; + test_missub_indexof(a, b); + + // search non matching variable size substring in string (32 chars). + a = " 1111111111111xx1111111111111xx1z"; + b = "1111111111111xx1111111111111xx1y"; + test_missub_indexof(a, b); + + // search non matching variable size substring in string (17 chars). + a = " 1111111111111xx1z"; + b = "1111111111111xx1y"; + test_missub_indexof(a, b); + + // search non matching variable size substring in string (16 chars). + a = " 111111111111xx1z"; + b = "111111111111xx1y"; + test_missub_indexof(a, b); + + // search non matching variable size substring in string (8 chars). + a = " 1111xx1z"; + b = "1111xx1y"; + test_missub_indexof(a, b); + + // search non matching variable size substring in string (7 chars). + a = " 111xx1z"; + b = "111xx1y"; + test_missub_indexof(a, b); + + + + // Testing constant substring search in variable size string. + + // search constant substring (17 chars). + b = " 1111111111111xx1111111111111xx1x"; // +1 to execute b.substring(1) first + TestCon tc = new TestCon17(); + test_consub_indexof(tc, b); + + // search constant substring (16 chars). + b = " 1111111111111xx1111111111111xx1x"; + tc = new TestCon16(); + test_consub_indexof(tc, b); + + // search constant substring (9 chars). + b = " 1111111111111xx1111111111111xx1x"; + tc = new TestCon9(); + test_consub_indexof(tc, b); + + // search constant substring (8 chars). + b = " 1111111111111xx1111111111111xx1x"; + tc = new TestCon8(); + test_consub_indexof(tc, b); + + // search constant substring (4 chars). + b = " 1111111111111xx1111111111111xx1x"; + tc = new TestCon4(); + test_consub_indexof(tc, b); + + // search constant substring (3 chars). + b = " 1111111111111xx1111111111111xx1x"; + tc = new TestCon3(); + test_consub_indexof(tc, b); + + // search constant substring (2 chars). + b = " 1111111111111xx1111111111111xx1y"; + tc = new TestCon2(); + test_consub_indexof(tc, b); + + // search constant substring (1 chars). + b = " 1111111111111xx1111111111111xx1y"; + tc = new TestCon1(); + test_consub_indexof(tc, b); + + + // search non matching constant substring (17 chars). + b = " 1111111111111xx1111111111111xx1z"; // +1 to execute b.substring(1) first + tc = new TestCon17(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (16 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon16(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (9 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon9(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (8 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon8(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (4 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon4(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (3 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon3(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (2 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon2(); + test_conmis_indexof(tc, b); + + // search non matching constant substring (1 chars). + b = " 1111111111111xx1111111111111xx1z"; + tc = new TestCon1(); + test_conmis_indexof(tc, b); + + long end_total = System.currentTimeMillis(); + System.out.println("End run time: " + (end_total - start_total)); + + } + + public static long test_init(String a, String b) { + for (int i = 0; i < 512; i++) { + strings[i * 2] = new String(b.toCharArray()); + strings[i * 2 + 1] = new String(a.toCharArray()); + } + System.out.print(a.length() + " " + b.length() + " "); + return System.currentTimeMillis(); + } + + public static void test_end(String a, String b, int v, int expected, long start) { + long end = System.currentTimeMillis(); + int res = (v/ITERATIONS); + System.out.print(" " + res); + System.out.println(" time:" + (end - start)); + if (res != expected) { + System.out.println("wrong indexOf result: " + res + ", expected " + expected); + System.out.println("\"" + b + "\".indexOf(\"" + a + "\")"); + System.exit(97); + } + } + + public static int test_subvar() { + int s = 0; + int v = 0; + for (int i = 0; i < ITERATIONS; i++) { + v += strings[s].indexOf(strings[s + 1]); + s += 2; + if (s >= strings.length) s = 0; + } + return v; + } + + public static void test_varsub_indexof(String a, String b) { + System.out.println("Start search variable size substring in string (" + b.length() + " chars)"); + long start_it = System.currentTimeMillis(); + int limit = 1; // last a.length() == 1 + while (a.length() > limit) { + a = a.substring(1); + long start = test_init(a, b); + int v = test_subvar(); + test_end(a, b, v, (b.length() - a.length()), start); + } + long end_it = System.currentTimeMillis(); + System.out.println("End search variable size substring in string (" + b.length() + " chars), time: " + (end_it - start_it)); + } + + public static void test_varstr_indexof(String a, String b) { + System.out.println("Start search substring (" + a.length() + " chars) in variable size string"); + long start_it = System.currentTimeMillis(); + int limit = a.length(); + while (b.length() > limit) { + b = b.substring(1); + long start = test_init(a, b); + int v = test_subvar(); + test_end(a, b, v, (b.length() - a.length()), start); + } + long end_it = System.currentTimeMillis(); + System.out.println("End search substring (" + a.length() + " chars) in variable size string, time: " + (end_it - start_it)); + } + + public static void test_missub_indexof(String a, String b) { + System.out.println("Start search non matching variable size substring in string (" + b.length() + " chars)"); + long start_it = System.currentTimeMillis(); + int limit = 1; // last a.length() == 1 + while (a.length() > limit) { + a = a.substring(1); + long start = test_init(a, b); + int v = test_subvar(); + test_end(a, b, v, (-1), start); + } + long end_it = System.currentTimeMillis(); + System.out.println("End search non matching variable size substring in string (" + b.length() + " chars), time: " + (end_it - start_it)); + } + + + + public static void test_consub_indexof(TestCon tc, String b) { + System.out.println("Start search constant substring (" + tc.constr().length() + " chars)"); + long start_it = System.currentTimeMillis(); + int limit = tc.constr().length(); + while (b.length() > limit) { + b = b.substring(1); + long start = test_init(tc.constr(), b); + int v = test_subcon(tc); + test_end(tc.constr(), b, v, (b.length() - tc.constr().length()), start); + } + long end_it = System.currentTimeMillis(); + System.out.println("End search constant substring (" + tc.constr().length() + " chars), time: " + (end_it - start_it)); + } + + public static void test_conmis_indexof(TestCon tc, String b) { + System.out.println("Start search non matching constant substring (" + tc.constr().length() + " chars)"); + long start_it = System.currentTimeMillis(); + int limit = tc.constr().length(); + while (b.length() > limit) { + b = b.substring(1); + long start = test_init(tc.constr(), b); + int v = test_subcon(tc); + test_end(tc.constr(), b, v, (-1), start); + } + long end_it = System.currentTimeMillis(); + System.out.println("End search non matching constant substring (" + tc.constr().length() + " chars), time: " + (end_it - start_it)); + } + + public static int test_subcon(TestCon tc) { + int s = 0; + int v = 0; + for (int i = 0; i < ITERATIONS; i++) { + v += tc.indexOf(strings[s]); + s += 2; + if (s >= strings.length) s = 0; + } + return v; + } + + private interface TestCon { + public String constr(); + public int indexOf(String str); + } + + // search constant substring (17 chars). + private final static class TestCon17 implements TestCon { + private static final String constr = "1111111111111xx1x"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + // search constant substring (16 chars). + private final static class TestCon16 implements TestCon { + private static final String constr = "111111111111xx1x"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + // search constant substring (9 chars). + private final static class TestCon9 implements TestCon { + private static final String constr = "11111xx1x"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + // search constant substring (8 chars). + private final static class TestCon8 implements TestCon { + private static final String constr = "1111xx1x"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + // search constant substring (4 chars). + private final static class TestCon4 implements TestCon { + private static final String constr = "xx1x"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + // search constant substring (3 chars). + private final static class TestCon3 implements TestCon { + private static final String constr = "x1x"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + // search constant substring (2 chars). + private final static class TestCon2 implements TestCon { + private static final String constr = "1y"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } + + + // search constant substring (1 chars). + private final static class TestCon1 implements TestCon { + private static final String constr = "y"; + public String constr() { return constr; } + public int indexOf(String str) { return str.indexOf(constr); } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/6878713/Test6878713.sh Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,74 @@ +#!/bin/sh + +## +## @test +## @bug 6878713 +## @summary Verifier heap corruption, relating to backward jsrs +## @run shell/timeout=120 Test6878713.sh +## + +if [ "${TESTSRC}" = "" ] +then TESTSRC=. +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 + +BIT_FLAG="" + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS | Linux ) + NULL=/dev/null + PS=":" + FS="/" + ## for solaris, linux it's HOME + FILE_LOCATION=$HOME + if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" ] + then + BIT_FLAG=`cat ${FILE_LOCATION}${FS}JDK64BIT | grep -v '^#'` + fi + ;; + Windows_* ) + NULL=NUL + PS=";" + FS="\\" + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + +JEMMYPATH=${CPAPPEND} +CLASSPATH=.${PS}${TESTCLASSES}${PS}${JEMMYPATH} ; export CLASSPATH + +THIS_DIR=`pwd` + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -version + +${TESTJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar + +${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} OOMCrashClass1960_2 > test.out 2>&1 + +if [ -s core -o -s "hs_*.log" ] +then + cat hs*.log + echo "Test Failed" + exit 1 +else + echo "Test Passed" + exit 0 +fi
--- a/jaxp/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/jaxp/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -107,3 +107,4 @@ ab107c1bc4b918404b191838c455e9b2892389f3 jdk7-b130 eab6f27131e4e2f0af0016b35b18ae65cdd249d9 jdk7-b131 abe04c59a556a3821c30bd8839e3c74f5d4281d1 jdk7-b132 +8e1148c7911b02e00a727461525f239da025cab7 jdk7-b133
--- a/jaxp/jaxp.properties Fri Mar 18 07:17:24 2011 -0700 +++ b/jaxp/jaxp.properties Fri Mar 18 10:59:12 2011 -0700 @@ -25,13 +25,13 @@ drops.master.copy.base=${drops.dir} -jaxp_src.bundle.name=jaxp-1_4_5-dev.zip -jaxp_src.bundle.md5.checksum=84e2c26853262c9144133c6ff7ef5dc9 +jaxp_src.bundle.name=jaxp-1_4_5-dev1.zip +jaxp_src.bundle.md5.checksum=53c95613c29852a12b93e7249f1aa227 jaxp_src.master.bundle.dir=${drops.master.copy.base} jaxp_src.master.bundle.url.base=http://download.java.net/jaxp/1.4.5/dev -jaxp_tests.bundle.name=jaxp-1_4_5-dev-unittests.zip -jaxp_tests.bundle.md5.checksum=0377e715fa21814cb8006768c5967dc5 +jaxp_tests.bundle.name=jaxp-1_4_5-dev1-unittests.zip +jaxp_tests.bundle.md5.checksum=754aaba2f4944f69bfea91dec11daf4c jaxp_tests.master.bundle.dir=${drops.master.copy.base} jaxp_tests.master.bundle.url.base=http://download.java.net/jaxp/1.4.5/dev
--- a/jaxp/make/Makefile Fri Mar 18 07:17:24 2011 -0700 +++ b/jaxp/make/Makefile Fri Mar 18 10:59:12 2011 -0700 @@ -136,7 +136,7 @@ else ANT = ant ifneq ($(shell which $(ANT) > /dev/null; echo $$?), 0) - $(error "\"ant\" not found; please set ANT_HOME or put \"ant\" on your PATH") + $(error "'ant' not found; please set ANT_HOME or put 'ant' on your PATH") endif endif
--- a/jaxws/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/jaxws/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -107,3 +107,4 @@ ba1fac1c2083196422a12130db174334179a4d44 jdk7-b130 438abc0356cd97d91b25f67cd1abc9883e22f6ed jdk7-b131 0e57c3272d377eee04cc32c898e9a558051516b0 jdk7-b132 +359d0c8c00a02d3a094c19f8a485b2217c99a4e0 jdk7-b133
--- a/jaxws/make/Makefile Fri Mar 18 07:17:24 2011 -0700 +++ b/jaxws/make/Makefile Fri Mar 18 10:59:12 2011 -0700 @@ -136,7 +136,7 @@ else ANT = ant ifneq ($(shell which $(ANT) > /dev/null; echo $$?), 0) - $(error "\"ant\" not found; please set ANT_HOME or put \"ant\" on your PATH") + $(error "'ant' not found; please set ANT_HOME or put 'ant' on your PATH") endif endif
--- a/jdk/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -108,3 +108,4 @@ 8ac52c85f9e91336dc00b52ef90b42eecf3230b3 jdk7-b131 6bbc7a4734952ae7604578f270e1566639fa8752 jdk7-b132 5e5f68a01d12a4432172f384d5201f3a05254493 jdk7-b133 +554adcfb615e63e62af530b1c10fcf7813a75b26 jdk7-b134
--- a/jdk/make/common/Demo.gmk Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/make/common/Demo.gmk Fri Mar 18 10:59:12 2011 -0700 @@ -118,8 +118,11 @@ DEMO_ALL_NATIVE_SOURCES += $(filter %.hpp,$(DEMO_ALL_FILES)) # If we have java sources, then define the jar file we will create +ifndef DEMO_JAR_NAME + DEMO_JAR_NAME = $(DEMONAME).jar +endif ifneq ($(strip $(DEMO_JAVA_SOURCES)),) - DEMO_JAR = $(DEMO_DESTDIR)/$(DEMONAME).jar + DEMO_JAR = $(DEMO_DESTDIR)/$(DEMO_JAR_NAME) endif # If we have native sources, define the native library we will create @@ -252,6 +255,17 @@ $(MKDIR) -p $(DEMO_JAR_IMAGE) $(JAVAC_CMD) -d $(DEMO_JAR_IMAGE) -sourcepath $(DEMO_BUILD_SRCDIR) \ @$(DEMO_JAVAC_INPUT) + ifeq ($(DEMO_INCL_SRC),true) + $(CP) $(DEMO_JAVA_SOURCES:%=$(DEMO_BUILD_SRCDIR)/%) $(DEMO_JAR_IMAGE) + endif + ifeq ($(DEMO_ONLY_SRC),true) + $(RM) -r $(DEMO_JAR_IMAGE) + $(MKDIR) -p $(DEMO_JAR_IMAGE) + $(CP) -r $(DEMO_BUILD_SRCDIR)/* $(DEMO_JAR_IMAGE) + ifneq ($(DEMO_TOPFILES),) + $(CP) $(DEMO_ROOT)/$(DEMO_TOPFILES) $(DEMO_JAR_IMAGE) + endif + endif $(BOOT_JAR_CMD) -cfm $@ $(DEMO_MANIFEST) \ -C $(DEMO_JAR_IMAGE) . \ $(BOOT_JAR_JFLAGS) @@ -324,9 +338,9 @@ ifdef DEMO_IS_APPLET @$(ECHO) "Expanding jar file into demos area at $(DEMO_DESTDIR)" ( $(CD) $(DEMO_DESTDIR) && \ - $(BOOT_JAR_CMD) -xfv $(DEMONAME).jar \ + $(BOOT_JAR_CMD) -xfv $(DEMO_JAR_NAME) \ $(BOOT_JAR_JFLAGS) && \ - $(RM) -r META-INF $(DEMONAME).jar && \ + $(RM) -r META-INF $(DEMO_JAR_NAME) && \ $(java-vm-cleanup) ) @( $(CD) $(DEMO_DESTDIR) && $(java-vm-cleanup) ) @$(ECHO) "Expanding source into demos area at $(DEMO_DESTDIR)"
--- a/jdk/make/common/shared/Compiler-msvc.gmk Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/make/common/shared/Compiler-msvc.gmk Fri Mar 18 10:59:12 2011 -0700 @@ -153,6 +153,9 @@ ifndef COMPILER_VERSION COMPILER_VERSION := $(error COMPILER_VERSION cannot be empty here) endif + ifneq ($(COMPILER_VERSION),VS2010) + COMPILER_VERSION := $(error COMPILER_VERSION must be VS2010) + endif # Shared library generation flag SHARED_LIBRARY_FLAG = -LD
--- a/jdk/make/common/shared/Platform.gmk Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/make/common/shared/Platform.gmk Fri Mar 18 10:59:12 2011 -0700 @@ -148,7 +148,7 @@ # Suffix for file bundles used in previous release BUNDLE_FILE_SUFFIX=.tar # How much RAM does this machine have: - MB_OF_MEMORY=$(shell /etc/prtconf | fgrep 'Memory size:' | expand | cut -d' ' -f3) + MB_OF_MEMORY=$(shell /usr/sbin/prtconf | fgrep 'Memory size:' | expand | cut -d' ' -f3) endif # Platform settings specific to Linux
--- a/jdk/make/mkdemo/jfc/SwingSet2/Makefile Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/make/mkdemo/jfc/SwingSet2/Makefile Fri Mar 18 10:59:12 2011 -0700 @@ -37,6 +37,7 @@ DEMO_MAINCLASS = $(DEMONAME) DEMO_MANIFEST_ATTR = SplashScreen-Image: resources/images/splash.png DEMO_DESTDIR = $(DEMODIR)/jfc/$(DEMONAME) +DEMO_INCL_SRC = true # # Demo jar building rules.
--- a/jdk/make/mkdemo/jpda/Makefile Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/make/mkdemo/jpda/Makefile Fri Mar 18 10:59:12 2011 -0700 @@ -32,6 +32,8 @@ DEMO_PKGDIR = com/sun/tools/example DEMO_TOPFILES = ./com/sun/tools/example/README DEMO_DESTDIR = $(DEMODIR)/jpda +DEMO_JAR_NAME = examples.jar +DEMO_ONLY_SRC = true # # Demo jar building rules.
--- a/jdk/make/tools/manifest.mf Fri Mar 18 07:17:24 2011 -0700 +++ b/jdk/make/tools/manifest.mf Fri Mar 18 10:59:12 2011 -0700 @@ -1,6 +1,6 @@ Manifest-Version: 1.0 Specification-Title: Java Platform API Specification -Specification-Version: 1.6 +Specification-Version: 1.7 Specification-Vendor: Oracle Implementation-Title: Java Runtime Environment Implementation-Version: @@RELEASE@@
--- a/langtools/.hgtags Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/.hgtags Fri Mar 18 10:59:12 2011 -0700 @@ -107,3 +107,4 @@ 7a98db8cbfce77a619057aa4fdde69d2a06d4101 jdk7-b130 67221b8643b478c4fceacc89240db876455aae76 jdk7-b131 e3d011d59a33acef79eff7523bef069557e91002 jdk7-b132 +e77e98f936e83d94c9b56cc7af218dc822a06122 jdk7-b133
--- a/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, 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 @@ -280,7 +280,7 @@ } if (verbose) - printVerbose("total", Long.toString(System.currentTimeMillis() - msec)); + log.printVerbose("total", Long.toString(System.currentTimeMillis() - msec)); chk.reportDeferredDiagnostics();
--- a/langtools/src/share/classes/com/sun/tools/apt/util/Bark.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/apt/util/Bark.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, 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 @@ -48,15 +48,15 @@ * Preregisters factories to create and use a Bark object for use as * both a Log and a Bark. */ - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(barkKey, new Context.Factory<Bark>() { - public Bark make() { - return new Bark(context); + public Bark make(Context c) { + return new Bark(c); } }); context.put(Log.logKey, new Context.Factory<Log>() { - public Log make() { - return Bark.instance(context); + public Log make(Context c) { + return Bark.instance(c); } }); }
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, 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 @@ -156,7 +156,7 @@ if (index < 0) { return htmlstr; } - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); int previndex = 0; while (true) { // Search for lowercase version of {@docRoot} @@ -2279,7 +2279,7 @@ */ public String commentTagsToString(Tag holderTag, Doc doc, Tag[] tags, boolean isFirstSentence) { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); // Array of all possible inline tags for this javadoc run configuration.tagletManager.checkTags(doc, tags, true); for (int i = 0; i < tags.length; i++) { @@ -2315,7 +2315,7 @@ StringTokenizer lines = new StringTokenizer(text, "\r\n", true); StringBuffer textBuff = new StringBuffer(); while (lines.hasMoreTokens()) { - StringBuffer line = new StringBuffer(lines.nextToken()); + StringBuilder line = new StringBuilder(lines.nextToken()); Util.replaceTabs(configuration.sourcetab, line); textBuff.append(line.toString()); } @@ -2473,7 +2473,7 @@ return text; } int endindex = startindex + tobe.length(); - StringBuffer replaced = new StringBuffer(); + StringBuilder replaced = new StringBuilder(); if (startindex > 0) { replaced.append(text.substring(0, startindex)); }
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlSerialFieldWriter.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, 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 @@ -30,7 +30,6 @@ import com.sun.javadoc.*; import com.sun.tools.doclets.internal.toolkit.*; import com.sun.tools.doclets.internal.toolkit.taglets.*; -import com.sun.tools.doclets.internal.toolkit.util.*; import com.sun.tools.doclets.formats.html.markup.*; /** @@ -53,7 +52,7 @@ } public List<FieldDoc> members(ClassDoc cd) { - return Util.asList(cd.serializableFields()); + return Arrays.asList(cd.serializableFields()); } protected void printTypeLinkNoDimension(Type type) {
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/SourceToHTMLConverter.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -266,7 +266,7 @@ private static void addLine(Content pre, String line, int tabLength, int currentLineNo) { if (line != null) { - StringBuffer lineBuffer = new StringBuffer(Util.escapeHtmlChars(line)); + StringBuilder lineBuffer = new StringBuilder(Util.escapeHtmlChars(line)); Util.replaceTabs(tabLength, lineBuffer); pre.addContent(new RawHtml(lineBuffer.toString())); Content anchor = HtmlTree.A_NAME("line." + Integer.toString(currentLineNo));
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Fri Mar 18 10:59:12 2011 -0700 @@ -11,15 +11,25 @@ doclet.Interface_Hierarchy=Interface Hierarchy doclet.Enum_Hierarchy=Enum Hierarchy doclet.Annotation_Type_Hierarchy=Annotation Type Hierarchy +# The following ALL CAPS words should be translated. It is used as "Previous" link on javadoc. doclet.Prev=PREV +# The following ALL CAPS words should be translated. It is used as "Next" link on javadoc. doclet.Next=NEXT +# The following ALL CAPS words should be translated. It is used as "Previous Class" link on javadoc. doclet.Prev_Class=PREV CLASS +# The following ALL CAPS words should be translated. It is used as "Next Class" link on javadoc. doclet.Next_Class=NEXT CLASS +# The following ALL CAPS words should be translated. It is used as "Previous Package" link on javadoc. doclet.Prev_Package=PREV PACKAGE +# The following ALL CAPS words should be translated. It is used as "Next Package" link on javadoc. doclet.Next_Package=NEXT PACKAGE +# The following ALL CAPS words should be translated. It is used as "Previous Letter" link on javadoc alphabetical index. doclet.Prev_Letter=PREV LETTER +# The following ALL CAPS words should be translated. It is used as "Next Letter" link on javadoc alphabetical index. doclet.Next_Letter=NEXT LETTER +# The following ALL CAPS words should be translated. It is used as "Show List" link on javadoc. doclet.Show_Lists=SHOW LISTS +# The following ALL CAPS words should be translated. It is used as "Hide List" link on javadoc. doclet.Hide_Lists=HIDE LISTS doclet.Href_Class_Title=class in {0} doclet.Href_Interface_Title=interface in {0} @@ -27,16 +37,27 @@ doclet.Href_Enum_Title=enum in {0} doclet.Href_Type_Param_Title=type parameter in {0} doclet.Href_Class_Or_Interface_Title=class or interface in {0} +# The following ALL CAPS words should be translated. It's used as SUMMARY: NESTED | FIELD | CONSTR | METHOD, meaning Nested Class Summary, Field Summary, Constructor Summary, or Method Summary. doclet.Summary=SUMMARY: +# The following ALL CAPS words should be translated. It is used as DETAIL: FIELD | CONSTR | METHOD, meaning Field Detail, Constructor Detail, or Method Detail. doclet.Detail=DETAIL: +# The following ALL CAPS words should be translated. It is used as "Nested" (Nested Class Summary) link on javadoc. doclet.navNested=NESTED +# The following ALL CAPS words should be translated. It is used as "Optional" (Optional Element Summary) link on javadoc. doclet.navAnnotationTypeOptionalMember=OPTIONAL +# The following ALL CAPS words should be translated. It is used as "Required" (Required Element Summary) link on javadoc. doclet.navAnnotationTypeRequiredMember=REQUIRED +# The following ALL CAPS words should be translated. It is used as "Element" (Required Element Summary) link on javadoc. doclet.navAnnotationTypeMember=ELEMENT +# The following ALL CAPS words should be translated. It is used as "Field" (Field Detail) link on javadoc. doclet.navField=FIELD +# The following ALL CAPS words should be translated. It is used as "Enum Constants" link on javadoc. doclet.navEnum=ENUM CONSTANTS +# The following ALL CAPS words should be translated. It is used as "Constructor" (Constructor Detail) link on javadoc. doclet.navConstructor=CONSTR +# The following ALL CAPS words should be translated. It is used as "Method" (Method Detail) link on javadoc. doclet.navMethod=METHOD +# The following resource does not seem to be used anymore. doclet.navFactoryMethod=FACTORY doclet.Index=Index doclet.Window_Single_Index=Index @@ -45,8 +66,11 @@ doclet.Skip_navigation_links=Skip navigation links doclet.New_Page=NewPage doclet.None=None +# The following resource does not seem to be used anymore doclet.CLASSES=CLASSES +# The following resource does not seem to be used anymore doclet.MEMBERS=MEMBERS +# The following resource does not seem to be used anymore doclet.NONE=NONE doclet.Factory_Method_Detail=Static Factory Method Detail doclet.navDeprecated=Deprecated @@ -112,7 +136,9 @@ doclet.Option=Option doclet.Or=Or doclet.Frames=Frames +# The following ALL CAPS words should be translated. It is used as "FRAMES" javadoc navigation link to indicate displaying the page with HTML frames. doclet.FRAMES=FRAMES +# The following ALL CAPS words should be translated. It is used as "NO FRAMES" javadoc navigation link to indicate displaying the page without HTML frames. doclet.NO_FRAMES=NO FRAMES doclet.Package_Hierarchies=Package Hierarchies: doclet.Hierarchy_For_Package=Hierarchy For Package {0}
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/SerializedFormBuilder.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -375,8 +375,7 @@ */ public void buildFieldSerializationOverview(ClassDoc classDoc, Content classContentTree) { if (classDoc.definesSerializableFields()) { - FieldDoc serialPersistentField = - Util.asList(classDoc.serializableFields()).get(0); + FieldDoc serialPersistentField = classDoc.serializableFields()[0]; // Check to see if there are inline comments, tags or deprecation // information to be printed. if (fieldWriter.shouldPrintOverview(serialPersistentField)) {
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/Util.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -382,7 +382,7 @@ out.close(); } } catch (IOException ie) { - ie.printStackTrace(); + ie.printStackTrace(System.err); throw new DocletAbortException(); } } @@ -399,12 +399,12 @@ String pkgPath = DirectoryManager.getDirectoryPath(pkgDoc); String completePath = new SourcePath(configuration.sourcepath). getDirectory(pkgPath) + DirectoryManager.URL_FILE_SEPARATOR; - //Make sure that both paths are using the same seperators. + //Make sure that both paths are using the same separators. completePath = Util.replaceText(completePath, File.separator, DirectoryManager.URL_FILE_SEPARATOR); pkgPath = Util.replaceText(pkgPath, File.separator, DirectoryManager.URL_FILE_SEPARATOR); - return completePath.substring(0, completePath.indexOf(pkgPath)); + return completePath.substring(0, completePath.lastIndexOf(pkgPath)); } catch (Exception e){ return ""; } @@ -536,15 +536,6 @@ findAllInterfaceTypes(results, (ClassDoc) type, true, configuration); } - - public static <T extends ProgramElementDoc> List<T> asList(T[] members) { - List<T> list = new ArrayList<T>(); - for (int i = 0; i < members.length; i++) { - list.add(members[i]); - } - return list; - } - /** * Enclose in quotes, used for paths and filenames that contains spaces */ @@ -583,14 +574,7 @@ if (oldStr == null || newStr == null || oldStr.equals(newStr)) { return originalStr; } - StringBuffer result = new StringBuffer(originalStr); - int startIndex = 0; - while ((startIndex = result.indexOf(oldStr, startIndex)) != -1) { - result = result.replace(startIndex, startIndex + oldStr.length(), - newStr); - startIndex += newStr.length(); - } - return result.toString(); + return originalStr.replace(oldStr, newStr); } /** @@ -833,19 +817,17 @@ * @param tabLength the length of each tab. * @param s the String to scan. */ - public static void replaceTabs(int tabLength, StringBuffer s) { - int index, col; - StringBuffer whitespace; - while ((index = s.indexOf("\t")) != -1) { - whitespace = new StringBuffer(); - col = index; - do { - whitespace.append(" "); - col++; - } while ((col%tabLength) != 0); - s.replace(index, index+1, whitespace.toString()); + public static void replaceTabs(int tabLength, StringBuilder s) { + if (whitespace == null || whitespace.length() < tabLength) + whitespace = String.format("%" + tabLength + "s", " "); + int index = 0; + while ((index = s.indexOf("\t", index)) != -1) { + int spaceCount = tabLength - index % tabLength; + s.replace(index, index+1, whitespace.substring(0, spaceCount)); + index += spaceCount; } } + private static String whitespace; /** * The documentation for values() and valueOf() in Enums are set by the
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTool.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, 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 @@ -157,19 +157,19 @@ /** * Register that a compilation is about to start. */ - void beginContext(final Context context) { + void beginContext(Context context) { if (compilationInProgress) throw new IllegalStateException("Compilation in progress"); compilationInProgress = true; final JavaFileManager givenFileManager = context.get(JavaFileManager.class); context.put(JavaFileManager.class, (JavaFileManager)null); context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { - public JavaFileManager make() { + public JavaFileManager make(Context c) { if (givenFileManager != null) { - context.put(JavaFileManager.class, givenFileManager); + c.put(JavaFileManager.class, givenFileManager); return givenFileManager; } else { - return new JavacFileManager(context, true, null); + return new JavacFileManager(c, true, null); } } });
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Fri Mar 18 10:59:12 2011 -0700 @@ -43,7 +43,7 @@ private Flags() {} // uninstantiable public static String toString(long flags) { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); String sep = ""; for (Flag s : asFlagSet(flags)) { buf.append(sep);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -163,6 +163,7 @@ case PARAMETER: case LOCAL_VARIABLE: case EXCEPTION_PARAMETER: + case RESOURCE_VARIABLE: return KindName.VAR; case CONSTRUCTOR:
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Mar 18 10:59:12 2011 -0700 @@ -831,6 +831,8 @@ ClassType t = (ClassType)type; if (t.interfaces_field == null) // FIXME: shouldn't be null t.interfaces_field = List.nil(); + if (t.all_interfaces_field != null) + return Type.getModelTypes(t.all_interfaces_field); return t.interfaces_field; } else { return List.nil(); @@ -846,7 +848,7 @@ // An interface has no superclass; its supertype is Object. return t.isInterface() ? Type.noType - : t.supertype_field; + : t.supertype_field.getModelType(); } else { return Type.noType; }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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,6 +26,8 @@ package com.sun.tools.javac.code; import java.util.*; +import javax.lang.model.type.TypeVisitor; +import javax.lang.model.element.ElementVisitor; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; @@ -345,7 +347,12 @@ target = Target.instance(context); // Create the unknown type - unknownType = new Type(TypeTags.UNKNOWN, null); + unknownType = new Type(TypeTags.UNKNOWN, null) { + @Override + public <R, P> R accept(TypeVisitor<R, P> v, P p) { + return v.visitUnknown(this, p); + } + }; // create the basic builtin symbols rootPackage = new PackageSymbol(names.empty, null); @@ -355,13 +362,20 @@ return messages.getLocalizedString("compiler.misc.unnamed.package"); } }; - noSymbol = new TypeSymbol(0, names.empty, Type.noType, rootPackage); + noSymbol = new TypeSymbol(0, names.empty, Type.noType, rootPackage) { + public <R, P> R accept(ElementVisitor<R, P> v, P p) { + return v.visitUnknown(this, p); + } + }; noSymbol.kind = Kinds.NIL; // create the error symbols errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage); + errType = new ErrorType(errSymbol, Type.noType); + unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString("<any?>"), null, rootPackage); - errType = new ErrorType(errSymbol, Type.noType); + unknownSymbol.members_field = new Scope.ErrorScope(unknownSymbol); + unknownSymbol.type = unknownType; // initialize builtin types initType(byteType, "byte", "Byte"); @@ -382,9 +396,11 @@ // VGJ boundClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Bound, noSymbol); + boundClass.members_field = new Scope.ErrorScope(boundClass); // the builtin class of all methods methodClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Method, noSymbol); + methodClass.members_field = new Scope.ErrorScope(boundClass); // Create class to hold all predefined constants and operations. predefClass = new ClassSymbol(PUBLIC|ACYCLIC, names.empty, rootPackage);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Fri Mar 18 10:59:12 2011 -0700 @@ -93,6 +93,22 @@ return null; } + /** + * Get the representation of this type used for modelling purposes. + * By default, this is itself. For ErrorType, a different value + * may be provided, + */ + public Type getModelType() { + return this; + } + + public static List<Type> getModelTypes(List<Type> ts) { + ListBuffer<Type> lb = new ListBuffer<Type>(); + for (Type t: ts) + lb.append(t.getModelType()); + return lb.toList(); + } + public <R,S> R accept(Type.Visitor<R,S> v, S s) { return v.visitType(this, s); } /** Define a type given its tag and type symbol @@ -190,7 +206,7 @@ if (ts.isEmpty()) { return ""; } else { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); buf.append(ts.head.toString()); for (List<Type> l = ts.tail; l.nonEmpty(); l = l.tail) buf.append(",").append(l.head.toString()); @@ -464,7 +480,7 @@ boolean isPrintingBound = false; public String toString() { - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); s.append(kind.toString()); if (kind != UNBOUND) s.append(type); @@ -538,6 +554,10 @@ */ public List<Type> interfaces_field; + /** All the interfaces of this class, including missing ones. + */ + public List<Type> all_interfaces_field; + public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) { super(CLASS, tsym); this.outer_field = outer; @@ -578,7 +598,7 @@ /** The Java source which this type represents. */ public String toString() { - StringBuffer buf = new StringBuffer(); + StringBuilder buf = new StringBuilder(); if (getEnclosingType().tag == CLASS && tsym.owner.kind == TYP) { buf.append(getEnclosingType().toString()); buf.append("."); @@ -596,7 +616,7 @@ //where private String className(Symbol sym, boolean longform) { if (sym.name.isEmpty() && (sym.flags() & COMPOUND) != 0) { - StringBuffer s = new StringBuffer(supertype_field.toString()); + StringBuilder s = new StringBuilder(supertype_field.toString()); for (List<Type> is=interfaces_field; is.nonEmpty(); is = is.tail) { s.append("&"); s.append(is.head.toString());
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Mar 18 10:59:12 2011 -0700 @@ -1992,7 +1992,11 @@ * @return true if t is a sub signature of s. */ public boolean isSubSignature(Type t, Type s) { - return hasSameArgs(t, s) || hasSameArgs(t, erasure(s)); + return isSubSignature(t, s, true); + } + + public boolean isSubSignature(Type t, Type s, boolean strict) { + return hasSameArgs(t, s, strict) || hasSameArgs(t, erasure(s), strict); } /** @@ -2129,10 +2133,24 @@ * where correspondence is by position in the type parameter list. */ public boolean hasSameArgs(Type t, Type s) { + return hasSameArgs(t, s, true); + } + + public boolean hasSameArgs(Type t, Type s, boolean strict) { + return hasSameArgs(t, s, strict ? hasSameArgs_strict : hasSameArgs_nonstrict); + } + + private boolean hasSameArgs(Type t, Type s, TypeRelation hasSameArgs) { return hasSameArgs.visit(t, s); } // where - private TypeRelation hasSameArgs = new TypeRelation() { + private class HasSameArgs extends TypeRelation { + + boolean strict; + + public HasSameArgs(boolean strict) { + this.strict = strict; + } public Boolean visitType(Type t, Type s) { throw new AssertionError(); @@ -2147,7 +2165,7 @@ @Override public Boolean visitForAll(ForAll t, Type s) { if (s.tag != FORALL) - return false; + return strict ? false : visitMethodType(t.asMethodType(), s); ForAll forAll = (ForAll)s; return hasSameBounds(t, forAll) @@ -2159,6 +2177,10 @@ return false; } }; + + TypeRelation hasSameArgs_strict = new HasSameArgs(true); + TypeRelation hasSameArgs_nonstrict = new HasSameArgs(false); + // </editor-fold> // <editor-fold defaultstate="collapsed" desc="subst"> @@ -2534,7 +2556,7 @@ } // where private String typaramsString(List<Type> tvars) { - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); s.append('<'); boolean first = true; for (Type t : tvars) { @@ -2545,7 +2567,7 @@ s.append('>'); return s.toString(); } - private void appendTyparamString(TypeVar t, StringBuffer buf) { + private void appendTyparamString(TypeVar t, StringBuilder buf) { buf.append(t); if (t.bound == null || t.bound.tsym.getQualifiedName() == names.java_lang_Object) @@ -2832,12 +2854,26 @@ while (ts.head.tag != CLASS && ts.head.tag != TYPEVAR) ts = ts.tail; Assert.check(!ts.isEmpty()); - List<Type> cl = closure(ts.head); + //step 1 - compute erased candidate set (EC) + List<Type> cl = erasedSupertypes(ts.head); for (Type t : ts.tail) { if (t.tag == CLASS || t.tag == TYPEVAR) - cl = intersect(cl, closure(t)); + cl = intersect(cl, erasedSupertypes(t)); } - return compoundMin(cl); + //step 2 - compute minimal erased candidate set (MEC) + List<Type> mec = closureMin(cl); + //step 3 - for each element G in MEC, compute lci(Inv(G)) + List<Type> candidates = List.nil(); + for (Type erasedSupertype : mec) { + List<Type> lci = List.of(asSuper(ts.head, erasedSupertype.tsym)); + for (Type t : ts) { + lci = intersect(lci, List.of(asSuper(t, erasedSupertype.tsym))); + } + candidates = candidates.appendList(lci); + } + //step 4 - let MEC be { G1, G2 ... Gn }, then we have that + //lub = lci(Inv(G1)) & lci(Inv(G2)) & ... & lci(Inv(Gn)) + return compoundMin(candidates); default: // calculate lub(A, B[]) @@ -2851,6 +2887,18 @@ } } // where + List<Type> erasedSupertypes(Type t) { + ListBuffer<Type> buf = lb(); + for (Type sup : closure(t)) { + if (sup.tag == TYPEVAR) { + buf.append(sup); + } else { + buf.append(erasure(sup)); + } + } + return buf.toList(); + } + private Type arraySuperType = null; private Type arraySuperType() { // initialized lazily to avoid problems during compiler startup
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Mar 18 10:59:12 2011 -0700 @@ -1425,7 +1425,7 @@ // qualifier omitted; check for existence // of an appropriate implicit qualifier. rs.resolveImplicitThis(tree.meth.pos(), - localEnv, site); + localEnv, site, true); } } else if (tree.meth.getTag() == JCTree.SELECT) { log.error(tree.meth.pos(), "illegal.qual.not.icls", @@ -1581,15 +1581,7 @@ // symbol + type back into the attributed tree. Type clazztype = attribType(clazz, env); Pair<Scope,Scope> mapping = getSyntheticScopeMapping(clazztype, cdef != null); - if (!TreeInfo.isDiamond(tree)) { - clazztype = chk.checkClassType( - tree.clazz.pos(), clazztype, true); - } else if (!clazztype.isErroneous() && - !clazztype.tsym.type.isParameterized()) { - log.error(tree.clazz.pos(), - "cant.apply.diamond.1", - clazztype, diags.fragment("diamond.non.generic", clazztype)); - } + clazztype = chk.checkDiamond(tree, clazztype); chk.validate(clazz, localEnv); if (tree.encl != null) { // We have to work in this case to store @@ -1614,10 +1606,12 @@ List<Type> argtypes = attribArgs(tree.args, localEnv); List<Type> typeargtypes = attribTypes(tree.typeargs, localEnv); - if (TreeInfo.isDiamond(tree) && clazztype.tsym.type.isParameterized()) { + if (TreeInfo.isDiamond(tree) && !clazztype.isErroneous()) { clazztype = attribDiamond(localEnv, tree, clazztype, mapping, argtypes, typeargtypes); clazz.type = clazztype; } else if (allowDiamondFinder && + tree.def == null && + !clazztype.isErroneous() && clazztype.getTypeArguments().nonEmpty() && findDiamonds) { boolean prevDeferDiags = log.deferDiagnostics; @@ -1641,8 +1635,7 @@ if (inferred != null && !inferred.isErroneous() && inferred.tag == CLASS && - types.isAssignable(inferred, pt.tag == NONE ? clazztype : pt, Warner.noWarnings) && - chk.checkDiamond((ClassType)inferred).isEmpty()) { + types.isAssignable(inferred, pt.tag == NONE ? clazztype : pt, Warner.noWarnings)) { String key = types.isSameType(clazztype, inferred) ? "diamond.redundant.args" : "diamond.redundant.args.1"; @@ -1857,34 +1850,9 @@ ex.diagnostic); } } - clazztype = chk.checkClassType(tree.clazz.pos(), + return chk.checkClassType(tree.clazz.pos(), clazztype, true); - if (clazztype.tag == CLASS) { - List<Type> invalidDiamondArgs = chk.checkDiamond((ClassType)clazztype); - if (!clazztype.isErroneous() && invalidDiamondArgs.nonEmpty()) { - //one or more types inferred in the previous steps is either a - //captured type or an intersection type --- we need to report an error. - String subkey = invalidDiamondArgs.size() > 1 ? - "diamond.invalid.args" : - "diamond.invalid.arg"; - //The error message is of the kind: - // - //cannot infer type arguments for {clazztype}<>; - //reason: {subkey} - // - //where subkey is a fragment of the kind: - // - //type argument(s) {invalidDiamondArgs} inferred for {clazztype}<> is not allowed in this context - log.error(tree.clazz.pos(), - "cant.apply.diamond.1", - diags.fragment("diamond", clazztype.tsym), - diags.fragment(subkey, - invalidDiamondArgs, - diags.fragment("diamond", clazztype.tsym))); - } - } - return clazztype; } /** Creates a synthetic scope containing fake generic constructors. @@ -2806,7 +2774,7 @@ sym.location()); owntype = new MethodType(owntype.getParameterTypes(), types.erasure(owntype.getReturnType()), - owntype.getThrownTypes(), + types.erasure(owntype.getThrownTypes()), syms.methodClass); } if (useVarargs) { @@ -2980,7 +2948,7 @@ // (see comment for TypeVar.bound). // In this case, generate a class tree that represents the // bound class, ... - JCTree extending; + JCExpression extending; List<JCExpression> implementing; if ((bs.head.tsym.flags() & INTERFACE) == 0) { extending = tree.bounds.head;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Mar 18 10:59:12 2011 -0700 @@ -664,40 +664,25 @@ return true; } - /** Check that the type inferred using the diamond operator does not contain - * non-denotable types such as captured types or intersection types. - * @param t the type inferred using the diamond operator + /** Check that usage of diamond operator is correct (i.e. diamond should not + * be used with non-generic classes or in anonymous class creation expressions) */ - List<Type> checkDiamond(ClassType t) { - DiamondTypeChecker dtc = new DiamondTypeChecker(); - ListBuffer<Type> buf = ListBuffer.lb(); - for (Type arg : t.getTypeArguments()) { - if (!dtc.visit(arg, null)) { - buf.append(arg); - } - } - return buf.toList(); - } - - static class DiamondTypeChecker extends Types.SimpleVisitor<Boolean, Void> { - public Boolean visitType(Type t, Void s) { - return true; - } - @Override - public Boolean visitClassType(ClassType t, Void s) { - if (t.isCompound()) { - return false; - } - for (Type targ : t.getTypeArguments()) { - if (!visit(targ, s)) { - return false; - } - } - return true; - } - @Override - public Boolean visitCapturedType(CapturedType t, Void s) { - return false; + Type checkDiamond(JCNewClass tree, Type t) { + if (!TreeInfo.isDiamond(tree) || + t.isErroneous()) { + return checkClassType(tree.clazz.pos(), t, true); + } else if (tree.def != null) { + log.error(tree.clazz.pos(), + "cant.apply.diamond.1", + t, diags.fragment("diamond.and.anon.class", t)); + return types.createErrorType(t); + } else if (!t.tsym.type.isParameterized()) { + log.error(tree.clazz.pos(), + "cant.apply.diamond.1", + t, diags.fragment("diamond.non.generic", t)); + return types.createErrorType(t); + } else { + return t; } } @@ -1679,7 +1664,8 @@ "(" + types.memberType(t2, s2).getParameterTypes() + ")"); return s2; } - } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2)) { + } else if (checkNameClash((ClassSymbol)site.tsym, s1, s2) && + !checkCommonOverriderIn(s1, s2, site)) { log.error(pos, "name.clash.same.erasure.no.override", s1, s1.location(), @@ -2113,7 +2099,7 @@ if (s1 == s2 || !sym.overrides(s2, site.tsym, types, false)) continue; //if (i) the signature of 'sym' is not a subsignature of m1 (seen as //a member of 'site') and (ii) m1 has the same erasure as m2, issue an error - if (!types.isSubSignature(sym.type, types.memberType(site, s1)) && + if (!types.isSubSignature(sym.type, types.memberType(site, s1), false) && types.hasSameArgs(s1.erasure(types), s2.erasure(types))) { sym.flags_field |= CLASH; String key = s2 == sym ? @@ -2145,7 +2131,7 @@ for (Symbol s : types.membersClosure(site).getElementsByName(sym.name, cf)) { //if (i) the signature of 'sym' is not a subsignature of m1 (seen as //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error - if (!types.isSubSignature(sym.type, types.memberType(site, s)) && + if (!types.isSubSignature(sym.type, types.memberType(site, s), false) && types.hasSameArgs(s.erasure(types), sym.erasure(types))) { log.error(pos, "name.clash.same.erasure.no.hide", @@ -2666,7 +2652,7 @@ if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) { varargsDuplicateError(pos, sym, e.sym); return true; - } else if (sym.kind == MTH && !hasSameSignature(sym.type, e.sym.type)) { + } else if (sym.kind == MTH && !types.hasSameArgs(sym.type, e.sym.type, false)) { duplicateErasureError(pos, sym, e.sym); sym.flags_field |= CLASH; return true; @@ -2678,15 +2664,6 @@ } return true; } - //where - boolean hasSameSignature(Type mt1, Type mt2) { - if (mt1.tag == FORALL && mt2.tag == FORALL) { - ForAll fa1 = (ForAll)mt1; - ForAll fa2 = (ForAll)mt2; - mt2 = types.subst(fa2, fa2.tvars, fa1.tvars); - } - return types.hasSameArgs(mt1.asMethodType(), mt2.asMethodType()); - } /** Report duplicate declaration error. */
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Mar 18 10:59:12 2011 -0700 @@ -272,7 +272,7 @@ /** The list of unreferenced automatic resources. */ - Map<VarSymbol, JCVariableDecl> unrefdResources; + Scope unrefdResources; /** Set when processing a loop body the second time for DU analysis. */ boolean loopPassTwo = false; @@ -804,14 +804,16 @@ ListBuffer<PendingExit> prevPendingExits = pendingExits; boolean prevLoopPassTwo = loopPassTwo; pendingExits = new ListBuffer<PendingExit>(); + int prevErrors = log.nerrors; do { Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); scanStat(tree.body); alive |= resolveContinues(tree); scanCond(tree.cond); - if (log.nerrors != 0 || + if (log.nerrors != prevErrors || loopPassTwo || - uninitsEntry.diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) + uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) break; inits = initsWhenTrue; uninits = uninitsEntry.andSet(uninitsWhenTrue); @@ -831,8 +833,10 @@ Bits initsCond; Bits uninitsCond; pendingExits = new ListBuffer<PendingExit>(); + int prevErrors = log.nerrors; do { Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); scanCond(tree.cond); initsCond = initsWhenFalse; uninitsCond = uninitsWhenFalse; @@ -841,9 +845,9 @@ alive = !tree.cond.type.isFalse(); scanStat(tree.body); alive |= resolveContinues(tree); - if (log.nerrors != 0 || + if (log.nerrors != prevErrors || loopPassTwo || - uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1) + uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) break; uninits = uninitsEntry.andSet(uninits); loopPassTwo = true; @@ -864,8 +868,10 @@ Bits initsCond; Bits uninitsCond; pendingExits = new ListBuffer<PendingExit>(); + int prevErrors = log.nerrors; do { Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); if (tree.cond != null) { scanCond(tree.cond); initsCond = initsWhenFalse; @@ -883,7 +889,7 @@ scanStat(tree.body); alive |= resolveContinues(tree); scan(tree.step); - if (log.nerrors != 0 || + if (log.nerrors != prevErrors || loopPassTwo || uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) break; @@ -897,8 +903,6 @@ alive = resolveBreaks(tree, prevPendingExits) || tree.cond != null && !tree.cond.type.isTrue(); nextadr = nextadrPrev; - inits.excludeFrom(nextadr); - uninits.excludeFrom(nextadr); } public void visitForeachLoop(JCEnhancedForLoop tree) { @@ -913,13 +917,15 @@ letInit(tree.pos(), tree.var.sym); pendingExits = new ListBuffer<PendingExit>(); + int prevErrors = log.nerrors; do { Bits uninitsEntry = uninits.dup(); + uninitsEntry.excludeFrom(nextadr); scanStat(tree.body); alive |= resolveContinues(tree); - if (log.nerrors != 0 || + if (log.nerrors != prevErrors || loopPassTwo || - uninitsEntry.diffSet(uninits).nextBit(firstadr) == -1) + uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) break; uninits = uninitsEntry.andSet(uninits); loopPassTwo = true; @@ -992,7 +998,6 @@ public void visitTry(JCTry tree) { List<Type> caughtPrev = caught; List<Type> thrownPrev = thrown; - Map<VarSymbol, JCVariableDecl> unrefdResourcesPrev = unrefdResources; thrown = List.nil(); for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) { List<JCExpression> subClauses = TreeInfo.isMultiCatch(l.head) ? @@ -1002,17 +1007,18 @@ caught = chk.incl(ct.type, caught); } } + ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb(); Bits uninitsTryPrev = uninitsTry; ListBuffer<PendingExit> prevPendingExits = pendingExits; pendingExits = new ListBuffer<PendingExit>(); Bits initsTry = inits.dup(); uninitsTry = uninits.dup(); - unrefdResources = new LinkedHashMap<VarSymbol, JCVariableDecl>(); for (JCTree resource : tree.resources) { if (resource instanceof JCVariableDecl) { JCVariableDecl vdecl = (JCVariableDecl) resource; visitVarDef(vdecl); - unrefdResources.put(vdecl.sym, vdecl); + unrefdResources.enter(vdecl.sym); + resourceVarDecls.append(vdecl); } else if (resource instanceof JCExpression) { scanExpr((JCExpression) resource); } else { @@ -1049,11 +1055,14 @@ Bits uninitsEnd = uninits; int nextadrCatch = nextadr; - if (!unrefdResources.isEmpty() && + if (!resourceVarDecls.isEmpty() && lint.isEnabled(Lint.LintCategory.TRY)) { - for (Map.Entry<VarSymbol, JCVariableDecl> e : unrefdResources.entrySet()) { - log.warning(Lint.LintCategory.TRY, e.getValue().pos(), - "try.resource.not.referenced", e.getKey()); + for (JCVariableDecl resVar : resourceVarDecls) { + if (unrefdResources.includes(resVar.sym)) { + log.warning(Lint.LintCategory.TRY, resVar.pos(), + "try.resource.not.referenced", resVar.sym); + unrefdResources.remove(resVar.sym); + } } } @@ -1143,7 +1152,6 @@ while (exits.nonEmpty()) pendingExits.append(exits.next()); } uninitsTry.andSet(uninitsTryPrev).andSet(uninits); - unrefdResources = unrefdResourcesPrev; } public void visitConditional(JCConditional tree) { @@ -1369,9 +1377,7 @@ } void referenced(Symbol sym) { - if (unrefdResources != null && unrefdResources.containsKey(sym)) { - unrefdResources.remove(sym); - } + unrefdResources.remove(sym); } public void visitTypeCast(JCTypeCast tree) { @@ -1430,6 +1436,7 @@ alive = true; this.thrown = this.caught = null; this.classDef = null; + unrefdResources = new Scope(env.enclClass.sym); scan(tree); } finally { // note that recursive invocations of this method fail hard @@ -1444,6 +1451,7 @@ this.make = null; this.thrown = this.caught = null; this.classDef = null; + unrefdResources = null; } } }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Mar 18 10:59:12 2011 -0700 @@ -465,10 +465,9 @@ // quantify result type with them final List<Type> inferredTypes = insttypes.toList(); final List<Type> all_tvars = tvars; //this is the wrong tvars - final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass); - mt2.restype = new ForAll(restvars.toList(), mt.restype) { + return new UninferredMethodType(mt, restvars.toList()) { @Override - public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { + List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { for (Type t : restundet.toList()) { UndetVar uv = (UndetVar)t; if (uv.qtype == tv) { @@ -481,21 +480,17 @@ } return List.nil(); } - @Override - public Type inst(List<Type> inferred, Types types) throws NoInstanceException { - List<Type> formals = types.subst(mt2.argtypes, tvars, inferred); + void check(List<Type> inferred, Types types) throws NoInstanceException { // check that actuals conform to inferred formals - checkArgumentsAcceptable(env, capturedArgs, formals, allowBoxing, useVarargs, warn); + checkArgumentsAcceptable(env, capturedArgs, getParameterTypes(), allowBoxing, useVarargs, warn); // check that inferred bounds conform to their bounds checkWithinBounds(all_tvars, types.subst(inferredTypes, tvars, inferred), warn); if (useVarargs) { - chk.checkVararg(env.tree.pos(), formals, msym); + chk.checkVararg(env.tree.pos(), getParameterTypes(), msym); } - return super.inst(inferred, types); }}; - return mt2; } else { // check that actuals conform to inferred formals @@ -506,6 +501,62 @@ } //where + /** + * A delegated type representing a partially uninferred method type. + * The return type of a partially uninferred method type is a ForAll + * type - when the return type is instantiated (see Infer.instantiateExpr) + * the underlying method type is also updated. + */ + static abstract class UninferredMethodType extends DelegatedType { + + final List<Type> tvars; + + public UninferredMethodType(MethodType mtype, List<Type> tvars) { + super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym)); + this.tvars = tvars; + asMethodType().restype = new UninferredReturnType(tvars, mtype.restype); + } + + @Override + public MethodType asMethodType() { + return qtype.asMethodType(); + } + + @Override + public Type map(Mapping f) { + return qtype.map(f); + } + + void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException { + //update method type with newly inferred type-arguments + qtype = new MethodType(types.subst(getParameterTypes(), tvars, inferred), + restype, + types.subst(UninferredMethodType.this.getThrownTypes(), tvars, inferred), + UninferredMethodType.this.qtype.tsym); + check(inferred, types); + } + + abstract void check(List<Type> inferred, Types types) throws NoInstanceException; + + abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck); + + class UninferredReturnType extends ForAll { + public UninferredReturnType(List<Type> tvars, Type restype) { + super(tvars, restype); + } + @Override + public Type inst(List<Type> actuals, Types types) { + Type newRestype = super.inst(actuals, types); + instantiateReturnType(newRestype, actuals, types); + return newRestype; + } + @Override + public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { + return UninferredMethodType.this.getConstraints(tv, ck); + } + } + } + private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals, boolean allowBoxing, boolean useVarargs, Warner warn) { try { @@ -518,25 +569,25 @@ } } - /** Try to instantiate argument type `that' to given type `to'. - * If this fails, try to insantiate `that' to `to' where - * every occurrence of a type variable in `tvars' is replaced - * by an unknown type. - */ - private Type instantiateArg(ForAll that, - Type to, - List<Type> tvars, - Warner warn) throws InferenceException { - List<Type> targs; - try { - return instantiateExpr(that, to, warn); - } catch (NoInstanceException ex) { - Type to1 = to; - for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) - to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType)); - return instantiateExpr(that, to1, warn); - } + /** Try to instantiate argument type `that' to given type `to'. + * If this fails, try to insantiate `that' to `to' where + * every occurrence of a type variable in `tvars' is replaced + * by an unknown type. + */ + private Type instantiateArg(ForAll that, + Type to, + List<Type> tvars, + Warner warn) throws InferenceException { + List<Type> targs; + try { + return instantiateExpr(that, to, warn); + } catch (NoInstanceException ex) { + Type to1 = to; + for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) + to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType)); + return instantiateExpr(that, to1, warn); } + } /** check that type parameters are within their bounds. */ @@ -616,4 +667,4 @@ return t; } }; -} + }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Mar 18 10:59:12 2011 -0700 @@ -2817,8 +2817,8 @@ // local class or this() call thisArg = makeThis(tree.meth.pos(), c.type.getEnclosingType().tsym); } else { - // super() call of nested class - thisArg = makeOwnerThis(tree.meth.pos(), c, false); + // super() call of nested class - never pick 'this' + thisArg = makeOwnerThisN(tree.meth.pos(), c, false); } tree.args = tree.args.prepend(thisArg); }
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Mar 18 10:59:12 2011 -0700 @@ -889,10 +889,11 @@ : (c.fullname == names.java_lang_Object) ? Type.noType : syms.objectType; - ct.supertype_field = supertype; + ct.supertype_field = modelMissingTypes(supertype, tree.extending, false); // Determine interfaces. ListBuffer<Type> interfaces = new ListBuffer<Type>(); + ListBuffer<Type> all_interfaces = null; // lazy init Set<Type> interfaceSet = new HashSet<Type>(); List<JCExpression> interfaceTrees = tree.implementing; if ((tree.mods.flags & Flags.ENUM) != 0 && target.compilerBootstrap(c)) { @@ -909,13 +910,22 @@ Type i = attr.attribBase(iface, baseEnv, false, true, true); if (i.tag == CLASS) { interfaces.append(i); + if (all_interfaces != null) all_interfaces.append(i); chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet); + } else { + if (all_interfaces == null) + all_interfaces = new ListBuffer<Type>().appendList(interfaces); + all_interfaces.append(modelMissingTypes(i, iface, true)); } } - if ((c.flags_field & ANNOTATION) != 0) + if ((c.flags_field & ANNOTATION) != 0) { ct.interfaces_field = List.of(syms.annotationType); - else + ct.all_interfaces_field = ct.interfaces_field; + } else { ct.interfaces_field = interfaces.toList(); + ct.all_interfaces_field = (all_interfaces == null) + ? ct.interfaces_field : all_interfaces.toList(); + } if (c.fullname == names.java_lang_Object) { if (tree.extending != null) { @@ -1066,6 +1076,125 @@ return result; } + Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) { + if (t.tag != ERROR) + return t; + + return new ErrorType(((ErrorType) t).getOriginalType(), t.tsym) { + private Type modelType; + + @Override + public Type getModelType() { + if (modelType == null) + modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree); + return modelType; + } + }; + } + // where + private class Synthesizer extends JCTree.Visitor { + Type originalType; + boolean interfaceExpected; + List<ClassSymbol> synthesizedSymbols = List.nil(); + Type result; + + Synthesizer(Type originalType, boolean interfaceExpected) { + this.originalType = originalType; + this.interfaceExpected = interfaceExpected; + } + + Type visit(JCTree tree) { + tree.accept(this); + return result; + } + + List<Type> visit(List<? extends JCTree> trees) { + ListBuffer<Type> lb = new ListBuffer<Type>(); + for (JCTree t: trees) + lb.append(visit(t)); + return lb.toList(); + } + + @Override + public void visitTree(JCTree tree) { + result = syms.errType; + } + + @Override + public void visitIdent(JCIdent tree) { + if (tree.type.tag != ERROR) { + result = tree.type; + } else { + result = synthesizeClass(tree.name, syms.unnamedPackage).type; + } + } + + @Override + public void visitSelect(JCFieldAccess tree) { + if (tree.type.tag != ERROR) { + result = tree.type; + } else { + Type selectedType; + boolean prev = interfaceExpected; + try { + interfaceExpected = false; + selectedType = visit(tree.selected); + } finally { + interfaceExpected = prev; + } + ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym); + result = c.type; + } + } + + @Override + public void visitTypeApply(JCTypeApply tree) { + if (tree.type.tag != ERROR) { + result = tree.type; + } else { + ClassType clazzType = (ClassType) visit(tree.clazz); + if (synthesizedSymbols.contains(clazzType.tsym)) + synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size()); + final List<Type> actuals = visit(tree.arguments); + result = new ErrorType(tree.type, clazzType.tsym) { + @Override + public List<Type> getTypeArguments() { + return actuals; + } + }; + } + } + + ClassSymbol synthesizeClass(Name name, Symbol owner) { + int flags = interfaceExpected ? INTERFACE : 0; + ClassSymbol c = new ClassSymbol(flags, name, owner); + c.members_field = new Scope.ErrorScope(c); + c.type = new ErrorType(originalType, c) { + @Override + public List<Type> getTypeArguments() { + return typarams_field; + } + }; + synthesizedSymbols = synthesizedSymbols.prepend(c); + return c; + } + + void synthesizeTyparams(ClassSymbol sym, int n) { + ClassType ct = (ClassType) sym.type; + Assert.check(ct.typarams_field.isEmpty()); + if (n == 1) { + TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType); + ct.typarams_field = ct.typarams_field.prepend(v); + } else { + for (int i = n; i > 0; i--) { + TypeVar v = new TypeVar(names.fromString("T" + i), sym, syms.botType); + ct.typarams_field = ct.typarams_field.prepend(v); + } + } + } + } + + /* *************************************************************************** * tree building ****************************************************************************/
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Mar 18 10:59:12 2011 -0700 @@ -45,7 +45,9 @@ import javax.lang.model.element.ElementVisitor; import java.util.Map; +import java.util.Set; import java.util.HashMap; +import java.util.HashSet; /** Helper class for name resolution, used mostly by the attribution phase. * @@ -896,7 +898,8 @@ bestSoFar, allowBoxing, useVarargs, - operator); + operator, + new HashSet<TypeSymbol>()); } // where private Symbol findMethod(Env<AttrContext> env, @@ -909,11 +912,13 @@ Symbol bestSoFar, boolean allowBoxing, boolean useVarargs, - boolean operator) { + boolean operator, + Set<TypeSymbol> seen) { for (Type ct = intype; ct.tag == CLASS || ct.tag == TYPEVAR; ct = types.supertype(ct)) { while (ct.tag == TYPEVAR) ct = ct.getUpperBound(); ClassSymbol c = (ClassSymbol)ct.tsym; + if (!seen.add(c)) return bestSoFar; if ((c.flags() & (ABSTRACT | INTERFACE | ENUM)) == 0) abstractok = false; for (Scope.Entry e = c.members().lookup(name); @@ -942,7 +947,7 @@ bestSoFar = findMethod(env, site, name, argtypes, typeargtypes, l.head, abstractok, bestSoFar, - allowBoxing, useVarargs, operator); + allowBoxing, useVarargs, operator, seen); } if (concrete != bestSoFar && concrete.kind < ERR && bestSoFar.kind < ERR && @@ -1736,24 +1741,26 @@ */ Symbol resolveSelfContaining(DiagnosticPosition pos, Env<AttrContext> env, - Symbol member) { + Symbol member, + boolean isSuperCall) { Name name = names._this; - Env<AttrContext> env1 = env; + Env<AttrContext> env1 = isSuperCall ? env.outer : env; boolean staticOnly = false; - while (env1.outer != null) { - if (isStatic(env1)) staticOnly = true; - if (env1.enclClass.sym.isSubClass(member.owner, types) && - isAccessible(env, env1.enclClass.sym.type, member)) { - Symbol sym = env1.info.scope.lookup(name).sym; - if (sym != null) { - if (staticOnly) sym = new StaticError(sym); - return access(sym, pos, env.enclClass.sym.type, - name, true); + if (env1 != null) { + while (env1 != null && env1.outer != null) { + if (isStatic(env1)) staticOnly = true; + if (env1.enclClass.sym.isSubClass(member.owner, types)) { + Symbol sym = env1.info.scope.lookup(name).sym; + if (sym != null) { + if (staticOnly) sym = new StaticError(sym); + return access(sym, pos, env.enclClass.sym.type, + name, true); + } } + if ((env1.enclClass.sym.flags() & STATIC) != 0) + staticOnly = true; + env1 = env1.outer; } - if ((env1.enclClass.sym.flags() & STATIC) != 0) - staticOnly = true; - env1 = env1.outer; } log.error(pos, "encl.class.required", member); return syms.errSymbol; @@ -1764,9 +1771,13 @@ * JLS2 8.8.5.1 and 15.9.2 */ Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t) { + return resolveImplicitThis(pos, env, t, false); + } + + Type resolveImplicitThis(DiagnosticPosition pos, Env<AttrContext> env, Type t, boolean isSuperCall) { Type thisType = (((t.tsym.owner.kind & (MTH|VAR)) != 0) ? resolveSelf(pos, env, t.getEnclosingType().tsym, names._this) - : resolveSelfContaining(pos, env, t.tsym)).type; + : resolveSelfContaining(pos, env, t.tsym, isSuperCall)).type; if (env.info.isSelfCall && thisType.tsym == env.enclClass.sym) log.error(pos, "cant.ref.before.ctor.called", "this"); return thisType;
--- a/langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Fri Mar 18 10:59:12 2011 -0700 @@ -44,13 +44,13 @@ public class CacheFSInfo extends FSInfo { /** - * Register a Context.Factory to create a singleton CacheFSInfo. + * Register a Context.Factory to create a CacheFSInfo. */ - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(FSInfo.class, new Context.Factory<FSInfo>() { - public FSInfo make() { + public FSInfo make(Context c) { FSInfo instance = new CacheFSInfo(); - context.put(FSInfo.class, instance); + c.put(FSInfo.class, instance); return instance; } });
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Mar 18 10:59:12 2011 -0700 @@ -129,10 +129,10 @@ /** * Register a Context.Factory to create a JavacFileManager. */ - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(JavaFileManager.class, new Context.Factory<JavaFileManager>() { - public JavaFileManager make() { - return new JavacFileManager(context, true, null); + public JavaFileManager make(Context c) { + return new JavacFileManager(c, true, null); } }); }
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Mar 18 10:59:12 2011 -0700 @@ -2183,7 +2183,7 @@ } currentClassFile = classfile; if (verbose) { - printVerbose("loading", currentClassFile.toString()); + log.printVerbose("loading", currentClassFile.toString()); } if (classfile.getKind() == JavaFileObject.Kind.CLASS) { filling = true; @@ -2452,13 +2452,13 @@ for (File file : fm.getLocation(SOURCE_PATH)) { path = path.prepend(file); } - printVerbose("sourcepath", path.reverse().toString()); + log.printVerbose("sourcepath", path.reverse().toString()); } else if (wantSourceFiles) { List<File> path = List.nil(); for (File file : fm.getLocation(CLASS_PATH)) { path = path.prepend(file); } - printVerbose("sourcepath", path.reverse().toString()); + log.printVerbose("sourcepath", path.reverse().toString()); } if (wantClassFiles) { List<File> path = List.nil(); @@ -2468,7 +2468,7 @@ for (File file : fm.getLocation(CLASS_PATH)) { path = path.prepend(file); } - printVerbose("classpath", path.reverse().toString()); + log.printVerbose("classpath", path.reverse().toString()); } } } @@ -2519,14 +2519,6 @@ } } - /** Output for "-verbose" option. - * @param key The key to look up the correct internationalized string. - * @param arg An argument for substitution into the output string. - */ - private void printVerbose(String key, CharSequence arg) { - log.printNoteLines("verbose." + key, arg); - } - /** Output for "-checkclassfile" option. * @param key The key to look up the correct internationalized string. * @param arg An argument for substitution into the output string.
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Mar 18 10:59:12 2011 -0700 @@ -1447,7 +1447,7 @@ try { writeClassFile(out, c); if (verbose) - log.printErrLines("verbose.wrote.file", outFile); + log.printVerbose("wrote.file", outFile); out.close(); out = null; } finally {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Mar 18 10:59:12 2011 -0700 @@ -299,6 +299,13 @@ protected JavaCompiler delegateCompiler; /** + * Command line options. + */ + protected Options options; + + protected Context context; + + /** * Flag set if any annotation processing occurred. **/ protected boolean annotationProcessingOccurred; @@ -308,11 +315,9 @@ **/ protected boolean implicitSourceFilesRead; - protected Context context; - /** Construct a new compiler using a shared context. */ - public JavaCompiler(final Context context) { + public JavaCompiler(Context context) { this.context = context; context.put(compilerKey, this); @@ -354,7 +359,7 @@ reader.sourceCompleter = this; - Options options = Options.instance(context); + options = Options.instance(context); verbose = options.isSet(VERBOSE); sourceOutput = options.isSet(PRINTSOURCE); // used to be -s @@ -580,7 +585,7 @@ null, List.<JCTree>nil()); if (content != null) { if (verbose) { - printVerbose("parsing.started", filename); + log.printVerbose("parsing.started", filename); } if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); @@ -589,7 +594,7 @@ Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); if (verbose) { - printVerbose("parsing.done", Long.toString(elapsed(msec))); + log.printVerbose("parsing.done", Long.toString(elapsed(msec))); } } @@ -676,7 +681,7 @@ try { new Pretty(out, true).printUnit(env.toplevel, cdef); if (verbose) - printVerbose("wrote.file", outFile); + log.printVerbose("wrote.file", outFile); } finally { out.close(); } @@ -792,6 +797,11 @@ throw new AssertionError("attempt to reuse JavaCompiler"); hasBeenUsed = true; + // forcibly set the equivalent of -Xlint:-options, so that no further + // warnings about command line options are generated from this point on + options.put(XLINT_CUSTOM + "-" + LintCategory.OPTIONS.option, "true"); + options.remove(XLINT_CUSTOM + LintCategory.OPTIONS.option); + start_msec = now(); try { @@ -857,7 +867,7 @@ if (verbose) { elapsed_msec = elapsed(start_msec); - printVerbose("total", Long.toString(elapsed_msec)); + log.printVerbose("total", Long.toString(elapsed_msec)); } reportDeferredDiagnostics(); @@ -963,7 +973,6 @@ public void initProcessAnnotations(Iterable<? extends Processor> processors) { // Process annotations if processing is not disabled and there // is at least one Processor available. - Options options = Options.instance(context); if (options.isSet(PROC, "none")) { processAnnotations = false; } else if (procEnvImpl == null) { @@ -1022,7 +1031,6 @@ // If there are no annotation processors present, and // annotation processing is to occur with compilation, // emit a warning. - Options options = Options.instance(context); if (options.isSet(PROC, "only")) { log.warning("proc.proc-only.requested.no.procs"); todo.clear(); @@ -1108,9 +1116,13 @@ } boolean explicitAnnotationProcessingRequested() { - Options options = Options.instance(context); return explicitAnnotationProcessingRequested || + explicitAnnotationProcessingRequested(options); + } + + static boolean explicitAnnotationProcessingRequested(Options options) { + return options.isSet(PROCESSOR) || options.isSet(PROCESSORPATH) || options.isSet(PROC, "only") || @@ -1142,7 +1154,7 @@ if (verboseCompilePolicy) printNote("[attribute " + env.enclClass.sym + "]"); if (verbose) - printVerbose("checking.attribution", env.enclClass.sym); + log.printVerbose("checking.attribution", env.enclClass.sym); if (taskListener != null) { TaskEvent e = new TaskEvent(TaskEvent.Kind.ANALYZE, env.toplevel, env.enclClass.sym); @@ -1508,7 +1520,8 @@ } public void reportDeferredDiagnostics() { - if (annotationProcessingOccurred + if (errorCount() == 0 + && annotationProcessingOccurred && implicitSourceFilesRead && implicitSourcePolicy == ImplicitSourcePolicy.UNSET) { if (explicitAnnotationProcessingRequested()) @@ -1562,14 +1575,6 @@ Log.printLines(log.noticeWriter, lines); } - /** Output for "-verbose" option. - * @param key The key to look up the correct internationalized string. - * @param arg An argument for substitution into the output string. - */ - protected void printVerbose(String key, Object arg) { - log.printNoteLines("verbose." + key, arg); - } - /** Print numbers of errors and warnings. */ protected void printCount(String kind, int count) {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -367,7 +367,11 @@ || options.isSet(VERSION) || options.isSet(FULLVERSION)) return EXIT_OK; - error("err.no.source.files"); + if (JavaCompiler.explicitAnnotationProcessingRequested(options)) { + error("err.no.source.files.classes"); + } else { + error("err.no.source.files"); + } return EXIT_CMDERR; } } catch (java.io.FileNotFoundException e) {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/OptionName.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/OptionName.java Fri Mar 18 10:59:12 2011 -0700 @@ -88,6 +88,7 @@ O("-O"), XJCOV("-Xjcov"), XD("-XD"), + AT("@"), SOURCEFILE("sourcefile"); public final String optionName;
--- a/langtools/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java Fri Mar 18 10:59:12 2011 -0700 @@ -168,6 +168,7 @@ O, XJCOV, XD, + AT, SOURCEFILE); static Set<OptionName> javacFileManagerOptions = EnumSet.of( @@ -565,12 +566,27 @@ } }, + // This option exists only for the purpose of documenting itself. + // It's actually implemented by the CommandLine class. + new Option(AT, "opt.arg.file", "opt.AT") { + @Override + String helpSynopsis() { + hasSuffix = true; + return super.helpSynopsis(); + } + @Override + public boolean process(Options options, String option) { + throw new AssertionError + ("the @ flag should be caught by CommandLine."); + } + }, + /* * TODO: With apt, the matches method accepts anything if * -XclassAsDecls is used; code elsewhere does the lookup to * see if the class name is both legal and found. * - * In apt, the process method adds the candiate class file + * In apt, the process method adds the candidate class file * name to a separate list. */ new HiddenOption(SOURCEFILE) {
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Mar 18 10:59:12 2011 -0700 @@ -2357,7 +2357,7 @@ List<JCTypeParameter> typarams = typeParametersOpt(); - JCTree extending = null; + JCExpression extending = null; if (S.token() == EXTENDS) { S.nextToken(); extending = parseType();
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Mar 18 10:59:12 2011 -0700 @@ -807,8 +807,6 @@ final JavaCompiler compiler; /** The log for the round. */ final Log log; - /** The number of warnings in the previous round. */ - final int priorWarnings; /** The ASTs to be compiled. */ List<JCCompilationUnit> roots; @@ -826,10 +824,10 @@ private Round(Context context, int number, int priorWarnings) { this.context = context; this.number = number; - this.priorWarnings = priorWarnings; compiler = JavaCompiler.instance(context); log = Log.instance(context); + log.nwarnings += priorWarnings; log.deferDiagnostics = true; // the following is for the benefit of JavacProcessingEnvironment.getContext() @@ -904,8 +902,8 @@ JavaCompiler finalCompiler(boolean errorStatus) { try { JavaCompiler c = JavaCompiler.instance(nextContext()); + c.log.nwarnings += compiler.log.nwarnings; if (errorStatus) { - c.log.nwarnings += priorWarnings + compiler.log.nwarnings; c.log.nerrors += compiler.log.nerrors; } return c; @@ -1045,7 +1043,7 @@ * other values are implicitly reset. */ private Context nextContext() { - Context next = new Context(); + Context next = new Context(context); Options options = Options.instance(context); Assert.checkNonNull(options);
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Mar 18 10:59:12 2011 -0700 @@ -1588,14 +1588,6 @@ compiler.misc.diamond.non.generic=\ cannot use ''<>'' with non-generic class {0} -# 0: list of type, 1: message segment -compiler.misc.diamond.invalid.arg=\ - type argument {0} inferred for {1} is not allowed in this context - -# 0: list of type, 1: message segment -compiler.misc.diamond.invalid.args=\ - type arguments {0} inferred for {1} are not allowed in this context - # 0: type, 1: list of type compiler.misc.explicit.param.do.not.conform.to.bounds=\ explicit type argument {0} does not conform to declared bound(s) {1} @@ -1803,8 +1795,8 @@ compiler.misc.varargs.clash.with=\ {0} in {1} overrides {2} in {3} -compiler.misc.non.denotable.type=\ - Non-denotable type {0} not allowed here +compiler.misc.diamond.and.anon.class=\ + cannot use ''<>'' with anonymous inner classes # 0: symbol kind, 1: symbol, 2: symbol, 3: message segment compiler.misc.inapplicable.method=\
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac.properties Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2011, 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 @@ -146,6 +146,8 @@ Print information about which annotations a processor is asked to process javac.opt.prefer=\ Specify which file to read when both a source file and class file are found for an implicitly compiled class +javac.opt.AT=\ + Read options and filenames from file ## errors @@ -161,6 +163,8 @@ invalid target release: {0} javac.err.no.source.files=\ no source files +javac.err.no.source.files.classes=\ + no source files or class names javac.err.req.arg=\ {0} requires an argument javac.err.invalid.source=\
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Fri Mar 18 10:59:12 2011 -0700 @@ -567,14 +567,14 @@ public JCModifiers mods; public Name name; public List<JCTypeParameter> typarams; - public JCTree extending; + public JCExpression extending; public List<JCExpression> implementing; public List<JCTree> defs; public ClassSymbol sym; protected JCClassDecl(JCModifiers mods, Name name, List<JCTypeParameter> typarams, - JCTree extending, + JCExpression extending, List<JCExpression> implementing, List<JCTree> defs, ClassSymbol sym) @@ -2104,7 +2104,7 @@ JCClassDecl ClassDef(JCModifiers mods, Name name, List<JCTypeParameter> typarams, - JCTree extending, + JCExpression extending, List<JCExpression> implementing, List<JCTree> defs); JCMethodDecl MethodDef(JCModifiers mods,
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Fri Mar 18 10:59:12 2011 -0700 @@ -135,7 +135,7 @@ JCClassDecl t = (JCClassDecl) node; JCModifiers mods = copy(t.mods, p); List<JCTypeParameter> typarams = copy(t.typarams, p); - JCTree extending = copy(t.extending, p); + JCExpression extending = copy(t.extending, p); List<JCExpression> implementing = copy(t.implementing, p); List<JCTree> defs = copy(t.defs, p); return M.at(t.pos).ClassDef(mods, t.name, typarams, extending, implementing, defs);
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Mar 18 10:59:12 2011 -0700 @@ -146,7 +146,7 @@ public JCClassDecl ClassDef(JCModifiers mods, Name name, List<JCTypeParameter> typarams, - JCTree extending, + JCExpression extending, List<JCExpression> implementing, List<JCTree> defs) {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Context.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Context.java Fri Mar 18 10:59:12 2011 -0700 @@ -108,7 +108,7 @@ * instance. */ public static interface Factory<T> { - T make(); + T make(Context c); }; /** @@ -124,6 +124,8 @@ Object old = ht.put(key, fac); if (old != null) throw new AssertionError("duplicate context value"); + checkState(ft); + ft.put(key, fac); // cannot be duplicate if unique in ht } /** Set the value for the key in this context. */ @@ -142,7 +144,7 @@ Object o = ht.get(key); if (o instanceof Factory<?>) { Factory<?> fac = (Factory<?>)o; - o = fac.make(); + o = fac.make(this); if (o instanceof Factory<?>) throw new AssertionError("T extends Context.Factory"); Assert.check(ht.get(key) == o); @@ -158,6 +160,20 @@ public Context() {} + /** + * The table of preregistered factories. + */ + private Map<Key<?>,Factory<?>> ft = new HashMap<Key<?>,Factory<?>>(); + + public Context(Context prev) { + kt.putAll(prev.kt); // retain all implicit keys + ft.putAll(prev.ft); // retain all factory objects + ht.putAll(prev.ft); // init main table with factories + } + + /* + * The key table, providing a unique Key<T> for each Class<T>. + */ private Map<Class<?>, Key<?>> kt = new HashMap<Class<?>, Key<?>>(); private <T> Key<T> key(Class<T> clss) { @@ -198,6 +214,7 @@ public void clear() { ht = null; kt = null; + ft = null; } private static void checkState(Map<?,?> t) {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, 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 @@ -329,7 +329,6 @@ printLines(errWriter, localize(key, args)); } - /** Print the text of a message to the noticeWriter stream, * translating newlines appropriately for the platform. */ @@ -337,6 +336,14 @@ printLines(noticeWriter, localize(key, args)); } + /** + * Print the localized text of a "verbose" message to the + * noticeWriter stream. + */ + public void printVerbose(String key, Object... args) { + printLines(noticeWriter, localize("verbose." + key, args)); + } + protected void directError(String key, Object... args) { printErrLines(key, args); errWriter.flush();
--- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -92,8 +92,9 @@ * @com.example.foo * Omit parens for marker annotations, and omit "value=" when allowed. */ + @Override public String toString() { - StringBuffer sb = new StringBuffer("@"); + StringBuilder sb = new StringBuilder("@"); sb.append(annotation.type.tsym); ElementValuePair vals[] = elementValues(); @@ -153,6 +154,7 @@ * Returns a string representation of this pair * of the form "name=value". */ + @Override public String toString() { return meth.name + "=" + value(); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotationValueImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -30,7 +30,6 @@ import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.TypeTags; @@ -114,6 +113,7 @@ * @return the text of a Java language annotation value expression * whose value is the value of this annotation type element. */ + @Override public String toString() { ToStringVisitor tv = new ToStringVisitor(); attr.accept(tv); @@ -121,8 +121,9 @@ } private class ToStringVisitor implements Attribute.Visitor { - private final StringBuffer sb = new StringBuffer(); + private final StringBuilder sb = new StringBuilder(); + @Override public String toString() { return sb.toString(); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -64,7 +64,6 @@ import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Position; -import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; /** @@ -147,6 +146,7 @@ /** * Return true if this is a class, not an interface. */ + @Override public boolean isClass() { return !Modifier.isInterface(getModifiers()); } @@ -155,6 +155,7 @@ * Return true if this is a ordinary class, * not an enumeration, exception, an error, or an interface. */ + @Override public boolean isOrdinaryClass() { if (isEnum() || isInterface() || isAnnotationType()) { return false; @@ -172,6 +173,7 @@ * Return true if this is an enumeration. * (For legacy doclets, return false.) */ + @Override public boolean isEnum() { return (getFlags() & Flags.ENUM) != 0 && @@ -182,6 +184,7 @@ * Return true if this is an interface, but not an annotation type. * Overridden by AnnotationTypeDocImpl. */ + @Override public boolean isInterface() { return Modifier.isInterface(getModifiers()); } @@ -189,6 +192,7 @@ /** * Return true if this is an exception class */ + @Override public boolean isException() { if (isEnum() || isInterface() || isAnnotationType()) { return false; @@ -204,6 +208,7 @@ /** * Return true if this is an error class */ + @Override public boolean isError() { if (isEnum() || isInterface() || isAnnotationType()) { return false; @@ -275,6 +280,7 @@ /** * Return the package that this class is contained in. */ + @Override public PackageDoc containingPackage() { PackageDocImpl p = env.getPackageDoc(tsym.packge()); if (p.setDocPath == false) { @@ -374,6 +380,7 @@ * Return the qualified name and any type parameters. * Each parameter is a type variable with optional bounds. */ + @Override public String toString() { return classToString(env, tsym, true); } @@ -401,7 +408,7 @@ * qualified by their enclosing class(es) only. */ static String classToString(DocEnv env, ClassSymbol c, boolean full) { - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); if (!c.isInner()) { // if c is not an inner class s.append(getClassName(c, full)); } else { @@ -449,10 +456,12 @@ * Return the modifier string for this class. If it's an interface * exclude 'abstract' keyword from the modifier string */ + @Override public String modifiers() { return Modifier.toString(modifierSpecifier()); } + @Override public int modifierSpecifier() { int modifiers = getModifiers(); return (isInterface() || isAnnotationType()) @@ -1285,6 +1294,7 @@ * Return the source position of the entity, or null if * no position is available. */ + @Override public SourcePosition position() { if (tsym.sourcefile == null) return null; return SourcePositionImpl.make(tsym.sourcefile,
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -25,6 +25,7 @@ package com.sun.tools.javadoc; +import java.io.DataInputStream; import java.io.InputStream; import java.io.IOException; import java.text.CollationKey; @@ -33,6 +34,8 @@ import com.sun.javadoc.*; import com.sun.tools.javac.util.Position; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * abstract base class of all Doc classes. Doc item's are representations @@ -166,51 +169,28 @@ * Utility for subclasses which read HTML documentation files. */ String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException { - int filesize = input.available(); - byte[] filecontents = new byte[filesize]; - input.read(filecontents, 0, filesize); - input.close(); + byte[] filecontents = new byte[input.available()]; + try { + DataInputStream dataIn = new DataInputStream(input); + dataIn.readFully(filecontents); + } finally { + input.close(); + } String encoding = env.getEncoding(); String rawDoc = (encoding!=null) ? new String(filecontents, encoding) : new String(filecontents); - String upper = null; - int bodyIdx = rawDoc.indexOf("<body"); - if (bodyIdx == -1) { - bodyIdx = rawDoc.indexOf("<BODY"); - if (bodyIdx == -1) { - upper = rawDoc.toUpperCase(); - bodyIdx = upper.indexOf("<BODY"); - if (bodyIdx == -1) { - env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), - "javadoc.Body_missing_from_html_file"); - return ""; - } - } - } - bodyIdx = rawDoc.indexOf('>', bodyIdx); - if (bodyIdx == -1) { - env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), - "javadoc.Body_missing_from_html_file"); + Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*"); + Matcher m = bodyPat.matcher(rawDoc); + if (m.matches()) { + return m.group(1); + } else { + String key = rawDoc.matches("(?is).*<body\\b.*") + ? "javadoc.End_body_missing_from_html_file" + : "javadoc.Body_missing_from_html_file"; + env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key); return ""; } - ++bodyIdx; - int endIdx = rawDoc.indexOf("</body", bodyIdx); - if (endIdx == -1) { - endIdx = rawDoc.indexOf("</BODY", bodyIdx); - if (endIdx == -1) { - if (upper == null) { - upper = rawDoc.toUpperCase(); - } - endIdx = upper.indexOf("</BODY", bodyIdx); - if (endIdx == -1) { - env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), - "javadoc.End_body_missing_from_html_file"); - return ""; - } - } - } - return rawDoc.substring(bodyIdx, endIdx); } /** @@ -256,6 +236,7 @@ /** * Returns a string representation of this Doc item. */ + @Override public String toString() { return qualifiedName(); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2011, 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 @@ -31,14 +31,13 @@ import com.sun.tools.javac.util.List; -import java.net.*; +import java.io.File; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.net.URLClassLoader; -import java.io.File; -import java.io.IOException; -import java.util.StringTokenizer; /** * Class creates, controls and invokes doclets.
--- a/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ExecutableMemberDocImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -226,7 +226,7 @@ } private String makeSignature(boolean full) { - StringBuffer result = new StringBuffer(); + StringBuilder result = new StringBuilder(); result.append("("); for (List<Type> types = sym.type.getParameterTypes(); types.nonEmpty(); ) { Type t = types.head; @@ -251,6 +251,7 @@ /** * Generate a key for sorting. */ + @Override CollationKey generateKey() { String k = name() + flatSignature() + typeParametersString(); // ',' and '&' are between '$' and 'a': normalize to spaces. @@ -263,6 +264,7 @@ * Return the source position of the entity, or null if * no position is available. */ + @Override public SourcePosition position() { if (sym.enclClass().sourcefile == null) return null; return SourcePositionImpl.make(sym.enclClass().sourcefile,
--- a/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -142,7 +142,7 @@ return v + (suffix == 'f' || suffix == 'F' ? "" + suffix : ""); } private static String sourceForm(char c) { - StringBuffer buf = new StringBuffer(8); + StringBuilder buf = new StringBuilder(8); buf.append('\''); sourceChar(c, buf); buf.append('\''); @@ -152,7 +152,7 @@ return "0x" + Integer.toString(c & 0xff, 16); } private static String sourceForm(String s) { - StringBuffer buf = new StringBuffer(s.length() + 5); + StringBuilder buf = new StringBuilder(s.length() + 5); buf.append('\"'); for (int i=0; i<s.length(); i++) { char c = s.charAt(i); @@ -161,7 +161,7 @@ buf.append('\"'); return buf.toString(); } - private static void sourceChar(char c, StringBuffer buf) { + private static void sourceChar(char c, StringBuilder buf) { switch (c) { case '\b': buf.append("\\b"); return; case '\t': buf.append("\\t"); return; @@ -179,7 +179,7 @@ return; } } - private static void unicodeEscape(char c, StringBuffer buf) { + private static void unicodeEscape(char c, StringBuilder buf) { final String chars = "0123456789abcdef"; buf.append("\\u"); buf.append(chars.charAt(15 & (c>>12))); @@ -201,6 +201,7 @@ /** * Is this Doc item a field (but not an enum constant? */ + @Override public boolean isField() { return !isEnumConstant(); } @@ -209,6 +210,7 @@ * Is this Doc item an enum constant? * (For legacy doclets, return false.) */ + @Override public boolean isEnumConstant() { return (getFlags() & Flags.ENUM) != 0 && !env.legacyDoclet; @@ -257,6 +259,7 @@ * Return the source position of the entity, or null if * no position is available. */ + @Override public SourcePosition position() { if (sym.enclClass().sourcefile == null) return null; return SourcePositionImpl.make(sym.enclClass().sourcefile,
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocClassReader.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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,10 +44,10 @@ return (JavadocClassReader)instance; } - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(classReaderKey, new Context.Factory<ClassReader>() { - public ClassReader make() { - return new JavadocClassReader(context); + public ClassReader make(Context c) { + return new JavadocClassReader(c); } }); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocEnter.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2011, 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 @@ -48,10 +48,10 @@ return (JavadocEnter)instance; } - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(enterKey, new Context.Factory<Enter>() { - public Enter make() { - return new JavadocEnter(context); + public Enter make(Context c) { + return new JavadocEnter(c); } }); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocMemberEnter.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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,10 +46,10 @@ return (JavadocMemberEnter)instance; } - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(memberEnterKey, new Context.Factory<MemberEnter>() { - public MemberEnter make() { - return new JavadocMemberEnter(context); + public MemberEnter make(Context c) { + return new JavadocMemberEnter(c); } }); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTodo.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTodo.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -34,10 +34,10 @@ * @author Neal Gafter */ public class JavadocTodo extends Todo { - public static void preRegister(final Context context) { + public static void preRegister(Context context) { context.put(todoKey, new Context.Factory<Todo>() { - public Todo make() { - return new JavadocTodo(context); + public Todo make(Context c) { + return new JavadocTodo(c); } }); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/Messager.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -57,23 +57,23 @@ return (Messager)instance; } - public static void preRegister(final Context context, + public static void preRegister(Context context, final String programName) { context.put(logKey, new Context.Factory<Log>() { - public Log make() { - return new Messager(context, + public Log make(Context c) { + return new Messager(c, programName); } }); } - public static void preRegister(final Context context, + public static void preRegister(Context context, final String programName, final PrintWriter errWriter, final PrintWriter warnWriter, final PrintWriter noticeWriter) { context.put(logKey, new Context.Factory<Log>() { - public Log make() { - return new Messager(context, + public Log make(Context c) { + return new Messager(c, programName, errWriter, warnWriter, @@ -143,11 +143,9 @@ * if needed. */ private String getString(String key) { - ResourceBundle messageRB = this.messageRB; if (messageRB == null) { try { - this.messageRB = messageRB = - ResourceBundle.getBundle( + messageRB = ResourceBundle.getBundle( "com.sun.tools.javadoc.resources.javadoc"); } catch (MissingResourceException e) { throw new Error("Fatal: Resource for javadoc is missing"); @@ -456,8 +454,6 @@ * Print exit message. */ public void exitNotice() { - int nerrors = nerrors(); - int nwarnings = nwarnings(); if (nerrors > 0) { notice((nerrors > 1) ? "main.errors" : "main.error", "" + nerrors);
--- a/langtools/src/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ParameterizedTypeImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -25,15 +25,11 @@ package com.sun.tools.javadoc; - import com.sun.javadoc.*; -import static com.sun.javadoc.LanguageVersion.*; - import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; -import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.TypeTags.*; @@ -55,6 +51,7 @@ /** * Return the generic class or interface that declared this type. */ + @Override public ClassDoc asClassDoc() { return env.getClassDoc((ClassSymbol)type.tsym); } @@ -111,14 +108,17 @@ // Asking for the "name" of a parameterized type doesn't exactly make // sense. It's a type expression. Return the name of its generic // type. + @Override public String typeName() { return TypeMaker.getTypeName(type, false); } + @Override public ParameterizedType asParameterizedType() { return this; } + @Override public String toString() { return parameterizedTypeToString(env, (ClassType)type, true); } @@ -128,7 +128,7 @@ if (env.legacyDoclet) { return TypeMaker.getTypeName(cl, full); } - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); if (cl.getEnclosingType().tag != CLASS) { // if not an inner class... s.append(TypeMaker.getTypeName(cl, full)); } else {
--- a/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/RootDocImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -322,6 +322,7 @@ /** * Do lazy initialization of "documentation" string. */ + @Override protected String documentation() { if (documentation == null) { int cnt = options.length(); @@ -348,6 +349,7 @@ * Return the source position of the entity, or null if * no position is available. */ + @Override public SourcePosition position() { JavaFileObject path; return ((path = getOverviewPath()) == null) ?
--- a/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/SeeTagImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -358,14 +358,14 @@ String parameters; - StringBuffer typeId; + StringBuilder typeId; ListBuffer<String> paramList; ParameterParseMachine(String parameters) { this.parameters = parameters; this.paramList = new ListBuffer<String>(); - typeId = new StringBuffer(); + typeId = new StringBuilder(); } public String[] parseParameters() { @@ -464,6 +464,7 @@ /** * Return the kind of this tag. */ + @Override public String kind() { return "@see"; }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/Start.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/Start.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -396,6 +396,10 @@ boolean ok = root != null; if (ok) ok = docletInvoker.start(root); + Messager docletMessager = Messager.instance0(context); + messager.nwarnings += docletMessager.nwarnings; + messager.nerrors += docletMessager.nerrors; + // We're done. if (compOpts.get("-verbose") != null) { tm = System.currentTimeMillis() - tm;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -27,15 +27,12 @@ import com.sun.javadoc.*; -import static com.sun.javadoc.LanguageVersion.*; - import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.ClassType; import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.code.Type.ArrayType; -import com.sun.tools.javac.code.Types; import com.sun.tools.javac.util.List; import static com.sun.tools.javac.code.TypeTags.*; @@ -109,12 +106,13 @@ public static String getTypeName(Type t, boolean full) { switch (t.tag) { case ARRAY: - StringBuffer dimension = new StringBuffer(); + StringBuilder s = new StringBuilder(); while (t.tag == ARRAY) { - dimension = dimension.append("[]"); + s.append("[]"); t = ((ArrayType)t).elemtype; } - return getTypeName(t, full) + dimension; + s.insert(0, getTypeName(t, full)); + return s.toString(); case CLASS: return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full); default: @@ -130,12 +128,13 @@ static String getTypeString(DocEnv env, Type t, boolean full) { switch (t.tag) { case ARRAY: - StringBuffer dimension = new StringBuffer(); + StringBuilder s = new StringBuilder(); while (t.tag == ARRAY) { - dimension = dimension.append("[]"); + s.append("[]"); t = env.types.elemtype(t); } - return getTypeString(env, t, full) + dimension; + s.insert(0, getTypeString(env, t, full)); + return s.toString(); case CLASS: return ParameterizedTypeImpl. parameterizedTypeToString(env, (ClassType)t, full); @@ -157,7 +156,7 @@ if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) { return ""; } - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); for (Type t : sym.type.getTypeArguments()) { s.append(s.length() == 0 ? "<" : ", "); s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full)); @@ -175,7 +174,7 @@ if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) { return ""; } - StringBuffer s = new StringBuffer(); + StringBuilder s = new StringBuilder(); for (Type t : cl.getTypeArguments()) { s.append(s.length() == 0 ? "<" : ", "); s.append(getTypeString(env, t, full)); @@ -213,9 +212,9 @@ * For example, a two dimensional array of String returns '[][]'. */ public String dimension() { - StringBuffer dimension = new StringBuffer(); + StringBuilder dimension = new StringBuilder(); for (Type t = arrayType; t.tag == ARRAY; t = env.types.elemtype(t)) { - dimension = dimension.append("[]"); + dimension.append("[]"); } return dimension.toString(); } @@ -304,6 +303,7 @@ * * @return name of type including any dimension information. */ + @Override public String toString() { return qualifiedTypeName() + dimension(); }
--- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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,14 +78,17 @@ /** * Return the ClassDoc of the erasure of this type variable. */ + @Override public ClassDoc asClassDoc() { return env.getClassDoc((ClassSymbol)env.types.erasure(type).tsym); } + @Override public TypeVariable asTypeVariable() { return this; } + @Override public String toString() { return typeVarToString(env, (TypeVar)type, true); } @@ -96,7 +99,7 @@ * "extends" clause. Class names are qualified if "full" is true. */ static String typeVarToString(DocEnv env, TypeVar v, boolean full) { - StringBuffer s = new StringBuffer(v.toString()); + StringBuilder s = new StringBuilder(v.toString()); List<Type> bounds = getBounds(v, env); if (bounds.nonEmpty()) { boolean first = true;
--- a/langtools/src/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/WildcardTypeImpl.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, 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 @@ -28,8 +28,6 @@ import com.sun.javadoc.*; -import static com.sun.javadoc.LanguageVersion.*; - import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.util.List; @@ -69,18 +67,24 @@ /** * Return the ClassDoc of the erasure of this wildcard type. */ + @Override public ClassDoc asClassDoc() { return env.getClassDoc((ClassSymbol)env.types.erasure(type).tsym); } + @Override public WildcardType asWildcardType() { return this; } + @Override public String typeName() { return "?"; } + @Override public String qualifiedTypeName() { return "?"; } + @Override public String simpleTypeName() { return "?"; } + @Override public String toString() { return wildcardTypeToString(env, (Type.WildcardType)type, true); } @@ -96,7 +100,7 @@ if (env.legacyDoclet) { return TypeMaker.getTypeName(env.types.erasure(wildThing), full); } - StringBuffer s = new StringBuffer("?"); + StringBuilder s = new StringBuilder("?"); List<Type> bounds = getExtendsBounds(wildThing); if (bounds.nonEmpty()) { s.append(" extends ");
--- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc.properties Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2011, 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 @@ -104,7 +104,7 @@ tag.End_delimiter_missing_for_possible_SeeTag=End Delimiter } missing for possible See Tag in comment string: "{0}" tag.Improper_Use_Of_Link_Tag=Missing closing ''}'' character for inline tag: "{0}" javadoc.File_Read_Error=Error while reading file {0} -javadoc.Body_missing_from_html_file=Body tag missing from HTML +javadoc.Body_missing_from_html_file=Body tag missing from HTML file javadoc.End_body_missing_from_html_file=Close body tag missing from HTML file javadoc.Multiple_package_comments=Multiple sources of package comments found for package "{0}" javadoc.class_not_found=Class {0} not found.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7023703/T7023703neg.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, 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 7023703 + * @summary Valid code doesn't compile + * @compile/fail/ref=T7023703neg.out -XDrawDiagnostics T7023703neg.java + */ + +class T7023703neg { + + void testForLoop(boolean cond) { + final int bug; + final int bug2; + for (;cond;) { + final int item = 0; + bug2 = 1; //error + } + bug = 0; //ok + } + + void testForEachLoop(java.util.Collection<Integer> c) { + final int bug; + final int bug2; + for (Integer i : c) { + final int item = 0; + bug2 = 1; //error + } + bug = 0; //ok + } + + void testWhileLoop(boolean cond) { + final int bug; + final int bug2; + while (cond) { + final int item = 0; + bug2 = 1; //error + } + bug = 0; //ok + } + + void testDoWhileLoop(boolean cond) { + final int bug; + final int bug2; + do { + final int item = 0; + bug2 = 1; //error + } while (cond); + bug = 0; //ok + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7023703/T7023703neg.out Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,5 @@ +T7023703neg.java:37:13: compiler.err.var.might.be.assigned.in.loop: bug2 +T7023703neg.java:47:13: compiler.err.var.might.be.assigned.in.loop: bug2 +T7023703neg.java:57:13: compiler.err.var.might.be.assigned.in.loop: bug2 +T7023703neg.java:67:13: compiler.err.var.might.be.assigned.in.loop: bug2 +4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7023703/T7023703pos.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011, 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 7023703 + * @summary Valid code doesn't compile + * @compile T7023703pos.java + */ + +class T7023703pos { + + void testForLoop() { + final int bug; + for (;"a".equals("b");) { + final int item = 0; + } + bug = 0; //ok + } + + void testForEachLoop(boolean cond, java.util.Collection<Integer> c) { + final int bug; + for (Integer i : c) { + if (cond) { + final int item = 0; + } + } + bug = 0; //ok + } + + void testWhileLoop() { + final int bug; + while ("a".equals("b")) { + final int item = 0; + } + bug = 0; //ok + } + + void testDoWhileLoop() { + final int bug; + do { + final int item = 0; + } while ("a".equals("b")); + bug = 0; //ok + } + + private static class Inner { + private final int a, b, c, d, e; + + public Inner() { + a = b = c = d = e = 0; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7024568/T7024568.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011, 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 7024568 + * @summary Very long method resolution causing OOM error + * @compile/fail/ref=T7024568.out -XDrawDiagnostics T7024568.java + */ + +class Main { + void test(Obj o) { + o.test(0, 0, 0, 0, 0, 0, 0, 0, undefined); + } +} + +interface Test { + public void test(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, String str); + public void test(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, long l); +} + +interface Obj extends Test, A, B, C, D, E {} +interface A extends Test {} +interface B extends A, Test {} +interface C extends A, B, Test {} +interface D extends A, B, C, Test {} +interface E extends A, B, C, D, Test {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7024568/T7024568.out Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,2 @@ +T7024568.java:32:40: compiler.err.cant.resolve.location: kindname.variable, undefined, , , (compiler.misc.location: kindname.class, Main, null) +1 error
--- a/langtools/test/tools/javac/AnonStaticMember_2.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/AnonStaticMember_2.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 4279339 + * @bug 4279339 6969184 * @summary Verify that an anonymous class cannot contain a static method. * @author maddox *
--- a/langtools/test/tools/javac/InterfaceInInner.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/InterfaceInInner.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 4063740 + * @bug 4063740 6969184 * @summary Interfaces may only be declared in top level classes. * @author turnidge *
--- a/langtools/test/tools/javac/QualifiedNew.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/QualifiedNew.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 4406966 + * @bug 4406966 6969184 * @summary null qualifying inner instance creation should be error. * @author gafter *
--- a/langtools/test/tools/javac/T6900037.java Fri Mar 18 07:17:24 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2010, 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 6900037 - * @summary javac should warn if earlier -source is used and bootclasspath not set - * @compile T6900037.java - * @compile -source 1.6 T6900037.java - * @compile/fail/ref=T6900037.out -XDrawDiagnostics -Werror -source 1.6 T6900037.java - * @compile -Werror -source 1.6 -Xlint:-options T6900037.java - */ - -class T6900037 { }
--- a/langtools/test/tools/javac/T6900037.out Fri Mar 18 07:17:24 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -- compiler.warn.source.no.bootclasspath: 1.6 -- compiler.err.warnings.and.werror -1 error -1 warning
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/T7022711.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,20 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7022711 + * @summary compiler crash in try-with-resources + * @compile/fail/ref=T7022711.out -XDrawDiagnostics T7022711.java + */ + +import java.io.*; + +class T7022711 { + public static void main (String args[]) throws Exception { + try (DataInputStream is = new DataInputStream(new FileInputStream("x"))) { + while (true) { + is.getChar(); // method not found + } + } catch (EOFException e) { + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/T7022711.out Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,2 @@ +T7022711.java:14:19: compiler.err.cant.resolve.location.args: kindname.method, getChar, , , (compiler.misc.location.1: kindname.variable, is, java.io.DataInputStream) +1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/TryWithResources/UnusedResourcesTest.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2011, 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 7023233 + * @summary False positive for -Xlint:try with nested try with resources blocks + */ + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.JCDiagnostic; +import java.net.URI; +import java.util.Arrays; +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +public class UnusedResourcesTest { + + enum XlintOption { + NONE("none"), + TRY("try"); + + String opt; + + XlintOption(String opt) { + this.opt = opt; + } + + String getXlintOption() { + return "-Xlint:" + opt; + } + } + + enum TwrStmt { + TWR1("res1"), + TWR2("res2"), + TWR3("res3"); + + final String resourceName; + + private TwrStmt(String resourceName) { + this.resourceName = resourceName; + } + } + + enum SuppressLevel { + NONE, + SUPPRESS; + + String getSuppressAnno() { + return this == SUPPRESS ? + "@SuppressWarnings(\"try\")" : + ""; + } + } + + enum ResourceUsage { + NONE(null), + USE_R1(TwrStmt.TWR1), + USE_R2(TwrStmt.TWR2), + USE_R3(TwrStmt.TWR3); + + TwrStmt stmt; + + private ResourceUsage(TwrStmt stmt) { + this.stmt = stmt; + } + + String usedResourceName() { + return stmt != null ? stmt.resourceName : null; + } + + boolean isUsedIn(TwrStmt res, TwrStmt stmt) { + return this.stmt == res && + stmt.ordinal() >= this.stmt.ordinal(); + } + + String getUsage(TwrStmt stmt) { + return this != NONE && stmt.ordinal() >= this.stmt.ordinal() ? + "use(" + usedResourceName() + ");" : + ""; + } + } + + static class JavaSource extends SimpleJavaFileObject { + + String template = "class Resource implements AutoCloseable {\n" + + "public void close() {}\n" + + "}\n" + + "class Test {\n" + + "void use(Resource r) {}\n" + + "#S void test() {\n" + + "try (Resource #R1 = new Resource()) {\n" + + "#U1_R1\n" + + "#U1_R2\n" + + "#U1_R3\n" + + "try (Resource #R2 = new Resource()) {\n" + + "#U2_R1\n" + + "#U2_R2\n" + + "#U2_R3\n" + + "try (Resource #R3 = new Resource()) {\n" + + "#U3_R1\n" + + "#U3_R2\n" + + "#U3_R3\n" + + "}\n" + + "}\n" + + "}\n" + + "}\n" + + "}\n"; + + String source; + + public JavaSource(SuppressLevel suppressLevel, ResourceUsage usage1, + ResourceUsage usage2, ResourceUsage usage3) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = template.replace("#S", suppressLevel.getSuppressAnno()). + replace("#R1", TwrStmt.TWR1.resourceName). + replace("#R2", TwrStmt.TWR2.resourceName). + replace("#R3", TwrStmt.TWR3.resourceName). + replace("#U1_R1", usage1.getUsage(TwrStmt.TWR1)). + replace("#U1_R2", usage2.getUsage(TwrStmt.TWR1)). + replace("#U1_R3", usage3.getUsage(TwrStmt.TWR1)). + replace("#U2_R1", usage1.getUsage(TwrStmt.TWR2)). + replace("#U2_R2", usage2.getUsage(TwrStmt.TWR2)). + replace("#U2_R3", usage3.getUsage(TwrStmt.TWR2)). + replace("#U3_R1", usage1.getUsage(TwrStmt.TWR3)). + replace("#U3_R2", usage2.getUsage(TwrStmt.TWR3)). + replace("#U3_R3", usage3.getUsage(TwrStmt.TWR3)); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + public static void main(String... args) throws Exception { + for (XlintOption xlint : XlintOption.values()) { + for (SuppressLevel suppressLevel : SuppressLevel.values()) { + for (ResourceUsage usage1 : ResourceUsage.values()) { + for (ResourceUsage usage2 : ResourceUsage.values()) { + for (ResourceUsage usage3 : ResourceUsage.values()) { + test(xlint, + suppressLevel, + usage1, + usage2, + usage3); + } + } + } + } + } + } + + // Create a single file manager and reuse it for each compile to save time. + static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); + + static void test(XlintOption xlint, SuppressLevel suppressLevel, ResourceUsage usage1, + ResourceUsage usage2, ResourceUsage usage3) throws Exception { + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(suppressLevel, usage1, usage2, usage3); + DiagnosticChecker dc = new DiagnosticChecker(); + JavacTask ct = (JavacTask)tool.getTask(null, fm, dc, + Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source)); + ct.analyze(); + check(source, xlint, suppressLevel, usage1, usage2, usage3, dc); + } + + static void check(JavaSource source, XlintOption xlint, SuppressLevel suppressLevel, + ResourceUsage usage1, ResourceUsage usage2, ResourceUsage usage3, DiagnosticChecker dc) { + + ResourceUsage[] usages = { usage1, usage2, usage3 }; + boolean[] unusedFound = { dc.unused_r1, dc.unused_r2, dc.unused_r3 }; + boolean[] usedResources = { false, false, false }; + + for (TwrStmt res : TwrStmt.values()) { + outer: for (TwrStmt stmt : TwrStmt.values()) { + for (ResourceUsage usage : usages) { + if (usage.isUsedIn(res, stmt)) { + usedResources[res.ordinal()] = true; + break outer; + } + } + } + } + + for (TwrStmt stmt : TwrStmt.values()) { + boolean unused = !usedResources[stmt.ordinal()] && + xlint == XlintOption.TRY && + suppressLevel != SuppressLevel.SUPPRESS; + if (unused != unusedFound[stmt.ordinal()]) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nOptions: " + xlint.getXlintOption() + + "\nFound unused res1: " + unusedFound[0] + + "\nFound unused res2: " + unusedFound[1] + + "\nFound unused res3: " + unusedFound[2] + + "\nExpected unused res1: " + !usedResources[0] + + "\nExpected unused res2: " + !usedResources[1] + + "\nExpected unused res3: " + !usedResources[2]); + } + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { + + boolean unused_r1 = false; + boolean unused_r2 = false; + boolean unused_r3 = false; + + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.WARNING && + diagnostic.getCode().contains("try.resource.not.referenced")) { + String varName = ((JCDiagnostic)diagnostic).getArgs()[0].toString(); + if (varName.equals(TwrStmt.TWR1.resourceName)) { + unused_r1 = true; + } else if (varName.equals(TwrStmt.TWR2.resourceName)) { + unused_r2 = true; + } else if (varName.equals(TwrStmt.TWR3.resourceName)) { + unused_r3 = true; + } + } + } + } +}
--- a/langtools/test/tools/javac/api/6557752/T6557752.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/api/6557752/T6557752.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2011, 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 @@ -119,7 +119,7 @@ Types types = task.getTypes(); if (types.asElement(trees.getOriginalType((ErrorType)typeMirror)) != null) { - throw new AssertionError("Ttypes.asElement() error!"); + throw new AssertionError("Types.asElement() error!"); } foundError = true; }
--- a/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java Fri Mar 18 10:59:12 2011 -0700 @@ -34,6 +34,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.file.*; import com.sun.tools.javac.main.Main; +import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.parser.Token; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration; @@ -107,8 +108,7 @@ JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos); Context c = t.getContext(); ArgTypeMessages.preRegister(c); - Options options = Options.instance(c); - Log.instance(c).setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options)); + ArgTypeJavaCompiler.preRegister(c); Boolean ok = t.call(); return ok; @@ -144,7 +144,7 @@ } }; JavacFileManager.preRegister(c); // can't create it until Log has been set up - ArgTypeDiagnosticFormatter.preRegister(c); + ArgTypeJavaCompiler.preRegister(c); ArgTypeMessages.preRegister(c); int result = main.compile(args.toArray(new String[args.size()]), c); @@ -170,7 +170,7 @@ Context c = new Context(); JavacFileManager.preRegister(c); // can't create it until Log has been set up - ArgTypeDiagnosticFormatter.preRegister(c); + ArgTypeJavaCompiler.preRegister(c); ArgTypeMessages.preRegister(c); com.sun.tools.javac.main.Main m = new com.sun.tools.javac.main.Main("javac", out); int rc = m.compile(args.toArray(new String[args.size()]), c); @@ -189,17 +189,6 @@ * arg types. */ static class ArgTypeDiagnosticFormatter extends AbstractDiagnosticFormatter { - static void preRegister(final Context context) { - context.put(Log.logKey, new Context.Factory<Log>() { - public Log make() { - Log log = new Log(context) { }; - Options options = Options.instance(context); - log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options)); - return log; - } - }); - - } ArgTypeDiagnosticFormatter(Options options) { super(null, new SimpleConfiguration(options, @@ -246,14 +235,37 @@ } /** + * Trivial subtype of JavaCompiler to get access to the protected compilerKey field. + * The factory is used to ensure that the log is initialized with an instance of + * ArgTypeDiagnosticFormatter before we create the required JavaCompiler. + */ + static class ArgTypeJavaCompiler extends JavaCompiler { + static void preRegister(Context context) { + context.put(compilerKey, new Context.Factory<JavaCompiler>() { + public JavaCompiler make(Context c) { + Log log = Log.instance(c); + Options options = Options.instance(c); + log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options)); + return new JavaCompiler(c); + } + }); + } + + // not used + private ArgTypeJavaCompiler() { + super(null); + } + } + + /** * Diagnostic formatter which "localizes" a message as a line * containing a key, and a possibly empty set of descriptive strings for the * arg types. */ static class ArgTypeMessages extends JavacMessages { - static void preRegister(final Context c) { - c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { - public JavacMessages make() { + static void preRegister(Context context) { + context.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { + public JavacMessages make(Context c) { return new ArgTypeMessages(c) { @Override public String getLocalizedString(Locale l, String key, Object... args) {
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java Fri Mar 18 10:59:12 2011 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 6964768 6964461 6964469 6964487 6964460 6964481 + * @bug 6964768 6964461 6964469 6964487 6964460 6964481 6980021 * @summary need test program to validate javac resource bundles */
--- a/langtools/test/tools/javac/diags/Example.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/diags/Example.java Fri Mar 18 10:59:12 2011 -0700 @@ -486,7 +486,7 @@ if (verbose) System.err.println("run_simple: " + opts + " " + files); - List<String> args = new ArrayList<String>(opts); + List<String> args = new ArrayList<String>(); if (out != null && raw) args.add("-XDrawDiagnostics"); @@ -522,10 +522,10 @@ super(context); } - static void preRegister(final Context c, final Set<String> keys) { + static void preRegister(Context c, final Set<String> keys) { if (keys != null) { c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() { - public JavacMessages make() { + public JavacMessages make(Context c) { return new MessageTracker(c) { @Override public String getLocalizedString(Locale l, String key, Object... args) {
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Mar 18 10:59:12 2011 -0700 @@ -70,7 +70,6 @@ compiler.misc.kindname.type.variable compiler.misc.kindname.type.variable.bound compiler.misc.kindname.value -compiler.misc.non.denotable.type compiler.misc.no.unique.minimal.instance.exists compiler.misc.resume.abort # prompt for a response compiler.misc.source.unavailable # DiagnosticSource
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/DiamondAndAnonClass.java Fri Mar 18 10:59:12 2011 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011, 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. + */ + +// key: compiler.misc.diamond.and.anon.class +// key: compiler.err.cant.apply.diamond.1 + +import java.util.*; + +class DiamondAndAnonClass { + void m() { + List<String> list = new ArrayList<>() {}; + } +}
--- a/langtools/test/tools/javac/diags/examples/DiamondInvalidArg.java Fri Mar 18 07:17:24 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ - -// key: compiler.misc.diamond.invalid.arg -// key: compiler.misc.diamond -// key: compiler.err.cant.apply.diamond.1 - -class DiamondInvalidArg { - static class Foo<X extends Number & Comparable<Number>> { } - Foo<?> foo = new Foo<>(); -}
--- a/langtools/test/tools/javac/diags/examples/DiamondInvalidArgs.java Fri Mar 18 07:17:24 2011 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ - -// key: compiler.misc.diamond.invalid.args -// key: compiler.misc.diamond -// key: compiler.err.cant.apply.diamond.1 - -class DiamondInvalidArgs { - static class Foo<X extends Number & Comparable<Number>, - Y extends Number & Comparable<Number>> { } - Foo<?,?> foo = new Foo<>(); -}
--- a/langtools/test/tools/javac/generics/6969184/T6969184.java Fri Mar 18 07:17:24 2011 -0700 +++ b/langtools/test/tools/javac/generics/6969184/T6969184.java Fri Mar 18 10:59:12 2011 -0700 @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 6956758 + * @bug 6969184 * * @summary poor error recovery after symbol not found * @author Maurizio Cimadamore