--- a/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,5 @@
142129d8599d1f56b29387e7f9a5fad53b6d61df jdk7-b123
aa894c225b1a517b665ac2a58295217ea2245134 jdk7-b124
f658ec2730fa29323c36d23c27e54c7219ef5e16 jdk7-b125
+f1df068076986679ea1105532a65529d63a89060 jdk7-b126
+f83cd8bd35c678f94e526990e03dc838d0ec2717 jdk7-b127
--- a/.hgtags-top-repo Fri Feb 18 11:15:40 2011 -0800
+++ b/.hgtags-top-repo Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,5 @@
ed6950da30cf1e8904b4bdb034d471647942271f jdk7-b123
024a6755895bf91b5a3c98984c89ee018efbf538 jdk7-b124
5c4df7e992775c102f08e9f1c0a124b324641b70 jdk7-b125
+b566d490905691787f8931f69947a92c67c6d5e4 jdk7-b126
+bd70f76b0309068f157ae759c36eac8f2c6d098e jdk7-b127
--- a/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -29,15 +29,6 @@
TOPDIR:=.
endif
-# Openjdk sources (only used if SKIP_OPENJDK_BUILD!=true)
-OPENJDK_SOURCETREE=$(TOPDIR)/openjdk
-OPENJDK_BUILDDIR:=$(shell \
- if [ -r $(OPENJDK_SOURCETREE)/Makefile ]; then \
- echo "$(OPENJDK_SOURCETREE)"; \
- else \
- echo "."; \
- fi)
-
ifndef JDK_TOPDIR
JDK_TOPDIR=$(TOPDIR)/jdk
endif
@@ -70,7 +61,7 @@
all::
@$(START_ECHO)
-all:: openjdk_check sanity
+all:: sanity
ifeq ($(SKIP_FASTDEBUG_BUILD), false)
all:: fastdebug_build
@@ -80,10 +71,6 @@
all:: debug_build
endif
-ifneq ($(SKIP_OPENJDK_BUILD), true)
- all:: openjdk_build
-endif
-
all:: all_product_build
all::
@@ -267,81 +254,6 @@
debug_build:: build_debug_image
fastdebug_build:: build_fastdebug_image
-# Check on whether we really can build the openjdk, need source etc.
-openjdk_check: FRC
-ifneq ($(SKIP_OPENJDK_BUILD), true)
- @$(ECHO) " "
- @$(ECHO) "================================================="
- @if [ ! -r $(OPENJDK_BUILDDIR)/Makefile ] ; then \
- $(ECHO) "ERROR: No openjdk source tree available at: $(OPENJDK_BUILDDIR)"; \
- exit 1; \
- else \
- $(ECHO) "OpenJDK will be built after JDK is built"; \
- $(ECHO) " OPENJDK_BUILDDIR=$(OPENJDK_BUILDDIR)"; \
- fi
- @$(ECHO) "================================================="
- @$(ECHO) " "
-endif
-
-# If we have bundle rules, we have a chance here to do a complete cycle
-# build, of production and open build.
-# FIXUP: We should create the openjdk source bundle and build that?
-# But how do we reliable create or get at a formal openjdk source tree?
-# The one we have needs to be trimmed of built bits and closed dirs.
-# The repositories might not be available.
-# The openjdk source bundle is probably not available.
-
-ifneq ($(SKIP_OPENJDK_BUILD), true)
- ifeq ($(BUILD_JDK), true)
- ifeq ($(BUNDLE_RULES_AVAILABLE), true)
-
-OPENJDK_OUTPUTDIR=$(ABS_OUTPUTDIR)/open-output
-OPENJDK_BUILD_NAME \
- = openjdk-$(JDK_MINOR_VERSION)-$(BUILD_NUMBER)-$(PLATFORM)-$(ARCH)-$(BUNDLE_DATE)
-OPENJDK_BUILD_BINARY_ZIP=$(ABS_BIN_BUNDLEDIR)/$(OPENJDK_BUILD_NAME).zip
-BUILT_IMAGE=$(ABS_OUTPUTDIR)/j2sdk-image
-ifeq ($(PLATFORM)$(ARCH_DATA_MODEL),solaris64)
- OPENJDK_BOOTDIR=$(BOOTDIR)
- OPENJDK_IMPORTJDK=$(JDK_IMPORT_PATH)
-else
- OPENJDK_BOOTDIR=$(BUILT_IMAGE)
- OPENJDK_IMPORTJDK=$(BUILT_IMAGE)
-endif
-
-openjdk_build:
- @$(START_ECHO)
- @$(ECHO) " "
- @$(ECHO) "================================================="
- @$(ECHO) "Starting openjdk build"
- @$(ECHO) " Using: ALT_JDK_DEVTOOLS_DIR=$(JDK_DEVTOOLS_DIR)"
- @$(ECHO) "================================================="
- @$(ECHO) " "
- $(RM) -r $(OPENJDK_OUTPUTDIR)
- $(MKDIR) -p $(OPENJDK_OUTPUTDIR)
- ($(CD) $(OPENJDK_BUILDDIR) && $(MAKE) \
- OPENJDK=true \
- GENERATE_DOCS=false \
- ALT_JDK_DEVTOOLS_DIR=$(JDK_DEVTOOLS_DIR) \
- ALT_OUTPUTDIR=$(OPENJDK_OUTPUTDIR) \
- ALT_BOOTDIR=$(OPENJDK_BOOTDIR) \
- ALT_JDK_IMPORT_PATH=$(OPENJDK_IMPORTJDK) \
- product_build )
- $(RM) $(OPENJDK_BUILD_BINARY_ZIP)
- ( $(CD) $(OPENJDK_OUTPUTDIR)/j2sdk-image && \
- $(ZIPEXE) -q -r $(OPENJDK_BUILD_BINARY_ZIP) .)
- $(RM) -r $(OPENJDK_OUTPUTDIR)
- @$(ECHO) " "
- @$(ECHO) "================================================="
- @$(ECHO) "Finished openjdk build"
- @$(ECHO) " Binary Bundle: $(OPENJDK_BUILD_BINARY_ZIP)"
- @$(ECHO) "================================================="
- @$(ECHO) " "
- @$(FINISH_ECHO)
-
- endif
- endif
-endif
-
clobber::
$(RM) -r $(OUTPUTDIR)/*
$(RM) -r $(OUTPUTDIR)/../$(PLATFORM)-$(ARCH)-debug/*
@@ -448,7 +360,6 @@
DEVTOOLS_PATH.desc = Directory containing zip and gnumake
CUPS_HEADERS_PATH.desc = Include directory location for CUPS header files
DXSDK_PATH.desc = Root directory of DirectX SDK
-MSVCRT_DLL_PATH.desc = Directory containing mscvrt.dll
# Make variables to print out (description and value)
VARIABLE_PRINTVAL_LIST += \
@@ -477,12 +388,10 @@
ifeq ($(PLATFORM), windows)
VARIABLE_PRINTVAL_LIST += \
- DXSDK_PATH \
- MSVCRT_DLL_PATH
+ DXSDK_PATH
VARIABLE_CHECKDIR_LIST += \
- DXSDK_PATH \
- MSVCRT_DLL_PATH
+ DXSDK_PATH
endif
--- a/README-builds.html Fri Feb 18 11:15:40 2011 -0800
+++ b/README-builds.html Fri Feb 18 12:04:36 2011 -0800
@@ -1414,14 +1414,14 @@
but it's normally found via the DirectX environment variable
<tt>DXSDK_DIR</tt>.
</blockquote>
- <strong><a name="msvcrt"><tt>MSVCR100.DLL</tt></a></strong>
+ <strong><a name="msvcrNN"><tt>MSVCR100.DLL</tt></a></strong>
<blockquote>
The OpenJDK build requires access to a redistributable
<tt>MSVCR100.DLL</tt>.
This is usually picked up automatically from the redist
directories of Visual Studio 2010.
If this cannot be found set the
- <a href="#ALT_MSVCRT_DLL_PATH"><tt>ALT_MSVCRT_DLL_PATH</tt></a>
+ <a href="#ALT_MSVCRNN_DLL_PATH"><tt>ALT_MSVCRNN_DLL_PATH</tt></a>
variable to the location of this file.
<p>
</blockquote>
@@ -1671,15 +1671,10 @@
variable <tt>DXSDK_DIR</tt>,
failing that, look in <tt>C:/DXSDK</tt>.
</dd>
- <dt><tt><a name="ALT_MSVCRT_DLL_PATH">ALT_MSVCRT_DLL_PATH</a></tt> </dt>
- <dd>
- The location of the
- <a href="#msvcrt"><tt>MSVCRT.DLL</tt></a>.
- </dd>
<dt><tt><a name="ALT_MSVCRNN_DLL_PATH">ALT_MSVCRNN_DLL_PATH</a></tt> </dt>
<dd>
The location of the
- <a href="#msvcrt"><tt>MSVCR100.DLL</tt></a>.
+ <a href="#msvcrNN"><tt>MSVCR100.DLL</tt></a>.
</dd>
</dl>
</dd>
--- a/corba/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/corba/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,5 @@
a230c142628cea22475ab9dc5cd544266ddf2466 jdk7-b123
f90b3e014e831eb4f32ef035a1dad2b8ba87949f jdk7-b124
1ce58c72b7892cb813eb920276c7e7f17a1b79fe jdk7-b125
+d7532bcd3742f1576dd07ff9fbb535c9c9a276e9 jdk7-b126
+64775e83f4df894355f45555f50c410de6727b4e jdk7-b127
--- a/hotspot/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -141,3 +141,6 @@
0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 jdk7-b124
0a8e0d4345b37b71ec49dda08ee03b68c4f1b592 hs20-b05
e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 jdk7-b125
+4c851c931d001a882cab809aaf3a55371b919244 jdk7-b126
+e24ab3fa6aafad3efabbe7dba9918c5f461a20b1 hs20-b06
+102466e70debc4b907afbd7624e34ddb1aafee9f jdk7-b127
--- a/hotspot/make/hotspot_version Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/make/hotspot_version Fri Feb 18 12:04:36 2011 -0800
@@ -35,7 +35,7 @@
HS_MAJOR_VER=20
HS_MINOR_VER=0
-HS_BUILD_NUMBER=06
+HS_BUILD_NUMBER=07
JDK_MAJOR_VER=1
JDK_MINOR_VER=7
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -4104,7 +4104,7 @@
ld_ptr(G2_thread, in_bytes(JavaThread::tlab_start_offset()), t1);
sub(top, t1, t1); // size of tlab's allocated portion
- incr_allocated_bytes(t1, 0, t2);
+ incr_allocated_bytes(t1, t2, t3);
// refill the tlab with an eden allocation
bind(do_refill);
@@ -4138,19 +4138,14 @@
delayed()->nop();
}
-void MacroAssembler::incr_allocated_bytes(Register var_size_in_bytes,
- int con_size_in_bytes,
- Register t1) {
+void MacroAssembler::incr_allocated_bytes(RegisterOrConstant size_in_bytes,
+ Register t1, Register t2) {
// Bump total bytes allocated by this thread
assert(t1->is_global(), "must be global reg"); // so all 64 bits are saved on a context switch
- assert_different_registers(var_size_in_bytes, t1);
+ assert_different_registers(size_in_bytes.register_or_noreg(), t1, t2);
// v8 support has gone the way of the dodo
ldx(G2_thread, in_bytes(JavaThread::allocated_bytes_offset()), t1);
- if (var_size_in_bytes->is_valid()) {
- add(t1, var_size_in_bytes, t1);
- } else {
- add(t1, con_size_in_bytes, t1);
- }
+ add(t1, ensure_simm13_or_reg(size_in_bytes, t2), t1);
stx(t1, G2_thread, in_bytes(JavaThread::allocated_bytes_offset()));
}
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -823,15 +823,23 @@
};
// test if x is within signed immediate range for nbits
- static bool is_simm(int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); }
+ static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 ) <= x && x < ( intptr_t(1) << nbits-1 ); }
// test if -4096 <= x <= 4095
- static bool is_simm13(int x) { return is_simm(x, 13); }
+ static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
+
+ static bool is_in_wdisp_range(address a, address b, int nbits) {
+ intptr_t d = intptr_t(b) - intptr_t(a);
+ return is_simm(d, nbits + 2);
+ }
// test if label is in simm16 range in words (wdisp16).
bool is_in_wdisp16_range(Label& L) {
- intptr_t d = intptr_t(pc()) - intptr_t(target(L));
- return is_simm(d, 18);
+ return is_in_wdisp_range(target(L), pc(), 16);
+ }
+ // test if the distance between two addresses fits in simm30 range in words
+ static bool is_in_wdisp30_range(address a, address b) {
+ return is_in_wdisp_range(a, b, 30);
}
enum ASIs { // page 72, v9
@@ -1843,6 +1851,8 @@
inline void jmp( Register s1, Register s2 );
inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() );
+ // Check if the call target is out of wdisp30 range (relative to the code cache)
+ static inline bool is_far_target(address d);
inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type );
inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type );
inline void callr( Register s1, Register s2 );
@@ -2389,7 +2399,8 @@
Label& slow_case // continuation point if fast allocation fails
);
void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
- void incr_allocated_bytes(Register var_size_in_bytes, int con_size_in_bytes, Register t1);
+ void incr_allocated_bytes(RegisterOrConstant size_in_bytes,
+ Register t1, Register t2);
// interface method calling
void lookup_interface_method(Register recv_klass,
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -588,10 +588,13 @@
inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); }
inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); }
+inline bool MacroAssembler::is_far_target(address d) {
+ return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound());
+}
+
// Call with a check to see if we need to deal with the added
// expense of relocation and if we overflow the displacement
-// of the quick call instruction./
-// Check to see if we have to deal with relocations
+// of the quick call instruction.
inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
#ifdef _LP64
intptr_t disp;
@@ -603,14 +606,12 @@
// Is this address within range of the call instruction?
// If not, use the expensive instruction sequence
- disp = (intptr_t)d - (intptr_t)pc();
- if ( disp != (intptr_t)(int32_t)disp ) {
+ if (is_far_target(d)) {
relocate(rt);
AddressLiteral dest(d);
jumpl_to(dest, O7, O7);
- }
- else {
- Assembler::call( d, rt );
+ } else {
+ Assembler::call(d, rt);
}
#else
Assembler::call( d, rt );
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -2358,6 +2358,8 @@
op->tmp3()->as_register() == G4 &&
op->tmp4()->as_register() == O1 &&
op->klass()->as_register() == G5, "must be");
+
+ LP64_ONLY( __ signx(op->len()->as_register()); )
if (UseSlowPath ||
(!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
(!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -170,11 +170,13 @@
Register t2, // temp register
Label& slow_case // continuation point if fast allocation fails
) {
+ RegisterOrConstant size_in_bytes = var_size_in_bytes->is_valid()
+ ? RegisterOrConstant(var_size_in_bytes) : RegisterOrConstant(con_size_in_bytes);
if (UseTLAB) {
tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
} else {
eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
- incr_allocated_bytes(var_size_in_bytes, con_size_in_bytes, t1);
+ incr_allocated_bytes(size_in_bytes, t1, t2);
}
}
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -343,9 +343,10 @@
// returned.
restore_live_registers(sasm);
- __ restore();
- __ br(Assembler::always, false, Assembler::pt, deopt_blob->unpack_with_reexecution(), relocInfo::runtime_call_type);
- __ delayed()->nop();
+
+ AddressLiteral dest(deopt_blob->unpack_with_reexecution());
+ __ jump_to(dest, O0);
+ __ delayed()->restore();
__ bind(no_deopt);
restore_live_registers(sasm);
@@ -461,7 +462,7 @@
// get the instance size
__ ld(G5_klass, klassOopDesc::header_size() * HeapWordSize + Klass::layout_helper_offset_in_bytes(), G1_obj_size);
__ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path);
- __ incr_allocated_bytes(G1_obj_size, 0, G3_t1);
+ __ incr_allocated_bytes(G1_obj_size, G3_t1, G4_t2);
__ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2);
__ verify_oop(O0_obj);
@@ -577,7 +578,7 @@
__ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size);
__ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size
- __ incr_allocated_bytes(G1_arr_size, 0, G3_t1);
+ __ incr_allocated_bytes(G1_arr_size, G3_t1, O1_t2);
__ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2);
__ ldub(klass_lh, G3_t1, klass_lh_header_size_offset);
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1295,16 +1295,13 @@
// Get the method data pointer from the methodOop and set the
// specified register to its value.
-void InterpreterMacroAssembler::set_method_data_pointer_offset(Register Roff) {
+void InterpreterMacroAssembler::set_method_data_pointer() {
assert(ProfileInterpreter, "must be profiling interpreter");
Label get_continue;
ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
test_method_data_pointer(get_continue);
add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr);
- if (Roff != noreg)
- // Roff contains a method data index ("mdi"). It defaults to zero.
- add(ImethodDataPtr, Roff, ImethodDataPtr);
bind(get_continue);
}
@@ -1315,10 +1312,11 @@
Label zero_continue;
// Test MDO to avoid the call if it is NULL.
- ld_ptr(Lmethod, methodOopDesc::method_data_offset(), ImethodDataPtr);
+ ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
test_method_data_pointer(zero_continue);
call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp);
- set_method_data_pointer_offset(O0);
+ add(ImethodDataPtr, in_bytes(methodDataOopDesc::data_offset()), ImethodDataPtr);
+ add(ImethodDataPtr, O0, ImethodDataPtr);
bind(zero_continue);
}
@@ -1369,7 +1367,6 @@
}
void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
- Register cur_bcp,
Register Rtmp,
Label &profile_continue) {
assert(ProfileInterpreter, "must be profiling interpreter");
@@ -1400,8 +1397,8 @@
delayed()->nop();
// Build it now.
- call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), cur_bcp);
- set_method_data_pointer_offset(O0);
+ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+ set_method_data_pointer_for_bcp();
ba(false, profile_continue);
delayed()->nop();
bind(done);
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -269,12 +269,11 @@
#ifndef CC_INTERP
// Interpreter profiling operations
- void set_method_data_pointer() { set_method_data_pointer_offset(noreg); }
+ void set_method_data_pointer();
void set_method_data_pointer_for_bcp();
- void set_method_data_pointer_offset(Register mdi_reg);
void test_method_data_pointer(Label& zero_continue);
void verify_method_data_pointer();
- void test_invocation_counter_for_mdp(Register invocation_count, Register cur_bcp, Register Rtmp, Label &profile_continue);
+ void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
void set_mdp_data_at(int constant, Register value);
void increment_mdp_data_at(Address counter, Register bumped_count,
--- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -395,7 +395,7 @@
//
// Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls.
-void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
// Here is the register state during an interpreted call,
// as set up by generate_method_handle_interpreter_entry():
// - G5: garbage temp (was MethodHandle.invoke methodOop, unused)
@@ -447,8 +447,9 @@
// exception. Since we use a C2I adapter to set up the
// interpreter state, arguments are expected in compiler
// argument registers.
- methodHandle mh(raise_exception_method());
- address c2i_entry = methodOopDesc::make_adapters(mh, CATCH);
+ assert(raise_exception_method(), "must be set");
+ address c2i_entry = raise_exception_method()->get_c2i_entry();
+ assert(c2i_entry, "method must be linked");
__ mov(O5_savedSP, SP); // Cut the stack back to where the caller started.
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -575,7 +575,11 @@
int MachCallRuntimeNode::ret_addr_offset() {
#ifdef _LP64
- return NativeFarCall::instruction_size; // farcall; delay slot
+ if (MacroAssembler::is_far_target(entry_point())) {
+ return NativeFarCall::instruction_size;
+ } else {
+ return NativeCall::instruction_size;
+ }
#else
return NativeCall::instruction_size; // call; delay slot
#endif
@@ -941,7 +945,7 @@
#endif
}
-void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false, bool force_far_call = false) {
+void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false) {
// The method which records debug information at every safepoint
// expects the call to be the first instruction in the snippet as
// it creates a PcDesc structure which tracks the offset of a call
@@ -963,20 +967,7 @@
int startpos = __ offset();
#endif /* ASSERT */
-#ifdef _LP64
- // Calls to the runtime or native may not be reachable from compiled code,
- // so we generate the far call sequence on 64 bit sparc.
- // This code sequence is relocatable to any address, even on LP64.
- if ( force_far_call ) {
- __ relocate(rtype);
- AddressLiteral dest(entry_point);
- __ jumpl_to(dest, O7, O7);
- }
- else
-#endif
- {
- __ call((address)entry_point, rtype);
- }
+ __ call((address)entry_point, rtype);
if (preserve_g2) __ delayed()->mov(G2, L7);
else __ delayed()->nop();
@@ -2507,7 +2498,7 @@
// CALL directly to the runtime
// The user of this is responsible for ensuring that R_L7 is empty (killed).
emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type,
- /*preserve_g2=*/true, /*force far call*/true);
+ /*preserve_g2=*/true);
%}
enc_class preserve_SP %{
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1364,15 +1364,8 @@
// We have decided to profile this method in the interpreter
__ bind(profile_method);
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), Lbcp, true);
-
-#ifdef ASSERT
- __ tst(O0);
- __ breakpoint_trap(Assembler::notEqual);
-#endif
-
- __ set_method_data_pointer();
-
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+ __ set_method_data_pointer_for_bcp();
__ ba(false, profile_method_continue);
__ delayed()->nop();
}
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1689,7 +1689,7 @@
const Register G4_invoke_ctr = G4;
__ increment_backedge_counter(G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
- __ test_invocation_counter_for_mdp(G4_invoke_ctr, Lbcp, G3_scratch, Lforward);
+ __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
if (UseOnStackReplacement) {
__ test_backedge_count_for_osr(O2_bumped_count, O0_cur_bcp, G3_scratch);
}
@@ -3447,7 +3447,8 @@
__ delayed()->nop();
// bump total bytes allocated by this thread
- __ incr_allocated_bytes(Roffset, 0, G1_scratch);
+ // RoldTopValue and RtopAddr are dead, so can use G1 and G3
+ __ incr_allocated_bytes(Roffset, G1_scratch, G3_scratch);
}
if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
--- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1641,12 +1641,14 @@
}
void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
+ Register len = op->len()->as_register();
+ LP64_ONLY( __ movslq(len, len); )
+
if (UseSlowPath ||
(!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
(!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {
__ jmp(*op->stub()->entry());
} else {
- Register len = op->len()->as_register();
Register tmp1 = op->tmp1()->as_register();
Register tmp2 = op->tmp2()->as_register();
Register tmp3 = op->tmp3()->as_register();
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -62,7 +62,7 @@
// due to lack of optimization caused by C++ compiler bugs
define_pd_global(intx, StackShadowPages, SOLARIS_ONLY(20) NOT_SOLARIS(6) DEBUG_ONLY(+2));
#else
-define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
+define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+5));
#endif // AMD64
define_pd_global(intx, PreInflateSpin, 10);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -819,7 +819,7 @@
// Set the method data pointer for the current bcp.
void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
assert(ProfileInterpreter, "must be profiling interpreter");
- Label zero_continue;
+ Label set_mdp;
push(rax);
push(rbx);
@@ -827,21 +827,17 @@
// Test MDO to avoid the call if it is NULL.
movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
testptr(rax, rax);
- jcc(Assembler::zero, zero_continue);
-
+ jcc(Assembler::zero, set_mdp);
// rbx,: method
// rsi: bcp
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, rsi);
// rax,: mdi
-
+ // mdo is guaranteed to be non-zero here, we checked for it before the call.
movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
- testptr(rbx, rbx);
- jcc(Assembler::zero, zero_continue);
addptr(rbx, in_bytes(methodDataOopDesc::data_offset()));
- addptr(rbx, rax);
- movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx);
-
- bind(zero_continue);
+ addptr(rax, rbx);
+ bind(set_mdp);
+ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
pop(rbx);
pop(rax);
}
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -855,7 +855,7 @@
// Set the method data pointer for the current bcp.
void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
assert(ProfileInterpreter, "must be profiling interpreter");
- Label zero_continue;
+ Label set_mdp;
push(rax);
push(rbx);
@@ -863,21 +863,17 @@
// Test MDO to avoid the call if it is NULL.
movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
testptr(rax, rax);
- jcc(Assembler::zero, zero_continue);
-
+ jcc(Assembler::zero, set_mdp);
// rbx: method
// r13: bcp
call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), rbx, r13);
// rax: mdi
-
+ // mdo is guaranteed to be non-zero here, we checked for it before the call.
movptr(rbx, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
- testptr(rbx, rbx);
- jcc(Assembler::zero, zero_continue);
addptr(rbx, in_bytes(methodDataOopDesc::data_offset()));
- addptr(rbx, rax);
- movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rbx);
-
- bind(zero_continue);
+ addptr(rax, rbx);
+ bind(set_mdp);
+ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
pop(rbx);
pop(rax);
}
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -390,7 +390,7 @@
//
// Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls.
-void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek, TRAPS) {
+void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
// Here is the register state during an interpreted call,
// as set up by generate_method_handle_interpreter_entry():
// - rbx: garbage temp (was MethodHandle.invoke methodOop, unused)
@@ -451,8 +451,9 @@
// exception. Since we use a C2I adapter to set up the
// interpreter state, arguments are expected in compiler
// argument registers.
- methodHandle mh(raise_exception_method());
- address c2i_entry = methodOopDesc::make_adapters(mh, CHECK);
+ assert(raise_exception_method(), "must be set");
+ address c2i_entry = raise_exception_method()->get_c2i_entry();
+ assert(c2i_entry, "method must be linked");
const Register rdi_pc = rax;
__ pop(rdi_pc); // caller PC
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1367,15 +1367,9 @@
if (ProfileInterpreter) {
// We have decided to profile this method in the interpreter
__ bind(profile_method);
-
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi, true);
-
- __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop
- __ movptr(rax, Address(rbx, in_bytes(methodOopDesc::method_data_offset())));
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
- __ test_method_data_pointer(rax, profile_method_continue);
- __ addptr(rax, in_bytes(methodDataOopDesc::data_offset()));
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rax);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+ __ set_method_data_pointer_for_bcp();
+ __ get_method(rbx);
__ jmp(profile_method_continue);
}
// Handle overflow of counter and compile method
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1383,20 +1383,9 @@
if (ProfileInterpreter) {
// We have decided to profile this method in the interpreter
__ bind(profile_method);
-
- __ call_VM(noreg,
- CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method),
- r13, true);
-
- __ movptr(rbx, Address(rbp, method_offset)); // restore methodOop
- __ movptr(rax, Address(rbx,
- in_bytes(methodOopDesc::method_data_offset())));
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
- rax);
- __ test_method_data_pointer(rax, profile_method_continue);
- __ addptr(rax, in_bytes(methodDataOopDesc::data_offset()));
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
- rax);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
+ __ set_method_data_pointer_for_bcp();
+ __ get_method(rbx);
__ jmp(profile_method_continue);
}
// Handle overflow of counter and compile method
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1665,16 +1665,9 @@
if (ProfileInterpreter) {
// Out-of-line code to allocate method data oop.
__ bind(profile_method);
- __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method), rsi);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ load_unsigned_byte(rbx, Address(rsi, 0)); // restore target bytecode
- __ movptr(rcx, Address(rbp, method_offset));
- __ movptr(rcx, Address(rcx, in_bytes(methodOopDesc::method_data_offset())));
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx);
- __ test_method_data_pointer(rcx, dispatch);
- // offset non-null mdp by MDO::data_offset() + IR::profile_method()
- __ addptr(rcx, in_bytes(methodDataOopDesc::data_offset()));
- __ addptr(rcx, rax);
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize), rcx);
+ __ set_method_data_pointer_for_bcp();
__ jmp(dispatch);
}
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1695,21 +1695,9 @@
if (ProfileInterpreter) {
// Out-of-line code to allocate method data oop.
__ bind(profile_method);
- __ call_VM(noreg,
- CAST_FROM_FN_PTR(address,
- InterpreterRuntime::profile_method), r13);
+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
__ load_unsigned_byte(rbx, Address(r13, 0)); // restore target bytecode
- __ movptr(rcx, Address(rbp, method_offset));
- __ movptr(rcx, Address(rcx,
- in_bytes(methodOopDesc::method_data_offset())));
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
- rcx);
- __ test_method_data_pointer(rcx, dispatch);
- // offset non-null mdp by MDO::data_offset() + IR::profile_method()
- __ addptr(rcx, in_bytes(methodDataOopDesc::data_offset()));
- __ addptr(rcx, rax);
- __ movptr(Address(rbp, frame::interpreter_frame_mdx_offset * wordSize),
- rcx);
+ __ set_method_data_pointer_for_bcp();
__ jmp(dispatch);
}
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1610,10 +1610,9 @@
const char* os::dll_file_extension() { return ".so"; }
-const char* os::get_temp_directory() {
- const char *prop = Arguments::get_property("java.io.tmpdir");
- return prop == NULL ? "/tmp" : prop;
-}
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
+const char* os::get_temp_directory() { return "/tmp"; }
static bool file_exists(const char* filename) {
struct stat statbuf;
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1884,10 +1884,9 @@
const char* os::dll_file_extension() { return ".so"; }
-const char* os::get_temp_directory() {
- const char *prop = Arguments::get_property("java.io.tmpdir");
- return prop == NULL ? "/tmp" : prop;
-}
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
+const char* os::get_temp_directory() { return "/tmp"; }
static bool file_exists(const char* filename) {
struct stat statbuf;
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1044,9 +1044,9 @@
return 0;
}
+// This must be hard coded because it's the system's temporary
+// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() {
- const char *prop = Arguments::get_property("java.io.tmpdir");
- if (prop != 0) return prop;
static char path_buf[MAX_PATH];
if (GetTempPath(MAX_PATH, path_buf)>0)
return path_buf;
--- a/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/linux_sparc/vm/atomic_linux_sparc.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -54,6 +54,8 @@
inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
inline jint Atomic::add (jint add_value, volatile jint* dest) {
intptr_t rv;
__asm__ volatile(
--- a/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/atomic_linux_x86.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -100,11 +100,6 @@
return exchange_value;
}
-extern "C" {
- // defined in linux_x86.s
- jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
-}
-
#ifdef AMD64
inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
@@ -164,9 +159,9 @@
return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
}
-#else
-//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
-//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
+#else // !AMD64
inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) {
return (intptr_t)Atomic::add((jint)add_value, (volatile jint*)dest);
@@ -189,6 +184,12 @@
return (intptr_t)xchg((jint)exchange_value, (volatile jint*)dest);
}
+extern "C" {
+ // defined in linux_x86.s
+ jlong _Atomic_cmpxchg_long(jlong, volatile jlong*, jlong, bool);
+ void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
+}
+
inline jlong Atomic::cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value) {
return _Atomic_cmpxchg_long(exchange_value, dest, compare_value, os::is_MP());
}
@@ -200,6 +201,21 @@
inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}
+
+inline jlong Atomic::load(volatile jlong* src) {
+ volatile jlong dest;
+ _Atomic_move_long(src, &dest);
+ return dest;
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+ _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+ _Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
#endif // AMD64
#endif // OS_CPU_LINUX_X86_VM_ATOMIC_LINUX_X86_INLINE_HPP
--- a/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/linux_x86_32.s Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -38,6 +38,7 @@
.globl _mmx_Copy_arrayof_conjoint_jshorts
.globl _Atomic_cmpxchg_long
+ .globl _Atomic_move_long
.text
@@ -653,3 +654,15 @@
popl %ebx
ret
+
+ # Support for jlong Atomic::load and Atomic::store.
+ # void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
+ .p2align 4,,15
+ .type _Atomic_move_long,@function
+_Atomic_move_long:
+ movl 4(%esp), %eax # src
+ fildll (%eax)
+ movl 8(%esp), %eax # dest
+ fistpll (%eax)
+ ret
+
--- a/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -25,6 +25,7 @@
#ifndef OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
#define OS_CPU_LINUX_X86_VM_ORDERACCESS_LINUX_X86_INLINE_HPP
+#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "vm_version_x86.hpp"
@@ -64,11 +65,11 @@
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
-inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
+inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
-inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
+inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@@ -79,11 +80,11 @@
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
-inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
+inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
-inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
+inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@@ -178,7 +179,7 @@
: "0" (v), "r" (p)
: "memory");
#else
- *p = v; fence();
+ release_store(p, v); fence();
#endif // AMD64
}
--- a/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -35,14 +35,12 @@
inline void Atomic::store (jbyte store_value, jbyte* dest) { *dest = store_value; }
inline void Atomic::store (jshort store_value, jshort* dest) { *dest = store_value; }
inline void Atomic::store (jint store_value, jint* dest) { *dest = store_value; }
-inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
inline void Atomic::store_ptr(intptr_t store_value, intptr_t* dest) { *dest = store_value; }
inline void Atomic::store_ptr(void* store_value, void* dest) { *(void**)dest = store_value; }
inline void Atomic::store (jbyte store_value, volatile jbyte* dest) { *dest = store_value; }
inline void Atomic::store (jshort store_value, volatile jshort* dest) { *dest = store_value; }
inline void Atomic::store (jint store_value, volatile jint* dest) { *dest = store_value; }
-inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline void Atomic::store_ptr(intptr_t store_value, volatile intptr_t* dest) { *dest = store_value; }
inline void Atomic::store_ptr(void* store_value, volatile void* dest) { *(void* volatile *)dest = store_value; }
@@ -54,8 +52,49 @@
inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); }
inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); }
+
+#ifdef _LP64
+
+inline void Atomic::store(jlong store_value, jlong* dest) { *dest = store_value; }
+inline void Atomic::store(jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline jlong Atomic::load(volatile jlong* src) { return *src; }
+#else
+
+extern "C" void _Atomic_move_long_v8(volatile jlong* src, volatile jlong* dst);
+extern "C" void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst);
+
+inline void Atomic_move_long(volatile jlong* src, volatile jlong* dst) {
+#ifdef COMPILER2
+ // Compiler2 does not support v8, it is used only for v9.
+ assert (VM_Version::v9_instructions_work(), "only supported on v9");
+ _Atomic_move_long_v9(src, dst);
+#else
+ // The branch is cheaper then emulated LDD.
+ if (VM_Version::v9_instructions_work()) {
+ _Atomic_move_long_v9(src, dst);
+ } else {
+ _Atomic_move_long_v8(src, dst);
+ }
+#endif
+}
+
+inline jlong Atomic::load(volatile jlong* src) {
+ volatile jlong dest;
+ Atomic_move_long(src, &dest);
+ return dest;
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+ Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+ Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
+#endif
+
#ifdef _GNU_SOURCE
inline jint Atomic::add (jint add_value, volatile jint* dest) {
--- a/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/orderAccess_solaris_sparc.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -77,11 +77,11 @@
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
-inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
+inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
-inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
+inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@@ -92,11 +92,11 @@
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
-inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
+inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
-inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
+inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@@ -120,11 +120,11 @@
inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); }
-inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); }
+inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); }
-inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); }
+inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
--- a/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/solaris_sparc.il Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2002, 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
@@ -152,6 +152,39 @@
.nonvolatile
.end
+ // Support for jlong Atomic::load and Atomic::store on v8.
+ //
+ // void _Atomic_move_long_v8(volatile jlong* src, volatile jlong* dst)
+ //
+ // Arguments:
+ // src: O0
+ // dest: O1
+ //
+ // Overwrites O2 and O3
+
+ .inline _Atomic_move_long_v8,2
+ .volatile
+ ldd [%o0], %o2
+ std %o2, [%o1]
+ .nonvolatile
+ .end
+
+ // Support for jlong Atomic::load and Atomic::store on v9.
+ //
+ // void _Atomic_move_long_v9(volatile jlong* src, volatile jlong* dst)
+ //
+ // Arguments:
+ // src: O0
+ // dest: O1
+ //
+ // Overwrites O2
+
+ .inline _Atomic_move_long_v9,2
+ .volatile
+ ldx [%o0], %o2
+ stx %o2, [%o1]
+ .nonvolatile
+ .end
// Support for jint Atomic::add(jint add_value, volatile jint* dest).
//
--- a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -151,14 +151,22 @@
return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}
-extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst);
+extern "C" void _Atomic_move_long(volatile jlong* src, volatile jlong* dst);
inline jlong Atomic::load(volatile jlong* src) {
volatile jlong dest;
- _Atomic_load_long(src, &dest);
+ _Atomic_move_long(src, &dest);
return dest;
}
+inline void Atomic::store(jlong store_value, jlong* dest) {
+ _Atomic_move_long((volatile jlong*)&store_value, (volatile jlong*)dest);
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+ _Atomic_move_long((volatile jlong*)&store_value, dest);
+}
+
#endif // AMD64
#ifdef _GNU_SOURCE
--- a/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/orderAccess_solaris_x86.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -25,6 +25,7 @@
#ifndef OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
#define OS_CPU_SOLARIS_X86_VM_ORDERACCESS_SOLARIS_X86_INLINE_HPP
+#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "vm_version_x86.hpp"
@@ -80,11 +81,11 @@
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
-inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
+inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
-inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
+inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@@ -95,11 +96,11 @@
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
-inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
+inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
-inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
+inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@@ -123,11 +124,11 @@
inline void OrderAccess::release_store_fence(volatile jbyte* p, jbyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jshort* p, jshort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jint* p, jint v) { *p = v; fence(); }
-inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); }
+inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile juint* p, juint v) { *p = v; fence(); }
-inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { *p = v; fence(); }
+inline void OrderAccess::release_store_fence(volatile julong* p, julong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jfloat* p, jfloat v) { *p = v; fence(); }
inline void OrderAccess::release_store_fence(volatile jdouble* p, jdouble v) { *p = v; fence(); }
--- a/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/solaris_x86/vm/solaris_x86_32.il Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -104,8 +104,9 @@
popl %ebx
.end
- // Support for void Atomic::load(volatile jlong* src, volatile jlong* dest).
- .inline _Atomic_load_long,2
+ // Support for jlong Atomic::load and Atomic::store.
+ // void _Atomic_move_long(volatile jlong* src, volatile jlong* dst)
+ .inline _Atomic_move_long,2
movl 0(%esp), %eax // src
fildll (%eax)
movl 4(%esp), %eax // dest
--- a/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/windows_x86/vm/atomic_windows_x86.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -137,10 +137,10 @@
return (void*)cmpxchg((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value);
}
+inline jlong Atomic::load(volatile jlong* src) { return *src; }
+
#else // !AMD64
-//inline void Atomic::store (jlong store_value, jlong* dest) { *dest = store_value; }
-//inline void Atomic::store (jlong store_value, volatile jlong* dest) { *dest = store_value; }
inline jint Atomic::add (jint add_value, volatile jint* dest) {
int mp = os::is_MP();
__asm {
@@ -254,6 +254,33 @@
inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) {
return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value);
}
+
+inline jlong Atomic::load(volatile jlong* src) {
+ volatile jlong dest;
+ volatile jlong* pdest = &dest;
+ __asm {
+ mov eax, src
+ fild qword ptr [eax]
+ mov eax, pdest
+ fistp qword ptr [eax]
+ }
+ return dest;
+}
+
+inline void Atomic::store(jlong store_value, volatile jlong* dest) {
+ volatile jlong* src = &store_value;
+ __asm {
+ mov eax, src
+ fild qword ptr [eax]
+ mov eax, dest
+ fistp qword ptr [eax]
+ }
+}
+
+inline void Atomic::store(jlong store_value, jlong* dest) {
+ Atomic::store(store_value, (volatile jlong*)dest);
+}
+
#endif // AMD64
#pragma warning(default: 4035) // Enables warnings reporting missing return statement
--- a/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/os_cpu/windows_x86/vm/orderAccess_windows_x86.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -25,6 +25,7 @@
#ifndef OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
#define OS_CPU_WINDOWS_X86_VM_ORDERACCESS_WINDOWS_X86_INLINE_HPP
+#include "runtime/atomic.hpp"
#include "runtime/orderAccess.hpp"
#include "vm_version_x86.hpp"
@@ -65,11 +66,11 @@
inline jbyte OrderAccess::load_acquire(volatile jbyte* p) { return *p; }
inline jshort OrderAccess::load_acquire(volatile jshort* p) { return *p; }
inline jint OrderAccess::load_acquire(volatile jint* p) { return *p; }
-inline jlong OrderAccess::load_acquire(volatile jlong* p) { return *p; }
+inline jlong OrderAccess::load_acquire(volatile jlong* p) { return Atomic::load(p); }
inline jubyte OrderAccess::load_acquire(volatile jubyte* p) { return *p; }
inline jushort OrderAccess::load_acquire(volatile jushort* p) { return *p; }
inline juint OrderAccess::load_acquire(volatile juint* p) { return *p; }
-inline julong OrderAccess::load_acquire(volatile julong* p) { return *p; }
+inline julong OrderAccess::load_acquire(volatile julong* p) { return Atomic::load((volatile jlong*)p); }
inline jfloat OrderAccess::load_acquire(volatile jfloat* p) { return *p; }
inline jdouble OrderAccess::load_acquire(volatile jdouble* p) { return *p; }
@@ -80,11 +81,11 @@
inline void OrderAccess::release_store(volatile jbyte* p, jbyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jshort* p, jshort v) { *p = v; }
inline void OrderAccess::release_store(volatile jint* p, jint v) { *p = v; }
-inline void OrderAccess::release_store(volatile jlong* p, jlong v) { *p = v; }
+inline void OrderAccess::release_store(volatile jlong* p, jlong v) { Atomic::store(v, p); }
inline void OrderAccess::release_store(volatile jubyte* p, jubyte v) { *p = v; }
inline void OrderAccess::release_store(volatile jushort* p, jushort v) { *p = v; }
inline void OrderAccess::release_store(volatile juint* p, juint v) { *p = v; }
-inline void OrderAccess::release_store(volatile julong* p, julong v) { *p = v; }
+inline void OrderAccess::release_store(volatile julong* p, julong v) { Atomic::store((jlong)v, (volatile jlong*)p); }
inline void OrderAccess::release_store(volatile jfloat* p, jfloat v) { *p = v; }
inline void OrderAccess::release_store(volatile jdouble* p, jdouble v) { *p = v; }
@@ -188,7 +189,7 @@
#endif // AMD64
}
-inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { *p = v; fence(); }
+inline void OrderAccess::release_store_fence(volatile jlong* p, jlong v) { release_store(p, v); fence(); }
inline void OrderAccess::release_store_fence(volatile jubyte* p, jubyte v) { release_store_fence((volatile jbyte*)p, (jbyte)v); }
inline void OrderAccess::release_store_fence(volatile jushort* p, jushort v) { release_store_fence((volatile jshort*)p, (jshort)v); }
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -319,24 +319,24 @@
case Bytecodes::_tableswitch: {
// set block for each case
- Bytecode_tableswitch *switch_ = Bytecode_tableswitch_at(s.cur_bcp());
- int l = switch_->length();
+ Bytecode_tableswitch sw(&s);
+ int l = sw.length();
for (int i = 0; i < l; i++) {
- make_block_at(cur_bci + switch_->dest_offset_at(i), current);
+ make_block_at(cur_bci + sw.dest_offset_at(i), current);
}
- make_block_at(cur_bci + switch_->default_offset(), current);
+ make_block_at(cur_bci + sw.default_offset(), current);
current = NULL;
break;
}
case Bytecodes::_lookupswitch: {
// set block for each case
- Bytecode_lookupswitch *switch_ = Bytecode_lookupswitch_at(s.cur_bcp());
- int l = switch_->number_of_pairs();
+ Bytecode_lookupswitch sw(&s);
+ int l = sw.number_of_pairs();
for (int i = 0; i < l; i++) {
- make_block_at(cur_bci + switch_->pair_at(i)->offset(), current);
+ make_block_at(cur_bci + sw.pair_at(i).offset(), current);
}
- make_block_at(cur_bci + switch_->default_offset(), current);
+ make_block_at(cur_bci + sw.default_offset(), current);
current = NULL;
break;
}
@@ -1275,15 +1275,15 @@
void GraphBuilder::table_switch() {
- Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(method()->code() + bci());
- const int l = switch_->length();
+ Bytecode_tableswitch sw(stream());
+ const int l = sw.length();
if (CanonicalizeNodes && l == 1) {
// total of 2 successors => use If instead of switch
// Note: This code should go into the canonicalizer as soon as it can
// can handle canonicalized forms that contain more than one node.
- Value key = append(new Constant(new IntConstant(switch_->low_key())));
- BlockBegin* tsux = block_at(bci() + switch_->dest_offset_at(0));
- BlockBegin* fsux = block_at(bci() + switch_->default_offset());
+ Value key = append(new Constant(new IntConstant(sw.low_key())));
+ BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
+ BlockBegin* fsux = block_at(bci() + sw.default_offset());
bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
ValueStack* state_before = is_bb ? copy_state_before() : NULL;
append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
@@ -1293,29 +1293,29 @@
int i;
bool has_bb = false;
for (i = 0; i < l; i++) {
- sux->at_put(i, block_at(bci() + switch_->dest_offset_at(i)));
- if (switch_->dest_offset_at(i) < 0) has_bb = true;
+ sux->at_put(i, block_at(bci() + sw.dest_offset_at(i)));
+ if (sw.dest_offset_at(i) < 0) has_bb = true;
}
// add default successor
- sux->at_put(i, block_at(bci() + switch_->default_offset()));
+ sux->at_put(i, block_at(bci() + sw.default_offset()));
ValueStack* state_before = has_bb ? copy_state_before() : NULL;
- append(new TableSwitch(ipop(), sux, switch_->low_key(), state_before, has_bb));
+ append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
}
}
void GraphBuilder::lookup_switch() {
- Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(method()->code() + bci());
- const int l = switch_->number_of_pairs();
+ Bytecode_lookupswitch sw(stream());
+ const int l = sw.number_of_pairs();
if (CanonicalizeNodes && l == 1) {
// total of 2 successors => use If instead of switch
// Note: This code should go into the canonicalizer as soon as it can
// can handle canonicalized forms that contain more than one node.
// simplify to If
- LookupswitchPair* pair = switch_->pair_at(0);
- Value key = append(new Constant(new IntConstant(pair->match())));
- BlockBegin* tsux = block_at(bci() + pair->offset());
- BlockBegin* fsux = block_at(bci() + switch_->default_offset());
+ LookupswitchPair pair = sw.pair_at(0);
+ Value key = append(new Constant(new IntConstant(pair.match())));
+ BlockBegin* tsux = block_at(bci() + pair.offset());
+ BlockBegin* fsux = block_at(bci() + sw.default_offset());
bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
ValueStack* state_before = is_bb ? copy_state_before() : NULL;
append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
@@ -1326,13 +1326,13 @@
int i;
bool has_bb = false;
for (i = 0; i < l; i++) {
- LookupswitchPair* pair = switch_->pair_at(i);
- if (pair->offset() < 0) has_bb = true;
- sux->at_put(i, block_at(bci() + pair->offset()));
- keys->at_put(i, pair->match());
+ LookupswitchPair pair = sw.pair_at(i);
+ if (pair.offset() < 0) has_bb = true;
+ sux->at_put(i, block_at(bci() + pair.offset()));
+ keys->at_put(i, pair.match());
}
// add default successor
- sux->at_put(i, block_at(bci() + switch_->default_offset()));
+ sux->at_put(i, block_at(bci() + sw.default_offset()));
ValueStack* state_before = has_bb ? copy_state_before() : NULL;
append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
}
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1990,9 +1990,8 @@
LIR_Opr reg = reg = rlock_result(x, x->basic_type());
+ get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile());
if (x->is_volatile() && os::is_MP()) __ membar_acquire();
- get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile());
- if (x->is_volatile() && os::is_MP()) __ membar();
}
@@ -2014,6 +2013,7 @@
if (x->is_volatile() && os::is_MP()) __ membar_release();
put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile());
+ if (x->is_volatile() && os::is_MP()) __ membar();
}
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -369,7 +369,7 @@
if (branch_bci != InvocationEntryBci) {
// Compute desination bci
address pc = method()->code_base() + branch_bci;
- Bytecodes::Code branch = Bytecodes::code_at(pc, method());
+ Bytecodes::Code branch = Bytecodes::code_at(method(), pc);
int offset = 0;
switch (branch) {
case Bytecodes::_if_icmplt: case Bytecodes::_iflt:
@@ -659,14 +659,14 @@
static klassOop resolve_field_return_klass(methodHandle caller, int bci, TRAPS) {
- Bytecode_field* field_access = Bytecode_field_at(caller, bci);
+ Bytecode_field field_access(caller, bci);
// This can be static or non-static field access
- Bytecodes::Code code = field_access->code();
+ Bytecodes::Code code = field_access.code();
// We must load class, initialize class and resolvethe field
FieldAccessInfo result; // initialize class if needed
constantPoolHandle constants(THREAD, caller->constants());
- LinkResolver::resolve_field(result, constants, field_access->index(), Bytecodes::java_code(code), false, CHECK_NULL);
+ LinkResolver::resolve_field(result, constants, field_access.index(), Bytecodes::java_code(code), false, CHECK_NULL);
return result.klass()();
}
@@ -767,7 +767,7 @@
Events::log("patch_code @ " INTPTR_FORMAT , caller_frame.pc());
- Bytecodes::Code code = Bytecode_at(caller_method->bcp_from(bci))->java_code();
+ Bytecodes::Code code = caller_method()->java_code_at(bci);
#ifndef PRODUCT
// this is used by assertions in the access_field_patching_id
@@ -779,11 +779,11 @@
Handle load_klass(THREAD, NULL); // oop needed by load_klass_patching code
if (stub_id == Runtime1::access_field_patching_id) {
- Bytecode_field* field_access = Bytecode_field_at(caller_method, bci);
+ Bytecode_field field_access(caller_method, bci);
FieldAccessInfo result; // initialize class if needed
- Bytecodes::Code code = field_access->code();
+ Bytecodes::Code code = field_access.code();
constantPoolHandle constants(THREAD, caller_method->constants());
- LinkResolver::resolve_field(result, constants, field_access->index(), Bytecodes::java_code(code), false, CHECK);
+ LinkResolver::resolve_field(result, constants, field_access.index(), Bytecodes::java_code(code), false, CHECK);
patch_field_offset = result.field_offset();
// If we're patching a field which is volatile then at compile it
@@ -811,36 +811,36 @@
}
break;
case Bytecodes::_new:
- { Bytecode_new* bnew = Bytecode_new_at(caller_method->bcp_from(bci));
- k = caller_method->constants()->klass_at(bnew->index(), CHECK);
+ { Bytecode_new bnew(caller_method(), caller_method->bcp_from(bci));
+ k = caller_method->constants()->klass_at(bnew.index(), CHECK);
}
break;
case Bytecodes::_multianewarray:
- { Bytecode_multianewarray* mna = Bytecode_multianewarray_at(caller_method->bcp_from(bci));
- k = caller_method->constants()->klass_at(mna->index(), CHECK);
+ { Bytecode_multianewarray mna(caller_method(), caller_method->bcp_from(bci));
+ k = caller_method->constants()->klass_at(mna.index(), CHECK);
}
break;
case Bytecodes::_instanceof:
- { Bytecode_instanceof* io = Bytecode_instanceof_at(caller_method->bcp_from(bci));
- k = caller_method->constants()->klass_at(io->index(), CHECK);
+ { Bytecode_instanceof io(caller_method(), caller_method->bcp_from(bci));
+ k = caller_method->constants()->klass_at(io.index(), CHECK);
}
break;
case Bytecodes::_checkcast:
- { Bytecode_checkcast* cc = Bytecode_checkcast_at(caller_method->bcp_from(bci));
- k = caller_method->constants()->klass_at(cc->index(), CHECK);
+ { Bytecode_checkcast cc(caller_method(), caller_method->bcp_from(bci));
+ k = caller_method->constants()->klass_at(cc.index(), CHECK);
}
break;
case Bytecodes::_anewarray:
- { Bytecode_anewarray* anew = Bytecode_anewarray_at(caller_method->bcp_from(bci));
- klassOop ek = caller_method->constants()->klass_at(anew->index(), CHECK);
+ { Bytecode_anewarray anew(caller_method(), caller_method->bcp_from(bci));
+ klassOop ek = caller_method->constants()->klass_at(anew.index(), CHECK);
k = Klass::cast(ek)->array_klass(CHECK);
}
break;
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
{
- Bytecode_loadconstant* cc = Bytecode_loadconstant_at(caller_method, bci);
- k = cc->resolve_constant(CHECK);
+ Bytecode_loadconstant cc(caller_method, bci);
+ k = cc.resolve_constant(CHECK);
assert(k != NULL && !k->is_klass(), "must be class mirror or other Java constant");
}
break;
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -761,15 +761,15 @@
case Bytecodes::_tableswitch:
{
state.spop();
- Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp());
- int len = switch_->length();
+ Bytecode_tableswitch sw(&s);
+ int len = sw.length();
int dest_bci;
for (int i = 0; i < len; i++) {
- dest_bci = s.cur_bci() + switch_->dest_offset_at(i);
+ dest_bci = s.cur_bci() + sw.dest_offset_at(i);
assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
successors.push(_methodBlocks->block_containing(dest_bci));
}
- dest_bci = s.cur_bci() + switch_->default_offset();
+ dest_bci = s.cur_bci() + sw.default_offset();
assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
successors.push(_methodBlocks->block_containing(dest_bci));
assert(s.next_bci() == limit_bci, "branch must end block");
@@ -779,15 +779,15 @@
case Bytecodes::_lookupswitch:
{
state.spop();
- Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp());
- int len = switch_->number_of_pairs();
+ Bytecode_lookupswitch sw(&s);
+ int len = sw.number_of_pairs();
int dest_bci;
for (int i = 0; i < len; i++) {
- dest_bci = s.cur_bci() + switch_->pair_at(i)->offset();
+ dest_bci = s.cur_bci() + sw.pair_at(i).offset();
assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
successors.push(_methodBlocks->block_containing(dest_bci));
}
- dest_bci = s.cur_bci() + switch_->default_offset();
+ dest_bci = s.cur_bci() + sw.default_offset();
assert(_methodBlocks->is_block_start(dest_bci), "branch destination must start a block");
successors.push(_methodBlocks->block_containing(dest_bci));
fall_through = false;
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -409,15 +409,15 @@
} else {
fail_type = _unloaded_ciinstance_klass;
}
- klassOop found_klass;
+ KlassHandle found_klass;
if (!require_local) {
- found_klass =
- SystemDictionary::find_constrained_instance_or_array_klass(sym, loader,
- KILL_COMPILE_ON_FATAL_(fail_type));
+ klassOop kls = SystemDictionary::find_constrained_instance_or_array_klass(
+ sym, loader, KILL_COMPILE_ON_FATAL_(fail_type));
+ found_klass = KlassHandle(THREAD, kls);
} else {
- found_klass =
- SystemDictionary::find_instance_or_array_klass(sym, loader, domain,
- KILL_COMPILE_ON_FATAL_(fail_type));
+ klassOop kls = SystemDictionary::find_instance_or_array_klass(
+ sym, loader, domain, KILL_COMPILE_ON_FATAL_(fail_type));
+ found_klass = KlassHandle(THREAD, kls);
}
// If we fail to find an array klass, look again for its element type.
@@ -444,9 +444,9 @@
}
}
- if (found_klass != NULL) {
+ if (found_klass() != NULL) {
// Found it. Build a CI handle.
- return get_object(found_klass)->as_klass();
+ return get_object(found_klass())->as_klass();
}
if (require_local) return NULL;
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -144,7 +144,7 @@
Bytecodes::Code java_code_at_bci(int bci) {
address bcp = code() + bci;
- return Bytecodes::java_code_at(bcp);
+ return Bytecodes::java_code_at(NULL, bcp);
}
BCEscapeAnalyzer *get_bcea();
ciMethodBlocks *get_method_blocks();
--- a/hotspot/src/share/vm/ci/ciMethodBlocks.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/ciMethodBlocks.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2010, 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
@@ -175,15 +175,15 @@
case Bytecodes::_tableswitch :
{
cur_block->set_control_bci(bci);
- Bytecode_tableswitch* switch_ = Bytecode_tableswitch_at(s.cur_bcp());
- int len = switch_->length();
+ Bytecode_tableswitch sw(&s);
+ int len = sw.length();
ciBlock *dest;
int dest_bci;
for (int i = 0; i < len; i++) {
- dest_bci = s.cur_bci() + switch_->dest_offset_at(i);
+ dest_bci = s.cur_bci() + sw.dest_offset_at(i);
dest = make_block_at(dest_bci);
}
- dest_bci = s.cur_bci() + switch_->default_offset();
+ dest_bci = s.cur_bci() + sw.default_offset();
make_block_at(dest_bci);
if (s.next_bci() < limit_bci) {
dest = make_block_at(s.next_bci());
@@ -194,15 +194,15 @@
case Bytecodes::_lookupswitch:
{
cur_block->set_control_bci(bci);
- Bytecode_lookupswitch* switch_ = Bytecode_lookupswitch_at(s.cur_bcp());
- int len = switch_->number_of_pairs();
+ Bytecode_lookupswitch sw(&s);
+ int len = sw.number_of_pairs();
ciBlock *dest;
int dest_bci;
for (int i = 0; i < len; i++) {
- dest_bci = s.cur_bci() + switch_->pair_at(i)->offset();
+ dest_bci = s.cur_bci() + sw.pair_at(i).offset();
dest = make_block_at(dest_bci);
}
- dest_bci = s.cur_bci() + switch_->default_offset();
+ dest_bci = s.cur_bci() + sw.default_offset();
dest = make_block_at(dest_bci);
if (s.next_bci() < limit_bci) {
dest = make_block_at(s.next_bci());
--- a/hotspot/src/share/vm/ci/ciMethodHandle.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/ciMethodHandle.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -38,11 +38,12 @@
// Return an adapter for this MethodHandle.
ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
VM_ENTRY_MARK;
-
Handle h(get_oop());
methodHandle callee(_callee->get_methodOop());
- MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
- methodHandle m = mhc.compile(CHECK_NULL);
+ // We catch all exceptions here that could happen in the method
+ // handle compiler and stop the VM.
+ MethodHandleCompiler mhc(h, callee, is_invokedynamic, CATCH);
+ methodHandle m = mhc.compile(CATCH);
return CURRENT_ENV->get_object(m())->as_method();
}
--- a/hotspot/src/share/vm/ci/ciStreams.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -78,8 +78,8 @@
else { assert(!is_wide(), "must not be a wide instruction"); }
}
- Bytecode* bytecode() const { return Bytecode_at(_bc_start); }
- Bytecode* next_bytecode() const { return Bytecode_at(_pc); }
+ Bytecode bytecode() const { return Bytecode(this, _bc_start); }
+ Bytecode next_bytecode() const { return Bytecode(this, _pc); }
public:
// End-Of-Bytecodes
@@ -151,11 +151,11 @@
bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
int get_index_u1() const {
- return bytecode()->get_index_u1(cur_bc_raw());
+ return bytecode().get_index_u1(cur_bc_raw());
}
int get_index_u1_cpcache() const {
- return bytecode()->get_index_u1_cpcache(cur_bc_raw());
+ return bytecode().get_index_u1_cpcache(cur_bc_raw());
}
// Get a byte index following this bytecode.
@@ -169,29 +169,29 @@
// Get 2-byte index (byte swapping depending on which bytecode)
int get_index_u2(bool is_wide = false) const {
- return bytecode()->get_index_u2(cur_bc_raw(), is_wide);
+ return bytecode().get_index_u2(cur_bc_raw(), is_wide);
}
// Get 2-byte index in native byte order. (Rewriter::rewrite makes these.)
int get_index_u2_cpcache() const {
- return bytecode()->get_index_u2_cpcache(cur_bc_raw());
+ return bytecode().get_index_u2_cpcache(cur_bc_raw());
}
// Get 4-byte index, for invokedynamic.
int get_index_u4() const {
- return bytecode()->get_index_u4(cur_bc_raw());
+ return bytecode().get_index_u4(cur_bc_raw());
}
bool has_index_u4() const {
- return bytecode()->has_index_u4(cur_bc_raw());
+ return bytecode().has_index_u4(cur_bc_raw());
}
// Get dimensions byte (multinewarray)
int get_dimensions() const { return *(unsigned char*)(_pc-1); }
// Sign-extended index byte/short, no widening
- int get_constant_u1() const { return bytecode()->get_constant_u1(instruction_size()-1, cur_bc_raw()); }
- int get_constant_u2(bool is_wide = false) const { return bytecode()->get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); }
+ int get_constant_u1() const { return bytecode().get_constant_u1(instruction_size()-1, cur_bc_raw()); }
+ int get_constant_u2(bool is_wide = false) const { return bytecode().get_constant_u2(instruction_size()-2, cur_bc_raw(), is_wide); }
// Get a byte signed constant for "iinc". Invalid for other bytecodes.
// If prefixed with a wide bytecode, get a wide constant
@@ -199,18 +199,18 @@
// 2-byte branch offset from current pc
int get_dest() const {
- return cur_bci() + bytecode()->get_offset_s2(cur_bc_raw());
+ return cur_bci() + bytecode().get_offset_s2(cur_bc_raw());
}
// 2-byte branch offset from next pc
int next_get_dest() const {
assert(_pc < _end, "");
- return next_bci() + next_bytecode()->get_offset_s2(Bytecodes::_ifeq);
+ return next_bci() + next_bytecode().get_offset_s2(Bytecodes::_ifeq);
}
// 4-byte branch offset from current pc
int get_far_dest() const {
- return cur_bci() + bytecode()->get_offset_s4(cur_bc_raw());
+ return cur_bci() + bytecode().get_offset_s4(cur_bc_raw());
}
// For a lookup or switch table, return target destination
@@ -407,4 +407,11 @@
}
};
+
+
+// Implementation for declarations in bytecode.hpp
+Bytecode::Bytecode(const ciBytecodeStream* stream, address bcp): _bcp(bcp != NULL ? bcp : stream->cur_bcp()), _code(Bytecodes::code_at(NULL, addr_at(0))) {}
+Bytecode_lookupswitch::Bytecode_lookupswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); }
+Bytecode_tableswitch::Bytecode_tableswitch(const ciBytecodeStream* stream): Bytecode(stream) { verify(); }
+
#endif // SHARE_VM_CI_CISTREAMS_HPP
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1698,18 +1698,17 @@
break;
case Bytecodes::_tableswitch: {
- Bytecode_tableswitch *tableswitch =
- Bytecode_tableswitch_at(str->cur_bcp());
+ Bytecode_tableswitch tableswitch(str);
- int len = tableswitch->length();
+ int len = tableswitch.length();
_successors =
new (arena) GrowableArray<Block*>(arena, len+1, 0, NULL);
- int bci = current_bci + tableswitch->default_offset();
+ int bci = current_bci + tableswitch.default_offset();
Block* block = analyzer->block_at(bci, jsrs);
assert(_successors->length() == SWITCH_DEFAULT, "");
_successors->append(block);
while (--len >= 0) {
- int bci = current_bci + tableswitch->dest_offset_at(len);
+ int bci = current_bci + tableswitch.dest_offset_at(len);
block = analyzer->block_at(bci, jsrs);
assert(_successors->length() >= SWITCH_CASES, "");
_successors->append_if_missing(block);
@@ -1718,19 +1717,18 @@
}
case Bytecodes::_lookupswitch: {
- Bytecode_lookupswitch *lookupswitch =
- Bytecode_lookupswitch_at(str->cur_bcp());
+ Bytecode_lookupswitch lookupswitch(str);
- int npairs = lookupswitch->number_of_pairs();
+ int npairs = lookupswitch.number_of_pairs();
_successors =
new (arena) GrowableArray<Block*>(arena, npairs+1, 0, NULL);
- int bci = current_bci + lookupswitch->default_offset();
+ int bci = current_bci + lookupswitch.default_offset();
Block* block = analyzer->block_at(bci, jsrs);
assert(_successors->length() == SWITCH_DEFAULT, "");
_successors->append(block);
while(--npairs >= 0) {
- LookupswitchPair *pair = lookupswitch->pair_at(npairs);
- int bci = current_bci + pair->offset();
+ LookupswitchPair pair = lookupswitch.pair_at(npairs);
+ int bci = current_bci + pair.offset();
Block* block = analyzer->block_at(bci, jsrs);
assert(_successors->length() >= SWITCH_CASES, "");
_successors->append_if_missing(block);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1382,3 +1382,61 @@
}
#endif //PRODUCT
+
+// Please keep following two functions at end of this file. With them placed at top or in middle of the file,
+// they could get inlined by agressive compiler, an unknown trick, see bug 6966589.
+void PerfClassTraceTime::initialize() {
+ if (!UsePerfData) return;
+
+ if (_eventp != NULL) {
+ // increment the event counter
+ _eventp->inc();
+ }
+
+ // stop the current active thread-local timer to measure inclusive time
+ _prev_active_event = -1;
+ for (int i=0; i < EVENT_TYPE_COUNT; i++) {
+ if (_timers[i].is_active()) {
+ assert(_prev_active_event == -1, "should have only one active timer");
+ _prev_active_event = i;
+ _timers[i].stop();
+ }
+ }
+
+ if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) {
+ // start the inclusive timer if not recursively called
+ _t.start();
+ }
+
+ // start thread-local timer of the given event type
+ if (!_timers[_event_type].is_active()) {
+ _timers[_event_type].start();
+ }
+}
+
+PerfClassTraceTime::~PerfClassTraceTime() {
+ if (!UsePerfData) return;
+
+ // stop the thread-local timer as the event completes
+ // and resume the thread-local timer of the event next on the stack
+ _timers[_event_type].stop();
+ jlong selftime = _timers[_event_type].ticks();
+
+ if (_prev_active_event >= 0) {
+ _timers[_prev_active_event].start();
+ }
+
+ if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return;
+
+ // increment the counters only on the leaf call
+ _t.stop();
+ _timep->inc(_t.ticks());
+ if (_selftimep != NULL) {
+ _selftimep->inc(selftime);
+ }
+ // add all class loading related event selftime to the accumulated time counter
+ ClassLoader::perf_accumulated_time()->inc(selftime);
+
+ // reset the timer
+ _timers[_event_type].reset();
+}
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -356,111 +356,57 @@
// (i.e. only one event type) are active at a time even multiple PerfClassTraceTime
// instances have been created as multiple events are happening.
class PerfClassTraceTime {
- public:
- enum {
- CLASS_LOAD = 0,
- PARSE_CLASS = 1,
- CLASS_LINK = 2,
- CLASS_VERIFY = 3,
- CLASS_CLINIT = 4,
- DEFINE_CLASS = 5,
- EVENT_TYPE_COUNT = 6
- };
- protected:
- // _t tracks time from initialization to destruction of this timer instance
- // including time for all other event types, and recursive calls of this type.
- // When a timer is called recursively, the elapsedTimer _t would not be used.
- elapsedTimer _t;
- PerfLongCounter* _timep;
- PerfLongCounter* _selftimep;
- PerfLongCounter* _eventp;
- // pointer to thread-local recursion counter and timer array
- // The thread_local timers track cumulative time for specific event types
- // exclusive of time for other event types, but including recursive calls
- // of the same type.
- int* _recursion_counters;
- elapsedTimer* _timers;
- int _event_type;
- int _prev_active_event;
-
- public:
-
- inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */
- PerfLongCounter* selftimep, /* counter incremented with exclusive time */
- PerfLongCounter* eventp, /* event counter */
- int* recursion_counters, /* thread-local recursion counter array */
- elapsedTimer* timers, /* thread-local timer array */
- int type /* event type */ ) :
- _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) {
- initialize();
- }
-
- inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */
- elapsedTimer* timers, /* thread-local timer array */
- int type /* event type */ ) :
- _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) {
- initialize();
- }
-
- void initialize() {
- if (!UsePerfData) return;
+ public:
+ enum {
+ CLASS_LOAD = 0,
+ PARSE_CLASS = 1,
+ CLASS_LINK = 2,
+ CLASS_VERIFY = 3,
+ CLASS_CLINIT = 4,
+ DEFINE_CLASS = 5,
+ EVENT_TYPE_COUNT = 6
+ };
+ protected:
+ // _t tracks time from initialization to destruction of this timer instance
+ // including time for all other event types, and recursive calls of this type.
+ // When a timer is called recursively, the elapsedTimer _t would not be used.
+ elapsedTimer _t;
+ PerfLongCounter* _timep;
+ PerfLongCounter* _selftimep;
+ PerfLongCounter* _eventp;
+ // pointer to thread-local recursion counter and timer array
+ // The thread_local timers track cumulative time for specific event types
+ // exclusive of time for other event types, but including recursive calls
+ // of the same type.
+ int* _recursion_counters;
+ elapsedTimer* _timers;
+ int _event_type;
+ int _prev_active_event;
- if (_eventp != NULL) {
- // increment the event counter
- _eventp->inc();
- }
+ public:
- // stop the current active thread-local timer to measure inclusive time
- _prev_active_event = -1;
- for (int i=0; i < EVENT_TYPE_COUNT; i++) {
- if (_timers[i].is_active()) {
- assert(_prev_active_event == -1, "should have only one active timer");
- _prev_active_event = i;
- _timers[i].stop();
- }
- }
-
- if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) {
- // start the inclusive timer if not recursively called
- _t.start();
- }
-
- // start thread-local timer of the given event type
- if (!_timers[_event_type].is_active()) {
- _timers[_event_type].start();
- }
- }
+ inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */
+ PerfLongCounter* selftimep, /* counter incremented with exclusive time */
+ PerfLongCounter* eventp, /* event counter */
+ int* recursion_counters, /* thread-local recursion counter array */
+ elapsedTimer* timers, /* thread-local timer array */
+ int type /* event type */ ) :
+ _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) {
+ initialize();
+ }
- inline void suspend() { _t.stop(); _timers[_event_type].stop(); }
- inline void resume() { _t.start(); _timers[_event_type].start(); }
-
- ~PerfClassTraceTime() {
- if (!UsePerfData) return;
-
- // stop the thread-local timer as the event completes
- // and resume the thread-local timer of the event next on the stack
- _timers[_event_type].stop();
- jlong selftime = _timers[_event_type].ticks();
-
- if (_prev_active_event >= 0) {
- _timers[_prev_active_event].start();
- }
+ inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */
+ elapsedTimer* timers, /* thread-local timer array */
+ int type /* event type */ ) :
+ _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) {
+ initialize();
+ }
- if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return;
+ inline void suspend() { _t.stop(); _timers[_event_type].stop(); }
+ inline void resume() { _t.start(); _timers[_event_type].start(); }
- // increment the counters only on the leaf call
- _t.stop();
- _timep->inc(_t.ticks());
- if (_selftimep != NULL) {
- _selftimep->inc(selftime);
- }
- // add all class loading related event selftime to the accumulated time counter
- ClassLoader::perf_accumulated_time()->inc(selftime);
-
- // reset the timer
- _timers[_event_type].reset();
- }
+ ~PerfClassTraceTime();
+ void initialize();
};
-
#endif // SHARE_VM_CLASSFILE_CLASSLOADER_HPP
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -172,6 +172,8 @@
\
template(sun_jkernel_DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
\
+ template(sun_misc_PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \
+ \
/* Preload boxing klasses */ \
template(Boolean_klass, java_lang_Boolean, Pre) \
template(Character_klass, java_lang_Character, Pre) \
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -111,6 +111,7 @@
template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
template(setBootClassLoaderHook_name, "setBootClassLoaderHook") \
+ template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
\
/* class file format tags */ \
template(tag_source_file, "SourceFile") \
--- a/hotspot/src/share/vm/code/nmethod.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/code/nmethod.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1863,9 +1863,9 @@
#ifndef SHARK
if (!method()->is_native()) {
SimpleScopeDesc ssd(this, fr.pc());
- Bytecode_invoke* call = Bytecode_invoke_at(ssd.method(), ssd.bci());
- bool has_receiver = call->has_receiver();
- symbolOop signature = call->signature();
+ Bytecode_invoke call(ssd.method(), ssd.bci());
+ bool has_receiver = call.has_receiver();
+ symbolOop signature = call.signature();
fr.oops_compiled_arguments_do(signature, has_receiver, reg_map, f);
}
#endif // !SHARK
@@ -2698,8 +2698,7 @@
} else if (sd->method()->is_native()) {
st->print("method is native");
} else {
- address bcp = sd->method()->bcp_from(sd->bci());
- Bytecodes::Code bc = Bytecodes::java_code_at(bcp);
+ Bytecodes::Code bc = sd->method()->java_code_at(sd->bci());
st->print(";*%s", Bytecodes::name(bc));
switch (bc) {
case Bytecodes::_invokevirtual:
@@ -2707,10 +2706,10 @@
case Bytecodes::_invokestatic:
case Bytecodes::_invokeinterface:
{
- Bytecode_invoke* invoke = Bytecode_invoke_at(sd->method(), sd->bci());
+ Bytecode_invoke invoke(sd->method(), sd->bci());
st->print(" ");
- if (invoke->name() != NULL)
- invoke->name()->print_symbol_on(st);
+ if (invoke.name() != NULL)
+ invoke.name()->print_symbol_on(st);
else
st->print("<UNKNOWN>");
break;
@@ -2720,10 +2719,10 @@
case Bytecodes::_getstatic:
case Bytecodes::_putstatic:
{
- Bytecode_field* field = Bytecode_field_at(sd->method(), sd->bci());
+ Bytecode_field field(sd->method(), sd->bci());
st->print(" ");
- if (field->name() != NULL)
- field->name()->print_symbol_on(st);
+ if (field.name() != NULL)
+ field.name()->print_symbol_on(st);
else
st->print("<UNKNOWN>");
}
--- a/hotspot/src/share/vm/compiler/methodLiveness.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -286,16 +286,15 @@
break;
case Bytecodes::_tableswitch:
{
- Bytecode_tableswitch *tableswitch =
- Bytecode_tableswitch_at(bytes.cur_bcp());
+ Bytecode_tableswitch tableswitch(&bytes);
- int len = tableswitch->length();
+ int len = tableswitch.length();
- dest = _block_map->at(bci + tableswitch->default_offset());
+ dest = _block_map->at(bci + tableswitch.default_offset());
assert(dest != NULL, "branch desination must start a block.");
dest->add_normal_predecessor(current_block);
while (--len >= 0) {
- dest = _block_map->at(bci + tableswitch->dest_offset_at(len));
+ dest = _block_map->at(bci + tableswitch.dest_offset_at(len));
assert(dest != NULL, "branch desination must start a block.");
dest->add_normal_predecessor(current_block);
}
@@ -304,17 +303,16 @@
case Bytecodes::_lookupswitch:
{
- Bytecode_lookupswitch *lookupswitch =
- Bytecode_lookupswitch_at(bytes.cur_bcp());
+ Bytecode_lookupswitch lookupswitch(&bytes);
- int npairs = lookupswitch->number_of_pairs();
+ int npairs = lookupswitch.number_of_pairs();
- dest = _block_map->at(bci + lookupswitch->default_offset());
+ dest = _block_map->at(bci + lookupswitch.default_offset());
assert(dest != NULL, "branch desination must start a block.");
dest->add_normal_predecessor(current_block);
while(--npairs >= 0) {
- LookupswitchPair *pair = lookupswitch->pair_at(npairs);
- dest = _block_map->at( bci + pair->offset());
+ LookupswitchPair pair = lookupswitch.pair_at(npairs);
+ dest = _block_map->at( bci + pair.offset());
assert(dest != NULL, "branch desination must start a block.");
dest->add_normal_predecessor(current_block);
}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -3478,6 +3478,7 @@
assert(_collectorState == InitialMarking, "Wrong collector state");
check_correct_thread_executing();
TraceCMSMemoryManagerStats tms(_collectorState);
+
ReferenceProcessor* rp = ref_processor();
SpecializationStats::clear();
assert(_restart_addr == NULL, "Control point invariant");
@@ -4978,6 +4979,7 @@
if (should_unload_classes()) {
CodeCache::gc_epilogue();
}
+ JvmtiExport::gc_epilogue();
// If we encountered any (marking stack / work queue) overflow
// events during the current CMS cycle, take appropriate
@@ -5940,11 +5942,6 @@
}
rp->verify_no_references_recorded();
assert(!rp->discovery_enabled(), "should have been disabled");
-
- // JVMTI object tagging is based on JNI weak refs. If any of these
- // refs were cleared then JVMTI needs to update its maps and
- // maybe post ObjectFrees to agents.
- JvmtiExport::cms_ref_processing_epilogue();
}
#ifndef PRODUCT
@@ -6305,6 +6302,7 @@
switch (op) {
case CMS_op_checkpointRootsInitial: {
+ SvcGCMarker sgcm(SvcGCMarker::OTHER);
checkpointRootsInitial(true); // asynch
if (PrintGC) {
_cmsGen->printOccupancy("initial-mark");
@@ -6312,6 +6310,7 @@
break;
}
case CMS_op_checkpointRootsFinal: {
+ SvcGCMarker sgcm(SvcGCMarker::OTHER);
checkpointRootsFinal(true, // asynch
false, // !clear_all_soft_refs
false); // !init_mark_was_synchronous
@@ -7881,25 +7880,23 @@
}
// We need this destructor to reclaim any space at the end
-// of the space, which do_blk below may not have added back to
-// the free lists. [basically dealing with the "fringe effect"]
+// of the space, which do_blk below may not yet have added back to
+// the free lists.
SweepClosure::~SweepClosure() {
assert_lock_strong(_freelistLock);
- // this should be treated as the end of a free run if any
- // The current free range should be returned to the free lists
- // as one coalesced chunk.
+ assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
+ "sweep _limit out of bounds");
+ // Flush any remaining coterminal free run as a single
+ // coalesced chunk to the appropriate free list.
if (inFreeRange()) {
- flushCurFreeChunk(freeFinger(),
- pointer_delta(_limit, freeFinger()));
- assert(freeFinger() < _limit, "the finger pointeth off base");
+ assert(freeFinger() < _limit, "freeFinger points too high");
+ flush_cur_free_chunk(freeFinger(), pointer_delta(_limit, freeFinger()));
if (CMSTraceSweeper) {
- gclog_or_tty->print("destructor:");
- gclog_or_tty->print("Sweep:put_free_blk 0x%x ("SIZE_FORMAT") "
- "[coalesced:"SIZE_FORMAT"]\n",
- freeFinger(), pointer_delta(_limit, freeFinger()),
- lastFreeRangeCoalesced());
- }
- }
+ gclog_or_tty->print("Sweep: last chunk: ");
+ gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") [coalesced:"SIZE_FORMAT"]\n",
+ freeFinger(), pointer_delta(_limit, freeFinger()), lastFreeRangeCoalesced());
+ }
+ } // else nothing to flush
NOT_PRODUCT(
if (Verbose && PrintGC) {
gclog_or_tty->print("Collected "SIZE_FORMAT" objects, "
@@ -7936,9 +7933,8 @@
void SweepClosure::initialize_free_range(HeapWord* freeFinger,
bool freeRangeInFreeLists) {
if (CMSTraceSweeper) {
- gclog_or_tty->print("---- Start free range 0x%x with free block [%d] (%d)\n",
- freeFinger, _sp->block_size(freeFinger),
- freeRangeInFreeLists);
+ gclog_or_tty->print("---- Start free range at 0x%x with free block (%d)\n",
+ freeFinger, freeRangeInFreeLists);
}
assert(!inFreeRange(), "Trampling existing free range");
set_inFreeRange(true);
@@ -7993,21 +7989,36 @@
// may have caused us to coalesce the block ending at the address _limit
// with a newly expanded chunk (this happens when _limit was set to the
// previous _end of the space), so we may have stepped past _limit; see CR 6977970.
- if (addr >= _limit) { // we have swept up to or past the limit, do nothing more
+ if (addr >= _limit) { // we have swept up to or past the limit: finish up
assert(_limit >= _sp->bottom() && _limit <= _sp->end(),
"sweep _limit out of bounds");
assert(addr < _sp->end(), "addr out of bounds");
- // help the closure application finish
+ // Flush any remaining coterminal free run as a single
+ // coalesced chunk to the appropriate free list.
+ if (inFreeRange()) {
+ assert(freeFinger() < _limit, "finger points too high");
+ flush_cur_free_chunk(freeFinger(),
+ pointer_delta(addr, freeFinger()));
+ if (CMSTraceSweeper) {
+ gclog_or_tty->print("Sweep: last chunk: ");
+ gclog_or_tty->print("put_free_blk 0x%x ("SIZE_FORMAT") "
+ "[coalesced:"SIZE_FORMAT"]\n",
+ freeFinger(), pointer_delta(addr, freeFinger()),
+ lastFreeRangeCoalesced());
+ }
+ }
+
+ // help the iterator loop finish
return pointer_delta(_sp->end(), addr);
}
+
assert(addr < _limit, "sweep invariant");
-
// check if we should yield
do_yield_check(addr);
if (fc->isFree()) {
// Chunk that is already free
res = fc->size();
- doAlreadyFreeChunk(fc);
+ do_already_free_chunk(fc);
debug_only(_sp->verifyFreeLists());
assert(res == fc->size(), "Don't expect the size to change");
NOT_PRODUCT(
@@ -8017,7 +8028,7 @@
NOT_PRODUCT(_last_fc = fc;)
} else if (!_bitMap->isMarked(addr)) {
// Chunk is fresh garbage
- res = doGarbageChunk(fc);
+ res = do_garbage_chunk(fc);
debug_only(_sp->verifyFreeLists());
NOT_PRODUCT(
_numObjectsFreed++;
@@ -8025,7 +8036,7 @@
)
} else {
// Chunk that is alive.
- res = doLiveChunk(fc);
+ res = do_live_chunk(fc);
debug_only(_sp->verifyFreeLists());
NOT_PRODUCT(
_numObjectsLive++;
@@ -8078,7 +8089,7 @@
// to a free list which may be overpopulated.
//
-void SweepClosure::doAlreadyFreeChunk(FreeChunk* fc) {
+void SweepClosure::do_already_free_chunk(FreeChunk* fc) {
size_t size = fc->size();
// Chunks that cannot be coalesced are not in the
// free lists.
@@ -8094,23 +8105,23 @@
// addr and purported end of this block.
_bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
- // Some chunks cannot be coalesced in under any circumstances.
+ // Some chunks cannot be coalesced under any circumstances.
// See the definition of cantCoalesce().
if (!fc->cantCoalesce()) {
// This chunk can potentially be coalesced.
if (_sp->adaptive_freelists()) {
// All the work is done in
- doPostIsFreeOrGarbageChunk(fc, size);
+ do_post_free_or_garbage_chunk(fc, size);
} else { // Not adaptive free lists
// this is a free chunk that can potentially be coalesced by the sweeper;
if (!inFreeRange()) {
// if the next chunk is a free block that can't be coalesced
// it doesn't make sense to remove this chunk from the free lists
FreeChunk* nextChunk = (FreeChunk*)(addr + size);
- assert((HeapWord*)nextChunk <= _limit, "sweep invariant");
- if ((HeapWord*)nextChunk < _limit && // there's a next chunk...
- nextChunk->isFree() && // which is free...
- nextChunk->cantCoalesce()) { // ... but cant be coalesced
+ assert((HeapWord*)nextChunk <= _sp->end(), "Chunk size out of bounds?");
+ if ((HeapWord*)nextChunk < _sp->end() && // There is another free chunk to the right ...
+ nextChunk->isFree() && // ... which is free...
+ nextChunk->cantCoalesce()) { // ... but can't be coalesced
// nothing to do
} else {
// Potentially the start of a new free range:
@@ -8156,14 +8167,14 @@
// as the end of a free run if any
if (inFreeRange()) {
// we kicked some butt; time to pick up the garbage
- assert(freeFinger() < addr, "the finger pointeth off base");
- flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
+ assert(freeFinger() < addr, "freeFinger points too high");
+ flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
}
// else, nothing to do, just continue
}
}
-size_t SweepClosure::doGarbageChunk(FreeChunk* fc) {
+size_t SweepClosure::do_garbage_chunk(FreeChunk* fc) {
// This is a chunk of garbage. It is not in any free list.
// Add it to a free list or let it possibly be coalesced into
// a larger chunk.
@@ -8175,7 +8186,7 @@
// addr and purported end of just dead object.
_bitMap->verifyNoOneBitsInRange(addr + 1, addr + size);
- doPostIsFreeOrGarbageChunk(fc, size);
+ do_post_free_or_garbage_chunk(fc, size);
} else {
if (!inFreeRange()) {
// start of a new free range
@@ -8214,35 +8225,16 @@
return size;
}
-size_t SweepClosure::doLiveChunk(FreeChunk* fc) {
+size_t SweepClosure::do_live_chunk(FreeChunk* fc) {
HeapWord* addr = (HeapWord*) fc;
// The sweeper has just found a live object. Return any accumulated
// left hand chunk to the free lists.
if (inFreeRange()) {
- if (_sp->adaptive_freelists()) {
- flushCurFreeChunk(freeFinger(),
- pointer_delta(addr, freeFinger()));
- } else { // not adaptive freelists
- set_inFreeRange(false);
- // Add the free range back to the free list if it is not already
- // there.
- if (!freeRangeInFreeLists()) {
- assert(freeFinger() < addr, "the finger pointeth off base");
- if (CMSTraceSweeper) {
- gclog_or_tty->print("Sweep:put_free_blk 0x%x (%d) "
- "[coalesced:%d]\n",
- freeFinger(), pointer_delta(addr, freeFinger()),
- lastFreeRangeCoalesced());
- }
- _sp->addChunkAndRepairOffsetTable(freeFinger(),
- pointer_delta(addr, freeFinger()), lastFreeRangeCoalesced());
- }
- }
- }
-
- // Common code path for original and adaptive free lists.
-
- // this object is live: we'd normally expect this to be
+ assert(freeFinger() < addr, "freeFinger points too high");
+ flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
+ }
+
+ // This object is live: we'd normally expect this to be
// an oop, and like to assert the following:
// assert(oop(addr)->is_oop(), "live block should be an oop");
// However, as we commented above, this may be an object whose
@@ -8257,7 +8249,7 @@
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
"alignment problem");
- #ifdef DEBUG
+#ifdef DEBUG
if (oop(addr)->klass_or_null() != NULL &&
( !_collector->should_unload_classes()
|| (oop(addr)->is_parsable()) &&
@@ -8271,7 +8263,7 @@
CompactibleFreeListSpace::adjustObjectSize(oop(addr)->size()),
"P-mark and computed size do not agree");
}
- #endif
+#endif
} else {
// This should be an initialized object that's alive.
@@ -8298,18 +8290,16 @@
return size;
}
-void SweepClosure::doPostIsFreeOrGarbageChunk(FreeChunk* fc,
- size_t chunkSize) {
- // doPostIsFreeOrGarbageChunk() should only be called in the smart allocation
- // scheme.
+void SweepClosure::do_post_free_or_garbage_chunk(FreeChunk* fc,
+ size_t chunkSize) {
+ // do_post_free_or_garbage_chunk() should only be called in the case
+ // of the adaptive free list allocator.
bool fcInFreeLists = fc->isFree();
assert(_sp->adaptive_freelists(), "Should only be used in this case.");
assert((HeapWord*)fc <= _limit, "sweep invariant");
if (CMSTestInFreeList && fcInFreeLists) {
- assert(_sp->verifyChunkInFreeLists(fc),
- "free chunk is not in free lists");
- }
-
+ assert(_sp->verifyChunkInFreeLists(fc), "free chunk is not in free lists");
+ }
if (CMSTraceSweeper) {
gclog_or_tty->print_cr(" -- pick up another chunk at 0x%x (%d)", fc, chunkSize);
@@ -8382,20 +8372,21 @@
if (inFreeRange()) {
// In a free range but cannot coalesce with the right hand chunk.
// Put the current free range into the free lists.
- flushCurFreeChunk(freeFinger(),
- pointer_delta(addr, freeFinger()));
+ flush_cur_free_chunk(freeFinger(),
+ pointer_delta(addr, freeFinger()));
}
// Set up for new free range. Pass along whether the right hand
// chunk is in the free lists.
initialize_free_range((HeapWord*)fc, fcInFreeLists);
}
}
-void SweepClosure::flushCurFreeChunk(HeapWord* chunk, size_t size) {
+
+void SweepClosure::flush_cur_free_chunk(HeapWord* chunk, size_t size) {
assert(inFreeRange(), "Should only be called if currently in a free range.");
assert(size > 0,
"A zero sized chunk cannot be added to the free lists.");
if (!freeRangeInFreeLists()) {
- if(CMSTestInFreeList) {
+ if (CMSTestInFreeList) {
FreeChunk* fc = (FreeChunk*) chunk;
fc->setSize(size);
assert(!_sp->verifyChunkInFreeLists(fc),
@@ -8430,7 +8421,7 @@
// chunk just flushed, they will need to wait for the next
// sweep to be coalesced.
if (inFreeRange()) {
- flushCurFreeChunk(freeFinger(), pointer_delta(addr, freeFinger()));
+ flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger()));
}
// First give up the locks, then yield, then re-lock.
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -1701,7 +1701,9 @@
CMSCollector* _collector; // collector doing the work
ConcurrentMarkSweepGeneration* _g; // Generation being swept
CompactibleFreeListSpace* _sp; // Space being swept
- HeapWord* _limit;
+ HeapWord* _limit;// the address at which the sweep should stop because
+ // we do not expect blocks eligible for sweeping past
+ // that address.
Mutex* _freelistLock; // Free list lock (in space)
CMSBitMap* _bitMap; // Marking bit map (in
// generation)
@@ -1745,14 +1747,13 @@
private:
// Code that is common to a free chunk or garbage when
// encountered during sweeping.
- void doPostIsFreeOrGarbageChunk(FreeChunk *fc,
- size_t chunkSize);
+ void do_post_free_or_garbage_chunk(FreeChunk *fc, size_t chunkSize);
// Process a free chunk during sweeping.
- void doAlreadyFreeChunk(FreeChunk *fc);
+ void do_already_free_chunk(FreeChunk *fc);
// Process a garbage chunk during sweeping.
- size_t doGarbageChunk(FreeChunk *fc);
+ size_t do_garbage_chunk(FreeChunk *fc);
// Process a live chunk during sweeping.
- size_t doLiveChunk(FreeChunk* fc);
+ size_t do_live_chunk(FreeChunk* fc);
// Accessors.
HeapWord* freeFinger() const { return _freeFinger; }
@@ -1769,7 +1770,7 @@
// Initialize a free range.
void initialize_free_range(HeapWord* freeFinger, bool freeRangeInFreeLists);
// Return this chunk to the free lists.
- void flushCurFreeChunk(HeapWord* chunk, size_t size);
+ void flush_cur_free_chunk(HeapWord* chunk, size_t size);
// Check if we should yield and do so when necessary.
inline void do_yield_check(HeapWord* addr);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -31,6 +31,7 @@
#include "gc_implementation/g1/g1RemSet.hpp"
#include "gc_implementation/g1/heapRegionRemSet.hpp"
#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "gc_implementation/shared/vmGCOperations.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "memory/referencePolicy.hpp"
#include "memory/resourceArea.hpp"
@@ -457,6 +458,7 @@
_marking_task_overhead(1.0),
_cleanup_sleep_factor(0.0),
_cleanup_task_overhead(1.0),
+ _cleanup_list("Cleanup List"),
_region_bm(max_regions, false /* in_resource_area*/),
_card_bm((rs.size() + CardTableModRefBS::card_size - 1) >>
CardTableModRefBS::card_shift,
@@ -520,12 +522,6 @@
SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
satb_qs.set_buffer_size(G1SATBBufferSize);
- int size = (int) MAX2(ParallelGCThreads, (size_t)1);
- _par_cleanup_thread_state = NEW_C_HEAP_ARRAY(ParCleanupThreadState*, size);
- for (int i = 0 ; i < size; i++) {
- _par_cleanup_thread_state[i] = new ParCleanupThreadState;
- }
-
_tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num);
_accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num);
@@ -710,11 +706,6 @@
}
ConcurrentMark::~ConcurrentMark() {
- int size = (int) MAX2(ParallelGCThreads, (size_t)1);
- for (int i = 0; i < size; i++) delete _par_cleanup_thread_state[i];
- FREE_C_HEAP_ARRAY(ParCleanupThreadState*,
- _par_cleanup_thread_state);
-
for (int i = 0; i < (int) _max_task_num; ++i) {
delete _task_queues->queue(i);
delete _tasks[i];
@@ -1142,6 +1133,8 @@
return;
}
+ SvcGCMarker sgcm(SvcGCMarker::OTHER);
+
if (VerifyDuringGC) {
HandleMark hm; // handle scope
gclog_or_tty->print(" VerifyDuringGC:(before)");
@@ -1168,12 +1161,12 @@
if (G1TraceMarkStackOverflow)
gclog_or_tty->print_cr("\nRemark led to restart for overflow.");
} else {
+ SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
// We're done with marking.
// This is the end of the marking cycle, we're expected all
// threads to have SATB queues with active set to true.
- JavaThread::satb_mark_queue_set().set_active_all_threads(
- false, /* new active value */
- true /* expected_active */);
+ satb_mq_set.set_active_all_threads(false, /* new active value */
+ true /* expected_active */);
if (VerifyDuringGC) {
HandleMark hm; // handle scope
@@ -1507,21 +1500,20 @@
size_t _max_live_bytes;
size_t _regions_claimed;
size_t _freed_bytes;
- size_t _cleared_h_regions;
- size_t _freed_regions;
- UncleanRegionList* _unclean_region_list;
+ FreeRegionList _local_cleanup_list;
+ HumongousRegionSet _humongous_proxy_set;
double _claimed_region_time;
double _max_region_time;
public:
G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
- UncleanRegionList* list,
int worker_num);
size_t freed_bytes() { return _freed_bytes; }
- size_t cleared_h_regions() { return _cleared_h_regions; }
- size_t freed_regions() { return _freed_regions; }
- UncleanRegionList* unclean_region_list() {
- return _unclean_region_list;
+ FreeRegionList* local_cleanup_list() {
+ return &_local_cleanup_list;
+ }
+ HumongousRegionSet* humongous_proxy_set() {
+ return &_humongous_proxy_set;
}
bool doHeapRegion(HeapRegion *r);
@@ -1534,25 +1526,22 @@
class G1ParNoteEndTask: public AbstractGangTask {
friend class G1NoteEndOfConcMarkClosure;
+
protected:
G1CollectedHeap* _g1h;
size_t _max_live_bytes;
size_t _freed_bytes;
- ConcurrentMark::ParCleanupThreadState** _par_cleanup_thread_state;
+ FreeRegionList* _cleanup_list;
+
public:
G1ParNoteEndTask(G1CollectedHeap* g1h,
- ConcurrentMark::ParCleanupThreadState**
- par_cleanup_thread_state) :
+ FreeRegionList* cleanup_list) :
AbstractGangTask("G1 note end"), _g1h(g1h),
- _max_live_bytes(0), _freed_bytes(0),
- _par_cleanup_thread_state(par_cleanup_thread_state)
- {}
+ _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { }
void work(int i) {
double start = os::elapsedTime();
- G1NoteEndOfConcMarkClosure g1_note_end(_g1h,
- &_par_cleanup_thread_state[i]->list,
- i);
+ G1NoteEndOfConcMarkClosure g1_note_end(_g1h, i);
if (G1CollectedHeap::use_parallel_gc_threads()) {
_g1h->heap_region_par_iterate_chunked(&g1_note_end, i,
HeapRegion::NoteEndClaimValue);
@@ -1561,14 +1550,18 @@
}
assert(g1_note_end.complete(), "Shouldn't have yielded!");
- // Now finish up freeing the current thread's regions.
- _g1h->finish_free_region_work(g1_note_end.freed_bytes(),
- g1_note_end.cleared_h_regions(),
- 0, NULL);
+ // Now update the lists
+ _g1h->update_sets_after_freeing_regions(g1_note_end.freed_bytes(),
+ NULL /* free_list */,
+ g1_note_end.humongous_proxy_set(),
+ true /* par */);
{
MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
_max_live_bytes += g1_note_end.max_live_bytes();
_freed_bytes += g1_note_end.freed_bytes();
+
+ _cleanup_list->add_as_tail(g1_note_end.local_cleanup_list());
+ assert(g1_note_end.local_cleanup_list()->is_empty(), "post-condition");
}
double end = os::elapsedTime();
if (G1PrintParCleanupStats) {
@@ -1609,30 +1602,28 @@
G1NoteEndOfConcMarkClosure::
G1NoteEndOfConcMarkClosure(G1CollectedHeap* g1,
- UncleanRegionList* list,
int worker_num)
: _g1(g1), _worker_num(worker_num),
_max_live_bytes(0), _regions_claimed(0),
- _freed_bytes(0), _cleared_h_regions(0), _freed_regions(0),
+ _freed_bytes(0),
_claimed_region_time(0.0), _max_region_time(0.0),
- _unclean_region_list(list)
-{}
-
-bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *r) {
+ _local_cleanup_list("Local Cleanup List"),
+ _humongous_proxy_set("Local Cleanup Humongous Proxy Set") { }
+
+bool G1NoteEndOfConcMarkClosure::doHeapRegion(HeapRegion *hr) {
// We use a claim value of zero here because all regions
// were claimed with value 1 in the FinalCount task.
- r->reset_gc_time_stamp();
- if (!r->continuesHumongous()) {
+ hr->reset_gc_time_stamp();
+ if (!hr->continuesHumongous()) {
double start = os::elapsedTime();
_regions_claimed++;
- r->note_end_of_marking();
- _max_live_bytes += r->max_live_bytes();
- _g1->free_region_if_totally_empty_work(r,
- _freed_bytes,
- _cleared_h_regions,
- _freed_regions,
- _unclean_region_list,
- true /*par*/);
+ hr->note_end_of_marking();
+ _max_live_bytes += hr->max_live_bytes();
+ _g1->free_region_if_totally_empty(hr,
+ &_freed_bytes,
+ &_local_cleanup_list,
+ &_humongous_proxy_set,
+ true /* par */);
double region_time = (os::elapsedTime() - start);
_claimed_region_time += region_time;
if (region_time > _max_region_time) _max_region_time = region_time;
@@ -1652,6 +1643,8 @@
return;
}
+ g1h->verify_region_sets_optional();
+
if (VerifyDuringGC) {
HandleMark hm; // handle scope
gclog_or_tty->print(" VerifyDuringGC:(before)");
@@ -1716,7 +1709,7 @@
// Note end of marking in all heap regions.
double note_end_start = os::elapsedTime();
- G1ParNoteEndTask g1_par_note_end_task(g1h, _par_cleanup_thread_state);
+ G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list);
if (G1CollectedHeap::use_parallel_gc_threads()) {
int n_workers = g1h->workers()->total_workers();
g1h->set_par_threads(n_workers);
@@ -1728,9 +1721,14 @@
} else {
g1_par_note_end_task.work(0);
}
- g1h->set_unclean_regions_coming(true);
+
+ if (!cleanup_list_is_empty()) {
+ // The cleanup list is not empty, so we'll have to process it
+ // concurrently. Notify anyone else that might be wanting free
+ // regions that there will be more free regions coming soon.
+ g1h->set_free_regions_coming();
+ }
double note_end_end = os::elapsedTime();
- // Tell the mutators that there might be unclean regions coming...
if (G1PrintParCleanupStats) {
gclog_or_tty->print_cr(" note end of marking: %8.3f ms.",
(note_end_end - note_end_start)*1000.0);
@@ -1796,33 +1794,63 @@
/* silent */ false,
/* prev marking */ true);
}
+
+ g1h->verify_region_sets_optional();
}
void ConcurrentMark::completeCleanup() {
- // A full collection intervened.
if (has_aborted()) return;
- int first = 0;
- int last = (int)MAX2(ParallelGCThreads, (size_t)1);
- for (int t = 0; t < last; t++) {
- UncleanRegionList* list = &_par_cleanup_thread_state[t]->list;
- assert(list->well_formed(), "Inv");
- HeapRegion* hd = list->hd();
- while (hd != NULL) {
- // Now finish up the other stuff.
- hd->rem_set()->clear();
- HeapRegion* next_hd = hd->next_from_unclean_list();
- (void)list->pop();
- assert(list->hd() == next_hd, "how not?");
- _g1h->put_region_on_unclean_list(hd);
- if (!hd->isHumongous()) {
- // Add this to the _free_regions count by 1.
- _g1h->finish_free_region_work(0, 0, 1, NULL);
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+ _cleanup_list.verify_optional();
+ FreeRegionList local_free_list("Local Cleanup List");
+
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
+ "cleanup list has "SIZE_FORMAT" entries",
+ _cleanup_list.length());
+ }
+
+ // Noone else should be accessing the _cleanup_list at this point,
+ // so it's not necessary to take any locks
+ while (!_cleanup_list.is_empty()) {
+ HeapRegion* hr = _cleanup_list.remove_head();
+ assert(hr != NULL, "the list was not empty");
+ hr->rem_set()->clear();
+ local_free_list.add_as_tail(hr);
+
+ // Instead of adding one region at a time to the secondary_free_list,
+ // we accumulate them in the local list and move them a few at a
+ // time. This also cuts down on the number of notify_all() calls
+ // we do during this process. We'll also append the local list when
+ // _cleanup_list is empty (which means we just removed the last
+ // region from the _cleanup_list).
+ if ((local_free_list.length() % G1SecondaryFreeListAppendLength == 0) ||
+ _cleanup_list.is_empty()) {
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [complete cleanup] : "
+ "appending "SIZE_FORMAT" entries to the "
+ "secondary_free_list, clean list still has "
+ SIZE_FORMAT" entries",
+ local_free_list.length(),
+ _cleanup_list.length());
}
- hd = list->hd();
- assert(hd == next_hd, "how not?");
+
+ {
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ g1h->secondary_free_list_add_as_tail(&local_free_list);
+ SecondaryFreeList_lock->notify_all();
+ }
+
+ if (G1StressConcRegionFreeing) {
+ for (uintx i = 0; i < G1StressConcRegionFreeingDelayMillis; ++i) {
+ os::sleep(Thread::current(), (jlong) 1, false);
+ }
+ }
}
}
+ assert(local_free_list.is_empty(), "post-condition");
}
bool G1CMIsAliveClosure::do_object_b(oop obj) {
@@ -2894,9 +2922,9 @@
virtual void do_oop( oop* p) { do_oop_work(p); }
template <class T> void do_oop_work(T* p) {
- assert(_g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
- assert(!_g1h->heap_region_containing((HeapWord*) p)->is_on_free_list(),
- "invariant");
+ assert( _g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
+ assert(!_g1h->is_on_free_list(
+ _g1h->heap_region_containing((HeapWord*) p)), "invariant");
oop obj = oopDesc::load_decode_heap_oop(p);
if (_cm->verbose_high())
@@ -3116,8 +3144,8 @@
void CMTask::push(oop obj) {
HeapWord* objAddr = (HeapWord*) obj;
assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
- assert(!_g1h->heap_region_containing(objAddr)->is_on_free_list(),
- "invariant");
+ assert(!_g1h->is_on_free_list(
+ _g1h->heap_region_containing((HeapWord*) objAddr)), "invariant");
assert(!_g1h->is_obj_ill(obj), "invariant");
assert(_nextMarkBitMap->isMarked(objAddr), "invariant");
@@ -3362,8 +3390,8 @@
(void*) obj);
assert(_g1h->is_in_g1_reserved((HeapWord*) obj), "invariant" );
- assert(!_g1h->heap_region_containing(obj)->is_on_free_list(),
- "invariant");
+ assert(!_g1h->is_on_free_list(
+ _g1h->heap_region_containing((HeapWord*) obj)), "invariant");
scan_object(obj);
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -25,7 +25,7 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
-#include "gc_implementation/g1/heapRegion.hpp"
+#include "gc_implementation/g1/heapRegionSets.hpp"
#include "utilities/taskqueue.hpp"
class G1CollectedHeap;
@@ -369,13 +369,7 @@
double _cleanup_sleep_factor;
double _cleanup_task_overhead;
- // Stuff related to age cohort processing.
- struct ParCleanupThreadState {
- char _pre[64];
- UncleanRegionList list;
- char _post[64];
- };
- ParCleanupThreadState** _par_cleanup_thread_state;
+ FreeRegionList _cleanup_list;
// CMS marking support structures
CMBitMap _markBitMap1;
@@ -484,6 +478,10 @@
// prints all gathered CM-related statistics
void print_stats();
+ bool cleanup_list_is_empty() {
+ return _cleanup_list.is_empty();
+ }
+
// accessor methods
size_t parallel_marking_threads() { return _parallel_marking_threads; }
double sleep_factor() { return _sleep_factor; }
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -95,8 +95,8 @@
_vtime_start = os::elapsedVTime();
wait_for_universe_init();
- G1CollectedHeap* g1 = G1CollectedHeap::heap();
- G1CollectorPolicy* g1_policy = g1->g1_policy();
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ G1CollectorPolicy* g1_policy = g1h->g1_policy();
G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
Thread *current_thread = Thread::current();
@@ -119,7 +119,7 @@
if (!g1_policy->in_young_gc_mode()) {
// this ensures the flag is not set if we bail out of the marking
// cycle; normally the flag is cleared immediately after cleanup
- g1->set_marking_complete();
+ g1h->set_marking_complete();
if (g1_policy->adaptive_young_list_length()) {
double now = os::elapsedTime();
@@ -228,10 +228,20 @@
VM_CGC_Operation op(&cl_cl, verbose_str);
VMThread::execute(&op);
} else {
- G1CollectedHeap::heap()->set_marking_complete();
+ g1h->set_marking_complete();
}
- if (!cm()->has_aborted()) {
+ // Check if cleanup set the free_regions_coming flag. If it
+ // hasn't, we can just skip the next step.
+ if (g1h->free_regions_coming()) {
+ // The following will finish freeing up any regions that we
+ // found to be empty during cleanup. We'll do this part
+ // without joining the suspendible set. If an evacuation pause
+ // takes places, then we would carry on freeing regions in
+ // case they are needed by the pause. If a Full GC takes
+ // places, it would wait for us to process the regions
+ // reclaimed by cleanup.
+
double cleanup_start_sec = os::elapsedTime();
if (PrintGC) {
gclog_or_tty->date_stamp(PrintGCDateStamps);
@@ -240,23 +250,22 @@
}
// Now do the remainder of the cleanup operation.
- _sts.join();
_cm->completeCleanup();
- if (!cm()->has_aborted()) {
- g1_policy->record_concurrent_mark_cleanup_completed();
+ g1_policy->record_concurrent_mark_cleanup_completed();
- double cleanup_end_sec = os::elapsedTime();
- if (PrintGC) {
- gclog_or_tty->date_stamp(PrintGCDateStamps);
- gclog_or_tty->stamp(PrintGCTimeStamps);
- gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
- cleanup_end_sec - cleanup_start_sec);
- }
+ double cleanup_end_sec = os::elapsedTime();
+ if (PrintGC) {
+ gclog_or_tty->date_stamp(PrintGCDateStamps);
+ gclog_or_tty->stamp(PrintGCTimeStamps);
+ gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
+ cleanup_end_sec - cleanup_start_sec);
}
- _sts.leave();
+
+ // We're done: no more free regions coming.
+ g1h->reset_free_regions_coming();
}
- // We're done: no more unclean regions coming.
- G1CollectedHeap::heap()->set_unclean_regions_coming(false);
+ guarantee(cm()->cleanup_list_is_empty(),
+ "at this point there should be no regions on the cleanup list");
if (cm()->has_aborted()) {
if (PrintGC) {
@@ -278,7 +287,7 @@
// Java thread is waiting for a full GC to happen (e.g., it
// called System.gc() with +ExplicitGCInvokesConcurrent).
_sts.join();
- g1->increment_full_collections_completed(true /* concurrent */);
+ g1h->increment_full_collections_completed(true /* concurrent */);
_sts.leave();
}
assert(_should_terminate, "just checking");
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentZFThread.cpp Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc_implementation/g1/concurrentZFThread.hpp"
-#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
-#include "gc_implementation/g1/heapRegion.hpp"
-#include "memory/space.inline.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "utilities/copy.hpp"
-
-// ======= Concurrent Zero-Fill Thread ========
-
-// The CM thread is created when the G1 garbage collector is used
-
-int ConcurrentZFThread::_region_allocs = 0;
-int ConcurrentZFThread::_sync_zfs = 0;
-int ConcurrentZFThread::_zf_waits = 0;
-int ConcurrentZFThread::_regions_filled = 0;
-
-ConcurrentZFThread::ConcurrentZFThread() :
- ConcurrentGCThread()
-{
- create_and_start();
-}
-
-void ConcurrentZFThread::wait_for_ZF_completed(HeapRegion* hr) {
- assert(ZF_mon->owned_by_self(), "Precondition.");
- note_zf_wait();
- while (hr->zero_fill_state() == HeapRegion::ZeroFilling) {
- ZF_mon->wait(Mutex::_no_safepoint_check_flag);
- }
-}
-
-void ConcurrentZFThread::processHeapRegion(HeapRegion* hr) {
- assert(!Universe::heap()->is_gc_active(),
- "This should not happen during GC.");
- assert(hr != NULL, "Precondition");
- // These are unlocked reads, but if this test is successful, then no
- // other thread will attempt this zero filling. Only a GC thread can
- // modify the ZF state of a region whose state is zero-filling, and this
- // should only happen while the ZF thread is locking out GC.
- if (hr->zero_fill_state() == HeapRegion::ZeroFilling
- && hr->zero_filler() == Thread::current()) {
- assert(hr->top() == hr->bottom(), "better be empty!");
- assert(!hr->isHumongous(), "Only free regions on unclean list.");
- Copy::fill_to_words(hr->bottom(), hr->capacity()/HeapWordSize);
- note_region_filled();
- }
-}
-
-void ConcurrentZFThread::run() {
- initialize_in_thread();
- Thread* thr_self = Thread::current();
- _vtime_start = os::elapsedVTime();
- wait_for_universe_init();
-
- G1CollectedHeap* g1 = G1CollectedHeap::heap();
- _sts.join();
- while (!_should_terminate) {
- _sts.leave();
-
- {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
-
- // This local variable will hold a region being zero-filled. This
- // region will neither be on the unclean or zero-filled lists, and
- // will not be available for allocation; thus, we might have an
- // allocation fail, causing a full GC, because of this, but this is a
- // price we will pay. (In future, we might want to make the fact
- // that there's a region being zero-filled apparent to the G1 heap,
- // which could then wait for it in this extreme case...)
- HeapRegion* to_fill;
-
- while (!g1->should_zf()
- || (to_fill = g1->pop_unclean_region_list_locked()) == NULL)
- ZF_mon->wait(Mutex::_no_safepoint_check_flag);
- while (to_fill->zero_fill_state() == HeapRegion::ZeroFilling)
- ZF_mon->wait(Mutex::_no_safepoint_check_flag);
-
- // So now to_fill is non-NULL and is not ZeroFilling. It might be
- // Allocated or ZeroFilled. (The latter could happen if this thread
- // starts the zero-filling of a region, but a GC intervenes and
- // pushes new regions needing on the front of the filling on the
- // front of the list.)
-
- switch (to_fill->zero_fill_state()) {
- case HeapRegion::Allocated:
- to_fill = NULL;
- break;
-
- case HeapRegion::NotZeroFilled:
- to_fill->set_zero_fill_in_progress(thr_self);
-
- ZF_mon->unlock();
- _sts.join();
- processHeapRegion(to_fill);
- _sts.leave();
- ZF_mon->lock_without_safepoint_check();
-
- if (to_fill->zero_fill_state() == HeapRegion::ZeroFilling
- && to_fill->zero_filler() == thr_self) {
- to_fill->set_zero_fill_complete();
- (void)g1->put_free_region_on_list_locked(to_fill);
- }
- break;
-
- case HeapRegion::ZeroFilled:
- (void)g1->put_free_region_on_list_locked(to_fill);
- break;
-
- case HeapRegion::ZeroFilling:
- ShouldNotReachHere();
- break;
- }
- }
- _vtime_accum = (os::elapsedVTime() - _vtime_start);
- _sts.join();
- }
- _sts.leave();
-
- assert(_should_terminate, "just checking");
- terminate();
-}
-
-bool ConcurrentZFThread::offer_yield() {
- if (_sts.should_yield()) {
- _sts.yield("Concurrent ZF");
- return true;
- } else {
- return false;
- }
-}
-
-void ConcurrentZFThread::stop() {
- // it is ok to take late safepoints here, if needed
- MutexLockerEx mu(Terminator_lock);
- _should_terminate = true;
- while (!_has_terminated) {
- Terminator_lock->wait();
- }
-}
-
-void ConcurrentZFThread::print() const {
- print_on(tty);
-}
-
-void ConcurrentZFThread::print_on(outputStream* st) const {
- st->print("\"G1 Concurrent Zero-Fill Thread\" ");
- Thread::print_on(st);
- st->cr();
-}
-
-
-double ConcurrentZFThread::_vtime_accum;
-
-void ConcurrentZFThread::print_summary_info() {
- gclog_or_tty->print("\nConcurrent Zero-Filling:\n");
- gclog_or_tty->print(" Filled %d regions, used %5.2fs.\n",
- _regions_filled,
- vtime_accum());
- gclog_or_tty->print(" Of %d region allocs, %d (%5.2f%%) required sync ZF,\n",
- _region_allocs, _sync_zfs,
- (_region_allocs > 0 ?
- (float)_sync_zfs/(float)_region_allocs*100.0 :
- 0.0));
- gclog_or_tty->print(" and %d (%5.2f%%) required a ZF wait.\n",
- _zf_waits,
- (_region_allocs > 0 ?
- (float)_zf_waits/(float)_region_allocs*100.0 :
- 0.0));
-
-}
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentZFThread.hpp Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2001, 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.
- *
- */
-
-#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTZFTHREAD_HPP
-#define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTZFTHREAD_HPP
-
-#include "gc_implementation/shared/concurrentGCThread.hpp"
-
-// The Concurrent ZF Thread. Performs concurrent zero-filling.
-
-class ConcurrentZFThread: public ConcurrentGCThread {
- friend class VMStructs;
- friend class ZeroFillRegionClosure;
-
- private:
-
- // Zero fill the heap region.
- void processHeapRegion(HeapRegion* r);
-
- // Stats
- // Allocation (protected by heap lock).
- static int _region_allocs; // Number of regions allocated
- static int _sync_zfs; // Synchronous zero-fills +
- static int _zf_waits; // Wait for conc zero-fill completion.
-
- // Number of regions CFZ thread fills.
- static int _regions_filled;
-
- double _vtime_start; // Initial virtual time.
-
- // These are static because the "print_summary_info" method is, and
- // it currently assumes there is only one ZF thread. We'll change when
- // we need to.
- static double _vtime_accum; // Initial virtual time.
- static double vtime_accum() { return _vtime_accum; }
-
- // Offer yield for GC. Returns true if yield occurred.
- bool offer_yield();
-
- public:
- // Constructor
- ConcurrentZFThread();
-
- // Main loop.
- virtual void run();
-
- // Printing
- void print_on(outputStream* st) const;
- void print() const;
-
- // Waits until "r" has been zero-filled. Requires caller to hold the
- // ZF_mon.
- static void wait_for_ZF_completed(HeapRegion* r);
-
- // Get or clear the current unclean region. Should be done
- // while holding the ZF_needed_mon lock.
-
- // shutdown
- void stop();
-
- // Stats
- static void note_region_alloc() {_region_allocs++; }
- static void note_sync_zfs() { _sync_zfs++; }
- static void note_zf_wait() { _zf_waits++; }
- static void note_region_filled() { _regions_filled++; }
-
- static void print_summary_info();
-};
-
-#endif // SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTZFTHREAD_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -222,7 +222,7 @@
// Action_mark - update the BOT for the block [blk_start, blk_end).
// Current typical use is for splitting a block.
-// Action_single - udpate the BOT for an allocation.
+// Action_single - update the BOT for an allocation.
// Action_verify - BOT verification.
void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start,
HeapWord* blk_end,
@@ -331,47 +331,6 @@
do_block_internal(blk_start, blk_end, Action_mark);
}
-void G1BlockOffsetArray::join_blocks(HeapWord* blk1, HeapWord* blk2) {
- HeapWord* blk1_start = Universe::heap()->block_start(blk1);
- HeapWord* blk2_start = Universe::heap()->block_start(blk2);
- assert(blk1 == blk1_start && blk2 == blk2_start,
- "Must be block starts.");
- assert(blk1 + _sp->block_size(blk1) == blk2, "Must be contiguous.");
- size_t blk1_start_index = _array->index_for(blk1);
- size_t blk2_start_index = _array->index_for(blk2);
- assert(blk1_start_index <= blk2_start_index, "sanity");
- HeapWord* blk2_card_start = _array->address_for_index(blk2_start_index);
- if (blk2 == blk2_card_start) {
- // blk2 starts a card. Does blk1 start on the prevous card, or futher
- // back?
- assert(blk1_start_index < blk2_start_index, "must be lower card.");
- if (blk1_start_index + 1 == blk2_start_index) {
- // previous card; new value for blk2 card is size of blk1.
- _array->set_offset_array(blk2_start_index, (u_char) _sp->block_size(blk1));
- } else {
- // Earlier card; go back a card.
- _array->set_offset_array(blk2_start_index, N_words);
- }
- } else {
- // blk2 does not start a card. Does it cross a card? If not, nothing
- // to do.
- size_t blk2_end_index =
- _array->index_for(blk2 + _sp->block_size(blk2) - 1);
- assert(blk2_end_index >= blk2_start_index, "sanity");
- if (blk2_end_index > blk2_start_index) {
- // Yes, it crosses a card. The value for the next card must change.
- if (blk1_start_index + 1 == blk2_start_index) {
- // previous card; new value for second blk2 card is size of blk1.
- _array->set_offset_array(blk2_start_index + 1,
- (u_char) _sp->block_size(blk1));
- } else {
- // Earlier card; go back a card.
- _array->set_offset_array(blk2_start_index + 1, N_words);
- }
- }
- }
-}
-
HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) {
assert(_bottom <= addr && addr < _end,
"addr must be covered by this Array");
@@ -580,15 +539,50 @@
#endif
}
-void
-G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) {
- assert(_end == new_end, "_end should have already been updated");
+bool
+G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
+ size_t word_size) const {
+ size_t first_card = _array->index_for(obj_start);
+ size_t last_card = _array->index_for(obj_start + word_size - 1);
+ if (!_array->is_card_boundary(obj_start)) {
+ // If the object is not on a card boundary the BOT entry of the
+ // first card should point to another object so we should not
+ // check that one.
+ first_card += 1;
+ }
+ for (size_t card = first_card; card <= last_card; card += 1) {
+ HeapWord* card_addr = _array->address_for_index(card);
+ HeapWord* block_start = block_start_const(card_addr);
+ if (block_start != obj_start) {
+ gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
+ "card index: "SIZE_FORMAT" "
+ "card addr: "PTR_FORMAT" BOT entry: %u "
+ "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
+ "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
+ block_start, card, card_addr,
+ _array->offset_array(card),
+ obj_start, word_size, first_card, last_card);
+ return false;
+ }
+ }
+ return true;
+}
- // The first BOT entry should have offset 0.
- _array->set_offset_array(_array->index_for(_bottom), 0);
- // The rest should point to the first one.
- set_remainder_to_point_to_start(_bottom + N_words, new_end);
+#ifndef PRODUCT
+void
+G1BlockOffsetArray::print_on(outputStream* out) {
+ size_t from_index = _array->index_for(_bottom);
+ size_t to_index = _array->index_for(_end);
+ out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
+ "cards ["SIZE_FORMAT","SIZE_FORMAT")",
+ _bottom, _end, from_index, to_index);
+ for (size_t i = from_index; i < to_index; ++i) {
+ out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
+ i, _array->address_for_index(i),
+ (uint) _array->offset_array(i));
+ }
}
+#endif // !PRODUCT
//////////////////////////////////////////////////////////////////////
// G1BlockOffsetArrayContigSpace
@@ -641,10 +635,20 @@
}
void
-G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) {
- G1BlockOffsetArray::set_for_starts_humongous(new_end);
+G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
+ assert(new_top <= _end, "_end should have already been updated");
+
+ // The first BOT entry should have offset 0.
+ zero_bottom_entry();
+ initialize_threshold();
+ alloc_block(_bottom, new_top);
+ }
- // Make sure _next_offset_threshold and _next_offset_index point to new_end.
- _next_offset_threshold = new_end;
- _next_offset_index = _array->index_for(new_end);
+#ifndef PRODUCT
+void
+G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
+ G1BlockOffsetArray::print_on(out);
+ out->print_cr(" next offset threshold: "PTR_FORMAT, _next_offset_threshold);
+ out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index);
}
+#endif // !PRODUCT
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -352,11 +352,6 @@
// The following methods are useful and optimized for a
// general, non-contiguous space.
- // The given arguments are required to be the starts of adjacent ("blk1"
- // before "blk2") well-formed blocks covered by "this". After this call,
- // they should be considered to form one block.
- virtual void join_blocks(HeapWord* blk1, HeapWord* blk2);
-
// Given a block [blk_start, blk_start + full_blk_size), and
// a left_blk_size < full_blk_size, adjust the BOT to show two
// blocks [blk_start, blk_start + left_blk_size) and
@@ -429,6 +424,12 @@
verify_single_block(blk, blk + size);
}
+ // Used by region verification. Checks that the contents of the
+ // BOT reflect that there's a single object that spans the address
+ // range [obj_start, obj_start + word_size); returns true if this is
+ // the case, returns false if it's not.
+ bool verify_for_object(HeapWord* obj_start, size_t word_size) const;
+
// Verify that the given block is before _unallocated_block
inline void verify_not_unallocated(HeapWord* blk_start,
HeapWord* blk_end) const {
@@ -444,7 +445,7 @@
void check_all_cards(size_t left_card, size_t right_card) const;
- virtual void set_for_starts_humongous(HeapWord* new_end);
+ virtual void print_on(outputStream* out) PRODUCT_RETURN;
};
// A subtype of BlockOffsetArray that takes advantage of the fact
@@ -494,7 +495,9 @@
HeapWord* block_start_unsafe(const void* addr);
HeapWord* block_start_unsafe_const(const void* addr) const;
- virtual void set_for_starts_humongous(HeapWord* new_end);
+ void set_for_starts_humongous(HeapWord* new_top);
+
+ virtual void print_on(outputStream* out) PRODUCT_RETURN;
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -28,7 +28,6 @@
#include "gc_implementation/g1/concurrentG1Refine.hpp"
#include "gc_implementation/g1/concurrentG1RefineThread.hpp"
#include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
-#include "gc_implementation/g1/concurrentZFThread.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
#include "gc_implementation/g1/g1MarkSweep.hpp"
@@ -425,11 +424,9 @@
void G1CollectedHeap::stop_conc_gc_threads() {
_cg1r->stop();
- _czft->stop();
_cmThread->stop();
}
-
void G1CollectedHeap::check_ct_logs_at_safepoint() {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
CardTableModRefBS* ct_bs = (CardTableModRefBS*)barrier_set();
@@ -481,49 +478,92 @@
// Private methods.
-// Finds a HeapRegion that can be used to allocate a given size of block.
-
-
-HeapRegion* G1CollectedHeap::newAllocRegion_work(size_t word_size,
- bool do_expand,
- bool zero_filled) {
- ConcurrentZFThread::note_region_alloc();
- HeapRegion* res = alloc_free_region_from_lists(zero_filled);
+HeapRegion*
+G1CollectedHeap::new_region_try_secondary_free_list(size_t word_size) {
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ while (!_secondary_free_list.is_empty() || free_regions_coming()) {
+ if (!_secondary_free_list.is_empty()) {
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+ "secondary_free_list has "SIZE_FORMAT" entries",
+ _secondary_free_list.length());
+ }
+ // It looks as if there are free regions available on the
+ // secondary_free_list. Let's move them to the free_list and try
+ // again to allocate from it.
+ append_secondary_free_list();
+
+ assert(!_free_list.is_empty(), "if the secondary_free_list was not "
+ "empty we should have moved at least one entry to the free_list");
+ HeapRegion* res = _free_list.remove_head();
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+ "allocated "HR_FORMAT" from secondary_free_list",
+ HR_FORMAT_PARAMS(res));
+ }
+ return res;
+ }
+
+ // Wait here until we get notifed either when (a) there are no
+ // more free regions coming or (b) some regions have been moved on
+ // the secondary_free_list.
+ SecondaryFreeList_lock->wait(Mutex::_no_safepoint_check_flag);
+ }
+
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+ "could not allocate from secondary_free_list");
+ }
+ return NULL;
+}
+
+HeapRegion* G1CollectedHeap::new_region_work(size_t word_size,
+ bool do_expand) {
+ assert(!isHumongous(word_size) ||
+ word_size <= (size_t) HeapRegion::GrainWords,
+ "the only time we use this to allocate a humongous region is "
+ "when we are allocating a single humongous region");
+
+ HeapRegion* res;
+ if (G1StressConcRegionFreeing) {
+ if (!_secondary_free_list.is_empty()) {
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+ "forced to look at the secondary_free_list");
+ }
+ res = new_region_try_secondary_free_list(word_size);
+ if (res != NULL) {
+ return res;
+ }
+ }
+ }
+ res = _free_list.remove_head_or_null();
+ if (res == NULL) {
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
+ "res == NULL, trying the secondary_free_list");
+ }
+ res = new_region_try_secondary_free_list(word_size);
+ }
if (res == NULL && do_expand) {
expand(word_size * HeapWordSize);
- res = alloc_free_region_from_lists(zero_filled);
- assert(res == NULL ||
- (!res->isHumongous() &&
- (!zero_filled ||
- res->zero_fill_state() == HeapRegion::Allocated)),
- "Alloc Regions must be zero filled (and non-H)");
+ res = _free_list.remove_head_or_null();
}
if (res != NULL) {
- if (res->is_empty()) {
- _free_regions--;
- }
- assert(!res->isHumongous() &&
- (!zero_filled || res->zero_fill_state() == HeapRegion::Allocated),
- err_msg("Non-young alloc Regions must be zero filled (and non-H):"
- " res->isHumongous()=%d, zero_filled=%d, res->zero_fill_state()=%d",
- res->isHumongous(), zero_filled, res->zero_fill_state()));
- assert(!res->is_on_unclean_list(),
- "Alloc Regions must not be on the unclean list");
if (G1PrintHeapRegions) {
- gclog_or_tty->print_cr("new alloc region %d:["PTR_FORMAT", "PTR_FORMAT"], "
- "top "PTR_FORMAT,
- res->hrs_index(), res->bottom(), res->end(), res->top());
+ gclog_or_tty->print_cr("new alloc region %d:["PTR_FORMAT","PTR_FORMAT"], "
+ "top "PTR_FORMAT, res->hrs_index(),
+ res->bottom(), res->end(), res->top());
}
}
return res;
}
-HeapRegion* G1CollectedHeap::newAllocRegionWithExpansion(int purpose,
- size_t word_size,
- bool zero_filled) {
+HeapRegion* G1CollectedHeap::new_gc_alloc_region(int purpose,
+ size_t word_size) {
HeapRegion* alloc_region = NULL;
if (_gc_alloc_region_counts[purpose] < g1_policy()->max_regions(purpose)) {
- alloc_region = newAllocRegion_work(word_size, true, zero_filled);
+ alloc_region = new_region_work(word_size, true /* do_expand */);
if (purpose == GCAllocForSurvived && alloc_region != NULL) {
alloc_region->set_survivor();
}
@@ -534,81 +574,220 @@
return alloc_region;
}
+int G1CollectedHeap::humongous_obj_allocate_find_first(size_t num_regions,
+ size_t word_size) {
+ int first = -1;
+ if (num_regions == 1) {
+ // Only one region to allocate, no need to go through the slower
+ // path. The caller will attempt the expasion if this fails, so
+ // let's not try to expand here too.
+ HeapRegion* hr = new_region_work(word_size, false /* do_expand */);
+ if (hr != NULL) {
+ first = hr->hrs_index();
+ } else {
+ first = -1;
+ }
+ } else {
+ // We can't allocate humongous regions while cleanupComplete() is
+ // running, since some of the regions we find to be empty might not
+ // yet be added to the free list and it is not straightforward to
+ // know which list they are on so that we can remove them. Note
+ // that we only need to do this if we need to allocate more than
+ // one region to satisfy the current humongous allocation
+ // request. If we are only allocating one region we use the common
+ // region allocation code (see above).
+ wait_while_free_regions_coming();
+ append_secondary_free_list_if_not_empty();
+
+ if (free_regions() >= num_regions) {
+ first = _hrs->find_contiguous(num_regions);
+ if (first != -1) {
+ for (int i = first; i < first + (int) num_regions; ++i) {
+ HeapRegion* hr = _hrs->at(i);
+ assert(hr->is_empty(), "sanity");
+ assert(is_on_free_list(hr), "sanity");
+ hr->set_pending_removal(true);
+ }
+ _free_list.remove_all_pending(num_regions);
+ }
+ }
+ }
+ return first;
+}
+
// If could fit into free regions w/o expansion, try.
// Otherwise, if can expand, do so.
// Otherwise, if using ex regions might help, try with ex given back.
HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
- assert_heap_locked_or_at_safepoint();
- assert(regions_accounted_for(), "Region leakage!");
-
- // We can't allocate humongous regions while cleanupComplete is
- // running, since some of the regions we find to be empty might not
- // yet be added to the unclean list. If we're already at a
- // safepoint, this call is unnecessary, not to mention wrong.
- if (!SafepointSynchronize::is_at_safepoint()) {
- wait_for_cleanup_complete();
- }
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
+
+ verify_region_sets_optional();
size_t num_regions =
round_to(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords;
-
- // Special case if < one region???
-
- // Remember the ft size.
size_t x_size = expansion_regions();
-
- HeapWord* res = NULL;
- bool eliminated_allocated_from_lists = false;
-
- // Can the allocation potentially fit in the free regions?
- if (free_regions() >= num_regions) {
- res = _hrs->obj_allocate(word_size);
- }
- if (res == NULL) {
- // Try expansion.
- size_t fs = _hrs->free_suffix();
+ size_t fs = _hrs->free_suffix();
+ int first = humongous_obj_allocate_find_first(num_regions, word_size);
+ if (first == -1) {
+ // The only thing we can do now is attempt expansion.
if (fs + x_size >= num_regions) {
expand((num_regions - fs) * HeapRegion::GrainBytes);
- res = _hrs->obj_allocate(word_size);
- assert(res != NULL, "This should have worked.");
- } else {
- // Expansion won't help. Are there enough free regions if we get rid
- // of reservations?
- size_t avail = free_regions();
- if (avail >= num_regions) {
- res = _hrs->obj_allocate(word_size);
- if (res != NULL) {
- remove_allocated_regions_from_lists();
- eliminated_allocated_from_lists = true;
- }
+ first = humongous_obj_allocate_find_first(num_regions, word_size);
+ assert(first != -1, "this should have worked");
+ }
+ }
+
+ if (first != -1) {
+ // Index of last region in the series + 1.
+ int last = first + (int) num_regions;
+
+ // We need to initialize the region(s) we just discovered. This is
+ // a bit tricky given that it can happen concurrently with
+ // refinement threads refining cards on these regions and
+ // potentially wanting to refine the BOT as they are scanning
+ // those cards (this can happen shortly after a cleanup; see CR
+ // 6991377). So we have to set up the region(s) carefully and in
+ // a specific order.
+
+ // The word size sum of all the regions we will allocate.
+ size_t word_size_sum = num_regions * HeapRegion::GrainWords;
+ assert(word_size <= word_size_sum, "sanity");
+
+ // This will be the "starts humongous" region.
+ HeapRegion* first_hr = _hrs->at(first);
+ // The header of the new object will be placed at the bottom of
+ // the first region.
+ HeapWord* new_obj = first_hr->bottom();
+ // This will be the new end of the first region in the series that
+ // should also match the end of the last region in the seriers.
+ HeapWord* new_end = new_obj + word_size_sum;
+ // This will be the new top of the first region that will reflect
+ // this allocation.
+ HeapWord* new_top = new_obj + word_size;
+
+ // First, we need to zero the header of the space that we will be
+ // allocating. When we update top further down, some refinement
+ // threads might try to scan the region. By zeroing the header we
+ // ensure that any thread that will try to scan the region will
+ // come across the zero klass word and bail out.
+ //
+ // NOTE: It would not have been correct to have used
+ // CollectedHeap::fill_with_object() and make the space look like
+ // an int array. The thread that is doing the allocation will
+ // later update the object header to a potentially different array
+ // type and, for a very short period of time, the klass and length
+ // fields will be inconsistent. This could cause a refinement
+ // thread to calculate the object size incorrectly.
+ Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
+
+ // We will set up the first region as "starts humongous". This
+ // will also update the BOT covering all the regions to reflect
+ // that there is a single object that starts at the bottom of the
+ // first region.
+ first_hr->set_startsHumongous(new_top, new_end);
+
+ // Then, if there are any, we will set up the "continues
+ // humongous" regions.
+ HeapRegion* hr = NULL;
+ for (int i = first + 1; i < last; ++i) {
+ hr = _hrs->at(i);
+ hr->set_continuesHumongous(first_hr);
+ }
+ // If we have "continues humongous" regions (hr != NULL), then the
+ // end of the last one should match new_end.
+ assert(hr == NULL || hr->end() == new_end, "sanity");
+
+ // Up to this point no concurrent thread would have been able to
+ // do any scanning on any region in this series. All the top
+ // fields still point to bottom, so the intersection between
+ // [bottom,top] and [card_start,card_end] will be empty. Before we
+ // update the top fields, we'll do a storestore to make sure that
+ // no thread sees the update to top before the zeroing of the
+ // object header and the BOT initialization.
+ OrderAccess::storestore();
+
+ // Now that the BOT and the object header have been initialized,
+ // we can update top of the "starts humongous" region.
+ assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
+ "new_top should be in this region");
+ first_hr->set_top(new_top);
+
+ // Now, we will update the top fields of the "continues humongous"
+ // regions. The reason we need to do this is that, otherwise,
+ // these regions would look empty and this will confuse parts of
+ // G1. For example, the code that looks for a consecutive number
+ // of empty regions will consider them empty and try to
+ // re-allocate them. We can extend is_empty() to also include
+ // !continuesHumongous(), but it is easier to just update the top
+ // fields here. The way we set top for all regions (i.e., top ==
+ // end for all regions but the last one, top == new_top for the
+ // last one) is actually used when we will free up the humongous
+ // region in free_humongous_region().
+ hr = NULL;
+ for (int i = first + 1; i < last; ++i) {
+ hr = _hrs->at(i);
+ if ((i + 1) == last) {
+ // last continues humongous region
+ assert(hr->bottom() < new_top && new_top <= hr->end(),
+ "new_top should fall on this region");
+ hr->set_top(new_top);
+ } else {
+ // not last one
+ assert(new_top > hr->end(), "new_top should be above this region");
+ hr->set_top(hr->end());
}
}
- }
- if (res != NULL) {
- // Increment by the number of regions allocated.
- // FIXME: Assumes regions all of size GrainBytes.
-#ifndef PRODUCT
- mr_bs()->verify_clean_region(MemRegion(res, res + num_regions *
- HeapRegion::GrainWords));
-#endif
- if (!eliminated_allocated_from_lists)
- remove_allocated_regions_from_lists();
- _summary_bytes_used += word_size * HeapWordSize;
- _free_regions -= num_regions;
- _num_humongous_regions += (int) num_regions;
- }
- assert(regions_accounted_for(), "Region Leakage");
- return res;
+ // If we have continues humongous regions (hr != NULL), then the
+ // end of the last one should match new_end and its top should
+ // match new_top.
+ assert(hr == NULL ||
+ (hr->end() == new_end && hr->top() == new_top), "sanity");
+
+ assert(first_hr->used() == word_size * HeapWordSize, "invariant");
+ _summary_bytes_used += first_hr->used();
+ _humongous_set.add(first_hr);
+
+ return new_obj;
+ }
+
+ verify_region_sets_optional();
+ return NULL;
}
void
G1CollectedHeap::retire_cur_alloc_region(HeapRegion* cur_alloc_region) {
- // The cleanup operation might update _summary_bytes_used
- // concurrently with this method. So, right now, if we don't wait
- // for it to complete, updates to _summary_bytes_used might get
- // lost. This will be resolved in the near future when the operation
- // of the free region list is revamped as part of CR 6977804.
- wait_for_cleanup_complete();
+ // Other threads might still be trying to allocate using CASes out
+ // of the region we are retiring, as they can do so without holding
+ // the Heap_lock. So we first have to make sure that noone else can
+ // allocate in it by doing a maximal allocation. Even if our CAS
+ // attempt fails a few times, we'll succeed sooner or later given
+ // that a failed CAS attempt mean that the region is getting closed
+ // to being full (someone else succeeded in allocating into it).
+ size_t free_word_size = cur_alloc_region->free() / HeapWordSize;
+
+ // This is the minimum free chunk we can turn into a dummy
+ // object. If the free space falls below this, then noone can
+ // allocate in this region anyway (all allocation requests will be
+ // of a size larger than this) so we won't have to perform the dummy
+ // allocation.
+ size_t min_word_size_to_fill = CollectedHeap::min_fill_size();
+
+ while (free_word_size >= min_word_size_to_fill) {
+ HeapWord* dummy =
+ cur_alloc_region->par_allocate_no_bot_updates(free_word_size);
+ if (dummy != NULL) {
+ // If the allocation was successful we should fill in the space.
+ CollectedHeap::fill_with_object(dummy, free_word_size);
+ break;
+ }
+
+ free_word_size = cur_alloc_region->free() / HeapWordSize;
+ // It's also possible that someone else beats us to the
+ // allocation and they fill up the region. In that case, we can
+ // just get out of the loop
+ }
+ assert(cur_alloc_region->free() / HeapWordSize < min_word_size_to_fill,
+ "sanity");
retire_cur_alloc_region_common(cur_alloc_region);
assert(_cur_alloc_region == NULL, "post-condition");
@@ -621,7 +800,7 @@
bool at_safepoint,
bool do_dirtying,
bool can_expand) {
- assert_heap_locked_or_at_safepoint();
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
assert(_cur_alloc_region == NULL,
"replace_cur_alloc_region_and_allocate() should only be called "
"after retiring the previous current alloc region");
@@ -632,25 +811,12 @@
"we are not allowed to expand the young gen");
if (can_expand || !g1_policy()->is_young_list_full()) {
- if (!at_safepoint) {
- // The cleanup operation might update _summary_bytes_used
- // concurrently with this method. So, right now, if we don't
- // wait for it to complete, updates to _summary_bytes_used might
- // get lost. This will be resolved in the near future when the
- // operation of the free region list is revamped as part of
- // CR 6977804. If we're already at a safepoint, this call is
- // unnecessary, not to mention wrong.
- wait_for_cleanup_complete();
- }
-
- HeapRegion* new_cur_alloc_region = newAllocRegion(word_size,
- false /* zero_filled */);
+ HeapRegion* new_cur_alloc_region = new_alloc_region(word_size);
if (new_cur_alloc_region != NULL) {
assert(new_cur_alloc_region->is_empty(),
"the newly-allocated region should be empty, "
"as right now we only allocate new regions out of the free list");
g1_policy()->update_region_num(true /* next_is_young */);
- _summary_bytes_used -= new_cur_alloc_region->used();
set_region_short_lived_locked(new_cur_alloc_region);
assert(!new_cur_alloc_region->isHumongous(),
@@ -661,27 +827,29 @@
// young type.
OrderAccess::storestore();
- // Now allocate out of the new current alloc region. We could
- // have re-used allocate_from_cur_alloc_region() but its
- // operation is slightly different to what we need here. First,
- // allocate_from_cur_alloc_region() is only called outside a
- // safepoint and will always unlock the Heap_lock if it returns
- // a non-NULL result. Second, it assumes that the current alloc
- // region is what's already assigned in _cur_alloc_region. What
- // we want here is to actually do the allocation first before we
- // assign the new region to _cur_alloc_region. This ordering is
- // not currently important, but it will be essential when we
- // change the code to support CAS allocation in the future (see
- // CR 6994297).
- //
- // This allocate method does BOT updates and we don't need them in
- // the young generation. This will be fixed in the near future by
- // CR 6994297.
- HeapWord* result = new_cur_alloc_region->allocate(word_size);
+ // Now, perform the allocation out of the region we just
+ // allocated. Note that noone else can access that region at
+ // this point (as _cur_alloc_region has not been updated yet),
+ // so we can just go ahead and do the allocation without any
+ // atomics (and we expect this allocation attempt to
+ // suceeded). Given that other threads can attempt an allocation
+ // with a CAS and without needing the Heap_lock, if we assigned
+ // the new region to _cur_alloc_region before first allocating
+ // into it other threads might have filled up the new region
+ // before we got a chance to do the allocation ourselves. In
+ // that case, we would have needed to retire the region, grab a
+ // new one, and go through all this again. Allocating out of the
+ // new region before assigning it to _cur_alloc_region avoids
+ // all this.
+ HeapWord* result =
+ new_cur_alloc_region->allocate_no_bot_updates(word_size);
assert(result != NULL, "we just allocate out of an empty region "
"so allocation should have been successful");
assert(is_in(result), "result should be in the heap");
+ // Now make sure that the store to _cur_alloc_region does not
+ // float above the store to top.
+ OrderAccess::storestore();
_cur_alloc_region = new_cur_alloc_region;
if (!at_safepoint) {
@@ -698,7 +866,7 @@
assert(_cur_alloc_region == NULL, "we failed to allocate a new current "
"alloc region, it should still be NULL");
- assert_heap_locked_or_at_safepoint();
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
return NULL;
}
@@ -710,6 +878,10 @@
assert(!isHumongous(word_size), "attempt_allocation_slow() should not be "
"used for humongous allocations");
+ // We should only reach here when we were unable to allocate
+ // otherwise. So, we should have not active current alloc region.
+ assert(_cur_alloc_region == NULL, "current alloc region should be NULL");
+
// We will loop while succeeded is false, which means that we tried
// to do a collection, but the VM op did not succeed. So, when we
// exit the loop, either one of the allocation attempts was
@@ -718,28 +890,8 @@
for (int try_count = 1; /* we'll return or break */; try_count += 1) {
bool succeeded = true;
- {
- // We may have concurrent cleanup working at the time. Wait for
- // it to complete. In the future we would probably want to make
- // the concurrent cleanup truly concurrent by decoupling it from
- // the allocation. This will happen in the near future as part
- // of CR 6977804 which will revamp the operation of the free
- // region list. The fact that wait_for_cleanup_complete() will
- // do a wait() means that we'll give up the Heap_lock. So, it's
- // possible that when we exit wait_for_cleanup_complete() we
- // might be able to allocate successfully (since somebody else
- // might have done a collection meanwhile). So, we'll attempt to
- // allocate again, just in case. When we make cleanup truly
- // concurrent with allocation, we should remove this allocation
- // attempt as it's redundant (we only reach here after an
- // allocation attempt has been unsuccessful).
- wait_for_cleanup_complete();
- HeapWord* result = attempt_allocation(word_size);
- if (result != NULL) {
- assert_heap_not_locked();
- return result;
- }
- }
+ // Every time we go round the loop we should be holding the Heap_lock.
+ assert_heap_locked();
if (GC_locker::is_active_and_needs_gc()) {
// We are locked out of GC because of the GC locker. We can
@@ -748,7 +900,6 @@
if (g1_policy()->can_expand_young_list()) {
// Yes, we are allowed to expand the young gen. Let's try to
// allocate a new current alloc region.
-
HeapWord* result =
replace_cur_alloc_region_and_allocate(word_size,
false, /* at_safepoint */
@@ -771,20 +922,23 @@
// rather than causing more, now probably unnecessary, GC attempts.
JavaThread* jthr = JavaThread::current();
assert(jthr != NULL, "sanity");
- if (!jthr->in_critical()) {
- MutexUnlocker mul(Heap_lock);
- GC_locker::stall_until_clear();
-
- // We'll then fall off the end of the ("if GC locker active")
- // if-statement and retry the allocation further down in the
- // loop.
- } else {
+ if (jthr->in_critical()) {
if (CheckJNICalls) {
fatal("Possible deadlock due to allocating while"
" in jni critical section");
}
+ // We are returning NULL so the protocol is that we're still
+ // holding the Heap_lock.
+ assert_heap_locked();
return NULL;
}
+
+ Heap_lock->unlock();
+ GC_locker::stall_until_clear();
+
+ // No need to relock the Heap_lock. We'll fall off to the code
+ // below the else-statement which assumes that we are not
+ // holding the Heap_lock.
} else {
// We are not locked out. So, let's try to do a GC. The VM op
// will retry the allocation before it completes.
@@ -805,11 +959,10 @@
dirty_young_block(result, word_size);
return result;
}
-
- Heap_lock->lock();
}
- assert_heap_locked();
+ // Both paths that get us here from above unlock the Heap_lock.
+ assert_heap_not_locked();
// We can reach here when we were unsuccessful in doing a GC,
// because another thread beat us to it, or because we were locked
@@ -854,7 +1007,7 @@
// allocation paths that attempt to allocate a humongous object
// should eventually reach here. Currently, the only paths are from
// mem_allocate() and attempt_allocation_at_safepoint().
- assert_heap_locked_or_at_safepoint();
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
assert(isHumongous(word_size), "attempt_allocation_humongous() "
"should only be used for humongous allocations");
assert(SafepointSynchronize::is_at_safepoint() == at_safepoint,
@@ -931,13 +1084,13 @@
}
}
- assert_heap_locked_or_at_safepoint();
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
return NULL;
}
HeapWord* G1CollectedHeap::attempt_allocation_at_safepoint(size_t word_size,
bool expect_null_cur_alloc_region) {
- assert_at_safepoint();
+ assert_at_safepoint(true /* should_be_vm_thread */);
assert(_cur_alloc_region == NULL || !expect_null_cur_alloc_region,
err_msg("the current alloc region was unexpectedly found "
"to be non-NULL, cur alloc region: "PTR_FORMAT" "
@@ -948,10 +1101,8 @@
if (!expect_null_cur_alloc_region) {
HeapRegion* cur_alloc_region = _cur_alloc_region;
if (cur_alloc_region != NULL) {
- // This allocate method does BOT updates and we don't need them in
- // the young generation. This will be fixed in the near future by
- // CR 6994297.
- HeapWord* result = cur_alloc_region->allocate(word_size);
+ // We are at a safepoint so no reason to use the MT-safe version.
+ HeapWord* result = cur_alloc_region->allocate_no_bot_updates(word_size);
if (result != NULL) {
assert(is_in(result), "result should be in the heap");
@@ -983,20 +1134,17 @@
assert_heap_not_locked_and_not_at_safepoint();
assert(!isHumongous(word_size), "we do not allow TLABs of humongous size");
- Heap_lock->lock();
-
- // First attempt: try allocating out of the current alloc region or
- // after replacing the current alloc region.
+ // First attempt: Try allocating out of the current alloc region
+ // using a CAS. If that fails, take the Heap_lock and retry the
+ // allocation, potentially replacing the current alloc region.
HeapWord* result = attempt_allocation(word_size);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
- assert_heap_locked();
-
- // Second attempt: go into the even slower path where we might
- // try to schedule a collection.
+ // Second attempt: Go to the slower path where we might try to
+ // schedule a collection.
result = attempt_allocation_slow(word_size);
if (result != NULL) {
assert_heap_not_locked();
@@ -1004,6 +1152,7 @@
}
assert_heap_locked();
+ // Need to unlock the Heap_lock before returning.
Heap_lock->unlock();
return NULL;
}
@@ -1022,11 +1171,10 @@
for (int try_count = 1; /* we'll return */; try_count += 1) {
unsigned int gc_count_before;
{
- Heap_lock->lock();
-
if (!isHumongous(word_size)) {
- // First attempt: try allocating out of the current alloc
- // region or after replacing the current alloc region.
+ // First attempt: Try allocating out of the current alloc region
+ // using a CAS. If that fails, take the Heap_lock and retry the
+ // allocation, potentially replacing the current alloc region.
HeapWord* result = attempt_allocation(word_size);
if (result != NULL) {
assert_heap_not_locked();
@@ -1035,14 +1183,17 @@
assert_heap_locked();
- // Second attempt: go into the even slower path where we might
- // try to schedule a collection.
+ // Second attempt: Go to the slower path where we might try to
+ // schedule a collection.
result = attempt_allocation_slow(word_size);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
} else {
+ // attempt_allocation_humongous() requires the Heap_lock to be held.
+ Heap_lock->lock();
+
HeapWord* result = attempt_allocation_humongous(word_size,
false /* at_safepoint */);
if (result != NULL) {
@@ -1054,7 +1205,8 @@
assert_heap_locked();
// Read the gc count while the heap lock is held.
gc_count_before = SharedHeap::heap()->total_collections();
- // We cannot be at a safepoint, so it is safe to unlock the Heap_lock
+
+ // Release the Heap_lock before attempting the collection.
Heap_lock->unlock();
}
@@ -1092,22 +1244,18 @@
}
void G1CollectedHeap::abandon_cur_alloc_region() {
- if (_cur_alloc_region != NULL) {
- // We're finished with the _cur_alloc_region.
- if (_cur_alloc_region->is_empty()) {
- _free_regions++;
- free_region(_cur_alloc_region);
- } else {
- // As we're builing (at least the young portion) of the collection
- // set incrementally we'll add the current allocation region to
- // the collection set here.
- if (_cur_alloc_region->is_young()) {
- g1_policy()->add_region_to_incremental_cset_lhs(_cur_alloc_region);
- }
- _summary_bytes_used += _cur_alloc_region->used();
- }
- _cur_alloc_region = NULL;
- }
+ assert_at_safepoint(true /* should_be_vm_thread */);
+
+ HeapRegion* cur_alloc_region = _cur_alloc_region;
+ if (cur_alloc_region != NULL) {
+ assert(!cur_alloc_region->is_empty(),
+ "the current alloc region can never be empty");
+ assert(cur_alloc_region->is_young(),
+ "the current alloc region should be young");
+
+ retire_cur_alloc_region_common(cur_alloc_region);
+ }
+ assert(_cur_alloc_region == NULL, "post-condition");
}
void G1CollectedHeap::abandon_gc_alloc_regions() {
@@ -1188,19 +1336,20 @@
bool G1CollectedHeap::do_collection(bool explicit_gc,
bool clear_all_soft_refs,
size_t word_size) {
+ assert_at_safepoint(true /* should_be_vm_thread */);
+
if (GC_locker::check_active_before_gc()) {
return false;
}
- DTraceGCProbeMarker gc_probe_marker(true /* full */);
+ SvcGCMarker sgcm(SvcGCMarker::FULL);
ResourceMark rm;
if (PrintHeapAtGC) {
Universe::print_heap_before_gc();
}
- assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
- assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
+ verify_region_sets_optional();
const bool do_clear_all_soft_refs = clear_all_soft_refs ||
collector_policy()->should_clear_all_soft_refs();
@@ -1223,6 +1372,9 @@
double start = os::elapsedTime();
g1_policy()->record_full_collection_start();
+ wait_while_free_regions_coming();
+ append_secondary_free_list_if_not_empty();
+
gc_prologue(true);
increment_total_collections(true /* full gc */);
@@ -1235,7 +1387,6 @@
gclog_or_tty->print(" VerifyBeforeGC:");
Universe::verify(true);
}
- assert(regions_accounted_for(), "Region leakage!");
COMPILER2_PRESENT(DerivedPointerTable::clear());
@@ -1259,7 +1410,6 @@
assert(_cur_alloc_region == NULL, "Invariant.");
g1_rem_set()->cleanupHRRS();
tear_down_region_lists();
- set_used_regions_to_need_zero_fill();
// We may have added regions to the current incremental collection
// set between the last GC or pause and now. We need to clear the
@@ -1294,9 +1444,7 @@
HandleMark hm; // Discard invalid handles created during gc
G1MarkSweep::invoke_at_safepoint(ref_processor(), do_clear_all_soft_refs);
}
- // Because freeing humongous regions may have added some unclean
- // regions, it is necessary to tear down again before rebuilding.
- tear_down_region_lists();
+ assert(free_regions() == 0, "we should not have added any free regions");
rebuild_region_lists();
_summary_bytes_used = recalculate_used();
@@ -1378,7 +1526,6 @@
JavaThread::dirty_card_queue_set().abandon_logs();
assert(!G1DeferredRSUpdate
|| (G1DeferredRSUpdate && (dirty_card_queue_set().completed_buffers_num() == 0)), "Should not be any");
- assert(regions_accounted_for(), "Region leakage!");
}
if (g1_policy()->in_young_gc_mode()) {
@@ -1392,6 +1539,8 @@
// Update the number of full collections that have been completed.
increment_full_collections_completed(false /* concurrent */);
+ verify_region_sets_optional();
+
if (PrintHeapAtGC) {
Universe::print_heap_after_gc();
}
@@ -1532,10 +1681,7 @@
HeapWord*
G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
bool* succeeded) {
- assert(SafepointSynchronize::is_at_safepoint(),
- "satisfy_failed_allocation() should only be called at a safepoint");
- assert(Thread::current()->is_VM_thread(),
- "satisfy_failed_allocation() should only be called by the VM thread");
+ assert_at_safepoint(true /* should_be_vm_thread */);
*succeeded = true;
// Let's attempt the allocation first.
@@ -1607,53 +1753,22 @@
// allocated block, or else "NULL".
HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
- assert(SafepointSynchronize::is_at_safepoint(),
- "expand_and_allocate() should only be called at a safepoint");
- assert(Thread::current()->is_VM_thread(),
- "expand_and_allocate() should only be called by the VM thread");
+ assert_at_safepoint(true /* should_be_vm_thread */);
+
+ verify_region_sets_optional();
size_t expand_bytes = word_size * HeapWordSize;
if (expand_bytes < MinHeapDeltaBytes) {
expand_bytes = MinHeapDeltaBytes;
}
expand(expand_bytes);
- assert(regions_accounted_for(), "Region leakage!");
+
+ verify_region_sets_optional();
return attempt_allocation_at_safepoint(word_size,
false /* expect_null_cur_alloc_region */);
}
-size_t G1CollectedHeap::free_region_if_totally_empty(HeapRegion* hr) {
- size_t pre_used = 0;
- size_t cleared_h_regions = 0;
- size_t freed_regions = 0;
- UncleanRegionList local_list;
- free_region_if_totally_empty_work(hr, pre_used, cleared_h_regions,
- freed_regions, &local_list);
-
- finish_free_region_work(pre_used, cleared_h_regions, freed_regions,
- &local_list);
- return pre_used;
-}
-
-void
-G1CollectedHeap::free_region_if_totally_empty_work(HeapRegion* hr,
- size_t& pre_used,
- size_t& cleared_h,
- size_t& freed_regions,
- UncleanRegionList* list,
- bool par) {
- assert(!hr->continuesHumongous(), "should have filtered these out");
- size_t res = 0;
- if (hr->used() > 0 && hr->garbage_bytes() == hr->used() &&
- !hr->is_young()) {
- if (G1PolicyVerbose > 0)
- gclog_or_tty->print_cr("Freeing empty region "PTR_FORMAT "(" SIZE_FORMAT " bytes)"
- " during cleanup", hr, hr->used());
- free_region_work(hr, pre_used, cleared_h, freed_regions, list, par);
- }
-}
-
// FIXME: both this and shrink could probably be more efficient by
// doing one "VirtualSpace::expand_by" call rather than several.
void G1CollectedHeap::expand(size_t expand_bytes) {
@@ -1686,19 +1801,7 @@
// Add it to the HeapRegionSeq.
_hrs->insert(hr);
- // Set the zero-fill state, according to whether it's already
- // zeroed.
- {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- if (is_zeroed) {
- hr->set_zero_fill_complete();
- put_free_region_on_list_locked(hr);
- } else {
- hr->set_zero_fill_needed();
- put_region_on_unclean_list_locked(hr);
- }
- }
- _free_regions++;
+ _free_list.add_as_tail(hr);
// And we used up an expansion region to create it.
_expansion_regions--;
// Tell the cardtable about it.
@@ -1707,6 +1810,7 @@
_bot_shared->resize(_g1_committed.word_size());
}
}
+
if (Verbose && PrintGC) {
size_t new_mem_size = _g1_storage.committed_size();
gclog_or_tty->print_cr("Expanding garbage-first heap from %ldK by %ldK to %ldK",
@@ -1731,7 +1835,6 @@
assert(mr.start() == (HeapWord*)_g1_storage.high(), "Bad shrink!");
_g1_committed.set_end(mr.start());
- _free_regions -= num_regions_deleted;
_expansion_regions += num_regions_deleted;
// Tell the cardtable about it.
@@ -1751,10 +1854,17 @@
}
void G1CollectedHeap::shrink(size_t shrink_bytes) {
+ verify_region_sets_optional();
+
release_gc_alloc_regions(true /* totally */);
+ // Instead of tearing down / rebuilding the free lists here, we
+ // could instead use the remove_all_pending() method on free_list to
+ // remove only the ones that we need to remove.
tear_down_region_lists(); // We will rebuild them in a moment.
shrink_helper(shrink_bytes);
rebuild_region_lists();
+
+ verify_region_sets_optional();
}
// Public methods.
@@ -1773,18 +1883,17 @@
_ref_processor(NULL),
_process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)),
_bot_shared(NULL),
- _par_alloc_during_gc_lock(Mutex::leaf, "par alloc during GC lock"),
_objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL),
_evac_failure_scan_stack(NULL) ,
_mark_in_progress(false),
- _cg1r(NULL), _czft(NULL), _summary_bytes_used(0),
+ _cg1r(NULL), _summary_bytes_used(0),
_cur_alloc_region(NULL),
_refine_cte_cl(NULL),
- _free_region_list(NULL), _free_region_list_size(0),
- _free_regions(0),
_full_collection(false),
- _unclean_region_list(),
- _unclean_regions_coming(false),
+ _free_list("Master Free List"),
+ _secondary_free_list("Secondary Free List"),
+ _humongous_set("Master Humongous Set"),
+ _free_regions_coming(false),
_young_list(new YoungList(this)),
_gc_time_stamp(0),
_surviving_young_words(NULL),
@@ -1868,7 +1977,7 @@
ReservedSpace heap_rs(max_byte_size + pgs->max_size(),
HeapRegion::GrainBytes,
- false /*ism*/, addr);
+ UseLargePages, addr);
if (UseCompressedOops) {
if (addr != NULL && !heap_rs.is_reserved()) {
@@ -1877,13 +1986,13 @@
// Try again to reserver heap higher.
addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
- false /*ism*/, addr);
+ UseLargePages, addr);
if (addr != NULL && !heap_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up.
addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
- false /*ism*/, addr);
+ UseLargePages, addr);
heap_rs = heap_rs1;
} else {
heap_rs = heap_rs0;
@@ -1905,8 +2014,6 @@
_expansion_regions = max_byte_size/HeapRegion::GrainBytes;
- _num_humongous_regions = 0;
-
// Create the gen rem set (and barrier set) for the entire reserved region.
_rem_set = collector_policy()->create_rem_set(_reserved, 2);
set_barrier_set(rem_set()->bs());
@@ -1951,6 +2058,8 @@
guarantee((size_t) HeapRegion::CardsPerRegion < max_cards_per_region,
"too many cards per region");
+ HeapRegionSet::set_unrealistically_long_length(max_regions() + 1);
+
_bot_shared = new G1BlockOffsetSharedArray(_reserved,
heap_word_size(init_byte_size));
@@ -1975,11 +2084,6 @@
_cm = new ConcurrentMark(heap_rs, (int) max_regions());
_cmThread = _cm->cmThread();
- // ...and the concurrent zero-fill thread, if necessary.
- if (G1ConcZeroFill) {
- _czft = new ConcurrentZFThread();
- }
-
// Initialize the from_card cache structure of HeapRegionRemSet.
HeapRegionRemSet::init_heap(max_regions());
@@ -2153,7 +2257,7 @@
#endif // PRODUCT
size_t G1CollectedHeap::unsafe_max_alloc() {
- if (_free_regions > 0) return HeapRegion::GrainBytes;
+ if (free_regions() > 0) return HeapRegion::GrainBytes;
// otherwise, is there space in the current allocation region?
// We need to store the current allocation region in a local variable
@@ -2233,8 +2337,7 @@
}
void G1CollectedHeap::collect_as_vm_thread(GCCause::Cause cause) {
- assert(Thread::current()->is_VM_thread(), "Precondition#1");
- assert(Heap_lock->is_locked(), "Precondition#2");
+ assert_at_safepoint(true /* should_be_vm_thread */);
GCCauseSetter gcs(this, cause);
switch (cause) {
case GCCause::_heap_inspection:
@@ -2257,12 +2360,6 @@
{
MutexLocker ml(Heap_lock);
- // Don't want to do a GC until cleanup is completed. This
- // limitation will be removed in the near future when the
- // operation of the free region list is revamped as part of
- // CR 6977804.
- wait_for_cleanup_complete();
-
// Read the GC count while holding the Heap_lock
gc_count_before = SharedHeap::heap()->total_collections();
full_gc_count_before = SharedHeap::heap()->total_full_collections();
@@ -2641,10 +2738,6 @@
}
}
-bool G1CollectedHeap::allocs_are_zero_filled() {
- return false;
-}
-
size_t G1CollectedHeap::large_typearray_limit() {
// FIXME
return HeapRegion::GrainBytes/HeapWordSize;
@@ -2659,7 +2752,6 @@
return 0;
}
-
void G1CollectedHeap::prepare_for_verify() {
if (SafepointSynchronize::is_at_safepoint() || ! UseTLAB) {
ensure_parsability(false);
@@ -2870,7 +2962,9 @@
&rootsCl);
bool failures = rootsCl.failures();
rem_set()->invalidate(perm_gen()->used_region(), false);
- if (!silent) { gclog_or_tty->print("heapRegions "); }
+ if (!silent) { gclog_or_tty->print("HeapRegionSets "); }
+ verify_region_sets();
+ if (!silent) { gclog_or_tty->print("HeapRegions "); }
if (GCParallelVerificationEnabled && ParallelGCThreads > 1) {
assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue),
"sanity check");
@@ -2898,7 +2992,7 @@
failures = true;
}
}
- if (!silent) gclog_or_tty->print("remset ");
+ if (!silent) gclog_or_tty->print("RemSet ");
rem_set()->verify();
if (failures) {
@@ -2969,15 +3063,10 @@
if (G1CollectedHeap::use_parallel_gc_threads()) {
workers()->print_worker_threads_on(st);
}
-
_cmThread->print_on(st);
st->cr();
-
_cm->print_worker_threads_on(st);
-
_cg1r->print_worker_threads_on(st);
-
- _czft->print_on(st);
st->cr();
}
@@ -2987,7 +3076,6 @@
}
tc->do_thread(_cmThread);
_cg1r->threads_do(tc);
- tc->do_thread(_czft);
}
void G1CollectedHeap::print_tracing_info() const {
@@ -3003,15 +3091,10 @@
if (G1SummarizeConcMark) {
concurrent_mark()->print_summary_info();
}
- if (G1SummarizeZFStats) {
- ConcurrentZFThread::print_summary_info();
- }
g1_policy()->print_yg_surv_rate_info();
-
SpecializationStats::print();
}
-
int G1CollectedHeap::addr_to_arena_id(void* addr) const {
HeapRegion* hr = heap_region_containing(addr);
if (hr == NULL) {
@@ -3210,17 +3293,22 @@
bool
G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
+ assert_at_safepoint(true /* should_be_vm_thread */);
+ guarantee(!is_gc_active(), "collection is not reentrant");
+
if (GC_locker::check_active_before_gc()) {
return false;
}
- DTraceGCProbeMarker gc_probe_marker(false /* full */);
+ SvcGCMarker sgcm(SvcGCMarker::MINOR);
ResourceMark rm;
if (PrintHeapAtGC) {
Universe::print_heap_before_gc();
}
+ verify_region_sets_optional();
+
{
// This call will decide whether this pause is an initial-mark
// pause. If it is, during_initial_mark_pause() will return true
@@ -3251,10 +3339,16 @@
TraceMemoryManagerStats tms(false /* fullGC */);
- assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
- assert(Thread::current() == VMThread::vm_thread(), "should be in vm thread");
- guarantee(!is_gc_active(), "collection is not reentrant");
- assert(regions_accounted_for(), "Region leakage!");
+ // If there are any free regions available on the secondary_free_list
+ // make sure we append them to the free_list. However, we don't
+ // have to wait for the rest of the cleanup operation to
+ // finish. If it's still going on that's OK. If we run out of
+ // regions, the region allocation code will check the
+ // secondary_free_list and potentially wait if more free regions
+ // are coming (see new_region_try_secondary_free_list()).
+ if (!G1StressConcRegionFreeing) {
+ append_secondary_free_list_if_not_empty();
+ }
increment_gc_time_stamp();
@@ -3334,8 +3428,6 @@
// progress, this will be zero.
_cm->set_oops_do_bound();
- assert(regions_accounted_for(), "Region leakage.");
-
if (mark_in_progress())
concurrent_mark()->newCSet();
@@ -3431,8 +3523,6 @@
g1_policy()->record_pause_time_ms(pause_time_ms);
g1_policy()->record_collection_pause_end();
- assert(regions_accounted_for(), "Region leakage.");
-
MemoryService::track_memory_usage();
if (VerifyAfterGC && total_collections() >= VerifyGCStartAt) {
@@ -3463,8 +3553,6 @@
gc_epilogue(false);
}
- assert(verify_region_lists(), "Bad region lists.");
-
if (ExitAfterGCNum > 0 && total_collections() == ExitAfterGCNum) {
gclog_or_tty->print_cr("Stopping after GC #%d", ExitAfterGCNum);
print_tracing_info();
@@ -3472,6 +3560,8 @@
}
}
+ verify_region_sets_optional();
+
TASKQUEUE_STATS_ONLY(if (ParallelGCVerbose) print_taskqueue_stats());
TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
@@ -3578,7 +3668,7 @@
void G1CollectedHeap::push_gc_alloc_region(HeapRegion* hr) {
assert(Thread::current()->is_VM_thread() ||
- par_alloc_during_gc_lock()->owned_by_self(), "Precondition");
+ FreeList_lock->owned_by_self(), "Precondition");
assert(!hr->is_gc_alloc_region() && !hr->in_collection_set(),
"Precondition.");
hr->set_is_gc_alloc_region(true);
@@ -3600,7 +3690,7 @@
#endif // G1_DEBUG
void G1CollectedHeap::forget_alloc_region_list() {
- assert(Thread::current()->is_VM_thread(), "Precondition");
+ assert_at_safepoint(true /* should_be_vm_thread */);
while (_gc_alloc_region_list != NULL) {
HeapRegion* r = _gc_alloc_region_list;
assert(r->is_gc_alloc_region(), "Invariant.");
@@ -3620,9 +3710,6 @@
_young_list->add_survivor_region(r);
}
}
- if (r->is_empty()) {
- ++_free_regions;
- }
}
#ifdef G1_DEBUG
FindGCAllocRegion fa;
@@ -3675,7 +3762,7 @@
if (alloc_region == NULL) {
// we will get a new GC alloc region
- alloc_region = newAllocRegionWithExpansion(ap, 0);
+ alloc_region = new_gc_alloc_region(ap, 0);
} else {
// the region was retained from the last collection
++_gc_alloc_region_counts[ap];
@@ -3730,11 +3817,9 @@
set_gc_alloc_region(ap, NULL);
if (r->is_empty()) {
- // we didn't actually allocate anything in it; let's just put
- // it on the free list
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- r->set_zero_fill_complete();
- put_free_region_on_list_locked(r);
+ // We didn't actually allocate anything in it; let's just put
+ // it back on the free list.
+ _free_list.add_as_tail(r);
} else if (_retain_gc_alloc_region[ap] && !totally) {
// retain it so that we can use it at the beginning of the next GC
_retained_gc_alloc_regions[ap] = r;
@@ -3856,13 +3941,15 @@
size_t _next_marked_bytes;
OopsInHeapRegionClosure *_cl;
public:
- RemoveSelfPointerClosure(G1CollectedHeap* g1, OopsInHeapRegionClosure* cl) :
- _g1(g1), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0),
+ RemoveSelfPointerClosure(G1CollectedHeap* g1, HeapRegion* hr,
+ OopsInHeapRegionClosure* cl) :
+ _g1(g1), _hr(hr), _cm(_g1->concurrent_mark()), _prev_marked_bytes(0),
_next_marked_bytes(0), _cl(cl) {}
size_t prev_marked_bytes() { return _prev_marked_bytes; }
size_t next_marked_bytes() { return _next_marked_bytes; }
+ // <original comment>
// The original idea here was to coalesce evacuated and dead objects.
// However that caused complications with the block offset table (BOT).
// In particular if there were two TLABs, one of them partially refined.
@@ -3871,15 +3958,24 @@
// of TLAB_2. If the last object of the TLAB_1 and the first object
// of TLAB_2 are coalesced, then the cards of the unrefined part
// would point into middle of the filler object.
+ // The current approach is to not coalesce and leave the BOT contents intact.
+ // </original comment>
//
- // The current approach is to not coalesce and leave the BOT contents intact.
+ // We now reset the BOT when we start the object iteration over the
+ // region and refine its entries for every object we come across. So
+ // the above comment is not really relevant and we should be able
+ // to coalesce dead objects if we want to.
void do_object(oop obj) {
+ HeapWord* obj_addr = (HeapWord*) obj;
+ assert(_hr->is_in(obj_addr), "sanity");
+ size_t obj_size = obj->size();
+ _hr->update_bot_for_object(obj_addr, obj_size);
if (obj->is_forwarded() && obj->forwardee() == obj) {
// The object failed to move.
assert(!_g1->is_obj_dead(obj), "We should not be preserving dead objs.");
_cm->markPrev(obj);
assert(_cm->isPrevMarked(obj), "Should be marked!");
- _prev_marked_bytes += (obj->size() * HeapWordSize);
+ _prev_marked_bytes += (obj_size * HeapWordSize);
if (_g1->mark_in_progress() && !_g1->is_obj_ill(obj)) {
_cm->markAndGrayObjectIfNecessary(obj);
}
@@ -3901,7 +3997,7 @@
} else {
// The object has been either evacuated or is dead. Fill it with a
// dummy object.
- MemRegion mr((HeapWord*)obj, obj->size());
+ MemRegion mr((HeapWord*)obj, obj_size);
CollectedHeap::fill_with_object(mr);
_cm->clearRangeBothMaps(mr);
}
@@ -3921,10 +4017,13 @@
HeapRegion* cur = g1_policy()->collection_set();
while (cur != NULL) {
assert(g1_policy()->assertMarkedBytesDataOK(), "Should be!");
-
- RemoveSelfPointerClosure rspc(_g1h, cl);
+ assert(!cur->isHumongous(), "sanity");
+
if (cur->evacuation_failed()) {
assert(cur->in_collection_set(), "bad CS");
+ RemoveSelfPointerClosure rspc(_g1h, cur, cl);
+
+ cur->reset_bot();
cl->set_region(cur);
cur->object_iterate(&rspc);
@@ -3989,15 +4088,6 @@
}
}
-void G1CollectedHeap::handle_evacuation_failure(oop old) {
- markOop m = old->mark();
- // forward to self
- assert(!old->is_forwarded(), "precondition");
-
- old->forward_to(old);
- handle_evacuation_failure_common(old, m);
-}
-
oop
G1CollectedHeap::handle_evacuation_failure_par(OopsInHeapRegionClosure* cl,
oop old) {
@@ -4084,8 +4174,6 @@
HeapWord* block = alloc_region->par_allocate(word_size);
if (block == NULL) {
- MutexLockerEx x(par_alloc_during_gc_lock(),
- Mutex::_no_safepoint_check_flag);
block = allocate_during_gc_slow(purpose, alloc_region, true, word_size);
}
return block;
@@ -4114,6 +4202,12 @@
err_msg("we should not be seeing humongous allocation requests "
"during GC, word_size = "SIZE_FORMAT, word_size));
+ // We need to make sure we serialize calls to this method. Given
+ // that the FreeList_lock guards accesses to the free_list anyway,
+ // and we need to potentially remove a region from it, we'll use it
+ // to protect the whole call.
+ MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+
HeapWord* block = NULL;
// In the parallel case, a previous thread to obtain the lock may have
// already assigned a new gc_alloc_region.
@@ -4159,7 +4253,7 @@
}
// Now allocate a new region for allocation.
- alloc_region = newAllocRegionWithExpansion(purpose, word_size, false /*zero_filled*/);
+ alloc_region = new_gc_alloc_region(purpose, word_size);
// let the caller handle alloc failure
if (alloc_region != NULL) {
@@ -4167,9 +4261,6 @@
assert(check_gc_alloc_regions(), "alloc regions messed up");
assert(alloc_region->saved_mark_at_top(),
"Mark should have been saved already.");
- // We used to assert that the region was zero-filled here, but no
- // longer.
-
// This must be done last: once it's installed, other regions may
// allocate in it (without holding the lock.)
set_gc_alloc_region(purpose, alloc_region);
@@ -4834,91 +4925,91 @@
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
}
-void G1CollectedHeap::free_region(HeapRegion* hr) {
- size_t pre_used = 0;
- size_t cleared_h_regions = 0;
- size_t freed_regions = 0;
- UncleanRegionList local_list;
-
- HeapWord* start = hr->bottom();
- HeapWord* end = hr->prev_top_at_mark_start();
- size_t used_bytes = hr->used();
- size_t live_bytes = hr->max_live_bytes();
- if (used_bytes > 0) {
- guarantee( live_bytes <= used_bytes, "invariant" );
- } else {
- guarantee( live_bytes == 0, "invariant" );
- }
-
- size_t garbage_bytes = used_bytes - live_bytes;
- if (garbage_bytes > 0)
- g1_policy()->decrease_known_garbage_bytes(garbage_bytes);
-
- free_region_work(hr, pre_used, cleared_h_regions, freed_regions,
- &local_list);
- finish_free_region_work(pre_used, cleared_h_regions, freed_regions,
- &local_list);
-}
-
-void
-G1CollectedHeap::free_region_work(HeapRegion* hr,
- size_t& pre_used,
- size_t& cleared_h_regions,
- size_t& freed_regions,
- UncleanRegionList* list,
- bool par) {
- pre_used += hr->used();
- if (hr->isHumongous()) {
- assert(hr->startsHumongous(),
- "Only the start of a humongous region should be freed.");
- int ind = _hrs->find(hr);
- assert(ind != -1, "Should have an index.");
- // Clear the start region.
- hr->hr_clear(par, true /*clear_space*/);
- list->insert_before_head(hr);
- cleared_h_regions++;
- freed_regions++;
- // Clear any continued regions.
- ind++;
- while ((size_t)ind < n_regions()) {
- HeapRegion* hrc = _hrs->at(ind);
- if (!hrc->continuesHumongous()) break;
- // Otherwise, does continue the H region.
- assert(hrc->humongous_start_region() == hr, "Huh?");
- hrc->hr_clear(par, true /*clear_space*/);
- cleared_h_regions++;
- freed_regions++;
- list->insert_before_head(hrc);
- ind++;
+void G1CollectedHeap::free_region_if_totally_empty(HeapRegion* hr,
+ size_t* pre_used,
+ FreeRegionList* free_list,
+ HumongousRegionSet* humongous_proxy_set,
+ bool par) {
+ if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young()) {
+ if (hr->isHumongous()) {
+ assert(hr->startsHumongous(), "we should only see starts humongous");
+ free_humongous_region(hr, pre_used, free_list, humongous_proxy_set, par);
+ } else {
+ free_region(hr, pre_used, free_list, par);
}
- } else {
- hr->hr_clear(par, true /*clear_space*/);
- list->insert_before_head(hr);
- freed_regions++;
- // If we're using clear2, this should not be enabled.
- // assert(!hr->in_cohort(), "Can't be both free and in a cohort.");
}
}
-void G1CollectedHeap::finish_free_region_work(size_t pre_used,
- size_t cleared_h_regions,
- size_t freed_regions,
- UncleanRegionList* list) {
- if (list != NULL && list->sz() > 0) {
- prepend_region_list_on_unclean_list(list);
- }
- // Acquire a lock, if we're parallel, to update possibly-shared
- // variables.
- Mutex* lock = (n_par_threads() > 0) ? ParGCRareEvent_lock : NULL;
- {
+void G1CollectedHeap::free_region(HeapRegion* hr,
+ size_t* pre_used,
+ FreeRegionList* free_list,
+ bool par) {
+ assert(!hr->isHumongous(), "this is only for non-humongous regions");
+ assert(!hr->is_empty(), "the region should not be empty");
+ assert(free_list != NULL, "pre-condition");
+
+ *pre_used += hr->used();
+ hr->hr_clear(par, true /* clear_space */);
+ free_list->add_as_tail(hr);
+}
+
+void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
+ size_t* pre_used,
+ FreeRegionList* free_list,
+ HumongousRegionSet* humongous_proxy_set,
+ bool par) {
+ assert(hr->startsHumongous(), "this is only for starts humongous regions");
+ assert(free_list != NULL, "pre-condition");
+ assert(humongous_proxy_set != NULL, "pre-condition");
+
+ size_t hr_used = hr->used();
+ size_t hr_capacity = hr->capacity();
+ size_t hr_pre_used = 0;
+ _humongous_set.remove_with_proxy(hr, humongous_proxy_set);
+ hr->set_notHumongous();
+ free_region(hr, &hr_pre_used, free_list, par);
+
+ int i = hr->hrs_index() + 1;
+ size_t num = 1;
+ while ((size_t) i < n_regions()) {
+ HeapRegion* curr_hr = _hrs->at(i);
+ if (!curr_hr->continuesHumongous()) {
+ break;
+ }
+ curr_hr->set_notHumongous();
+ free_region(curr_hr, &hr_pre_used, free_list, par);
+ num += 1;
+ i += 1;
+ }
+ assert(hr_pre_used == hr_used,
+ err_msg("hr_pre_used: "SIZE_FORMAT" and hr_used: "SIZE_FORMAT" "
+ "should be the same", hr_pre_used, hr_used));
+ *pre_used += hr_pre_used;
+}
+
+void G1CollectedHeap::update_sets_after_freeing_regions(size_t pre_used,
+ FreeRegionList* free_list,
+ HumongousRegionSet* humongous_proxy_set,
+ bool par) {
+ if (pre_used > 0) {
+ Mutex* lock = (par) ? ParGCRareEvent_lock : NULL;
MutexLockerEx x(lock, Mutex::_no_safepoint_check_flag);
+ assert(_summary_bytes_used >= pre_used,
+ err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" "
+ "should be >= pre_used: "SIZE_FORMAT,
+ _summary_bytes_used, pre_used));
_summary_bytes_used -= pre_used;
- _num_humongous_regions -= (int) cleared_h_regions;
- _free_regions += freed_regions;
+ }
+ if (free_list != NULL && !free_list->is_empty()) {
+ MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
+ _free_list.add_as_tail(free_list);
+ }
+ if (humongous_proxy_set != NULL && !humongous_proxy_set->is_empty()) {
+ MutexLockerEx x(OldSets_lock, Mutex::_no_safepoint_check_flag);
+ _humongous_set.update_from_proxy(humongous_proxy_set);
}
}
-
void G1CollectedHeap::dirtyCardsForYoungRegions(CardTableModRefBS* ct_bs, HeapRegion* list) {
while (list != NULL) {
guarantee( list->is_young(), "invariant" );
@@ -5041,6 +5132,9 @@
}
void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) {
+ size_t pre_used = 0;
+ FreeRegionList local_free_list("Local List for CSet Freeing");
+
double young_time_ms = 0.0;
double non_young_time_ms = 0.0;
@@ -5059,6 +5153,8 @@
size_t rs_lengths = 0;
while (cur != NULL) {
+ assert(!is_on_free_list(cur), "sanity");
+
if (non_young) {
if (cur->is_young()) {
double end_sec = os::elapsedTime();
@@ -5069,14 +5165,12 @@
non_young = false;
}
} else {
- if (!cur->is_on_free_list()) {
- double end_sec = os::elapsedTime();
- double elapsed_ms = (end_sec - start_sec) * 1000.0;
- young_time_ms += elapsed_ms;
-
- start_sec = os::elapsedTime();
- non_young = true;
- }
+ double end_sec = os::elapsedTime();
+ double elapsed_ms = (end_sec - start_sec) * 1000.0;
+ young_time_ms += elapsed_ms;
+
+ start_sec = os::elapsedTime();
+ non_young = true;
}
rs_lengths += cur->rem_set()->occupied();
@@ -5109,9 +5203,8 @@
if (!cur->evacuation_failed()) {
// And the region is empty.
- assert(!cur->is_empty(),
- "Should not have empty regions in a CS.");
- free_region(cur);
+ assert(!cur->is_empty(), "Should not have empty regions in a CS.");
+ free_region(cur, &pre_used, &local_free_list, false /* par */);
} else {
cur->uninstall_surv_rate_group();
if (cur->is_young())
@@ -5132,6 +5225,9 @@
else
young_time_ms += elapsed_ms;
+ update_sets_after_freeing_regions(pre_used, &local_free_list,
+ NULL /* humongous_proxy_set */,
+ false /* par */);
policy->record_young_free_cset_time_ms(young_time_ms);
policy->record_non_young_free_cset_time_ms(non_young_time_ms);
}
@@ -5157,291 +5253,53 @@
}
}
-HeapRegion*
-G1CollectedHeap::alloc_region_from_unclean_list_locked(bool zero_filled) {
- assert(ZF_mon->owned_by_self(), "Precondition");
- HeapRegion* res = pop_unclean_region_list_locked();
- if (res != NULL) {
- assert(!res->continuesHumongous() &&
- res->zero_fill_state() != HeapRegion::Allocated,
- "Only free regions on unclean list.");
- if (zero_filled) {
- res->ensure_zero_filled_locked();
- res->set_zero_fill_allocated();
- }
- }
- return res;
-}
-
-HeapRegion* G1CollectedHeap::alloc_region_from_unclean_list(bool zero_filled) {
- MutexLockerEx zx(ZF_mon, Mutex::_no_safepoint_check_flag);
- return alloc_region_from_unclean_list_locked(zero_filled);
+void G1CollectedHeap::set_free_regions_coming() {
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [cm thread] : "
+ "setting free regions coming");
+ }
+
+ assert(!free_regions_coming(), "pre-condition");
+ _free_regions_coming = true;
}
-void G1CollectedHeap::put_region_on_unclean_list(HeapRegion* r) {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- put_region_on_unclean_list_locked(r);
- if (should_zf()) ZF_mon->notify_all(); // Wake up ZF thread.
-}
-
-void G1CollectedHeap::set_unclean_regions_coming(bool b) {
- MutexLockerEx x(Cleanup_mon);
- set_unclean_regions_coming_locked(b);
-}
-
-void G1CollectedHeap::set_unclean_regions_coming_locked(bool b) {
- assert(Cleanup_mon->owned_by_self(), "Precondition");
- _unclean_regions_coming = b;
- // Wake up mutator threads that might be waiting for completeCleanup to
- // finish.
- if (!b) Cleanup_mon->notify_all();
-}
-
-void G1CollectedHeap::wait_for_cleanup_complete() {
- assert_not_at_safepoint();
- MutexLockerEx x(Cleanup_mon);
- wait_for_cleanup_complete_locked();
-}
-
-void G1CollectedHeap::wait_for_cleanup_complete_locked() {
- assert(Cleanup_mon->owned_by_self(), "precondition");
- while (_unclean_regions_coming) {
- Cleanup_mon->wait();
+void G1CollectedHeap::reset_free_regions_coming() {
+ {
+ assert(free_regions_coming(), "pre-condition");
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ _free_regions_coming = false;
+ SecondaryFreeList_lock->notify_all();
+ }
+
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [cm thread] : "
+ "reset free regions coming");
}
}
-void
-G1CollectedHeap::put_region_on_unclean_list_locked(HeapRegion* r) {
- assert(ZF_mon->owned_by_self(), "precondition.");
-#ifdef ASSERT
- if (r->is_gc_alloc_region()) {
- ResourceMark rm;
- stringStream region_str;
- print_on(®ion_str);
- assert(!r->is_gc_alloc_region(), err_msg("Unexpected GC allocation region: %s",
- region_str.as_string()));
- }
-#endif
- _unclean_region_list.insert_before_head(r);
-}
-
-void
-G1CollectedHeap::prepend_region_list_on_unclean_list(UncleanRegionList* list) {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- prepend_region_list_on_unclean_list_locked(list);
- if (should_zf()) ZF_mon->notify_all(); // Wake up ZF thread.
-}
-
-void
-G1CollectedHeap::
-prepend_region_list_on_unclean_list_locked(UncleanRegionList* list) {
- assert(ZF_mon->owned_by_self(), "precondition.");
- _unclean_region_list.prepend_list(list);
-}
-
-HeapRegion* G1CollectedHeap::pop_unclean_region_list_locked() {
- assert(ZF_mon->owned_by_self(), "precondition.");
- HeapRegion* res = _unclean_region_list.pop();
- if (res != NULL) {
- // Inform ZF thread that there's a new unclean head.
- if (_unclean_region_list.hd() != NULL && should_zf())
- ZF_mon->notify_all();
- }
- return res;
-}
-
-HeapRegion* G1CollectedHeap::peek_unclean_region_list_locked() {
- assert(ZF_mon->owned_by_self(), "precondition.");
- return _unclean_region_list.hd();
-}
-
-
-bool G1CollectedHeap::move_cleaned_region_to_free_list_locked() {
- assert(ZF_mon->owned_by_self(), "Precondition");
- HeapRegion* r = peek_unclean_region_list_locked();
- if (r != NULL && r->zero_fill_state() == HeapRegion::ZeroFilled) {
- // Result of below must be equal to "r", since we hold the lock.
- (void)pop_unclean_region_list_locked();
- put_free_region_on_list_locked(r);
- return true;
- } else {
- return false;
- }
-}
-
-bool G1CollectedHeap::move_cleaned_region_to_free_list() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- return move_cleaned_region_to_free_list_locked();
-}
-
-
-void G1CollectedHeap::put_free_region_on_list_locked(HeapRegion* r) {
- assert(ZF_mon->owned_by_self(), "precondition.");
- assert(_free_region_list_size == free_region_list_length(), "Inv");
- assert(r->zero_fill_state() == HeapRegion::ZeroFilled,
- "Regions on free list must be zero filled");
- assert(!r->isHumongous(), "Must not be humongous.");
- assert(r->is_empty(), "Better be empty");
- assert(!r->is_on_free_list(),
- "Better not already be on free list");
- assert(!r->is_on_unclean_list(),
- "Better not already be on unclean list");
- r->set_on_free_list(true);
- r->set_next_on_free_list(_free_region_list);
- _free_region_list = r;
- _free_region_list_size++;
- assert(_free_region_list_size == free_region_list_length(), "Inv");
-}
-
-void G1CollectedHeap::put_free_region_on_list(HeapRegion* r) {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- put_free_region_on_list_locked(r);
-}
-
-HeapRegion* G1CollectedHeap::pop_free_region_list_locked() {
- assert(ZF_mon->owned_by_self(), "precondition.");
- assert(_free_region_list_size == free_region_list_length(), "Inv");
- HeapRegion* res = _free_region_list;
- if (res != NULL) {
- _free_region_list = res->next_from_free_list();
- _free_region_list_size--;
- res->set_on_free_list(false);
- res->set_next_on_free_list(NULL);
- assert(_free_region_list_size == free_region_list_length(), "Inv");
- }
- return res;
-}
-
-
-HeapRegion* G1CollectedHeap::alloc_free_region_from_lists(bool zero_filled) {
- // By self, or on behalf of self.
- assert(Heap_lock->is_locked(), "Precondition");
- HeapRegion* res = NULL;
- bool first = true;
- while (res == NULL) {
- if (zero_filled || !first) {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- res = pop_free_region_list_locked();
- if (res != NULL) {
- assert(!res->zero_fill_is_allocated(),
- "No allocated regions on free list.");
- res->set_zero_fill_allocated();
- } else if (!first) {
- break; // We tried both, time to return NULL.
- }
- }
-
- if (res == NULL) {
- res = alloc_region_from_unclean_list(zero_filled);
- }
- assert(res == NULL ||
- !zero_filled ||
- res->zero_fill_is_allocated(),
- "We must have allocated the region we're returning");
- first = false;
- }
- return res;
-}
-
-void G1CollectedHeap::remove_allocated_regions_from_lists() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- {
- HeapRegion* prev = NULL;
- HeapRegion* cur = _unclean_region_list.hd();
- while (cur != NULL) {
- HeapRegion* next = cur->next_from_unclean_list();
- if (cur->zero_fill_is_allocated()) {
- // Remove from the list.
- if (prev == NULL) {
- (void)_unclean_region_list.pop();
- } else {
- _unclean_region_list.delete_after(prev);
- }
- cur->set_on_unclean_list(false);
- cur->set_next_on_unclean_list(NULL);
- } else {
- prev = cur;
- }
- cur = next;
- }
- assert(_unclean_region_list.sz() == unclean_region_list_length(),
- "Inv");
+void G1CollectedHeap::wait_while_free_regions_coming() {
+ // Most of the time we won't have to wait, so let's do a quick test
+ // first before we take the lock.
+ if (!free_regions_coming()) {
+ return;
+ }
+
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [other] : "
+ "waiting for free regions");
}
{
- HeapRegion* prev = NULL;
- HeapRegion* cur = _free_region_list;
- while (cur != NULL) {
- HeapRegion* next = cur->next_from_free_list();
- if (cur->zero_fill_is_allocated()) {
- // Remove from the list.
- if (prev == NULL) {
- _free_region_list = cur->next_from_free_list();
- } else {
- prev->set_next_on_free_list(cur->next_from_free_list());
- }
- cur->set_on_free_list(false);
- cur->set_next_on_free_list(NULL);
- _free_region_list_size--;
- } else {
- prev = cur;
- }
- cur = next;
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ while (free_regions_coming()) {
+ SecondaryFreeList_lock->wait(Mutex::_no_safepoint_check_flag);
}
- assert(_free_region_list_size == free_region_list_length(), "Inv");
- }
-}
-
-bool G1CollectedHeap::verify_region_lists() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- return verify_region_lists_locked();
-}
-
-bool G1CollectedHeap::verify_region_lists_locked() {
- HeapRegion* unclean = _unclean_region_list.hd();
- while (unclean != NULL) {
- guarantee(unclean->is_on_unclean_list(), "Well, it is!");
- guarantee(!unclean->is_on_free_list(), "Well, it shouldn't be!");
- guarantee(unclean->zero_fill_state() != HeapRegion::Allocated,
- "Everything else is possible.");
- unclean = unclean->next_from_unclean_list();
- }
- guarantee(_unclean_region_list.sz() == unclean_region_list_length(), "Inv");
-
- HeapRegion* free_r = _free_region_list;
- while (free_r != NULL) {
- assert(free_r->is_on_free_list(), "Well, it is!");
- assert(!free_r->is_on_unclean_list(), "Well, it shouldn't be!");
- switch (free_r->zero_fill_state()) {
- case HeapRegion::NotZeroFilled:
- case HeapRegion::ZeroFilling:
- guarantee(false, "Should not be on free list.");
- break;
- default:
- // Everything else is possible.
- break;
- }
- free_r = free_r->next_from_free_list();
- }
- guarantee(_free_region_list_size == free_region_list_length(), "Inv");
- // If we didn't do an assertion...
- return true;
-}
-
-size_t G1CollectedHeap::free_region_list_length() {
- assert(ZF_mon->owned_by_self(), "precondition.");
- size_t len = 0;
- HeapRegion* cur = _free_region_list;
- while (cur != NULL) {
- len++;
- cur = cur->next_from_free_list();
- }
- return len;
-}
-
-size_t G1CollectedHeap::unclean_region_list_length() {
- assert(ZF_mon->owned_by_self(), "precondition.");
- return _unclean_region_list.length();
+ }
+
+ if (G1ConcRegionFreeingVerbose) {
+ gclog_or_tty->print_cr("G1ConcRegionFreeing [other] : "
+ "done waiting for free regions");
+ }
}
size_t G1CollectedHeap::n_regions() {
@@ -5454,55 +5312,6 @@
HeapRegion::GrainBytes;
}
-size_t G1CollectedHeap::free_regions() {
- /* Possibly-expensive assert.
- assert(_free_regions == count_free_regions(),
- "_free_regions is off.");
- */
- return _free_regions;
-}
-
-bool G1CollectedHeap::should_zf() {
- return _free_region_list_size < (size_t) G1ConcZFMaxRegions;
-}
-
-class RegionCounter: public HeapRegionClosure {
- size_t _n;
-public:
- RegionCounter() : _n(0) {}
- bool doHeapRegion(HeapRegion* r) {
- if (r->is_empty()) {
- assert(!r->isHumongous(), "H regions should not be empty.");
- _n++;
- }
- return false;
- }
- int res() { return (int) _n; }
-};
-
-size_t G1CollectedHeap::count_free_regions() {
- RegionCounter rc;
- heap_region_iterate(&rc);
- size_t n = rc.res();
- if (_cur_alloc_region != NULL && _cur_alloc_region->is_empty())
- n--;
- return n;
-}
-
-size_t G1CollectedHeap::count_free_regions_list() {
- size_t n = 0;
- size_t o = 0;
- ZF_mon->lock_without_safepoint_check();
- HeapRegion* cur = _free_region_list;
- while (cur != NULL) {
- cur = cur->next_from_free_list();
- n++;
- }
- size_t m = unclean_region_list_length();
- ZF_mon->unlock();
- return n + m;
-}
-
void G1CollectedHeap::set_region_short_lived_locked(HeapRegion* hr) {
assert(heap_lock_held_for_gc(),
"the heap lock should already be held by or for this thread");
@@ -5574,28 +5383,19 @@
}
}
-
// Done at the start of full GC.
void G1CollectedHeap::tear_down_region_lists() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- while (pop_unclean_region_list_locked() != NULL) ;
- assert(_unclean_region_list.hd() == NULL && _unclean_region_list.sz() == 0,
- "Postconditions of loop.");
- while (pop_free_region_list_locked() != NULL) ;
- assert(_free_region_list == NULL, "Postcondition of loop.");
- if (_free_region_list_size != 0) {
- gclog_or_tty->print_cr("Size is %d.", _free_region_list_size);
- print_on(gclog_or_tty, true /* extended */);
- }
- assert(_free_region_list_size == 0, "Postconditions of loop.");
+ _free_list.remove_all();
}
-
class RegionResetter: public HeapRegionClosure {
- G1CollectedHeap* _g1;
- int _n;
+ G1CollectedHeap* _g1h;
+ FreeRegionList _local_free_list;
+
public:
- RegionResetter() : _g1(G1CollectedHeap::heap()), _n(0) {}
+ RegionResetter() : _g1h(G1CollectedHeap::heap()),
+ _local_free_list("Local Free List for RegionResetter") { }
+
bool doHeapRegion(HeapRegion* r) {
if (r->continuesHumongous()) return false;
if (r->top() > r->bottom()) {
@@ -5603,152 +5403,32 @@
Copy::fill_to_words(r->top(),
pointer_delta(r->end(), r->top()));
}
- r->set_zero_fill_allocated();
} else {
assert(r->is_empty(), "tautology");
- _n++;
- switch (r->zero_fill_state()) {
- case HeapRegion::NotZeroFilled:
- case HeapRegion::ZeroFilling:
- _g1->put_region_on_unclean_list_locked(r);
- break;
- case HeapRegion::Allocated:
- r->set_zero_fill_complete();
- // no break; go on to put on free list.
- case HeapRegion::ZeroFilled:
- _g1->put_free_region_on_list_locked(r);
- break;
- }
+ _local_free_list.add_as_tail(r);
}
return false;
}
- int getFreeRegionCount() {return _n;}
+ void update_free_lists() {
+ _g1h->update_sets_after_freeing_regions(0, &_local_free_list, NULL,
+ false /* par */);
+ }
};
// Done at the end of full GC.
void G1CollectedHeap::rebuild_region_lists() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
// This needs to go at the end of the full GC.
RegionResetter rs;
heap_region_iterate(&rs);
- _free_regions = rs.getFreeRegionCount();
- // Tell the ZF thread it may have work to do.
- if (should_zf()) ZF_mon->notify_all();
-}
-
-class UsedRegionsNeedZeroFillSetter: public HeapRegionClosure {
- G1CollectedHeap* _g1;
- int _n;
-public:
- UsedRegionsNeedZeroFillSetter() : _g1(G1CollectedHeap::heap()), _n(0) {}
- bool doHeapRegion(HeapRegion* r) {
- if (r->continuesHumongous()) return false;
- if (r->top() > r->bottom()) {
- // There are assertions in "set_zero_fill_needed()" below that
- // require top() == bottom(), so this is technically illegal.
- // We'll skirt the law here, by making that true temporarily.
- DEBUG_ONLY(HeapWord* save_top = r->top();
- r->set_top(r->bottom()));
- r->set_zero_fill_needed();
- DEBUG_ONLY(r->set_top(save_top));
- }
- return false;
- }
-};
-
-// Done at the start of full GC.
-void G1CollectedHeap::set_used_regions_to_need_zero_fill() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- // This needs to go at the end of the full GC.
- UsedRegionsNeedZeroFillSetter rs;
- heap_region_iterate(&rs);
+ rs.update_free_lists();
}
void G1CollectedHeap::set_refine_cte_cl_concurrency(bool concurrent) {
_refine_cte_cl->set_concurrent(concurrent);
}
-#ifndef PRODUCT
-
-class PrintHeapRegionClosure: public HeapRegionClosure {
-public:
- bool doHeapRegion(HeapRegion *r) {
- gclog_or_tty->print("Region: "PTR_FORMAT":", r);
- if (r != NULL) {
- if (r->is_on_free_list())
- gclog_or_tty->print("Free ");
- if (r->is_young())
- gclog_or_tty->print("Young ");
- if (r->isHumongous())
- gclog_or_tty->print("Is Humongous ");
- r->print();
- }
- return false;
- }
-};
-
-class SortHeapRegionClosure : public HeapRegionClosure {
- size_t young_regions,free_regions, unclean_regions;
- size_t hum_regions, count;
- size_t unaccounted, cur_unclean, cur_alloc;
- size_t total_free;
- HeapRegion* cur;
-public:
- SortHeapRegionClosure(HeapRegion *_cur) : cur(_cur), young_regions(0),
- free_regions(0), unclean_regions(0),
- hum_regions(0),
- count(0), unaccounted(0),
- cur_alloc(0), total_free(0)
- {}
- bool doHeapRegion(HeapRegion *r) {
- count++;
- if (r->is_on_free_list()) free_regions++;
- else if (r->is_on_unclean_list()) unclean_regions++;
- else if (r->isHumongous()) hum_regions++;
- else if (r->is_young()) young_regions++;
- else if (r == cur) cur_alloc++;
- else unaccounted++;
- return false;
- }
- void print() {
- total_free = free_regions + unclean_regions;
- gclog_or_tty->print("%d regions\n", count);
- gclog_or_tty->print("%d free: free_list = %d unclean = %d\n",
- total_free, free_regions, unclean_regions);
- gclog_or_tty->print("%d humongous %d young\n",
- hum_regions, young_regions);
- gclog_or_tty->print("%d cur_alloc\n", cur_alloc);
- gclog_or_tty->print("UHOH unaccounted = %d\n", unaccounted);
- }
-};
-
-void G1CollectedHeap::print_region_counts() {
- SortHeapRegionClosure sc(_cur_alloc_region);
- PrintHeapRegionClosure cl;
- heap_region_iterate(&cl);
- heap_region_iterate(&sc);
- sc.print();
- print_region_accounting_info();
-};
-
-bool G1CollectedHeap::regions_accounted_for() {
- // TODO: regions accounting for young/survivor/tenured
- return true;
-}
-
-bool G1CollectedHeap::print_region_accounting_info() {
- gclog_or_tty->print_cr("Free regions: %d (count: %d count list %d) (clean: %d unclean: %d).",
- free_regions(),
- count_free_regions(), count_free_regions_list(),
- _free_region_list_size, _unclean_region_list.sz());
- gclog_or_tty->print_cr("cur_alloc: %d.",
- (_cur_alloc_region == NULL ? 0 : 1));
- gclog_or_tty->print_cr("H regions: %d.", _num_humongous_regions);
-
- // TODO: check regions accounting for young/survivor/tenured
- return true;
-}
+#ifdef ASSERT
bool G1CollectedHeap::is_in_closed_subset(const void* p) const {
HeapRegion* hr = heap_region_containing(p);
@@ -5758,8 +5438,84 @@
return hr->is_in(p);
}
}
-#endif // !PRODUCT
-
-void G1CollectedHeap::g1_unimplemented() {
- // Unimplemented();
+#endif // ASSERT
+
+class VerifyRegionListsClosure : public HeapRegionClosure {
+private:
+ HumongousRegionSet* _humongous_set;
+ FreeRegionList* _free_list;
+ size_t _region_count;
+
+public:
+ VerifyRegionListsClosure(HumongousRegionSet* humongous_set,
+ FreeRegionList* free_list) :
+ _humongous_set(humongous_set), _free_list(free_list),
+ _region_count(0) { }
+
+ size_t region_count() { return _region_count; }
+
+ bool doHeapRegion(HeapRegion* hr) {
+ _region_count += 1;
+
+ if (hr->continuesHumongous()) {
+ return false;
+ }
+
+ if (hr->is_young()) {
+ // TODO
+ } else if (hr->startsHumongous()) {
+ _humongous_set->verify_next_region(hr);
+ } else if (hr->is_empty()) {
+ _free_list->verify_next_region(hr);
+ }
+ return false;
+ }
+};
+
+void G1CollectedHeap::verify_region_sets() {
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
+
+ // First, check the explicit lists.
+ _free_list.verify();
+ {
+ // Given that a concurrent operation might be adding regions to
+ // the secondary free list we have to take the lock before
+ // verifying it.
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ _secondary_free_list.verify();
+ }
+ _humongous_set.verify();
+
+ // If a concurrent region freeing operation is in progress it will
+ // be difficult to correctly attributed any free regions we come
+ // across to the correct free list given that they might belong to
+ // one of several (free_list, secondary_free_list, any local lists,
+ // etc.). So, if that's the case we will skip the rest of the
+ // verification operation. Alternatively, waiting for the concurrent
+ // operation to complete will have a non-trivial effect on the GC's
+ // operation (no concurrent operation will last longer than the
+ // interval between two calls to verification) and it might hide
+ // any issues that we would like to catch during testing.
+ if (free_regions_coming()) {
+ return;
+ }
+
+ {
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ // Make sure we append the secondary_free_list on the free_list so
+ // that all free regions we will come across can be safely
+ // attributed to the free_list.
+ append_secondary_free_list();
+ }
+
+ // Finally, make sure that the region accounting in the lists is
+ // consistent with what we see in the heap.
+ _humongous_set.verify_start();
+ _free_list.verify_start();
+
+ VerifyRegionListsClosure cl(&_humongous_set, &_free_list);
+ heap_region_iterate(&cl);
+
+ _humongous_set.verify_end();
+ _free_list.verify_end();
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -27,7 +27,7 @@
#include "gc_implementation/g1/concurrentMark.hpp"
#include "gc_implementation/g1/g1RemSet.hpp"
-#include "gc_implementation/g1/heapRegion.hpp"
+#include "gc_implementation/g1/heapRegionSets.hpp"
#include "gc_implementation/parNew/parGCAllocBuffer.hpp"
#include "memory/barrierSet.hpp"
#include "memory/memRegion.hpp"
@@ -66,8 +66,7 @@
enum G1GCThreadGroups {
G1CRGroup = 0,
G1ZFGroup = 1,
- G1CMGroup = 2,
- G1CLGroup = 3
+ G1CMGroup = 2
};
enum GCAllocPurpose {
@@ -155,6 +154,7 @@
friend class RefineCardTableEntryClosure;
friend class G1PrepareCompactClosure;
friend class RegionSorter;
+ friend class RegionResetter;
friend class CountRCClosure;
friend class EvacPopObjClosure;
friend class G1ParCleanupCTTask;
@@ -178,17 +178,20 @@
// The maximum part of _g1_storage that has ever been committed.
MemRegion _g1_max_committed;
- // The number of regions that are completely free.
- size_t _free_regions;
+ // The master free list. It will satisfy all new region allocations.
+ MasterFreeRegionList _free_list;
+
+ // The secondary free list which contains regions that have been
+ // freed up during the cleanup process. This will be appended to the
+ // master free list when appropriate.
+ SecondaryFreeRegionList _secondary_free_list;
+
+ // It keeps track of the humongous regions.
+ MasterHumongousRegionSet _humongous_set;
// The number of regions we could create by expansion.
size_t _expansion_regions;
- // Return the number of free regions in the heap (by direct counting.)
- size_t count_free_regions();
- // Return the number of free regions on the free and unclean lists.
- size_t count_free_regions_list();
-
// The block offset table for the G1 heap.
G1BlockOffsetSharedArray* _bot_shared;
@@ -196,9 +199,6 @@
// lists, before and after full GC.
void tear_down_region_lists();
void rebuild_region_lists();
- // This sets all non-empty regions to need zero-fill (which they will if
- // they are empty after full collection.)
- void set_used_regions_to_need_zero_fill();
// The sequence of all heap regions in the heap.
HeapRegionSeq* _hrs;
@@ -231,7 +231,7 @@
// Determines PLAB size for a particular allocation purpose.
static size_t desired_plab_sz(GCAllocPurpose purpose);
- // When called by par thread, require par_alloc_during_gc_lock() to be held.
+ // When called by par thread, requires the FreeList_lock to be held.
void push_gc_alloc_region(HeapRegion* hr);
// This should only be called single-threaded. Undeclares all GC alloc
@@ -294,10 +294,11 @@
// line number, file, etc.
#define heap_locking_asserts_err_msg(__extra_message) \
- err_msg("%s : Heap_lock %slocked, %sat a safepoint", \
+ err_msg("%s : Heap_lock locked: %s, at safepoint: %s, is VM thread: %s", \
(__extra_message), \
- (!Heap_lock->owned_by_self()) ? "NOT " : "", \
- (!SafepointSynchronize::is_at_safepoint()) ? "NOT " : "")
+ BOOL_TO_STR(Heap_lock->owned_by_self()), \
+ BOOL_TO_STR(SafepointSynchronize::is_at_safepoint()), \
+ BOOL_TO_STR(Thread::current()->is_VM_thread()))
#define assert_heap_locked() \
do { \
@@ -305,10 +306,11 @@
heap_locking_asserts_err_msg("should be holding the Heap_lock")); \
} while (0)
-#define assert_heap_locked_or_at_safepoint() \
+#define assert_heap_locked_or_at_safepoint(__should_be_vm_thread) \
do { \
assert(Heap_lock->owned_by_self() || \
- SafepointSynchronize::is_at_safepoint(), \
+ (SafepointSynchronize::is_at_safepoint() && \
+ ((__should_be_vm_thread) == Thread::current()->is_VM_thread())), \
heap_locking_asserts_err_msg("should be holding the Heap_lock or " \
"should be at a safepoint")); \
} while (0)
@@ -335,9 +337,10 @@
"should not be at a safepoint")); \
} while (0)
-#define assert_at_safepoint() \
+#define assert_at_safepoint(__should_be_vm_thread) \
do { \
- assert(SafepointSynchronize::is_at_safepoint(), \
+ assert(SafepointSynchronize::is_at_safepoint() && \
+ ((__should_be_vm_thread) == Thread::current()->is_VM_thread()), \
heap_locking_asserts_err_msg("should be at a safepoint")); \
} while (0)
@@ -362,31 +365,41 @@
// The current policy object for the collector.
G1CollectorPolicy* _g1_policy;
- // Parallel allocation lock to protect the current allocation region.
- Mutex _par_alloc_during_gc_lock;
- Mutex* par_alloc_during_gc_lock() { return &_par_alloc_during_gc_lock; }
+ // This is the second level of trying to allocate a new region. If
+ // new_region_work didn't find a region in the free_list, this call
+ // will check whether there's anything available in the
+ // secondary_free_list and/or wait for more regions to appear in that
+ // list, if _free_regions_coming is set.
+ HeapRegion* new_region_try_secondary_free_list(size_t word_size);
- // If possible/desirable, allocate a new HeapRegion for normal object
- // allocation sufficient for an allocation of the given "word_size".
- // If "do_expand" is true, will attempt to expand the heap if necessary
- // to to satisfy the request. If "zero_filled" is true, requires a
- // zero-filled region.
- // (Returning NULL will trigger a GC.)
- virtual HeapRegion* newAllocRegion_work(size_t word_size,
- bool do_expand,
- bool zero_filled);
+ // It will try to allocate a single non-humongous HeapRegion
+ // sufficient for an allocation of the given word_size. If
+ // do_expand is true, it will attempt to expand the heap if
+ // necessary to satisfy the allocation request. Note that word_size
+ // is only used to make sure that we expand sufficiently but, given
+ // that the allocation request is assumed not to be humongous,
+ // having word_size is not strictly necessary (expanding by a single
+ // region will always be sufficient). But let's keep that parameter
+ // in case we need it in the future.
+ HeapRegion* new_region_work(size_t word_size, bool do_expand);
- virtual HeapRegion* newAllocRegion(size_t word_size,
- bool zero_filled = true) {
- return newAllocRegion_work(word_size, false, zero_filled);
+ // It will try to allocate a new region to be used for allocation by
+ // mutator threads. It will not try to expand the heap if not region
+ // is available.
+ HeapRegion* new_alloc_region(size_t word_size) {
+ return new_region_work(word_size, false /* do_expand */);
}
- virtual HeapRegion* newAllocRegionWithExpansion(int purpose,
- size_t word_size,
- bool zero_filled = true);
+
+ // It will try to allocate a new region to be used for allocation by
+ // a GC thread. It will try to expand the heap if no region is
+ // available.
+ HeapRegion* new_gc_alloc_region(int purpose, size_t word_size);
+
+ int humongous_obj_allocate_find_first(size_t num_regions, size_t word_size);
// Attempt to allocate an object of the given (very large) "word_size".
// Returns "NULL" on failure.
- virtual HeapWord* humongous_obj_allocate(size_t word_size);
+ HeapWord* humongous_obj_allocate(size_t word_size);
// The following two methods, allocate_new_tlab() and
// mem_allocate(), are the two main entry points from the runtime
@@ -430,7 +443,8 @@
bool* gc_overhead_limit_was_exceeded);
// The following methods, allocate_from_cur_allocation_region(),
- // attempt_allocation(), replace_cur_alloc_region_and_allocate(),
+ // attempt_allocation(), attempt_allocation_locked(),
+ // replace_cur_alloc_region_and_allocate(),
// attempt_allocation_slow(), and attempt_allocation_humongous()
// have very awkward pre- and post-conditions with respect to
// locking:
@@ -481,20 +495,30 @@
// successfully manage to allocate it, or NULL.
// It tries to satisfy an allocation request out of the current
- // allocating region, which is passed as a parameter. It assumes
- // that the caller has checked that the current allocating region is
- // not NULL. Given that the caller has to check the current
- // allocating region for at least NULL, it might as well pass it as
- // the first parameter so that the method doesn't have to read it
- // from the _cur_alloc_region field again.
+ // alloc region, which is passed as a parameter. It assumes that the
+ // caller has checked that the current alloc region is not NULL.
+ // Given that the caller has to check the current alloc region for
+ // at least NULL, it might as well pass it as the first parameter so
+ // that the method doesn't have to read it from the
+ // _cur_alloc_region field again. It is called from both
+ // attempt_allocation() and attempt_allocation_locked() and the
+ // with_heap_lock parameter indicates whether the caller was holding
+ // the heap lock when it called it or not.
inline HeapWord* allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
- size_t word_size);
+ size_t word_size,
+ bool with_heap_lock);
- // It attempts to allocate out of the current alloc region. If that
- // fails, it retires the current alloc region (if there is one),
- // tries to get a new one and retries the allocation.
+ // First-level of allocation slow path: it attempts to allocate out
+ // of the current alloc region in a lock-free manner using a CAS. If
+ // that fails it takes the Heap_lock and calls
+ // attempt_allocation_locked() for the second-level slow path.
inline HeapWord* attempt_allocation(size_t word_size);
+ // Second-level of allocation slow path: while holding the Heap_lock
+ // it tries to allocate out of the current alloc region and, if that
+ // fails, tries to allocate out of a new current alloc region.
+ inline HeapWord* attempt_allocation_locked(size_t word_size);
+
// It assumes that the current alloc region has been retired and
// tries to allocate a new one. If it's successful, it performs the
// allocation out of the new current alloc region and updates
@@ -506,11 +530,11 @@
bool do_dirtying,
bool can_expand);
- // The slow path when we are unable to allocate a new current alloc
- // region to satisfy an allocation request (i.e., when
- // attempt_allocation() fails). It will try to do an evacuation
- // pause, which might stall due to the GC locker, and retry the
- // allocation attempt when appropriate.
+ // Third-level of allocation slow path: when we are unable to
+ // allocate a new current alloc region to satisfy an allocation
+ // request (i.e., when attempt_allocation_locked() fails). It will
+ // try to do an evacuation pause, which might stall due to the GC
+ // locker, and retry the allocation attempt when appropriate.
HeapWord* attempt_allocation_slow(size_t word_size);
// The method that tries to satisfy a humongous allocation
@@ -749,20 +773,29 @@
// Invoke "save_marks" on all heap regions.
void save_marks();
- // Free a heap region.
- void free_region(HeapRegion* hr);
- // A component of "free_region", exposed for 'batching'.
- // All the params after "hr" are out params: the used bytes of the freed
- // region(s), the number of H regions cleared, the number of regions
- // freed, and pointers to the head and tail of a list of freed contig
- // regions, linked throught the "next_on_unclean_list" field.
- void free_region_work(HeapRegion* hr,
- size_t& pre_used,
- size_t& cleared_h,
- size_t& freed_regions,
- UncleanRegionList* list,
- bool par = false);
+ // It frees a non-humongous region by initializing its contents and
+ // adding it to the free list that's passed as a parameter (this is
+ // usually a local list which will be appended to the master free
+ // list later). The used bytes of freed regions are accumulated in
+ // pre_used. If par is true, the region's RSet will not be freed
+ // up. The assumption is that this will be done later.
+ void free_region(HeapRegion* hr,
+ size_t* pre_used,
+ FreeRegionList* free_list,
+ bool par);
+ // It frees a humongous region by collapsing it into individual
+ // regions and calling free_region() for each of them. The freed
+ // regions will be added to the free list that's passed as a parameter
+ // (this is usually a local list which will be appended to the
+ // master free list later). The used bytes of freed regions are
+ // accumulated in pre_used. If par is true, the region's RSet will
+ // not be freed up. The assumption is that this will be done later.
+ void free_humongous_region(HeapRegion* hr,
+ size_t* pre_used,
+ FreeRegionList* free_list,
+ HumongousRegionSet* humongous_proxy_set,
+ bool par);
// The concurrent marker (and the thread it runs in.)
ConcurrentMark* _cm;
@@ -772,9 +805,6 @@
// The concurrent refiner.
ConcurrentG1Refine* _cg1r;
- // The concurrent zero-fill thread.
- ConcurrentZFThread* _czft;
-
// The parallel task queues
RefToScanQueueSet *_task_queues;
@@ -826,7 +856,6 @@
void finalize_for_evac_failure();
// An attempt to evacuate "obj" has failed; take necessary steps.
- void handle_evacuation_failure(oop obj);
oop handle_evacuation_failure_par(OopsInHeapRegionClosure* cl, oop obj);
void handle_evacuation_failure_common(oop obj, markOop m);
@@ -867,9 +896,7 @@
SubTasksDone* _process_strong_tasks;
- // List of regions which require zero filling.
- UncleanRegionList _unclean_region_list;
- bool _unclean_regions_coming;
+ volatile bool _free_regions_coming;
public:
@@ -992,71 +1019,64 @@
size_t max_regions();
// The number of regions that are completely free.
- size_t free_regions();
+ size_t free_regions() {
+ return _free_list.length();
+ }
// The number of regions that are not completely free.
size_t used_regions() { return n_regions() - free_regions(); }
- // True iff the ZF thread should run.
- bool should_zf();
-
// The number of regions available for "regular" expansion.
size_t expansion_regions() { return _expansion_regions; }
-#ifndef PRODUCT
- bool regions_accounted_for();
- bool print_region_accounting_info();
- void print_region_counts();
-#endif
-
- HeapRegion* alloc_region_from_unclean_list(bool zero_filled);
- HeapRegion* alloc_region_from_unclean_list_locked(bool zero_filled);
-
- void put_region_on_unclean_list(HeapRegion* r);
- void put_region_on_unclean_list_locked(HeapRegion* r);
+ // verify_region_sets() performs verification over the region
+ // lists. It will be compiled in the product code to be used when
+ // necessary (i.e., during heap verification).
+ void verify_region_sets();
- void prepend_region_list_on_unclean_list(UncleanRegionList* list);
- void prepend_region_list_on_unclean_list_locked(UncleanRegionList* list);
+ // verify_region_sets_optional() is planted in the code for
+ // list verification in non-product builds (and it can be enabled in
+ // product builds by definning HEAP_REGION_SET_FORCE_VERIFY to be 1).
+#if HEAP_REGION_SET_FORCE_VERIFY
+ void verify_region_sets_optional() {
+ verify_region_sets();
+ }
+#else // HEAP_REGION_SET_FORCE_VERIFY
+ void verify_region_sets_optional() { }
+#endif // HEAP_REGION_SET_FORCE_VERIFY
- void set_unclean_regions_coming(bool b);
- void set_unclean_regions_coming_locked(bool b);
- // Wait for cleanup to be complete.
- void wait_for_cleanup_complete();
- // Like above, but assumes that the calling thread owns the Heap_lock.
- void wait_for_cleanup_complete_locked();
-
- // Return the head of the unclean list.
- HeapRegion* peek_unclean_region_list_locked();
- // Remove and return the head of the unclean list.
- HeapRegion* pop_unclean_region_list_locked();
+#ifdef ASSERT
+ bool is_on_free_list(HeapRegion* hr) {
+ return hr->containing_set() == &_free_list;
+ }
- // List of regions which are zero filled and ready for allocation.
- HeapRegion* _free_region_list;
- // Number of elements on the free list.
- size_t _free_region_list_size;
+ bool is_on_humongous_set(HeapRegion* hr) {
+ return hr->containing_set() == &_humongous_set;
+}
+#endif // ASSERT
- // If the head of the unclean list is ZeroFilled, move it to the free
- // list.
- bool move_cleaned_region_to_free_list_locked();
- bool move_cleaned_region_to_free_list();
+ // Wrapper for the region list operations that can be called from
+ // methods outside this class.
- void put_free_region_on_list_locked(HeapRegion* r);
- void put_free_region_on_list(HeapRegion* r);
+ void secondary_free_list_add_as_tail(FreeRegionList* list) {
+ _secondary_free_list.add_as_tail(list);
+ }
- // Remove and return the head element of the free list.
- HeapRegion* pop_free_region_list_locked();
+ void append_secondary_free_list() {
+ _free_list.add_as_tail(&_secondary_free_list);
+ }
- // If "zero_filled" is true, we first try the free list, then we try the
- // unclean list, zero-filling the result. If "zero_filled" is false, we
- // first try the unclean list, then the zero-filled list.
- HeapRegion* alloc_free_region_from_lists(bool zero_filled);
+ void append_secondary_free_list_if_not_empty() {
+ if (!_secondary_free_list.is_empty()) {
+ MutexLockerEx x(SecondaryFreeList_lock, Mutex::_no_safepoint_check_flag);
+ append_secondary_free_list();
+ }
+ }
- // Verify the integrity of the region lists.
- void remove_allocated_regions_from_lists();
- bool verify_region_lists();
- bool verify_region_lists_locked();
- size_t unclean_region_list_length();
- size_t free_region_list_length();
+ void set_free_regions_coming();
+ void reset_free_regions_coming();
+ bool free_regions_coming() { return _free_regions_coming; }
+ void wait_while_free_regions_coming();
// Perform a collection of the heap; intended for use in implementing
// "System.gc". This probably implies as full a collection as the
@@ -1075,23 +1095,24 @@
// True iff a evacuation has failed in the most-recent collection.
bool evacuation_failed() { return _evacuation_failed; }
- // Free a region if it is totally full of garbage. Returns the number of
- // bytes freed (0 ==> didn't free it).
- size_t free_region_if_totally_empty(HeapRegion *hr);
- void free_region_if_totally_empty_work(HeapRegion *hr,
- size_t& pre_used,
- size_t& cleared_h_regions,
- size_t& freed_regions,
- UncleanRegionList* list,
- bool par = false);
+ // It will free a region if it has allocated objects in it that are
+ // all dead. It calls either free_region() or
+ // free_humongous_region() depending on the type of the region that
+ // is passed to it.
+ void free_region_if_totally_empty(HeapRegion* hr,
+ size_t* pre_used,
+ FreeRegionList* free_list,
+ HumongousRegionSet* humongous_proxy_set,
+ bool par);
- // If we've done free region work that yields the given changes, update
- // the relevant global variables.
- void finish_free_region_work(size_t pre_used,
- size_t cleared_h_regions,
- size_t freed_regions,
- UncleanRegionList* list);
-
+ // It appends the free list to the master free list and updates the
+ // master humongous list according to the contents of the proxy
+ // list. It also adjusts the total used bytes according to pre_used
+ // (if par is true, it will do so by taking the ParGCRareEvent_lock).
+ void update_sets_after_freeing_regions(size_t pre_used,
+ FreeRegionList* free_list,
+ HumongousRegionSet* humongous_proxy_set,
+ bool par);
// Returns "TRUE" iff "p" points into the allocated area of the heap.
virtual bool is_in(const void* p) const;
@@ -1304,8 +1325,6 @@
return true;
}
- virtual bool allocs_are_zero_filled();
-
// The boundary between a "large" and "small" array of primitives, in
// words.
virtual size_t large_typearray_limit();
@@ -1536,13 +1555,6 @@
protected:
size_t _max_heap_capacity;
-
-public:
- // Temporary: call to mark things unimplemented for the G1 heap (e.g.,
- // MemoryService). In productization, we can make this assert false
- // to catch such places (as well as searching for calls to this...)
- static void g1_unimplemented();
-
};
#define use_local_bitmaps 1
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -28,7 +28,7 @@
#include "gc_implementation/g1/concurrentMark.hpp"
#include "gc_implementation/g1/g1CollectedHeap.hpp"
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
-#include "gc_implementation/g1/heapRegionSeq.hpp"
+#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
#include "utilities/taskqueue.hpp"
// Inline functions for G1CollectedHeap
@@ -63,10 +63,12 @@
// assumptions of this method (and other related ones).
inline HeapWord*
G1CollectedHeap::allocate_from_cur_alloc_region(HeapRegion* cur_alloc_region,
- size_t word_size) {
- assert_heap_locked_and_not_at_safepoint();
+ size_t word_size,
+ bool with_heap_lock) {
+ assert_not_at_safepoint();
+ assert(with_heap_lock == Heap_lock->owned_by_self(),
+ "with_heap_lock and Heap_lock->owned_by_self() should be a tautology");
assert(cur_alloc_region != NULL, "pre-condition of the method");
- assert(cur_alloc_region == _cur_alloc_region, "pre-condition of the method");
assert(cur_alloc_region->is_young(),
"we only support young current alloc regions");
assert(!isHumongous(word_size), "allocate_from_cur_alloc_region() "
@@ -76,20 +78,24 @@
assert(!cur_alloc_region->is_empty(),
err_msg("region ["PTR_FORMAT","PTR_FORMAT"] should not be empty",
cur_alloc_region->bottom(), cur_alloc_region->end()));
- // This allocate method does BOT updates and we don't need them in
- // the young generation. This will be fixed in the near future by
- // CR 6994297.
- HeapWord* result = cur_alloc_region->allocate(word_size);
+ HeapWord* result = cur_alloc_region->par_allocate_no_bot_updates(word_size);
if (result != NULL) {
assert(is_in(result), "result should be in the heap");
- Heap_lock->unlock();
+ if (with_heap_lock) {
+ Heap_lock->unlock();
+ }
+ assert_heap_not_locked();
// Do the dirtying after we release the Heap_lock.
dirty_young_block(result, word_size);
return result;
}
- assert_heap_locked();
+ if (with_heap_lock) {
+ assert_heap_locked();
+ } else {
+ assert_heap_not_locked();
+ }
return NULL;
}
@@ -97,26 +103,75 @@
// assumptions of this method (and other related ones).
inline HeapWord*
G1CollectedHeap::attempt_allocation(size_t word_size) {
- assert_heap_locked_and_not_at_safepoint();
+ assert_heap_not_locked_and_not_at_safepoint();
assert(!isHumongous(word_size), "attempt_allocation() should not be called "
"for humongous allocation requests");
HeapRegion* cur_alloc_region = _cur_alloc_region;
if (cur_alloc_region != NULL) {
HeapWord* result = allocate_from_cur_alloc_region(cur_alloc_region,
- word_size);
+ word_size,
+ false /* with_heap_lock */);
+ assert_heap_not_locked();
+ if (result != NULL) {
+ return result;
+ }
+ }
+
+ // Our attempt to allocate lock-free failed as the current
+ // allocation region is either NULL or full. So, we'll now take the
+ // Heap_lock and retry.
+ Heap_lock->lock();
+
+ HeapWord* result = attempt_allocation_locked(word_size);
+ if (result != NULL) {
+ assert_heap_not_locked();
+ return result;
+ }
+
+ assert_heap_locked();
+ return NULL;
+}
+
+inline void
+G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) {
+ assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
+ assert(cur_alloc_region != NULL && cur_alloc_region == _cur_alloc_region,
+ "pre-condition of the call");
+ assert(cur_alloc_region->is_young(),
+ "we only support young current alloc regions");
+
+ // The region is guaranteed to be young
+ g1_policy()->add_region_to_incremental_cset_lhs(cur_alloc_region);
+ _summary_bytes_used += cur_alloc_region->used();
+ _cur_alloc_region = NULL;
+}
+
+inline HeapWord*
+G1CollectedHeap::attempt_allocation_locked(size_t word_size) {
+ assert_heap_locked_and_not_at_safepoint();
+ assert(!isHumongous(word_size), "attempt_allocation_locked() "
+ "should not be called for humongous allocation requests");
+
+ // First, reread the current alloc region and retry the allocation
+ // in case somebody replaced it while we were waiting to get the
+ // Heap_lock.
+ HeapRegion* cur_alloc_region = _cur_alloc_region;
+ if (cur_alloc_region != NULL) {
+ HeapWord* result = allocate_from_cur_alloc_region(
+ cur_alloc_region, word_size,
+ true /* with_heap_lock */);
if (result != NULL) {
assert_heap_not_locked();
return result;
}
- assert_heap_locked();
-
- // Since we couldn't successfully allocate into it, retire the
- // current alloc region.
+ // We failed to allocate out of the current alloc region, so let's
+ // retire it before getting a new one.
retire_cur_alloc_region(cur_alloc_region);
}
+ assert_heap_locked();
// Try to get a new region and allocate out of it
HeapWord* result = replace_cur_alloc_region_and_allocate(word_size,
false, /* at_safepoint */
@@ -131,20 +186,6 @@
return NULL;
}
-inline void
-G1CollectedHeap::retire_cur_alloc_region_common(HeapRegion* cur_alloc_region) {
- assert_heap_locked_or_at_safepoint();
- assert(cur_alloc_region != NULL && cur_alloc_region == _cur_alloc_region,
- "pre-condition of the call");
- assert(cur_alloc_region->is_young(),
- "we only support young current alloc regions");
-
- // The region is guaranteed to be young
- g1_policy()->add_region_to_incremental_cset_lhs(cur_alloc_region);
- _summary_bytes_used += cur_alloc_region->used();
- _cur_alloc_region = NULL;
-}
-
// It dirties the cards that cover the block so that so that the post
// write barrier never queues anything when updating objects on this
// block. It is assumed (and in fact we assert) that the block
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -2875,8 +2875,6 @@
// Adjust for expansion and slop.
max_live_bytes = max_live_bytes + expansion_bytes;
- assert(_g1->regions_accounted_for(), "Region leakage!");
-
HeapRegion* hr;
if (in_young_gc_mode()) {
double young_start_time_sec = os::elapsedTime();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -113,6 +113,7 @@
Threads::gc_epilogue();
CodeCache::gc_epilogue();
+ JvmtiExport::gc_epilogue();
// refs processing: clean slate
GenMarkSweep::_ref_processor = NULL;
@@ -180,26 +181,46 @@
}
class G1PrepareCompactClosure: public HeapRegionClosure {
+ G1CollectedHeap* _g1h;
ModRefBarrierSet* _mrbs;
CompactPoint _cp;
+ size_t _pre_used;
+ FreeRegionList _free_list;
+ HumongousRegionSet _humongous_proxy_set;
void free_humongous_region(HeapRegion* hr) {
- HeapWord* bot = hr->bottom();
HeapWord* end = hr->end();
assert(hr->startsHumongous(),
"Only the start of a humongous region should be freed.");
- G1CollectedHeap::heap()->free_region(hr);
+ _g1h->free_humongous_region(hr, &_pre_used, &_free_list,
+ &_humongous_proxy_set, false /* par */);
+ // Do we also need to do this for the continues humongous regions
+ // we just collapsed?
hr->prepare_for_compaction(&_cp);
// Also clear the part of the card table that will be unused after
// compaction.
- _mrbs->clear(MemRegion(hr->compaction_top(), hr->end()));
+ _mrbs->clear(MemRegion(hr->compaction_top(), end));
}
public:
- G1PrepareCompactClosure(CompactibleSpace* cs) :
+ G1PrepareCompactClosure(CompactibleSpace* cs)
+ : _g1h(G1CollectedHeap::heap()),
+ _mrbs(G1CollectedHeap::heap()->mr_bs()),
_cp(NULL, cs, cs->initialize_threshold()),
- _mrbs(G1CollectedHeap::heap()->mr_bs())
- {}
+ _pre_used(0),
+ _free_list("Local Free List for G1MarkSweep"),
+ _humongous_proxy_set("G1MarkSweep Humongous Proxy Set") { }
+
+ void update_sets() {
+ // We'll recalculate total used bytes and recreate the free list
+ // at the end of the GC, so no point in updating those values here.
+ _g1h->update_sets_after_freeing_regions(0, /* pre_used */
+ NULL, /* free_list */
+ &_humongous_proxy_set,
+ false /* par */);
+ _free_list.remove_all();
+ }
+
bool doHeapRegion(HeapRegion* hr) {
if (hr->isHumongous()) {
if (hr->startsHumongous()) {
@@ -265,6 +286,7 @@
G1PrepareCompactClosure blk(sp);
g1h->heap_region_iterate(&blk);
+ blk.update_sets();
CompactPoint perm_cp(pg, NULL, NULL);
pg->prepare_for_compaction(&perm_cp);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -75,21 +75,12 @@
"(0 means do not periodically generate this info); " \
"it also requires -XX:+G1SummarizeRSetStats") \
\
- diagnostic(bool, G1SummarizeZFStats, false, \
- "Summarize zero-filling info") \
- \
diagnostic(bool, G1TraceConcRefinement, false, \
"Trace G1 concurrent refinement") \
\
product(intx, G1MarkRegionStackSize, 1024 * 1024, \
"Size of the region stack for concurrent marking.") \
\
- develop(bool, G1ConcZeroFill, true, \
- "If true, run concurrent zero-filling thread") \
- \
- develop(intx, G1ConcZFMaxRegions, 1, \
- "Stop zero-filling when # of zf'd regions reaches") \
- \
develop(bool, G1SATBBarrierPrintNullPreVals, false, \
"If true, count frac of ptr writes with null pre-vals.") \
\
@@ -99,6 +90,13 @@
develop(intx, G1SATBProcessCompletedThreshold, 20, \
"Number of completed buffers that triggers log processing.") \
\
+ product(uintx, G1SATBBufferEnqueueingThresholdPercent, 60, \
+ "Before enqueueing them, each mutator thread tries to do some " \
+ "filtering on the SATB buffers it generates. If post-filtering " \
+ "the percentage of retained entries is over this threshold " \
+ "the buffer will be enqueued for processing. A value of 0 " \
+ "specifies that mutator threads should not do such filtering.") \
+ \
develop(intx, G1ExtraRegionSurvRate, 33, \
"If the young survival rate is S, and there's room left in " \
"to-space, we will allow regions whose survival rate is up to " \
@@ -282,7 +280,20 @@
"Size of a work unit of cards claimed by a worker thread" \
"during RSet scanning.") \
\
- develop(bool, ReduceInitialCardMarksForG1, false, \
+ develop(uintx, G1SecondaryFreeListAppendLength, 5, \
+ "The number of regions we will add to the secondary free list " \
+ "at every append operation") \
+ \
+ develop(bool, G1ConcRegionFreeingVerbose, false, \
+ "Enables verboseness during concurrent region freeing") \
+ \
+ develop(bool, G1StressConcRegionFreeing, false, \
+ "It stresses the concurrent region freeing operation") \
+ \
+ develop(uintx, G1StressConcRegionFreeingDelayMillis, 0, \
+ "Artificial delay during concurrent region freeing") \
+ \
+ develop(bool, ReduceInitialCardMarksForG1, false, \
"When ReduceInitialCardMarks is true, this flag setting " \
" controls whether G1 allows the RICM optimization")
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -23,7 +23,6 @@
*/
#include "precompiled.hpp"
-#include "gc_implementation/g1/concurrentZFThread.hpp"
#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
@@ -348,22 +347,20 @@
}
void HeapRegion::hr_clear(bool par, bool clear_space) {
- _humongous_type = NotHumongous;
- _humongous_start_region = NULL;
+ assert(_humongous_type == NotHumongous,
+ "we should have already filtered out humongous regions");
+ assert(_humongous_start_region == NULL,
+ "we should have already filtered out humongous regions");
+ assert(_end == _orig_end,
+ "we should have already filtered out humongous regions");
+
_in_collection_set = false;
_is_gc_alloc_region = false;
- // Age stuff (if parallel, this will be done separately, since it needs
- // to be sequential).
- G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
set_young_index_in_cset(-1);
uninstall_surv_rate_group();
set_young_type(NotYoung);
- // In case it had been the start of a humongous sequence, reset its end.
- set_end(_orig_end);
-
if (!par) {
// If this is parallel, this will be done later.
HeapRegionRemSet* hrrs = rem_set();
@@ -386,26 +383,49 @@
}
// </PREDICTION>
-void HeapRegion::set_startsHumongous(HeapWord* new_end) {
+void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) {
+ assert(!isHumongous(), "sanity / pre-condition");
assert(end() == _orig_end,
"Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty");
+ assert(bottom() <= new_top && new_top <= new_end, "pre-condition");
_humongous_type = StartsHumongous;
_humongous_start_region = this;
set_end(new_end);
- _offsets.set_for_starts_humongous(new_end);
+ _offsets.set_for_starts_humongous(new_top);
}
-void HeapRegion::set_continuesHumongous(HeapRegion* start) {
+void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) {
+ assert(!isHumongous(), "sanity / pre-condition");
assert(end() == _orig_end,
"Should be normal before the humongous object allocation");
assert(top() == bottom(), "should be empty");
- assert(start->startsHumongous(), "pre-condition");
+ assert(first_hr->startsHumongous(), "pre-condition");
_humongous_type = ContinuesHumongous;
- _humongous_start_region = start;
+ _humongous_start_region = first_hr;
+}
+
+void HeapRegion::set_notHumongous() {
+ assert(isHumongous(), "pre-condition");
+
+ if (startsHumongous()) {
+ assert(top() <= end(), "pre-condition");
+ set_end(_orig_end);
+ if (top() > end()) {
+ // at least one "continues humongous" region after it
+ set_top(end());
+ }
+ } else {
+ // continues humongous
+ assert(end() == _orig_end, "sanity");
+ }
+
+ assert(capacity() == (size_t) HeapRegion::GrainBytes, "pre-condition");
+ _humongous_type = NotHumongous;
+ _humongous_start_region = NULL;
}
bool HeapRegion::claimHeapRegion(jint claimValue) {
@@ -442,15 +462,6 @@
return low;
}
-void HeapRegion::set_next_on_unclean_list(HeapRegion* r) {
- assert(r == NULL || r->is_on_unclean_list(), "Malformed unclean list.");
- _next_in_special_set = r;
-}
-
-void HeapRegion::set_on_unclean_list(bool b) {
- _is_on_unclean_list = b;
-}
-
void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
G1OffsetTableContigSpace::initialize(mr, false, mangle_space);
hr_clear(false/*par*/, clear_space);
@@ -468,15 +479,16 @@
_hrs_index(-1),
_humongous_type(NotHumongous), _humongous_start_region(NULL),
_in_collection_set(false), _is_gc_alloc_region(false),
- _is_on_free_list(false), _is_on_unclean_list(false),
_next_in_special_set(NULL), _orig_end(NULL),
_claimed(InitialClaimValue), _evacuation_failed(false),
_prev_marked_bytes(0), _next_marked_bytes(0), _sort_index(-1),
_young_type(NotYoung), _next_young_region(NULL),
- _next_dirty_cards_region(NULL),
- _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1),
- _rem_set(NULL), _zfs(NotZeroFilled),
- _recorded_rs_length(0), _predicted_elapsed_time_ms(0),
+ _next_dirty_cards_region(NULL), _next(NULL), _pending_removal(false),
+#ifdef ASSERT
+ _containing_set(NULL),
+#endif // ASSERT
+ _young_index_in_cset(-1), _surv_rate_group(NULL), _age_index(-1),
+ _rem_set(NULL), _recorded_rs_length(0), _predicted_elapsed_time_ms(0),
_predicted_bytes_to_copy(0)
{
_orig_end = mr.end();
@@ -551,86 +563,6 @@
oops_in_mr_iterate(MemRegion(bottom(), saved_mark_word()), cl);
}
-#ifdef DEBUG
-HeapWord* HeapRegion::allocate(size_t size) {
- jint state = zero_fill_state();
- assert(!G1CollectedHeap::heap()->allocs_are_zero_filled() ||
- zero_fill_is_allocated(),
- "When ZF is on, only alloc in ZF'd regions");
- return G1OffsetTableContigSpace::allocate(size);
-}
-#endif
-
-void HeapRegion::set_zero_fill_state_work(ZeroFillState zfs) {
- assert(ZF_mon->owned_by_self() ||
- Universe::heap()->is_gc_active(),
- "Must hold the lock or be a full GC to modify.");
-#ifdef ASSERT
- if (top() != bottom() && zfs != Allocated) {
- ResourceMark rm;
- stringStream region_str;
- print_on(®ion_str);
- assert(top() == bottom() || zfs == Allocated,
- err_msg("Region must be empty, or we must be setting it to allocated. "
- "_zfs=%d, zfs=%d, region: %s", _zfs, zfs, region_str.as_string()));
- }
-#endif
- _zfs = zfs;
-}
-
-void HeapRegion::set_zero_fill_complete() {
- set_zero_fill_state_work(ZeroFilled);
- if (ZF_mon->owned_by_self()) {
- ZF_mon->notify_all();
- }
-}
-
-
-void HeapRegion::ensure_zero_filled() {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- ensure_zero_filled_locked();
-}
-
-void HeapRegion::ensure_zero_filled_locked() {
- assert(ZF_mon->owned_by_self(), "Precondition");
- bool should_ignore_zf = SafepointSynchronize::is_at_safepoint();
- assert(should_ignore_zf || Heap_lock->is_locked(),
- "Either we're in a GC or we're allocating a region.");
- switch (zero_fill_state()) {
- case HeapRegion::NotZeroFilled:
- set_zero_fill_in_progress(Thread::current());
- {
- ZF_mon->unlock();
- Copy::fill_to_words(bottom(), capacity()/HeapWordSize);
- ZF_mon->lock_without_safepoint_check();
- }
- // A trap.
- guarantee(zero_fill_state() == HeapRegion::ZeroFilling
- && zero_filler() == Thread::current(),
- "AHA! Tell Dave D if you see this...");
- set_zero_fill_complete();
- // gclog_or_tty->print_cr("Did sync ZF.");
- ConcurrentZFThread::note_sync_zfs();
- break;
- case HeapRegion::ZeroFilling:
- if (should_ignore_zf) {
- // We can "break" the lock and take over the work.
- Copy::fill_to_words(bottom(), capacity()/HeapWordSize);
- set_zero_fill_complete();
- ConcurrentZFThread::note_sync_zfs();
- break;
- } else {
- ConcurrentZFThread::wait_for_ZF_completed(this);
- }
- case HeapRegion::ZeroFilled:
- // Nothing to do.
- break;
- case HeapRegion::Allocated:
- guarantee(false, "Should not call on allocated regions.");
- }
- assert(zero_fill_state() == HeapRegion::ZeroFilled, "Post");
-}
-
HeapWord*
HeapRegion::object_iterate_mem_careful(MemRegion mr,
ObjectClosure* cl) {
@@ -782,9 +714,6 @@
verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy);
}
-#define OBJ_SAMPLE_INTERVAL 0
-#define BLOCK_SAMPLE_INTERVAL 100
-
// This really ought to be commoned up into OffsetTableContigSpace somehow.
// We would need a mechanism to make that code skip dead objects.
@@ -795,83 +724,125 @@
*failures = false;
HeapWord* p = bottom();
HeapWord* prev_p = NULL;
- int objs = 0;
- int blocks = 0;
VerifyLiveClosure vl_cl(g1, use_prev_marking);
bool is_humongous = isHumongous();
+ bool do_bot_verify = !is_young();
size_t object_num = 0;
while (p < top()) {
- size_t size = oop(p)->size();
- if (is_humongous != g1->isHumongous(size)) {
+ oop obj = oop(p);
+ size_t obj_size = obj->size();
+ object_num += 1;
+
+ if (is_humongous != g1->isHumongous(obj_size)) {
gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size ("
SIZE_FORMAT" words) in a %shumongous region",
- p, g1->isHumongous(size) ? "" : "non-",
- size, is_humongous ? "" : "non-");
+ p, g1->isHumongous(obj_size) ? "" : "non-",
+ obj_size, is_humongous ? "" : "non-");
*failures = true;
+ return;
+ }
+
+ // If it returns false, verify_for_object() will output the
+ // appropriate messasge.
+ if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) {
+ *failures = true;
+ return;
}
- object_num += 1;
- if (blocks == BLOCK_SAMPLE_INTERVAL) {
- HeapWord* res = block_start_const(p + (size/2));
- if (p != res) {
- gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and "
- SIZE_FORMAT" returned "PTR_FORMAT,
- p, size, res);
+
+ if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
+ if (obj->is_oop()) {
+ klassOop klass = obj->klass();
+ if (!klass->is_perm()) {
+ gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
+ "not in perm", klass, obj);
+ *failures = true;
+ return;
+ } else if (!klass->is_klass()) {
+ gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
+ "not a klass", klass, obj);
+ *failures = true;
+ return;
+ } else {
+ vl_cl.set_containing_obj(obj);
+ obj->oop_iterate(&vl_cl);
+ if (vl_cl.failures()) {
+ *failures = true;
+ }
+ if (G1MaxVerifyFailures >= 0 &&
+ vl_cl.n_failures() >= G1MaxVerifyFailures) {
+ return;
+ }
+ }
+ } else {
+ gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
*failures = true;
return;
}
- blocks = 0;
- } else {
- blocks++;
- }
- if (objs == OBJ_SAMPLE_INTERVAL) {
- oop obj = oop(p);
- if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) {
- if (obj->is_oop()) {
- klassOop klass = obj->klass();
- if (!klass->is_perm()) {
- gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
- "not in perm", klass, obj);
- *failures = true;
- return;
- } else if (!klass->is_klass()) {
- gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
- "not a klass", klass, obj);
- *failures = true;
- return;
- } else {
- vl_cl.set_containing_obj(obj);
- obj->oop_iterate(&vl_cl);
- if (vl_cl.failures()) {
- *failures = true;
- }
- if (G1MaxVerifyFailures >= 0 &&
- vl_cl.n_failures() >= G1MaxVerifyFailures) {
- return;
- }
- }
- } else {
- gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj);
- *failures = true;
- return;
- }
- }
- objs = 0;
- } else {
- objs++;
}
prev_p = p;
- p += size;
+ p += obj_size;
+ }
+
+ if (p != top()) {
+ gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
+ "does not match top "PTR_FORMAT, p, top());
+ *failures = true;
+ return;
}
- HeapWord* rend = end();
- HeapWord* rtop = top();
- if (rtop < rend) {
- HeapWord* res = block_start_const(rtop + (rend - rtop) / 2);
- if (res != rtop) {
- gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and "
- PTR_FORMAT" returned "PTR_FORMAT,
- rtop, rend, res);
+
+ HeapWord* the_end = end();
+ assert(p == top(), "it should still hold");
+ // Do some extra BOT consistency checking for addresses in the
+ // range [top, end). BOT look-ups in this range should yield
+ // top. No point in doing that if top == end (there's nothing there).
+ if (p < the_end) {
+ // Look up top
+ HeapWord* addr_1 = p;
+ HeapWord* b_start_1 = _offsets.block_start_const(addr_1);
+ if (b_start_1 != p) {
+ gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" "
+ " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+ addr_1, b_start_1, p);
+ *failures = true;
+ return;
+ }
+
+ // Look up top + 1
+ HeapWord* addr_2 = p + 1;
+ if (addr_2 < the_end) {
+ HeapWord* b_start_2 = _offsets.block_start_const(addr_2);
+ if (b_start_2 != p) {
+ gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" "
+ " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+ addr_2, b_start_2, p);
*failures = true;
return;
+ }
+ }
+
+ // Look up an address between top and end
+ size_t diff = pointer_delta(the_end, p) / 2;
+ HeapWord* addr_3 = p + diff;
+ if (addr_3 < the_end) {
+ HeapWord* b_start_3 = _offsets.block_start_const(addr_3);
+ if (b_start_3 != p) {
+ gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" "
+ " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+ addr_3, b_start_3, p);
+ *failures = true;
+ return;
+ }
+ }
+
+ // Loook up end - 1
+ HeapWord* addr_4 = the_end - 1;
+ HeapWord* b_start_4 = _offsets.block_start_const(addr_4);
+ if (b_start_4 != p) {
+ gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" "
+ " yielded "PTR_FORMAT", expecting "PTR_FORMAT,
+ addr_4, b_start_4, p);
+ *failures = true;
+ return;
}
}
@@ -880,12 +851,6 @@
"but has "SIZE_FORMAT", objects",
bottom(), end(), object_num);
*failures = true;
- }
-
- if (p != top()) {
- gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
- "does not match top "PTR_FORMAT, p, top());
- *failures = true;
return;
}
}
@@ -976,67 +941,3 @@
_offsets.set_space(this);
initialize(mr, !is_zeroed, SpaceDecorator::Mangle);
}
-
-size_t RegionList::length() {
- size_t len = 0;
- HeapRegion* cur = hd();
- DEBUG_ONLY(HeapRegion* last = NULL);
- while (cur != NULL) {
- len++;
- DEBUG_ONLY(last = cur);
- cur = get_next(cur);
- }
- assert(last == tl(), "Invariant");
- return len;
-}
-
-void RegionList::insert_before_head(HeapRegion* r) {
- assert(well_formed(), "Inv");
- set_next(r, hd());
- _hd = r;
- _sz++;
- if (tl() == NULL) _tl = r;
- assert(well_formed(), "Inv");
-}
-
-void RegionList::prepend_list(RegionList* new_list) {
- assert(well_formed(), "Precondition");
- assert(new_list->well_formed(), "Precondition");
- HeapRegion* new_tl = new_list->tl();
- if (new_tl != NULL) {
- set_next(new_tl, hd());
- _hd = new_list->hd();
- _sz += new_list->sz();
- if (tl() == NULL) _tl = new_list->tl();
- } else {
- assert(new_list->hd() == NULL && new_list->sz() == 0, "Inv");
- }
- assert(well_formed(), "Inv");
-}
-
-void RegionList::delete_after(HeapRegion* r) {
- assert(well_formed(), "Precondition");
- HeapRegion* next = get_next(r);
- assert(r != NULL, "Precondition");
- HeapRegion* next_tl = get_next(next);
- set_next(r, next_tl);
- dec_sz();
- if (next == tl()) {
- assert(next_tl == NULL, "Inv");
- _tl = r;
- }
- assert(well_formed(), "Inv");
-}
-
-HeapRegion* RegionList::pop() {
- assert(well_formed(), "Inv");
- HeapRegion* res = hd();
- if (res != NULL) {
- _hd = get_next(res);
- _sz--;
- set_next(res, NULL);
- if (sz() == 0) _tl = NULL;
- }
- assert(well_formed(), "Inv");
- return res;
-}
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -50,6 +50,11 @@
class HeapRegionRemSet;
class HeapRegionRemSetIterator;
class HeapRegion;
+class HeapRegionSetBase;
+
+#define HR_FORMAT "%d:["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
+#define HR_FORMAT_PARAMS(__hr) (__hr)->hrs_index(), (__hr)->bottom(), \
+ (__hr)->top(), (__hr)->end()
// A dirty card to oop closure for heap regions. It
// knows how to get the G1 heap and how to use the bitmap
@@ -173,6 +178,19 @@
virtual HeapWord* cross_threshold(HeapWord* start, HeapWord* end);
virtual void print() const;
+
+ void reset_bot() {
+ _offsets.zero_bottom_entry();
+ _offsets.initialize_threshold();
+ }
+
+ void update_bot_for_object(HeapWord* start, size_t word_size) {
+ _offsets.alloc_block(start, word_size);
+ }
+
+ void print_bot_on(outputStream* out) {
+ _offsets.print_on(out);
+ }
};
class HeapRegion: public G1OffsetTableContigSpace {
@@ -214,12 +232,6 @@
// True iff the region is in current collection_set.
bool _in_collection_set;
- // True iff the region is on the unclean list, waiting to be zero filled.
- bool _is_on_unclean_list;
-
- // True iff the region is on the free list, ready for allocation.
- bool _is_on_free_list;
-
// Is this or has it been an allocation region in the current collection
// pause.
bool _is_gc_alloc_region;
@@ -241,6 +253,13 @@
// Next region whose cards need cleaning
HeapRegion* _next_dirty_cards_region;
+ // Fields used by the HeapRegionSetBase class and subclasses.
+ HeapRegion* _next;
+#ifdef ASSERT
+ HeapRegionSetBase* _containing_set;
+#endif // ASSERT
+ bool _pending_removal;
+
// For parallel heapRegion traversal.
jint _claimed;
@@ -292,10 +311,6 @@
_top_at_conc_mark_count = bot;
}
- jint _zfs; // A member of ZeroFillState. Protected by ZF_lock.
- Thread* _zero_filler; // If _zfs is ZeroFilling, the thread that (last)
- // made it so.
-
void set_young_type(YoungType new_type) {
//assert(_young_type != new_type, "setting the same type" );
// TODO: add more assertions here
@@ -349,15 +364,14 @@
RebuildRSClaimValue = 5
};
- // Concurrent refinement requires contiguous heap regions (in which TLABs
- // might be allocated) to be zero-filled. Each region therefore has a
- // zero-fill-state.
- enum ZeroFillState {
- NotZeroFilled,
- ZeroFilling,
- ZeroFilled,
- Allocated
- };
+ inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
+ assert(is_young(), "we can only skip BOT updates on young regions");
+ return ContiguousSpace::par_allocate(word_size);
+ }
+ inline HeapWord* allocate_no_bot_updates(size_t word_size) {
+ assert(is_young(), "we can only skip BOT updates on young regions");
+ return ContiguousSpace::allocate(word_size);
+ }
// If this region is a member of a HeapRegionSeq, the index in that
// sequence, otherwise -1.
@@ -404,13 +418,38 @@
return _humongous_start_region;
}
- // Causes the current region to represent a humongous object spanning "n"
- // regions.
- void set_startsHumongous(HeapWord* new_end);
+ // Makes the current region be a "starts humongous" region, i.e.,
+ // the first region in a series of one or more contiguous regions
+ // that will contain a single "humongous" object. The two parameters
+ // are as follows:
+ //
+ // new_top : The new value of the top field of this region which
+ // points to the end of the humongous object that's being
+ // allocated. If there is more than one region in the series, top
+ // will lie beyond this region's original end field and on the last
+ // region in the series.
+ //
+ // new_end : The new value of the end field of this region which
+ // points to the end of the last region in the series. If there is
+ // one region in the series (namely: this one) end will be the same
+ // as the original end of this region.
+ //
+ // Updating top and end as described above makes this region look as
+ // if it spans the entire space taken up by all the regions in the
+ // series and an single allocation moved its top to new_top. This
+ // ensures that the space (capacity / allocated) taken up by all
+ // humongous regions can be calculated by just looking at the
+ // "starts humongous" regions and by ignoring the "continues
+ // humongous" regions.
+ void set_startsHumongous(HeapWord* new_top, HeapWord* new_end);
- // The regions that continue a humongous sequence should be added using
- // this method, in increasing address order.
- void set_continuesHumongous(HeapRegion* start);
+ // Makes the current region be a "continues humongous'
+ // region. first_hr is the "start humongous" region of the series
+ // which this region will be part of.
+ void set_continuesHumongous(HeapRegion* first_hr);
+
+ // Unsets the humongous-related fields on the region.
+ void set_notHumongous();
// If the region has a remembered set, return a pointer to it.
HeapRegionRemSet* rem_set() const {
@@ -458,45 +497,56 @@
_next_in_special_set = r;
}
- bool is_on_free_list() {
- return _is_on_free_list;
- }
+ // Methods used by the HeapRegionSetBase class and subclasses.
- void set_on_free_list(bool b) {
- _is_on_free_list = b;
- }
+ // Getter and setter for the next field used to link regions into
+ // linked lists.
+ HeapRegion* next() { return _next; }
+
+ void set_next(HeapRegion* next) { _next = next; }
- HeapRegion* next_from_free_list() {
- assert(is_on_free_list(),
- "Should only invoke on free space.");
- assert(_next_in_special_set == NULL ||
- _next_in_special_set->is_on_free_list(),
- "Malformed Free List.");
- return _next_in_special_set;
- }
+ // Every region added to a set is tagged with a reference to that
+ // set. This is used for doing consistency checking to make sure that
+ // the contents of a set are as they should be and it's only
+ // available in non-product builds.
+#ifdef ASSERT
+ void set_containing_set(HeapRegionSetBase* containing_set) {
+ assert((containing_set == NULL && _containing_set != NULL) ||
+ (containing_set != NULL && _containing_set == NULL),
+ err_msg("containing_set: "PTR_FORMAT" "
+ "_containing_set: "PTR_FORMAT,
+ containing_set, _containing_set));
+
+ _containing_set = containing_set;
+}
- void set_next_on_free_list(HeapRegion* r) {
- assert(r == NULL || r->is_on_free_list(), "Malformed free list.");
- _next_in_special_set = r;
- }
+ HeapRegionSetBase* containing_set() { return _containing_set; }
+#else // ASSERT
+ void set_containing_set(HeapRegionSetBase* containing_set) { }
- bool is_on_unclean_list() {
- return _is_on_unclean_list;
- }
+ // containing_set() is only used in asserts so there's not reason
+ // to provide a dummy version of it.
+#endif // ASSERT
- void set_on_unclean_list(bool b);
+ // If we want to remove regions from a list in bulk we can simply tag
+ // them with the pending_removal tag and call the
+ // remove_all_pending() method on the list.
- HeapRegion* next_from_unclean_list() {
- assert(is_on_unclean_list(),
- "Should only invoke on unclean space.");
- assert(_next_in_special_set == NULL ||
- _next_in_special_set->is_on_unclean_list(),
- "Malformed unclean List.");
- return _next_in_special_set;
+ bool pending_removal() { return _pending_removal; }
+
+ void set_pending_removal(bool pending_removal) {
+ // We can only set pending_removal to true, if it's false and the
+ // region belongs to a set.
+ assert(!pending_removal ||
+ (!_pending_removal && containing_set() != NULL), "pre-condition");
+ // We can only set pending_removal to false, if it's true and the
+ // region does not belong to a set.
+ assert( pending_removal ||
+ ( _pending_removal && containing_set() == NULL), "pre-condition");
+
+ _pending_removal = pending_removal;
}
- void set_next_on_unclean_list(HeapRegion* r);
-
HeapRegion* get_next_young_region() { return _next_young_region; }
void set_next_young_region(HeapRegion* hr) {
_next_young_region = hr;
@@ -515,11 +565,6 @@
void initialize(MemRegion mr, bool clear_space, bool mangle_space);
- // Ensure that "this" is zero-filled.
- void ensure_zero_filled();
- // This one requires that the calling thread holds ZF_mon.
- void ensure_zero_filled_locked();
-
// Get the start of the unmarked area in this region.
HeapWord* prev_top_at_mark_start() const { return _prev_top_at_mark_start; }
HeapWord* next_top_at_mark_start() const { return _next_top_at_mark_start; }
@@ -754,36 +799,6 @@
// "end" of the region if there is no such block.
HeapWord* next_block_start_careful(HeapWord* addr);
- // Returns the zero-fill-state of the current region.
- ZeroFillState zero_fill_state() { return (ZeroFillState)_zfs; }
- bool zero_fill_is_allocated() { return _zfs == Allocated; }
- Thread* zero_filler() { return _zero_filler; }
-
- // Indicate that the contents of the region are unknown, and therefore
- // might require zero-filling.
- void set_zero_fill_needed() {
- set_zero_fill_state_work(NotZeroFilled);
- }
- void set_zero_fill_in_progress(Thread* t) {
- set_zero_fill_state_work(ZeroFilling);
- _zero_filler = t;
- }
- void set_zero_fill_complete();
- void set_zero_fill_allocated() {
- set_zero_fill_state_work(Allocated);
- }
-
- void set_zero_fill_state_work(ZeroFillState zfs);
-
- // This is called when a full collection shrinks the heap.
- // We want to set the heap region to a value which says
- // it is no longer part of the heap. For now, we'll let "NotZF" fill
- // that role.
- void reset_zero_fill() {
- set_zero_fill_state_work(NotZeroFilled);
- _zero_filler = NULL;
- }
-
size_t recorded_rs_length() const { return _recorded_rs_length; }
double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; }
size_t predicted_bytes_to_copy() const { return _predicted_bytes_to_copy; }
@@ -822,10 +837,6 @@
// Override; it uses the "prev" marking information
virtual void verify(bool allow_dirty) const;
-
-#ifdef DEBUG
- HeapWord* allocate(size_t size);
-#endif
};
// HeapRegionClosure is used for iterating over regions.
@@ -848,113 +859,6 @@
bool complete() { return _complete; }
};
-// A linked lists of heap regions. It leaves the "next" field
-// unspecified; that's up to subtypes.
-class RegionList VALUE_OBJ_CLASS_SPEC {
-protected:
- virtual HeapRegion* get_next(HeapRegion* chr) = 0;
- virtual void set_next(HeapRegion* chr,
- HeapRegion* new_next) = 0;
-
- HeapRegion* _hd;
- HeapRegion* _tl;
- size_t _sz;
-
- // Protected constructor because this type is only meaningful
- // when the _get/_set next functions are defined.
- RegionList() : _hd(NULL), _tl(NULL), _sz(0) {}
-public:
- void reset() {
- _hd = NULL;
- _tl = NULL;
- _sz = 0;
- }
- HeapRegion* hd() { return _hd; }
- HeapRegion* tl() { return _tl; }
- size_t sz() { return _sz; }
- size_t length();
-
- bool well_formed() {
- return
- ((hd() == NULL && tl() == NULL && sz() == 0)
- || (hd() != NULL && tl() != NULL && sz() > 0))
- && (sz() == length());
- }
- virtual void insert_before_head(HeapRegion* r);
- void prepend_list(RegionList* new_list);
- virtual HeapRegion* pop();
- void dec_sz() { _sz--; }
- // Requires that "r" is an element of the list, and is not the tail.
- void delete_after(HeapRegion* r);
-};
-
-class EmptyNonHRegionList: public RegionList {
-protected:
- // Protected constructor because this type is only meaningful
- // when the _get/_set next functions are defined.
- EmptyNonHRegionList() : RegionList() {}
-
-public:
- void insert_before_head(HeapRegion* r) {
- // assert(r->is_empty(), "Better be empty");
- assert(!r->isHumongous(), "Better not be humongous.");
- RegionList::insert_before_head(r);
- }
- void prepend_list(EmptyNonHRegionList* new_list) {
- // assert(new_list->hd() == NULL || new_list->hd()->is_empty(),
- // "Better be empty");
- assert(new_list->hd() == NULL || !new_list->hd()->isHumongous(),
- "Better not be humongous.");
- // assert(new_list->tl() == NULL || new_list->tl()->is_empty(),
- // "Better be empty");
- assert(new_list->tl() == NULL || !new_list->tl()->isHumongous(),
- "Better not be humongous.");
- RegionList::prepend_list(new_list);
- }
-};
-
-class UncleanRegionList: public EmptyNonHRegionList {
-public:
- HeapRegion* get_next(HeapRegion* hr) {
- return hr->next_from_unclean_list();
- }
- void set_next(HeapRegion* hr, HeapRegion* new_next) {
- hr->set_next_on_unclean_list(new_next);
- }
-
- UncleanRegionList() : EmptyNonHRegionList() {}
-
- void insert_before_head(HeapRegion* r) {
- assert(!r->is_on_free_list(),
- "Better not already be on free list");
- assert(!r->is_on_unclean_list(),
- "Better not already be on unclean list");
- r->set_zero_fill_needed();
- r->set_on_unclean_list(true);
- EmptyNonHRegionList::insert_before_head(r);
- }
- void prepend_list(UncleanRegionList* new_list) {
- assert(new_list->tl() == NULL || !new_list->tl()->is_on_free_list(),
- "Better not already be on free list");
- assert(new_list->tl() == NULL || new_list->tl()->is_on_unclean_list(),
- "Better already be marked as on unclean list");
- assert(new_list->hd() == NULL || !new_list->hd()->is_on_free_list(),
- "Better not already be on free list");
- assert(new_list->hd() == NULL || new_list->hd()->is_on_unclean_list(),
- "Better already be marked as on unclean list");
- EmptyNonHRegionList::prepend_list(new_list);
- }
- HeapRegion* pop() {
- HeapRegion* res = RegionList::pop();
- if (res != NULL) res->set_on_unclean_list(false);
- return res;
- }
-};
-
-// Local Variables: ***
-// c-indentation-style: gnu ***
-// End: ***
-
#endif // SERIALGC
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -65,152 +65,6 @@
// Private methods.
-HeapWord*
-HeapRegionSeq::alloc_obj_from_region_index(int ind, size_t word_size) {
- assert(G1CollectedHeap::isHumongous(word_size),
- "Allocation size should be humongous");
- int cur = ind;
- int first = cur;
- size_t sumSizes = 0;
- while (cur < _regions.length() && sumSizes < word_size) {
- // Loop invariant:
- // For all i in [first, cur):
- // _regions.at(i)->is_empty()
- // && _regions.at(i) is contiguous with its predecessor, if any
- // && sumSizes is the sum of the sizes of the regions in the interval
- // [first, cur)
- HeapRegion* curhr = _regions.at(cur);
- if (curhr->is_empty()
- && (first == cur
- || (_regions.at(cur-1)->end() ==
- curhr->bottom()))) {
- sumSizes += curhr->capacity() / HeapWordSize;
- } else {
- first = cur + 1;
- sumSizes = 0;
- }
- cur++;
- }
- if (sumSizes >= word_size) {
- _alloc_search_start = cur;
-
- // We need to initialize the region(s) we just discovered. This is
- // a bit tricky given that it can happen concurrently with
- // refinement threads refining cards on these regions and
- // potentially wanting to refine the BOT as they are scanning
- // those cards (this can happen shortly after a cleanup; see CR
- // 6991377). So we have to set up the region(s) carefully and in
- // a specific order.
-
- // Currently, allocs_are_zero_filled() returns false. The zero
- // filling infrastructure will be going away soon (see CR 6977804).
- // So no need to do anything else here.
- bool zf = G1CollectedHeap::heap()->allocs_are_zero_filled();
- assert(!zf, "not supported");
-
- // This will be the "starts humongous" region.
- HeapRegion* first_hr = _regions.at(first);
- {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- first_hr->set_zero_fill_allocated();
- }
- // The header of the new object will be placed at the bottom of
- // the first region.
- HeapWord* new_obj = first_hr->bottom();
- // This will be the new end of the first region in the series that
- // should also match the end of the last region in the seriers.
- // (Note: sumSizes = "region size" x "number of regions we found").
- HeapWord* new_end = new_obj + sumSizes;
- // This will be the new top of the first region that will reflect
- // this allocation.
- HeapWord* new_top = new_obj + word_size;
-
- // First, we need to zero the header of the space that we will be
- // allocating. When we update top further down, some refinement
- // threads might try to scan the region. By zeroing the header we
- // ensure that any thread that will try to scan the region will
- // come across the zero klass word and bail out.
- //
- // NOTE: It would not have been correct to have used
- // CollectedHeap::fill_with_object() and make the space look like
- // an int array. The thread that is doing the allocation will
- // later update the object header to a potentially different array
- // type and, for a very short period of time, the klass and length
- // fields will be inconsistent. This could cause a refinement
- // thread to calculate the object size incorrectly.
- Copy::fill_to_words(new_obj, oopDesc::header_size(), 0);
-
- // We will set up the first region as "starts humongous". This
- // will also update the BOT covering all the regions to reflect
- // that there is a single object that starts at the bottom of the
- // first region.
- first_hr->set_startsHumongous(new_end);
-
- // Then, if there are any, we will set up the "continues
- // humongous" regions.
- HeapRegion* hr = NULL;
- for (int i = first + 1; i < cur; ++i) {
- hr = _regions.at(i);
- {
- MutexLockerEx x(ZF_mon, Mutex::_no_safepoint_check_flag);
- hr->set_zero_fill_allocated();
- }
- hr->set_continuesHumongous(first_hr);
- }
- // If we have "continues humongous" regions (hr != NULL), then the
- // end of the last one should match new_end.
- assert(hr == NULL || hr->end() == new_end, "sanity");
-
- // Up to this point no concurrent thread would have been able to
- // do any scanning on any region in this series. All the top
- // fields still point to bottom, so the intersection between
- // [bottom,top] and [card_start,card_end] will be empty. Before we
- // update the top fields, we'll do a storestore to make sure that
- // no thread sees the update to top before the zeroing of the
- // object header and the BOT initialization.
- OrderAccess::storestore();
-
- // Now that the BOT and the object header have been initialized,
- // we can update top of the "starts humongous" region.
- assert(first_hr->bottom() < new_top && new_top <= first_hr->end(),
- "new_top should be in this region");
- first_hr->set_top(new_top);
-
- // Now, we will update the top fields of the "continues humongous"
- // regions. The reason we need to do this is that, otherwise,
- // these regions would look empty and this will confuse parts of
- // G1. For example, the code that looks for a consecutive number
- // of empty regions will consider them empty and try to
- // re-allocate them. We can extend is_empty() to also include
- // !continuesHumongous(), but it is easier to just update the top
- // fields here.
- hr = NULL;
- for (int i = first + 1; i < cur; ++i) {
- hr = _regions.at(i);
- if ((i + 1) == cur) {
- // last continues humongous region
- assert(hr->bottom() < new_top && new_top <= hr->end(),
- "new_top should fall on this region");
- hr->set_top(new_top);
- } else {
- // not last one
- assert(new_top > hr->end(), "new_top should be above this region");
- hr->set_top(hr->end());
- }
- }
- // If we have continues humongous regions (hr != NULL), then the
- // end of the last one should match new_end and its top should
- // match new_top.
- assert(hr == NULL ||
- (hr->end() == new_end && hr->top() == new_top), "sanity");
-
- return new_obj;
- } else {
- // If we started from the beginning, we want to know why we can't alloc.
- return NULL;
- }
-}
-
void HeapRegionSeq::print_empty_runs() {
int empty_run = 0;
int n_empty = 0;
@@ -284,13 +138,67 @@
return res;
}
-HeapWord* HeapRegionSeq::obj_allocate(size_t word_size) {
- int cur = _alloc_search_start;
- // Make sure "cur" is a valid index.
- assert(cur >= 0, "Invariant.");
- HeapWord* res = alloc_obj_from_region_index(cur, word_size);
- if (res == NULL)
- res = alloc_obj_from_region_index(0, word_size);
+int HeapRegionSeq::find_contiguous_from(int from, size_t num) {
+ assert(num > 1, "pre-condition");
+ assert(0 <= from && from <= _regions.length(),
+ err_msg("from: %d should be valid and <= than %d",
+ from, _regions.length()));
+
+ int curr = from;
+ int first = -1;
+ size_t num_so_far = 0;
+ while (curr < _regions.length() && num_so_far < num) {
+ HeapRegion* curr_hr = _regions.at(curr);
+ if (curr_hr->is_empty()) {
+ if (first == -1) {
+ first = curr;
+ num_so_far = 1;
+ } else {
+ num_so_far += 1;
+ }
+ } else {
+ first = -1;
+ num_so_far = 0;
+ }
+ curr += 1;
+ }
+
+ assert(num_so_far <= num, "post-condition");
+ if (num_so_far == num) {
+ // we find enough space for the humongous object
+ assert(from <= first && first < _regions.length(), "post-condition");
+ assert(first < curr && (curr - first) == (int) num, "post-condition");
+ for (int i = first; i < first + (int) num; ++i) {
+ assert(_regions.at(i)->is_empty(), "post-condition");
+ }
+ return first;
+ } else {
+ // we failed to find enough space for the humongous object
+ return -1;
+ }
+}
+
+int HeapRegionSeq::find_contiguous(size_t num) {
+ assert(num > 1, "otherwise we should not be calling this");
+ assert(0 <= _alloc_search_start && _alloc_search_start <= _regions.length(),
+ err_msg("_alloc_search_start: %d should be valid and <= than %d",
+ _alloc_search_start, _regions.length()));
+
+ int start = _alloc_search_start;
+ int res = find_contiguous_from(start, num);
+ if (res == -1 && start != 0) {
+ // Try starting from the beginning. If _alloc_search_start was 0,
+ // no point in doing this again.
+ res = find_contiguous_from(0, num);
+ }
+ if (res != -1) {
+ assert(0 <= res && res < _regions.length(),
+ err_msg("res: %d should be valid", res));
+ _alloc_search_start = res + (int) num;
+ }
+ assert(0 < _alloc_search_start && _alloc_search_start <= _regions.length(),
+ err_msg("_alloc_search_start: %d should be valid",
+ _alloc_search_start));
return res;
}
@@ -376,6 +284,10 @@
MemRegion HeapRegionSeq::shrink_by(size_t shrink_bytes,
size_t& num_regions_deleted) {
+ // Reset this in case it's currently pointing into the regions that
+ // we just removed.
+ _alloc_search_start = 0;
+
assert(shrink_bytes % os::vm_page_size() == 0, "unaligned");
assert(shrink_bytes % HeapRegion::GrainBytes == 0, "unaligned");
@@ -395,7 +307,6 @@
}
assert(cur == _regions.top(), "Should be top");
if (!cur->is_empty()) break;
- cur->reset_zero_fill();
shrink_bytes -= cur->capacity();
num_regions_deleted++;
_regions.pop();
@@ -410,7 +321,6 @@
return MemRegion(last_start, end);
}
-
class PrintHeapRegionClosure : public HeapRegionClosure {
public:
bool doHeapRegion(HeapRegion* r) {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -41,9 +41,9 @@
// (For efficiency only; private to obj_allocate after initialization.)
int _alloc_search_start;
- // Attempts to allocate a block of the (assumed humongous) word_size,
- // starting at the region "ind".
- HeapWord* alloc_obj_from_region_index(int ind, size_t word_size);
+ // Finds a contiguous set of empty regions of length num, starting
+ // from a given index.
+ int find_contiguous_from(int from, size_t num);
// Currently, we're choosing collection sets in a round-robin fashion,
// starting here.
@@ -76,11 +76,8 @@
// that are available for allocation.
size_t free_suffix();
- // Requires "word_size" to be humongous (in the technical sense). If
- // possible, allocates a contiguous subsequence of the heap regions to
- // satisfy the allocation, and returns the address of the beginning of
- // that sequence, otherwise returns NULL.
- HeapWord* obj_allocate(size_t word_size);
+ // Finds a contiguous set of empty regions of length num.
+ int find_contiguous(size_t num);
// Apply the "doHeapRegion" method of "blk" to all regions in "this",
// in address order, terminating the iteration early
@@ -106,7 +103,7 @@
// If "addr" falls within a region in the sequence, return that region,
// or else NULL.
- HeapRegion* addr_to_region(const void* addr);
+ inline HeapRegion* addr_to_region(const void* addr);
void print();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,438 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
+
+size_t HeapRegionSetBase::_unrealistically_long_length = 0;
+
+//////////////////// HeapRegionSetBase ////////////////////
+
+void HeapRegionSetBase::set_unrealistically_long_length(size_t len) {
+ guarantee(_unrealistically_long_length == 0, "should only be set once");
+ _unrealistically_long_length = len;
+}
+
+size_t HeapRegionSetBase::calculate_region_num(HeapRegion* hr) {
+ assert(hr->startsHumongous(), "pre-condition");
+ assert(hr->capacity() % HeapRegion::GrainBytes == 0, "invariant");
+ size_t region_num = hr->capacity() >> HeapRegion::LogOfHRGrainBytes;
+ assert(region_num > 0, "sanity");
+ return region_num;
+}
+
+void HeapRegionSetBase::fill_in_ext_msg(hrl_ext_msg* msg, const char* message) {
+ msg->append("[%s] %s "
+ "ln: "SIZE_FORMAT" rn: "SIZE_FORMAT" "
+ "cy: "SIZE_FORMAT" ud: "SIZE_FORMAT,
+ name(), message, length(), region_num(),
+ total_capacity_bytes(), total_used_bytes());
+ fill_in_ext_msg_extra(msg);
+}
+
+bool HeapRegionSetBase::verify_region(HeapRegion* hr,
+ HeapRegionSetBase* expected_containing_set) {
+ const char* error_message = NULL;
+
+ if (!regions_humongous()) {
+ if (hr->isHumongous()) {
+ error_message = "the region should not be humongous";
+ }
+ } else {
+ if (!hr->isHumongous() || !hr->startsHumongous()) {
+ error_message = "the region should be 'starts humongous'";
+ }
+ }
+
+ if (!regions_empty()) {
+ if (hr->is_empty()) {
+ error_message = "the region should not be empty";
+ }
+ } else {
+ if (!hr->is_empty()) {
+ error_message = "the region should be empty";
+ }
+ }
+
+#ifdef ASSERT
+ // The _containing_set field is only available when ASSERT is defined.
+ if (hr->containing_set() != expected_containing_set) {
+ error_message = "inconsistent containing set found";
+ }
+#endif // ASSERT
+
+ const char* extra_error_message = verify_region_extra(hr);
+ if (extra_error_message != NULL) {
+ error_message = extra_error_message;
+ }
+
+ if (error_message != NULL) {
+ outputStream* out = tty;
+ out->cr();
+ out->print_cr("## [%s] %s", name(), error_message);
+ out->print_cr("## Offending Region: "PTR_FORMAT, hr);
+ out->print_cr(" "HR_FORMAT, HR_FORMAT_PARAMS(hr));
+#ifdef ASSERT
+ out->print_cr(" containing set: "PTR_FORMAT, hr->containing_set());
+#endif // ASSERT
+ out->print_cr("## Offending Region Set: "PTR_FORMAT, this);
+ print_on(out);
+ return false;
+ } else {
+ return true;
+ }
+}
+
+void HeapRegionSetBase::verify() {
+ // It's important that we also observe the MT safety protocol even
+ // for the verification calls. If we do verification without the
+ // appropriate locks and the set changes underneath our feet
+ // verification might fail and send us on a wild goose chase.
+ hrl_assert_mt_safety_ok(this);
+
+ guarantee(( is_empty() && length() == 0 && region_num() == 0 &&
+ total_used_bytes() == 0 && total_capacity_bytes() == 0) ||
+ (!is_empty() && length() >= 0 && region_num() >= 0 &&
+ total_used_bytes() >= 0 && total_capacity_bytes() >= 0),
+ hrl_ext_msg(this, "invariant"));
+
+ guarantee((!regions_humongous() && region_num() == length()) ||
+ ( regions_humongous() && region_num() >= length()),
+ hrl_ext_msg(this, "invariant"));
+
+ guarantee(!regions_empty() || total_used_bytes() == 0,
+ hrl_ext_msg(this, "invariant"));
+
+ guarantee(total_used_bytes() <= total_capacity_bytes(),
+ hrl_ext_msg(this, "invariant"));
+}
+
+void HeapRegionSetBase::verify_start() {
+ // See comment in verify() about MT safety and verification.
+ hrl_assert_mt_safety_ok(this);
+ assert(!_verify_in_progress,
+ hrl_ext_msg(this, "verification should not be in progress"));
+
+ // Do the basic verification first before we do the checks over the regions.
+ HeapRegionSetBase::verify();
+
+ _calc_length = 0;
+ _calc_region_num = 0;
+ _calc_total_capacity_bytes = 0;
+ _calc_total_used_bytes = 0;
+ _verify_in_progress = true;
+}
+
+void HeapRegionSetBase::verify_next_region(HeapRegion* hr) {
+ // See comment in verify() about MT safety and verification.
+ hrl_assert_mt_safety_ok(this);
+ assert(_verify_in_progress,
+ hrl_ext_msg(this, "verification should be in progress"));
+
+ guarantee(verify_region(hr, this), hrl_ext_msg(this, "region verification"));
+
+ _calc_length += 1;
+ if (!hr->isHumongous()) {
+ _calc_region_num += 1;
+ } else {
+ _calc_region_num += calculate_region_num(hr);
+ }
+ _calc_total_capacity_bytes += hr->capacity();
+ _calc_total_used_bytes += hr->used();
+}
+
+void HeapRegionSetBase::verify_end() {
+ // See comment in verify() about MT safety and verification.
+ hrl_assert_mt_safety_ok(this);
+ assert(_verify_in_progress,
+ hrl_ext_msg(this, "verification should be in progress"));
+
+ guarantee(length() == _calc_length,
+ hrl_err_msg("[%s] length: "SIZE_FORMAT" should be == "
+ "calc length: "SIZE_FORMAT,
+ name(), length(), _calc_length));
+
+ guarantee(region_num() == _calc_region_num,
+ hrl_err_msg("[%s] region num: "SIZE_FORMAT" should be == "
+ "calc region num: "SIZE_FORMAT,
+ name(), region_num(), _calc_region_num));
+
+ guarantee(total_capacity_bytes() == _calc_total_capacity_bytes,
+ hrl_err_msg("[%s] capacity bytes: "SIZE_FORMAT" should be == "
+ "calc capacity bytes: "SIZE_FORMAT,
+ name(),
+ total_capacity_bytes(), _calc_total_capacity_bytes));
+
+ guarantee(total_used_bytes() == _calc_total_used_bytes,
+ hrl_err_msg("[%s] used bytes: "SIZE_FORMAT" should be == "
+ "calc used bytes: "SIZE_FORMAT,
+ name(), total_used_bytes(), _calc_total_used_bytes));
+
+ _verify_in_progress = false;
+}
+
+void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
+ out->cr();
+ out->print_cr("Set: %s ("PTR_FORMAT")", name(), this);
+ out->print_cr(" Region Assumptions");
+ out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
+ out->print_cr(" empty : %s", BOOL_TO_STR(regions_empty()));
+ out->print_cr(" Attributes");
+ out->print_cr(" length : "SIZE_FORMAT_W(14), length());
+ out->print_cr(" region num : "SIZE_FORMAT_W(14), region_num());
+ out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes",
+ total_capacity_bytes());
+ out->print_cr(" total used : "SIZE_FORMAT_W(14)" bytes",
+ total_used_bytes());
+}
+
+void HeapRegionSetBase::clear() {
+ _length = 0;
+ _region_num = 0;
+ _total_used_bytes = 0;
+}
+
+HeapRegionSetBase::HeapRegionSetBase(const char* name)
+ : _name(name), _verify_in_progress(false),
+ _calc_length(0), _calc_region_num(0),
+ _calc_total_capacity_bytes(0), _calc_total_used_bytes(0) { }
+
+//////////////////// HeapRegionSet ////////////////////
+
+void HeapRegionSet::update_from_proxy(HeapRegionSet* proxy_set) {
+ hrl_assert_mt_safety_ok(this);
+ hrl_assert_mt_safety_ok(proxy_set);
+ hrl_assert_sets_match(this, proxy_set);
+
+ verify_optional();
+ proxy_set->verify_optional();
+
+ if (proxy_set->is_empty()) return;
+
+ assert(proxy_set->length() <= _length,
+ hrl_err_msg("[%s] proxy set length: "SIZE_FORMAT" "
+ "should be <= length: "SIZE_FORMAT,
+ name(), proxy_set->length(), _length));
+ _length -= proxy_set->length();
+
+ assert(proxy_set->region_num() <= _region_num,
+ hrl_err_msg("[%s] proxy set region num: "SIZE_FORMAT" "
+ "should be <= region num: "SIZE_FORMAT,
+ name(), proxy_set->region_num(), _region_num));
+ _region_num -= proxy_set->region_num();
+
+ assert(proxy_set->total_used_bytes() <= _total_used_bytes,
+ hrl_err_msg("[%s] proxy set used bytes: "SIZE_FORMAT" "
+ "should be <= used bytes: "SIZE_FORMAT,
+ name(), proxy_set->total_used_bytes(),
+ _total_used_bytes));
+ _total_used_bytes -= proxy_set->total_used_bytes();
+
+ proxy_set->clear();
+
+ verify_optional();
+ proxy_set->verify_optional();
+}
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+void HeapRegionLinkedList::fill_in_ext_msg_extra(hrl_ext_msg* msg) {
+ msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
+}
+
+void HeapRegionLinkedList::add_as_tail(HeapRegionLinkedList* from_list) {
+ hrl_assert_mt_safety_ok(this);
+ hrl_assert_mt_safety_ok(from_list);
+
+ verify_optional();
+ from_list->verify_optional();
+
+ if (from_list->is_empty()) return;
+
+#ifdef ASSERT
+ HeapRegionLinkedListIterator iter(from_list);
+ while (iter.more_available()) {
+ HeapRegion* hr = iter.get_next();
+ // In set_containing_set() we check that we either set the value
+ // from NULL to non-NULL or vice versa to catch bugs. So, we have
+ // to NULL it first before setting it to the value.
+ hr->set_containing_set(NULL);
+ hr->set_containing_set(this);
+ }
+#endif // ASSERT
+
+ if (_tail != NULL) {
+ assert(length() > 0 && _head != NULL, hrl_ext_msg(this, "invariant"));
+ _tail->set_next(from_list->_head);
+ } else {
+ assert(length() == 0 && _head == NULL, hrl_ext_msg(this, "invariant"));
+ _head = from_list->_head;
+ }
+ _tail = from_list->_tail;
+
+ _length += from_list->length();
+ _region_num += from_list->region_num();
+ _total_used_bytes += from_list->total_used_bytes();
+ from_list->clear();
+
+ verify_optional();
+ from_list->verify_optional();
+}
+
+void HeapRegionLinkedList::remove_all() {
+ hrl_assert_mt_safety_ok(this);
+ verify_optional();
+
+ HeapRegion* curr = _head;
+ while (curr != NULL) {
+ hrl_assert_region_ok(this, curr, this);
+
+ HeapRegion* next = curr->next();
+ curr->set_next(NULL);
+ curr->set_containing_set(NULL);
+ curr = next;
+ }
+ clear();
+
+ verify_optional();
+}
+
+void HeapRegionLinkedList::remove_all_pending(size_t target_count) {
+ hrl_assert_mt_safety_ok(this);
+ assert(target_count > 1, hrl_ext_msg(this, "pre-condition"));
+ assert(!is_empty(), hrl_ext_msg(this, "pre-condition"));
+
+ verify_optional();
+ DEBUG_ONLY(size_t old_length = length();)
+
+ HeapRegion* curr = _head;
+ HeapRegion* prev = NULL;
+ size_t count = 0;
+ while (curr != NULL) {
+ hrl_assert_region_ok(this, curr, this);
+ HeapRegion* next = curr->next();
+
+ if (curr->pending_removal()) {
+ assert(count < target_count,
+ hrl_err_msg("[%s] should not come across more regions "
+ "pending for removal than target_count: "SIZE_FORMAT,
+ name(), target_count));
+
+ if (prev == NULL) {
+ assert(_head == curr, hrl_ext_msg(this, "invariant"));
+ _head = next;
+ } else {
+ assert(_head != curr, hrl_ext_msg(this, "invariant"));
+ prev->set_next(next);
+ }
+ if (next == NULL) {
+ assert(_tail == curr, hrl_ext_msg(this, "invariant"));
+ _tail = prev;
+ } else {
+ assert(_tail != curr, hrl_ext_msg(this, "invariant"));
+ }
+
+ curr->set_next(NULL);
+ remove_internal(curr);
+ curr->set_pending_removal(false);
+
+ count += 1;
+
+ // If we have come across the target number of regions we can
+ // just bail out. However, for debugging purposes, we can just
+ // carry on iterating to make sure there are not more regions
+ // tagged with pending removal.
+ DEBUG_ONLY(if (count == target_count) break;)
+ } else {
+ prev = curr;
+ }
+ curr = next;
+ }
+
+ assert(count == target_count,
+ hrl_err_msg("[%s] count: "SIZE_FORMAT" should be == "
+ "target_count: "SIZE_FORMAT, name(), count, target_count));
+ assert(length() + target_count == old_length,
+ hrl_err_msg("[%s] new length should be consistent "
+ "new length: "SIZE_FORMAT" old length: "SIZE_FORMAT" "
+ "target_count: "SIZE_FORMAT,
+ name(), length(), old_length, target_count));
+
+ verify_optional();
+}
+
+void HeapRegionLinkedList::verify() {
+ // See comment in HeapRegionSetBase::verify() about MT safety and
+ // verification.
+ hrl_assert_mt_safety_ok(this);
+
+ // This will also do the basic verification too.
+ verify_start();
+
+ HeapRegion* curr = _head;
+ HeapRegion* prev1 = NULL;
+ HeapRegion* prev0 = NULL;
+ size_t count = 0;
+ while (curr != NULL) {
+ verify_next_region(curr);
+
+ count += 1;
+ guarantee(count < _unrealistically_long_length,
+ hrl_err_msg("[%s] the calculated length: "SIZE_FORMAT" "
+ "seems very long, is there maybe a cycle? "
+ "curr: "PTR_FORMAT" prev0: "PTR_FORMAT" "
+ "prev1: "PTR_FORMAT" length: "SIZE_FORMAT,
+ name(), count, curr, prev0, prev1, length()));
+
+ prev1 = prev0;
+ prev0 = curr;
+ curr = curr->next();
+ }
+
+ guarantee(_tail == prev0, hrl_ext_msg(this, "post-condition"));
+
+ verify_end();
+}
+
+void HeapRegionLinkedList::clear() {
+ HeapRegionSetBase::clear();
+ _head = NULL;
+ _tail = NULL;
+}
+
+void HeapRegionLinkedList::print_on(outputStream* out, bool print_contents) {
+ HeapRegionSetBase::print_on(out, print_contents);
+ out->print_cr(" Linking");
+ out->print_cr(" head : "PTR_FORMAT, _head);
+ out->print_cr(" tail : "PTR_FORMAT, _tail);
+
+ if (print_contents) {
+ out->print_cr(" Contents");
+ HeapRegionLinkedListIterator iter(this);
+ while (iter.more_available()) {
+ HeapRegion* hr = iter.get_next();
+ hr->print_on(out);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
+
+#include "gc_implementation/g1/heapRegion.hpp"
+
+// Large buffer for some cases where the output might be larger than normal.
+#define HRL_ERR_MSG_BUFSZ 512
+typedef FormatBuffer<HRL_ERR_MSG_BUFSZ> hrl_err_msg;
+
+// Set verification will be forced either if someone defines
+// HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which
+// asserts are compiled in.
+#ifndef HEAP_REGION_SET_FORCE_VERIFY
+#define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
+#endif // HEAP_REGION_SET_FORCE_VERIFY
+
+//////////////////// HeapRegionSetBase ////////////////////
+
+// Base class for all the classes that represent heap region sets. It
+// contains the basic attributes that each set needs to maintain
+// (e.g., length, region num, used bytes sum) plus any shared
+// functionality (e.g., verification).
+
+class hrl_ext_msg;
+
+class HeapRegionSetBase VALUE_OBJ_CLASS_SPEC {
+ friend class hrl_ext_msg;
+
+protected:
+ static size_t calculate_region_num(HeapRegion* hr);
+
+ static size_t _unrealistically_long_length;
+
+ // The number of regions added to the set. If the set contains
+ // only humongous regions, this reflects only 'starts humongous'
+ // regions and does not include 'continues humongous' ones.
+ size_t _length;
+
+ // The total number of regions represented by the set. If the set
+ // does not contain humongous regions, this should be the same as
+ // _length. If the set contains only humongous regions, this will
+ // include the 'continues humongous' regions.
+ size_t _region_num;
+
+ // We don't keep track of the total capacity explicitly, we instead
+ // recalculate it based on _region_num and the heap region size.
+
+ // The sum of used bytes in the all the regions in the set.
+ size_t _total_used_bytes;
+
+ const char* _name;
+
+ bool _verify_in_progress;
+ size_t _calc_length;
+ size_t _calc_region_num;
+ size_t _calc_total_capacity_bytes;
+ size_t _calc_total_used_bytes;
+
+ // verify_region() is used to ensure that the contents of a region
+ // added to / removed from a set are consistent. Different sets
+ // make different assumptions about the regions added to them. So
+ // each set can override verify_region_extra(), which is called
+ // from verify_region(), and do any extra verification it needs to
+ // perform in that.
+ virtual const char* verify_region_extra(HeapRegion* hr) { return NULL; }
+ bool verify_region(HeapRegion* hr,
+ HeapRegionSetBase* expected_containing_set);
+
+ // Indicates whether all regions in the set should be humongous or
+ // not. Only used during verification.
+ virtual bool regions_humongous() = 0;
+
+ // Indicates whether all regions in the set should be empty or
+ // not. Only used during verification.
+ virtual bool regions_empty() = 0;
+
+ // Subclasses can optionally override this to do MT safety protocol
+ // checks. It is called in an assert from all methods that perform
+ // updates on the set (and subclasses should also call it too).
+ virtual bool check_mt_safety() { return true; }
+
+ // fill_in_ext_msg() writes the the values of the set's attributes
+ // in the custom err_msg (hrl_ext_msg). fill_in_ext_msg_extra()
+ // allows subclasses to append further information.
+ virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg) { }
+ void fill_in_ext_msg(hrl_ext_msg* msg, const char* message);
+
+ // It updates the fields of the set to reflect hr being added to
+ // the set.
+ inline void update_for_addition(HeapRegion* hr);
+
+ // It updates the fields of the set to reflect hr being added to
+ // the set and tags the region appropriately.
+ inline void add_internal(HeapRegion* hr);
+
+ // It updates the fields of the set to reflect hr being removed
+ // from the set.
+ inline void update_for_removal(HeapRegion* hr);
+
+ // It updates the fields of the set to reflect hr being removed
+ // from the set and tags the region appropriately.
+ inline void remove_internal(HeapRegion* hr);
+
+ // It clears all the fields of the sets. Note: it will not iterate
+ // over the set and remove regions from it. It assumes that the
+ // caller has already done so. It will literally just clear the fields.
+ virtual void clear();
+
+ HeapRegionSetBase(const char* name);
+
+public:
+ static void set_unrealistically_long_length(size_t len);
+
+ const char* name() { return _name; }
+
+ size_t length() { return _length; }
+
+ bool is_empty() { return _length == 0; }
+
+ size_t region_num() { return _region_num; }
+
+ size_t total_capacity_bytes() {
+ return region_num() << HeapRegion::LogOfHRGrainBytes;
+ }
+
+ size_t total_used_bytes() { return _total_used_bytes; }
+
+ virtual void verify();
+ void verify_start();
+ void verify_next_region(HeapRegion* hr);
+ void verify_end();
+
+#if HEAP_REGION_SET_FORCE_VERIFY
+ void verify_optional() {
+ verify();
+ }
+#else // HEAP_REGION_SET_FORCE_VERIFY
+ void verify_optional() { }
+#endif // HEAP_REGION_SET_FORCE_VERIFY
+
+ virtual void print_on(outputStream* out, bool print_contents = false);
+};
+
+// Customized err_msg for heap region sets. Apart from a
+// assert/guarantee-specific message it also prints out the values of
+// the fields of the associated set. This can be very helpful in
+// diagnosing failures.
+
+class hrl_ext_msg : public hrl_err_msg {
+public:
+ hrl_ext_msg(HeapRegionSetBase* set, const char* message) : hrl_err_msg("") {
+ set->fill_in_ext_msg(this, message);
+ }
+};
+
+// These two macros are provided for convenience, to keep the uses of
+// these two asserts a bit more concise.
+
+#define hrl_assert_mt_safety_ok(_set_) \
+ do { \
+ assert((_set_)->check_mt_safety(), hrl_ext_msg((_set_), "MT safety")); \
+ } while (0)
+
+#define hrl_assert_region_ok(_set_, _hr_, _expected_) \
+ do { \
+ assert((_set_)->verify_region((_hr_), (_expected_)), \
+ hrl_ext_msg((_set_), "region verification")); \
+ } while (0)
+
+//////////////////// HeapRegionSet ////////////////////
+
+#define hrl_assert_sets_match(_set1_, _set2_) \
+ do { \
+ assert(((_set1_)->regions_humongous() == \
+ (_set2_)->regions_humongous()) && \
+ ((_set1_)->regions_empty() == (_set2_)->regions_empty()), \
+ hrl_err_msg("the contents of set %s and set %s should match", \
+ (_set1_)->name(), (_set2_)->name())); \
+ } while (0)
+
+// This class represents heap region sets whose members are not
+// explicitly tracked. It's helpful to group regions using such sets
+// so that we can reason about all the region groups in the heap using
+// the same interface (namely, the HeapRegionSetBase API).
+
+class HeapRegionSet : public HeapRegionSetBase {
+protected:
+ virtual const char* verify_region_extra(HeapRegion* hr) {
+ if (hr->next() != NULL) {
+ return "next() should always be NULL as we do not link the regions";
+ }
+
+ return HeapRegionSetBase::verify_region_extra(hr);
+ }
+
+ HeapRegionSet(const char* name) : HeapRegionSetBase(name) {
+ clear();
+ }
+
+public:
+ // It adds hr to the set. The region should not be a member of
+ // another set.
+ inline void add(HeapRegion* hr);
+
+ // It removes hr from the set. The region should be a member of
+ // this set.
+ inline void remove(HeapRegion* hr);
+
+ // It removes a region from the set. Instead of updating the fields
+ // of the set to reflect this removal, it accumulates the updates
+ // in proxy_set. The idea is that proxy_set is thread-local to
+ // avoid multiple threads updating the fields of the set
+ // concurrently and having to synchronize. The method
+ // update_from_proxy() will update the fields of the set from the
+ // proxy_set.
+ inline void remove_with_proxy(HeapRegion* hr, HeapRegionSet* proxy_set);
+
+ // After multiple calls to remove_with_proxy() the updates to the
+ // fields of the set are accumulated in proxy_set. This call
+ // updates the fields of the set from proxy_set.
+ void update_from_proxy(HeapRegionSet* proxy_set);
+};
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+// A set that links all the regions added to it in a singly-linked
+// list. We should try to avoid doing operations that iterate over
+// such lists in performance critical paths. Typically we should
+// add / remove one region at a time or concatenate two lists. All
+// those operations are done in constant time.
+
+class HeapRegionLinkedListIterator;
+
+class HeapRegionLinkedList : public HeapRegionSetBase {
+ friend class HeapRegionLinkedListIterator;
+
+private:
+ HeapRegion* _head;
+ HeapRegion* _tail;
+
+ // These are provided for use by the friend classes.
+ HeapRegion* head() { return _head; }
+ HeapRegion* tail() { return _tail; }
+
+protected:
+ virtual void fill_in_ext_msg_extra(hrl_ext_msg* msg);
+
+ // See the comment for HeapRegionSetBase::clear()
+ virtual void clear();
+
+ HeapRegionLinkedList(const char* name) : HeapRegionSetBase(name) {
+ clear();
+ }
+
+public:
+ // It adds hr to the list as the new tail. The region should not be
+ // a member of another set.
+ inline void add_as_tail(HeapRegion* hr);
+
+ // It removes and returns the head of the list. It assumes that the
+ // list is not empty so it will return a non-NULL value.
+ inline HeapRegion* remove_head();
+
+ // Convenience method.
+ inline HeapRegion* remove_head_or_null();
+
+ // It moves the regions from from_list to this list and empties
+ // from_list. The new regions will appear in the same order as they
+ // were in from_list and be linked in the end of this list.
+ void add_as_tail(HeapRegionLinkedList* from_list);
+
+ // It empties the list by removing all regions from it.
+ void remove_all();
+
+ // It removes all regions in the list that are pending for removal
+ // (i.e., they have been tagged with "pending_removal"). The list
+ // must not be empty, target_count should reflect the exact number
+ // of regions that are pending for removal in the list, and
+ // target_count should be > 1 (currently, we never need to remove a
+ // single region using this).
+ void remove_all_pending(size_t target_count);
+
+ virtual void verify();
+
+ virtual void print_on(outputStream* out, bool print_contents = false);
+};
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+// Iterator class that provides a convenient way to iterator over the
+// regions in a HeapRegionLinkedList instance.
+
+class HeapRegionLinkedListIterator : public StackObj {
+private:
+ HeapRegionLinkedList* _list;
+ HeapRegion* _curr;
+
+public:
+ bool more_available() {
+ return _curr != NULL;
+ }
+
+ HeapRegion* get_next() {
+ assert(more_available(),
+ "get_next() should be called when more regions are available");
+
+ // If we are going to introduce a count in the iterator we should
+ // do the "cycle" check.
+
+ HeapRegion* hr = _curr;
+ assert(_list->verify_region(hr, _list), "region verification");
+ _curr = hr->next();
+ return hr;
+ }
+
+ HeapRegionLinkedListIterator(HeapRegionLinkedList* list)
+ : _curr(NULL), _list(list) {
+ _curr = list->head();
+ }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
+
+#include "gc_implementation/g1/heapRegionSet.hpp"
+
+//////////////////// HeapRegionSetBase ////////////////////
+
+inline void HeapRegionSetBase::update_for_addition(HeapRegion* hr) {
+ // Assumes the caller has already verified the region.
+
+ _length += 1;
+ if (!hr->isHumongous()) {
+ _region_num += 1;
+ } else {
+ _region_num += calculate_region_num(hr);
+ }
+ _total_used_bytes += hr->used();
+}
+
+inline void HeapRegionSetBase::add_internal(HeapRegion* hr) {
+ hrl_assert_region_ok(this, hr, NULL);
+ assert(hr->next() == NULL, hrl_ext_msg(this, "should not already be linked"));
+
+ update_for_addition(hr);
+ hr->set_containing_set(this);
+}
+
+inline void HeapRegionSetBase::update_for_removal(HeapRegion* hr) {
+ // Assumes the caller has already verified the region.
+ assert(_length > 0, hrl_ext_msg(this, "pre-condition"));
+ _length -= 1;
+
+ size_t region_num_diff;
+ if (!hr->isHumongous()) {
+ region_num_diff = 1;
+ } else {
+ region_num_diff = calculate_region_num(hr);
+ }
+ assert(region_num_diff <= _region_num,
+ hrl_err_msg("[%s] region's region num: "SIZE_FORMAT" "
+ "should be <= region num: "SIZE_FORMAT,
+ name(), region_num_diff, _region_num));
+ _region_num -= region_num_diff;
+
+ size_t used_bytes = hr->used();
+ assert(used_bytes <= _total_used_bytes,
+ hrl_err_msg("[%s] region's used bytes: "SIZE_FORMAT" "
+ "should be <= used bytes: "SIZE_FORMAT,
+ name(), used_bytes, _total_used_bytes));
+ _total_used_bytes -= used_bytes;
+}
+
+inline void HeapRegionSetBase::remove_internal(HeapRegion* hr) {
+ hrl_assert_region_ok(this, hr, this);
+ assert(hr->next() == NULL, hrl_ext_msg(this, "should already be unlinked"));
+
+ hr->set_containing_set(NULL);
+ update_for_removal(hr);
+}
+
+//////////////////// HeapRegionSet ////////////////////
+
+inline void HeapRegionSet::add(HeapRegion* hr) {
+ hrl_assert_mt_safety_ok(this);
+ // add_internal() will verify the region.
+ add_internal(hr);
+}
+
+inline void HeapRegionSet::remove(HeapRegion* hr) {
+ hrl_assert_mt_safety_ok(this);
+ // remove_internal() will verify the region.
+ remove_internal(hr);
+}
+
+inline void HeapRegionSet::remove_with_proxy(HeapRegion* hr,
+ HeapRegionSet* proxy_set) {
+ // No need to fo the MT safety check here given that this method
+ // does not update the contents of the set but instead accumulates
+ // the changes in proxy_set which is assumed to be thread-local.
+ hrl_assert_sets_match(this, proxy_set);
+ hrl_assert_region_ok(this, hr, this);
+
+ hr->set_containing_set(NULL);
+ proxy_set->update_for_addition(hr);
+}
+
+//////////////////// HeapRegionLinkedList ////////////////////
+
+inline void HeapRegionLinkedList::add_as_tail(HeapRegion* hr) {
+ hrl_assert_mt_safety_ok(this);
+ assert((length() == 0 && _head == NULL && _tail == NULL) ||
+ (length() > 0 && _head != NULL && _tail != NULL),
+ hrl_ext_msg(this, "invariant"));
+ // add_internal() will verify the region.
+ add_internal(hr);
+
+ // Now link the region.
+ if (_tail != NULL) {
+ _tail->set_next(hr);
+ } else {
+ _head = hr;
+ }
+ _tail = hr;
+}
+
+inline HeapRegion* HeapRegionLinkedList::remove_head() {
+ hrl_assert_mt_safety_ok(this);
+ assert(!is_empty(), hrl_ext_msg(this, "the list should not be empty"));
+ assert(length() > 0 && _head != NULL && _tail != NULL,
+ hrl_ext_msg(this, "invariant"));
+
+ // We need to unlink it first.
+ HeapRegion* hr = _head;
+ _head = hr->next();
+ if (_head == NULL) {
+ _tail = NULL;
+ }
+ hr->set_next(NULL);
+
+ // remove_internal() will verify the region.
+ remove_internal(hr);
+ return hr;
+}
+
+inline HeapRegion* HeapRegionLinkedList::remove_head_or_null() {
+ hrl_assert_mt_safety_ok(this);
+
+ if (!is_empty()) {
+ return remove_head();
+ } else {
+ return NULL;
+ }
+}
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/heapRegionSets.hpp"
+
+//////////////////// FreeRegionList ////////////////////
+
+const char* FreeRegionList::verify_region_extra(HeapRegion* hr) {
+ if (hr->is_young()) {
+ return "the region should not be young";
+ }
+ // The superclass will check that the region is empty and
+ // not-humongous.
+ return HeapRegionLinkedList::verify_region_extra(hr);
+}
+
+//////////////////// MasterFreeRegionList ////////////////////
+
+bool MasterFreeRegionList::check_mt_safety() {
+ // Master Free List MT safety protocol:
+ // (a) If we're at a safepoint, operations on the master free list
+ // should be invoked by either the VM thread (which will serialize
+ // them) or by the GC workers while holding the
+ // FreeList_lock.
+ // (b) If we're not at a safepoint, operations on the master free
+ // list should be invoked while holding the Heap_lock.
+
+ guarantee((SafepointSynchronize::is_at_safepoint() &&
+ (Thread::current()->is_VM_thread() ||
+ FreeList_lock->owned_by_self())) ||
+ (!SafepointSynchronize::is_at_safepoint() &&
+ Heap_lock->owned_by_self()),
+ hrl_ext_msg(this, "master free list MT safety protocol"));
+
+ return FreeRegionList::check_mt_safety();
+}
+
+//////////////////// SecondaryFreeRegionList ////////////////////
+
+bool SecondaryFreeRegionList::check_mt_safety() {
+ // Secondary Free List MT safety protocol:
+ // Operations on the secondary free list should always be invoked
+ // while holding the SecondaryFreeList_lock.
+
+ guarantee(SecondaryFreeList_lock->owned_by_self(),
+ hrl_ext_msg(this, "secondary free list MT safety protocol"));
+
+ return FreeRegionList::check_mt_safety();
+}
+
+//////////////////// HumongousRegionSet ////////////////////
+
+const char* HumongousRegionSet::verify_region_extra(HeapRegion* hr) {
+ if (hr->is_young()) {
+ return "the region should not be young";
+ }
+ // The superclass will check that the region is not empty and
+ // humongous.
+ return HeapRegionSet::verify_region_extra(hr);
+}
+
+//////////////////// HumongousRegionSet ////////////////////
+
+bool MasterHumongousRegionSet::check_mt_safety() {
+ // Master Humongous Set MT safety protocol:
+ // (a) If we're at a safepoint, operations on the master humongous
+ // set should be invoked by either the VM thread (which will
+ // serialize them) or by the GC workers while holding the
+ // OldSets_lock.
+ // (b) If we're not at a safepoint, operations on the master
+ // humongous set should be invoked while holding the Heap_lock.
+
+ guarantee((SafepointSynchronize::is_at_safepoint() &&
+ (Thread::current()->is_VM_thread() ||
+ OldSets_lock->owned_by_self())) ||
+ (!SafepointSynchronize::is_at_safepoint() &&
+ Heap_lock->owned_by_self()),
+ hrl_ext_msg(this, "master humongous set MT safety protocol"));
+ return HumongousRegionSet::check_mt_safety();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSets.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
+
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
+
+//////////////////// FreeRegionList ////////////////////
+
+class FreeRegionList : public HeapRegionLinkedList {
+protected:
+ virtual const char* verify_region_extra(HeapRegion* hr);
+
+ virtual bool regions_humongous() { return false; }
+ virtual bool regions_empty() { return true; }
+
+public:
+ FreeRegionList(const char* name) : HeapRegionLinkedList(name) { }
+};
+
+//////////////////// MasterFreeRegionList ////////////////////
+
+class MasterFreeRegionList : public FreeRegionList {
+protected:
+ virtual bool check_mt_safety();
+
+public:
+ MasterFreeRegionList(const char* name) : FreeRegionList(name) { }
+};
+
+//////////////////// SecondaryFreeRegionList ////////////////////
+
+class SecondaryFreeRegionList : public FreeRegionList {
+protected:
+ virtual bool check_mt_safety();
+
+public:
+ SecondaryFreeRegionList(const char* name) : FreeRegionList(name) { }
+};
+
+//////////////////// HumongousRegionSet ////////////////////
+
+class HumongousRegionSet : public HeapRegionSet {
+protected:
+ virtual const char* verify_region_extra(HeapRegion* hr);
+
+ virtual bool regions_humongous() { return true; }
+ virtual bool regions_empty() { return false; }
+
+public:
+ HumongousRegionSet(const char* name) : HeapRegionSet(name) { }
+};
+
+//////////////////// MasterHumongousRegionSet ////////////////////
+
+class MasterHumongousRegionSet : public HumongousRegionSet {
+protected:
+ virtual bool check_mt_safety();
+
+public:
+ MasterHumongousRegionSet(const char* name) : HumongousRegionSet(name) { }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSETS_HPP
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -38,8 +38,8 @@
# include "thread_windows.inline.hpp"
#endif
-PtrQueue::PtrQueue(PtrQueueSet* qset_, bool perm, bool active) :
- _qset(qset_), _buf(NULL), _index(0), _active(active),
+PtrQueue::PtrQueue(PtrQueueSet* qset, bool perm, bool active) :
+ _qset(qset), _buf(NULL), _index(0), _active(active),
_perm(perm), _lock(NULL)
{}
@@ -153,10 +153,16 @@
}
void PtrQueue::handle_zero_index() {
- assert(0 == _index, "Precondition.");
+ assert(_index == 0, "Precondition.");
+
// This thread records the full buffer and allocates a new one (while
// holding the lock if there is one).
if (_buf != NULL) {
+ if (!should_enqueue_buffer()) {
+ assert(_index > 0, "the buffer can only be re-used if it's not full");
+ return;
+ }
+
if (_lock) {
assert(_lock->owned_by_self(), "Required.");
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -68,7 +68,7 @@
public:
// Initialize this queue to contain a null buffer, and be part of the
// given PtrQueueSet.
- PtrQueue(PtrQueueSet*, bool perm = false, bool active = false);
+ PtrQueue(PtrQueueSet* qset, bool perm = false, bool active = false);
// Release any contained resources.
void flush();
// Calls flush() when destroyed.
@@ -85,6 +85,14 @@
else enqueue_known_active(ptr);
}
+ // This method is called when we're doing the zero index handling
+ // and gives a chance to the queues to do any pre-enqueueing
+ // processing they might want to do on the buffer. It should return
+ // true if the buffer should be enqueued, or false if enough
+ // entries were cleared from it so that it can be re-used. It should
+ // not return false if the buffer is still full (otherwise we can
+ // get into an infinite loop).
+ virtual bool should_enqueue_buffer() { return true; }
void handle_zero_index();
void locking_enqueue_completed_buffer(void** buf);
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -23,12 +23,98 @@
*/
#include "precompiled.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/satbQueue.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/sharedHeap.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/thread.hpp"
+// This method removes entries from an SATB buffer that will not be
+// useful to the concurrent marking threads. An entry is removed if it
+// satisfies one of the following conditions:
+//
+// * it points to an object outside the G1 heap (G1's concurrent
+// marking only visits objects inside the G1 heap),
+// * it points to an object that has been allocated since marking
+// started (according to SATB those objects do not need to be
+// visited during marking), or
+// * it points to an object that has already been marked (no need to
+// process it again).
+//
+// The rest of the entries will be retained and are compacted towards
+// the top of the buffer. If with this filtering we clear a large
+// enough chunk of the buffer we can re-use it (instead of enqueueing
+// it) and we can just allow the mutator to carry on executing.
+
+bool ObjPtrQueue::should_enqueue_buffer() {
+ assert(_lock == NULL || _lock->owned_by_self(),
+ "we should have taken the lock before calling this");
+
+ // A value of 0 means "don't filter SATB buffers".
+ if (G1SATBBufferEnqueueingThresholdPercent == 0) {
+ return true;
+ }
+
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+ // This method should only be called if there is a non-NULL buffer
+ // that is full.
+ assert(_index == 0, "pre-condition");
+ assert(_buf != NULL, "pre-condition");
+
+ void** buf = _buf;
+ size_t sz = _sz;
+
+ // Used for sanity checking at the end of the loop.
+ debug_only(size_t entries = 0; size_t retained = 0;)
+
+ size_t i = sz;
+ size_t new_index = sz;
+
+ // Given that we are expecting _index == 0, we could have changed
+ // the loop condition to (i > 0). But we are using _index for
+ // generality.
+ while (i > _index) {
+ assert(i > 0, "we should have at least one more entry to process");
+ i -= oopSize;
+ debug_only(entries += 1;)
+ oop* p = (oop*) &buf[byte_index_to_index((int) i)];
+ oop obj = *p;
+ // NULL the entry so that unused parts of the buffer contain NULLs
+ // at the end. If we are going to retain it we will copy it to its
+ // final place. If we have retained all entries we have visited so
+ // far, we'll just end up copying it to the same place.
+ *p = NULL;
+
+ bool retain = g1h->is_obj_ill(obj);
+ if (retain) {
+ assert(new_index > 0, "we should not have already filled up the buffer");
+ new_index -= oopSize;
+ assert(new_index >= i,
+ "new_index should never be below i, as we alwaysr compact 'up'");
+ oop* new_p = (oop*) &buf[byte_index_to_index((int) new_index)];
+ assert(new_p >= p, "the destination location should never be below "
+ "the source as we always compact 'up'");
+ assert(*new_p == NULL,
+ "we should have already cleared the destination location");
+ *new_p = obj;
+ debug_only(retained += 1;)
+ }
+ }
+ size_t entries_calc = (sz - _index) / oopSize;
+ assert(entries == entries_calc, "the number of entries we counted "
+ "should match the number of entries we calculated");
+ size_t retained_calc = (sz - new_index) / oopSize;
+ assert(retained == retained_calc, "the number of retained entries we counted "
+ "should match the number of retained entries we calculated");
+ size_t perc = retained_calc * 100 / entries_calc;
+ bool should_enqueue = perc > (size_t) G1SATBBufferEnqueueingThresholdPercent;
+ _index = new_index;
+
+ return should_enqueue;
+}
+
void ObjPtrQueue::apply_closure(ObjectClosure* cl) {
if (_buf != NULL) {
apply_closure_to_buffer(cl, _buf, _index, _sz);
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -33,13 +33,18 @@
// A ptrQueue whose elements are "oops", pointers to object heads.
class ObjPtrQueue: public PtrQueue {
public:
- ObjPtrQueue(PtrQueueSet* qset_, bool perm = false) :
+ ObjPtrQueue(PtrQueueSet* qset, bool perm = false) :
// SATB queues are only active during marking cycles. We create
// them with their active field set to false. If a thread is
// created during a cycle and its SATB queue needs to be activated
// before the thread starts running, we'll need to set its active
// field to true. This is done in JavaThread::initialize_queues().
- PtrQueue(qset_, perm, false /* active */) { }
+ PtrQueue(qset, perm, false /* active */) { }
+
+ // Overrides PtrQueue::should_enqueue_buffer(). See the method's
+ // definition for more information.
+ virtual bool should_enqueue_buffer();
+
// Apply the closure to all elements, and reset the index to make the
// buffer empty.
void apply_closure(ObjectClosure* cl);
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -38,7 +38,6 @@
}
void VM_G1CollectForAllocation::doit() {
- JvmtiGCForAllocationMarker jgcm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
_result = g1h->satisfy_failed_allocation(_word_size, &_pause_succeeded);
assert(_result == NULL || _pause_succeeded,
@@ -46,7 +45,6 @@
}
void VM_G1CollectFull::doit() {
- JvmtiGCFullMarker jgcm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
GCCauseSetter x(g1h, _gc_cause);
g1h->do_full_collection(false /* clear_all_soft_refs */);
@@ -72,7 +70,6 @@
}
void VM_G1IncCollectionPause::doit() {
- JvmtiGCForAllocationMarker jgcm;
G1CollectedHeap* g1h = G1CollectedHeap::heap();
assert(!_should_initiate_conc_mark ||
((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -258,6 +258,7 @@
BiasedLocking::restore_marks();
Threads::gc_epilogue();
CodeCache::gc_epilogue();
+ JvmtiExport::gc_epilogue();
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1054,6 +1054,7 @@
Threads::gc_epilogue();
CodeCache::gc_epilogue();
+ JvmtiExport::gc_epilogue();
COMPILER2_PRESENT(DerivedPointerTable::update_pointers());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -42,8 +42,7 @@
}
void VM_ParallelGCFailedAllocation::doit() {
- JvmtiGCForAllocationMarker jgcm;
- notify_gc_begin(false);
+ SvcGCMarker sgcm(SvcGCMarker::MINOR);
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
@@ -54,8 +53,6 @@
if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
-
- notify_gc_end();
}
VM_ParallelGCFailedPermanentAllocation::VM_ParallelGCFailedPermanentAllocation(size_t size,
@@ -67,8 +64,7 @@
}
void VM_ParallelGCFailedPermanentAllocation::doit() {
- JvmtiGCFullMarker jgcm;
- notify_gc_begin(true);
+ SvcGCMarker sgcm(SvcGCMarker::FULL);
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "must be a ParallelScavengeHeap");
@@ -78,7 +74,6 @@
if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
- notify_gc_end();
}
// Only used for System.gc() calls
@@ -91,8 +86,7 @@
}
void VM_ParallelGCSystemGC::doit() {
- JvmtiGCFullMarker jgcm;
- notify_gc_begin(true);
+ SvcGCMarker sgcm(SvcGCMarker::FULL);
ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
assert(heap->kind() == CollectedHeap::ParallelScavengeHeap,
@@ -106,5 +100,4 @@
} else {
heap->invoke_full_gc(false);
}
- notify_gc_end();
}
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -31,7 +31,6 @@
#include "memory/oopFactory.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceRefKlass.hpp"
-#include "prims/jvmtiExport.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -40,6 +39,7 @@
#ifndef SERIALGC
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#endif
+
HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool);
HS_DTRACE_PROBE_DECL(hotspot, gc__end);
@@ -158,8 +158,7 @@
void VM_GenCollectForAllocation::doit() {
- JvmtiGCForAllocationMarker jgcm;
- notify_gc_begin(false);
+ SvcGCMarker sgcm(SvcGCMarker::MINOR);
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCauseSetter gccs(gch, _gc_cause);
@@ -169,22 +168,19 @@
if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
- notify_gc_end();
}
void VM_GenCollectFull::doit() {
- JvmtiGCFullMarker jgcm;
- notify_gc_begin(true);
+ SvcGCMarker sgcm(SvcGCMarker::FULL);
GenCollectedHeap* gch = GenCollectedHeap::heap();
GCCauseSetter gccs(gch, _gc_cause);
gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
- notify_gc_end();
}
void VM_GenCollectForPermanentAllocation::doit() {
- JvmtiGCForAllocationMarker jgcm;
- notify_gc_begin(true);
+ SvcGCMarker sgcm(SvcGCMarker::FULL);
+
SharedHeap* heap = (SharedHeap*)Universe::heap();
GCCauseSetter gccs(heap, _gc_cause);
switch (heap->kind()) {
@@ -209,5 +205,4 @@
if (_res == NULL && GC_locker::is_active_and_needs_gc()) {
set_gc_locked();
}
- notify_gc_end();
}
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -30,6 +30,7 @@
#include "runtime/jniHandles.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/vm_operations.hpp"
+#include "prims/jvmtiExport.hpp"
// The following class hierarchy represents
// a set of operations (VM_Operation) related to GC.
@@ -209,13 +210,17 @@
HeapWord* result() const { return _res; }
};
-class DTraceGCProbeMarker : public StackObj {
-public:
- DTraceGCProbeMarker(bool full) {
- VM_GC_Operation::notify_gc_begin(full);
+class SvcGCMarker : public StackObj {
+ private:
+ JvmtiGCMarker _jgcm;
+ public:
+ typedef enum { MINOR, FULL, OTHER } reason_type;
+
+ SvcGCMarker(reason_type reason ) {
+ VM_GC_Operation::notify_gc_begin(reason == FULL);
}
- ~DTraceGCProbeMarker() {
+ ~SvcGCMarker() {
VM_GC_Operation::notify_gc_end();
}
};
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -34,30 +34,6 @@
// Implementation of Bytecode
-bool Bytecode::check_must_rewrite(Bytecodes::Code code) const {
- assert(Bytecodes::can_rewrite(code), "post-check only");
-
- // Some codes are conditionally rewriting. Look closely at them.
- switch (code) {
- case Bytecodes::_aload_0:
- // Even if RewriteFrequentPairs is turned on,
- // the _aload_0 code might delay its rewrite until
- // a following _getfield rewrites itself.
- return false;
-
- case Bytecodes::_lookupswitch:
- return false; // the rewrite is not done by the interpreter
-
- case Bytecodes::_new:
- // (Could actually look at the class here, but the profit would be small.)
- return false; // the rewrite is not always done
- }
-
- // No other special cases.
- return true;
-}
-
-
#ifdef ASSERT
void Bytecode::assert_same_format_as(Bytecodes::Code testbc, bool is_wide) const {
@@ -188,17 +164,16 @@
// Note: Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
// at the same time it allocates per-call-site CP cache entries.
Bytecodes::Code rawc = code();
- Bytecode* invoke = bytecode();
- if (invoke->has_index_u4(rawc))
- return invoke->get_index_u4(rawc);
+ if (has_index_u4(rawc))
+ return get_index_u4(rawc);
else
- return invoke->get_index_u2_cpcache(rawc);
+ return get_index_u2_cpcache(rawc);
}
int Bytecode_member_ref::pool_index() const {
int index = this->index();
DEBUG_ONLY({
- if (!bytecode()->has_index_u4(code()))
+ if (!has_index_u4(code()))
index -= constantPoolOopDesc::CPCACHE_INDEX_TAG;
});
return _method->constants()->cache()->entry_at(index)->constant_pool_index();
@@ -214,13 +189,12 @@
// Implementation of Bytecode_loadconstant
int Bytecode_loadconstant::raw_index() const {
- Bytecode* bcp = bytecode();
- Bytecodes::Code rawc = bcp->code();
+ Bytecodes::Code rawc = code();
assert(rawc != Bytecodes::_wide, "verifier prevents this");
if (Bytecodes::java_code(rawc) == Bytecodes::_ldc)
- return bcp->get_index_u1(rawc);
+ return get_index_u1(rawc);
else
- return bcp->get_index_u2(rawc, false);
+ return get_index_u2(rawc, false);
}
int Bytecode_loadconstant::pool_index() const {
@@ -258,7 +232,7 @@
case Bytecodes::_lookupswitch:
{ int i = number_of_pairs() - 1;
while (i-- > 0) {
- assert(pair_at(i)->match() < pair_at(i+1)->match(), "unsorted table entries");
+ assert(pair_at(i).match() < pair_at(i+1).match(), "unsorted table entries");
}
}
break;
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -38,14 +38,20 @@
# include "bytes_zero.hpp"
#endif
-// Base class for different kinds of abstractions working
-// relative to an objects 'this' pointer.
+class ciBytecodeStream;
+
+// The base class for different kinds of bytecode abstractions.
+// Provides the primitive operations to manipulate code relative
+// to the bcp.
-class ThisRelativeObj VALUE_OBJ_CLASS_SPEC {
- public:
+class Bytecode: public StackObj {
+ protected:
+ const address _bcp;
+ const Bytecodes::Code _code;
+
// Address computation
- address addr_at (int offset) const { return (address)this + offset; }
- int byte_at (int offset) const { return *(addr_at(offset)); }
+ address addr_at (int offset) const { return (address)_bcp + offset; }
+ u_char byte_at(int offset) const { return *addr_at(offset); }
address aligned_addr_at (int offset) const { return (address)round_to((intptr_t)addr_at(offset), jintSize); }
int aligned_offset (int offset) const { return aligned_addr_at(offset) - addr_at(0); }
@@ -54,31 +60,20 @@
int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); }
int get_native_u2_at (int offset) const { return Bytes::get_native_u2(addr_at(offset)); }
int get_native_u4_at (int offset) const { return Bytes::get_native_u4(addr_at(offset)); }
-};
-
-
-// The base class for different kinds of bytecode abstractions.
-// Provides the primitive operations to manipulate code relative
-// to an objects 'this' pointer.
-// FIXME: Make this a ResourceObj, include the enclosing methodOop, and cache the opcode.
-
-class Bytecode: public ThisRelativeObj {
- protected:
- u_char byte_at(int offset) const { return *addr_at(offset); }
- bool check_must_rewrite(Bytecodes::Code bc) const;
public:
- // Attributes
- address bcp() const { return addr_at(0); }
- int instruction_size() const { return Bytecodes::length_at(bcp()); }
+ Bytecode(methodOop method, address bcp): _bcp(bcp), _code(Bytecodes::code_at(method, addr_at(0))) {
+ assert(method != NULL, "this form requires a valid methodOop");
+ }
+ // Defined in ciStreams.hpp
+ inline Bytecode(const ciBytecodeStream* stream, address bcp = NULL);
- // Warning: Use code() with caution on live bytecode streams. 4926272
- Bytecodes::Code code() const { return Bytecodes::code_at(addr_at(0)); }
+ // Attributes
+ address bcp() const { return _bcp; }
+ int instruction_size() const { return Bytecodes::length_for_code_at(_code, bcp()); }
+
+ Bytecodes::Code code() const { return _code; }
Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); }
- bool must_rewrite(Bytecodes::Code code) const { return Bytecodes::can_rewrite(code) && check_must_rewrite(code); }
-
- // Creation
- inline friend Bytecode* Bytecode_at(address bcp);
// Static functions for parsing bytecodes in place.
int get_index_u1(Bytecodes::Code bc) const {
@@ -89,7 +84,7 @@
assert_same_format_as(bc, is_wide); assert_index_size(2, bc, is_wide);
address p = addr_at(is_wide ? 2 : 1);
if (can_use_native_byte_order(bc, is_wide))
- return Bytes::get_native_u2(p);
+ return Bytes::get_native_u2(p);
else return Bytes::get_Java_u2(p);
}
int get_index_u1_cpcache(Bytecodes::Code bc) const {
@@ -138,20 +133,17 @@
}
};
-inline Bytecode* Bytecode_at(address bcp) {
- // Warning: Use with caution on live bytecode streams. 4926272
- return (Bytecode*)bcp;
-}
-
// Abstractions for lookupswitch bytecode
-
-class LookupswitchPair: ThisRelativeObj {
+class LookupswitchPair VALUE_OBJ_CLASS_SPEC {
private:
- int _match;
- int _offset;
+ const address _bcp;
+
+ address addr_at (int offset) const { return _bcp + offset; }
+ int get_Java_u4_at (int offset) const { return Bytes::get_Java_u4(addr_at(offset)); }
public:
+ LookupswitchPair(address bcp): _bcp(bcp) {}
int match() const { return get_Java_u4_at(0 * jintSize); }
int offset() const { return get_Java_u4_at(1 * jintSize); }
};
@@ -159,26 +151,25 @@
class Bytecode_lookupswitch: public Bytecode {
public:
+ Bytecode_lookupswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
+ // Defined in ciStreams.hpp
+ inline Bytecode_lookupswitch(const ciBytecodeStream* stream);
void verify() const PRODUCT_RETURN;
// Attributes
int default_offset() const { return get_Java_u4_at(aligned_offset(1 + 0*jintSize)); }
int number_of_pairs() const { return get_Java_u4_at(aligned_offset(1 + 1*jintSize)); }
- LookupswitchPair* pair_at(int i) const { assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
- return (LookupswitchPair*)aligned_addr_at(1 + (1 + i)*2*jintSize); }
- // Creation
- inline friend Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp);
+ LookupswitchPair pair_at(int i) const {
+ assert(0 <= i && i < number_of_pairs(), "pair index out of bounds");
+ return LookupswitchPair(aligned_addr_at(1 + (1 + i)*2*jintSize));
+ }
};
-inline Bytecode_lookupswitch* Bytecode_lookupswitch_at(address bcp) {
- Bytecode_lookupswitch* b = (Bytecode_lookupswitch*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
class Bytecode_tableswitch: public Bytecode {
public:
+ Bytecode_tableswitch(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
+ // Defined in ciStreams.hpp
+ inline Bytecode_tableswitch(const ciBytecodeStream* stream);
void verify() const PRODUCT_RETURN;
// Attributes
@@ -187,52 +178,36 @@
int high_key() const { return get_Java_u4_at(aligned_offset(1 + 2*jintSize)); }
int dest_offset_at(int i) const;
int length() { return high_key()-low_key()+1; }
-
- // Creation
- inline friend Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp);
};
-inline Bytecode_tableswitch* Bytecode_tableswitch_at(address bcp) {
- Bytecode_tableswitch* b = (Bytecode_tableswitch*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
// Common code for decoding invokes and field references.
-class Bytecode_member_ref: public ResourceObj {
+class Bytecode_member_ref: public Bytecode {
protected:
- methodHandle _method; // method containing the bytecode
- int _bci; // position of the bytecode
+ const methodHandle _method; // method containing the bytecode
- Bytecode_member_ref(methodHandle method, int bci) : _method(method), _bci(bci) {}
+ Bytecode_member_ref(methodHandle method, int bci) : Bytecode(method(), method()->bcp_from(bci)), _method(method) {}
+
+ methodHandle method() const { return _method; }
public:
- // Attributes
- methodHandle method() const { return _method; }
- int bci() const { return _bci; }
- address bcp() const { return _method->bcp_from(bci()); }
- Bytecode* bytecode() const { return Bytecode_at(bcp()); }
-
int index() const; // cache index (loaded from instruction)
int pool_index() const; // constant pool index
symbolOop name() const; // returns the name of the method or field
symbolOop signature() const; // returns the signature of the method or field
BasicType result_type(Thread* thread) const; // returns the result type of the getfield or invoke
-
- Bytecodes::Code code() const { return Bytecodes::code_at(bcp(), _method()); }
- Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); }
};
// Abstraction for invoke_{virtual, static, interface, special}
class Bytecode_invoke: public Bytecode_member_ref {
protected:
- Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) {}
+ // Constructor that skips verification
+ Bytecode_invoke(methodHandle method, int bci, bool unused) : Bytecode_member_ref(method, bci) {}
public:
+ Bytecode_invoke(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); }
void verify() const;
// Attributes
@@ -253,31 +228,20 @@
is_invokespecial() ||
is_invokedynamic(); }
- // Creation
- inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci);
-
- // Like Bytecode_invoke_at. Instead it returns NULL if the bci is not at an invoke.
- inline friend Bytecode_invoke* Bytecode_invoke_at_check(methodHandle method, int bci);
+ // Helper to skip verification. Used is_valid() to check if the result is really an invoke
+ inline friend Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci);
};
-inline Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci) {
- Bytecode_invoke* b = new Bytecode_invoke(method, bci);
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-inline Bytecode_invoke* Bytecode_invoke_at_check(methodHandle method, int bci) {
- Bytecode_invoke* b = new Bytecode_invoke(method, bci);
- return b->is_valid() ? b : NULL;
+inline Bytecode_invoke Bytecode_invoke_check(methodHandle method, int bci) {
+ return Bytecode_invoke(method, bci, false);
}
// Abstraction for all field accesses (put/get field/static)
class Bytecode_field: public Bytecode_member_ref {
- protected:
- Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) {}
+ public:
+ Bytecode_field(methodHandle method, int bci) : Bytecode_member_ref(method, bci) { verify(); }
- public:
// Testers
bool is_getfield() const { return java_code() == Bytecodes::_getfield; }
bool is_putfield() const { return java_code() == Bytecodes::_putfield; }
@@ -292,131 +256,64 @@
is_getstatic() ||
is_putstatic(); }
void verify() const;
-
- // Creation
- inline friend Bytecode_field* Bytecode_field_at(methodHandle method, int bci);
};
-inline Bytecode_field* Bytecode_field_at(methodHandle method, int bci) {
- Bytecode_field* b = new Bytecode_field(method, bci);
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
// Abstraction for checkcast
-
class Bytecode_checkcast: public Bytecode {
public:
+ Bytecode_checkcast(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
void verify() const { assert(Bytecodes::java_code(code()) == Bytecodes::_checkcast, "check checkcast"); }
// Returns index
long index() const { return get_index_u2(Bytecodes::_checkcast); };
-
- // Creation
- inline friend Bytecode_checkcast* Bytecode_checkcast_at(address bcp);
};
-inline Bytecode_checkcast* Bytecode_checkcast_at(address bcp) {
- Bytecode_checkcast* b = (Bytecode_checkcast*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
// Abstraction for instanceof
-
class Bytecode_instanceof: public Bytecode {
public:
+ Bytecode_instanceof(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
void verify() const { assert(code() == Bytecodes::_instanceof, "check instanceof"); }
// Returns index
long index() const { return get_index_u2(Bytecodes::_instanceof); };
-
- // Creation
- inline friend Bytecode_instanceof* Bytecode_instanceof_at(address bcp);
};
-inline Bytecode_instanceof* Bytecode_instanceof_at(address bcp) {
- Bytecode_instanceof* b = (Bytecode_instanceof*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
class Bytecode_new: public Bytecode {
public:
+ Bytecode_new(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
void verify() const { assert(java_code() == Bytecodes::_new, "check new"); }
// Returns index
long index() const { return get_index_u2(Bytecodes::_new); };
-
- // Creation
- inline friend Bytecode_new* Bytecode_new_at(address bcp);
};
-inline Bytecode_new* Bytecode_new_at(address bcp) {
- Bytecode_new* b = (Bytecode_new*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
class Bytecode_multianewarray: public Bytecode {
public:
+ Bytecode_multianewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
void verify() const { assert(java_code() == Bytecodes::_multianewarray, "check new"); }
// Returns index
long index() const { return get_index_u2(Bytecodes::_multianewarray); };
-
- // Creation
- inline friend Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp);
};
-inline Bytecode_multianewarray* Bytecode_multianewarray_at(address bcp) {
- Bytecode_multianewarray* b = (Bytecode_multianewarray*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
class Bytecode_anewarray: public Bytecode {
public:
+ Bytecode_anewarray(methodOop method, address bcp): Bytecode(method, bcp) { verify(); }
void verify() const { assert(java_code() == Bytecodes::_anewarray, "check anewarray"); }
// Returns index
long index() const { return get_index_u2(Bytecodes::_anewarray); };
-
- // Creation
- inline friend Bytecode_anewarray* Bytecode_anewarray_at(address bcp);
};
-inline Bytecode_anewarray* Bytecode_anewarray_at(address bcp) {
- Bytecode_anewarray* b = (Bytecode_anewarray*)bcp;
- DEBUG_ONLY(b->verify());
- return b;
-}
-
-
// Abstraction for ldc, ldc_w and ldc2_w
-
-class Bytecode_loadconstant: public ResourceObj {
+class Bytecode_loadconstant: public Bytecode {
private:
- int _bci;
- methodHandle _method;
-
- Bytecodes::Code code() const { return bytecode()->code(); }
+ const methodHandle _method;
int raw_index() const;
- Bytecode_loadconstant(methodHandle method, int bci) : _method(method), _bci(bci) {}
-
public:
- // Attributes
- methodHandle method() const { return _method; }
- int bci() const { return _bci; }
- address bcp() const { return _method->bcp_from(bci()); }
- Bytecode* bytecode() const { return Bytecode_at(bcp()); }
+ Bytecode_loadconstant(methodHandle method, int bci): Bytecode(method(), method->bcp_from(bci)), _method(method) { verify(); }
void verify() const {
assert(_method.not_null(), "must supply method");
@@ -437,15 +334,6 @@
BasicType result_type() const; // returns the result type of the ldc
oop resolve_constant(TRAPS) const;
-
- // Creation
- inline friend Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci);
};
-inline Bytecode_loadconstant* Bytecode_loadconstant_at(methodHandle method, int bci) {
- Bytecode_loadconstant* b = new Bytecode_loadconstant(method, bci);
- DEBUG_ONLY(b->verify());
- return b;
-}
-
#endif // SHARE_VM_INTERPRETER_BYTECODE_HPP
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -831,11 +831,11 @@
// much like trying to deopt at a poll return. In that has we simply
// get out of here
//
- if ( Bytecodes::code_at(pc, METHOD) == Bytecodes::_return_register_finalizer) {
+ if ( Bytecodes::code_at(METHOD, pc) == Bytecodes::_return_register_finalizer) {
// this will do the right thing even if an exception is pending.
goto handle_return;
}
- UPDATE_PC(Bytecodes::length_at(pc));
+ UPDATE_PC(Bytecodes::length_at(METHOD, pc));
if (THREAD->has_pending_exception()) goto handle_exception;
goto run;
}
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -59,7 +59,7 @@
// in raw mode, pretend indy is "bJJ__"
assert(size == 2, "raw invokedynamic instruction has 2-byte index only");
} else {
- bytecode()->assert_index_size(size, raw_code(), is_wide());
+ bytecode().assert_index_size(size, raw_code(), is_wide());
}
}
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -105,14 +105,14 @@
bool is_last_bytecode() const { return _next_bci >= _end_bci; }
address bcp() const { return method()->code_base() + _bci; }
- Bytecode* bytecode() const { return Bytecode_at(bcp()); }
+ Bytecode bytecode() const { return Bytecode(_method(), bcp()); }
// State changes
void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
// Bytecode-specific attributes
- int dest() const { return bci() + bytecode()->get_offset_s2(raw_code()); }
- int dest_w() const { return bci() + bytecode()->get_offset_s4(raw_code()); }
+ int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); }
+ int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); }
// One-byte indices.
int get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }
@@ -189,7 +189,7 @@
} else {
// get bytecode
address bcp = this->bcp();
- raw_code = Bytecodes::code_at(bcp);
+ raw_code = Bytecodes::code_at(_method(), bcp);
code = Bytecodes::java_code(raw_code);
// set next bytecode position
//
@@ -197,7 +197,7 @@
// tty bytecode otherwise the stepping is wrong!
// (carefull: length_for(...) must be used first!)
int l = Bytecodes::length_for(code);
- if (l == 0) l = Bytecodes::length_at(bcp);
+ if (l == 0) l = Bytecodes::length_at(_method(), bcp);
_next_bci += l;
assert(_bci < _next_bci, "length must be > 0");
// set attributes
@@ -219,16 +219,16 @@
Bytecodes::Code code() const { return _code; }
// Unsigned indices, widening
- int get_index() const { return is_wide() ? bytecode()->get_index_u2(raw_code(), true) : get_index_u1(); }
+ int get_index() const { return is_wide() ? bytecode().get_index_u2(raw_code(), true) : get_index_u1(); }
// Get an unsigned 2-byte index, swapping the bytes if necessary.
int get_index_u2() const { assert_raw_stream(false);
- return bytecode()->get_index_u2(raw_code(), false); }
+ return bytecode().get_index_u2(raw_code(), false); }
// Get an unsigned 2-byte index in native order.
int get_index_u2_cpcache() const { assert_raw_stream(false);
- return bytecode()->get_index_u2_cpcache(raw_code()); }
+ return bytecode().get_index_u2_cpcache(raw_code()); }
int get_index_u4() const { assert_raw_stream(false);
- return bytecode()->get_index_u4(raw_code()); }
- bool has_index_u4() const { return bytecode()->has_index_u4(raw_code()); }
+ return bytecode().get_index_u4(raw_code()); }
+ bool has_index_u4() const { return bytecode().has_index_u4(raw_code()); }
};
#endif // SHARE_VM_INTERPRETER_BYTECODESTREAM_HPP
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -100,9 +100,9 @@
Bytecodes::Code code;
if (is_wide()) {
// bcp wasn't advanced if previous bytecode was _wide.
- code = Bytecodes::code_at(bcp+1);
+ code = Bytecodes::code_at(method(), bcp+1);
} else {
- code = Bytecodes::code_at(bcp);
+ code = Bytecodes::code_at(method(), bcp);
}
_code = code;
int bci = bcp - method->code_base();
@@ -127,11 +127,11 @@
void trace(methodHandle method, address bcp, outputStream* st) {
_current_method = method();
ResourceMark rm;
- Bytecodes::Code code = Bytecodes::code_at(bcp);
+ Bytecodes::Code code = Bytecodes::code_at(method(), bcp);
// Set is_wide
_is_wide = (code == Bytecodes::_wide);
if (is_wide()) {
- code = Bytecodes::code_at(bcp+1);
+ code = Bytecodes::code_at(method(), bcp+1);
}
_code = code;
int bci = bcp - method->code_base();
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -54,18 +54,46 @@
Bytecodes::Code Bytecodes::_java_code [Bytecodes::number_of_codes];
u_short Bytecodes::_flags [(1<<BitsPerByte)*2];
+#ifdef ASSERT
+bool Bytecodes::check_method(const methodOopDesc* method, address bcp) {
+ return method->contains(bcp);
+}
+#endif
+
+bool Bytecodes::check_must_rewrite(Bytecodes::Code code) {
+ assert(can_rewrite(code), "post-check only");
+
+ // Some codes are conditionally rewriting. Look closely at them.
+ switch (code) {
+ case Bytecodes::_aload_0:
+ // Even if RewriteFrequentPairs is turned on,
+ // the _aload_0 code might delay its rewrite until
+ // a following _getfield rewrites itself.
+ return false;
+
+ case Bytecodes::_lookupswitch:
+ return false; // the rewrite is not done by the interpreter
+
+ case Bytecodes::_new:
+ // (Could actually look at the class here, but the profit would be small.)
+ return false; // the rewrite is not always done
+ }
+
+ // No other special cases.
+ return true;
+}
Bytecodes::Code Bytecodes::code_at(methodOop method, int bci) {
- return code_at(method->bcp_from(bci), method);
+ return code_at(method, method->bcp_from(bci));
}
-Bytecodes::Code Bytecodes::non_breakpoint_code_at(address bcp, methodOop method) {
- if (method == NULL) method = methodOopDesc::method_from_bcp(bcp);
+Bytecodes::Code Bytecodes::non_breakpoint_code_at(const methodOopDesc* method, address bcp) {
+ assert(method != NULL, "must have the method for breakpoint conversion");
+ assert(method->contains(bcp), "must be valid bcp in method");
return method->orig_bytecode_at(method->bci_from(bcp));
}
-int Bytecodes::special_length_at(address bcp, address end) {
- Code code = code_at(bcp);
+int Bytecodes::special_length_at(Bytecodes::Code code, address bcp, address end) {
switch (code) {
case _wide:
if (end != NULL && bcp + 1 >= end) {
@@ -120,7 +148,7 @@
if (code == _breakpoint) {
return 1;
} else {
- return special_length_at(bcp, end);
+ return special_length_at(code, bcp, end);
}
}
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -342,6 +342,12 @@
static void pd_initialize(); // platform specific initialization
static Code pd_base_code_for(Code code); // platform specific base_code_for implementation
+ // Verify that bcp points into method
+#ifdef ASSERT
+ static bool check_method(const methodOopDesc* method, address bcp);
+#endif
+ static bool check_must_rewrite(Bytecodes::Code bc);
+
public:
// Conversion
static void check (Code code) { assert(is_defined(code), "illegal code"); }
@@ -349,22 +355,30 @@
static Code cast (int code) { return (Code)code; }
- // Fetch a bytecode, hiding breakpoints as necessary:
- static Code code_at(address bcp, methodOop method = NULL) {
- Code code = cast(*bcp); return (code != _breakpoint) ? code : non_breakpoint_code_at(bcp, method);
- }
- static Code java_code_at(address bcp, methodOop method = NULL) {
- return java_code(code_at(bcp, method));
- }
+ // Fetch a bytecode, hiding breakpoints as necessary. The method
+ // argument is used for conversion of breakpoints into the original
+ // bytecode. The CI uses these methods but guarantees that
+ // breakpoints are hidden so the method argument should be passed as
+ // NULL since in that case the bcp and methodOop are unrelated
+ // memory.
+ static Code code_at(const methodOopDesc* method, address bcp) {
+ assert(method == NULL || check_method(method, bcp), "bcp must point into method");
+ Code code = cast(*bcp);
+ assert(code != _breakpoint || method != NULL, "need methodOop to decode breakpoint");
+ return (code != _breakpoint) ? code : non_breakpoint_code_at(method, bcp);
+ }
+ static Code java_code_at(const methodOopDesc* method, address bcp) {
+ return java_code(code_at(method, bcp));
+ }
- // Fetch a bytecode or a breakpoint:
- static Code code_or_bp_at(address bcp) { return (Code)cast(*bcp); }
+ // Fetch a bytecode or a breakpoint:
+ static Code code_or_bp_at(address bcp) { return (Code)cast(*bcp); }
- static Code code_at(methodOop method, int bci);
- static bool is_active_breakpoint_at(address bcp) { return (Code)*bcp == _breakpoint; }
+ static Code code_at(methodOop method, int bci);
+ static bool is_active_breakpoint_at(address bcp) { return (Code)*bcp == _breakpoint; }
- // find a bytecode, behind a breakpoint if necessary:
- static Code non_breakpoint_code_at(address bcp, methodOop method = NULL);
+ // find a bytecode, behind a breakpoint if necessary:
+ static Code non_breakpoint_code_at(const methodOopDesc* method, address bcp);
// Bytecode attributes
static bool is_defined (int code) { return 0 <= code && code < number_of_codes && flags(code, false) != 0; }
@@ -379,14 +393,17 @@
static bool can_trap (Code code) { check(code); return has_all_flags(code, _bc_can_trap, false); }
static Code java_code (Code code) { check(code); return _java_code [code]; }
static bool can_rewrite (Code code) { check(code); return has_all_flags(code, _bc_can_rewrite, false); }
+ static bool must_rewrite(Bytecodes::Code code) { return can_rewrite(code) && check_must_rewrite(code); }
static bool native_byte_order(Code code) { check(code); return has_all_flags(code, _fmt_has_nbo, false); }
static bool uses_cp_cache (Code code) { check(code); return has_all_flags(code, _fmt_has_j, false); }
// if 'end' is provided, it indicates the end of the code buffer which
// should not be read past when parsing.
- static int special_length_at(address bcp, address end = NULL);
+ static int special_length_at(Bytecodes::Code code, address bcp, address end = NULL);
+ static int special_length_at(methodOop method, address bcp, address end = NULL) { return special_length_at(code_at(method, bcp), bcp, end); }
static int raw_special_length_at(address bcp, address end = NULL);
- static int length_at (address bcp) { int l = length_for(code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
- static int java_length_at (address bcp) { int l = length_for(java_code_at(bcp)); return l > 0 ? l : special_length_at(bcp); }
+ static int length_for_code_at(Bytecodes::Code code, address bcp) { int l = length_for(code); return l > 0 ? l : special_length_at(code, bcp); }
+ static int length_at (methodOop method, address bcp) { return length_for_code_at(code_at(method, bcp), bcp); }
+ static int java_length_at (methodOop method, address bcp) { return length_for_code_at(java_code_at(method, bcp), bcp); }
static bool is_java_code (Code code) { return 0 <= code && code < number_of_java_codes; }
static bool is_aload (Code code) { return (code == _aload || code == _aload_0 || code == _aload_1
--- a/hotspot/src/share/vm/interpreter/interpreter.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -237,10 +237,9 @@
// Return true if the interpreter can prove that the given bytecode has
// not yet been executed (in Java semantics, not in actual operation).
bool AbstractInterpreter::is_not_reached(methodHandle method, int bci) {
- address bcp = method->bcp_from(bci);
- Bytecodes::Code code = Bytecodes::code_at(bcp, method());
+ Bytecodes::Code code = method()->code_at(bci);
- if (!Bytecode_at(bcp)->must_rewrite(code)) {
+ if (!Bytecodes::must_rewrite(code)) {
// might have been reached
return false;
}
@@ -286,12 +285,12 @@
// If deoptimization happens, this function returns the point of next bytecode to continue execution
address AbstractInterpreter::deopt_continue_after_entry(methodOop method, address bcp, int callee_parameters, bool is_top_frame) {
assert(method->contains(bcp), "just checkin'");
- Bytecodes::Code code = Bytecodes::java_code_at(bcp);
+ Bytecodes::Code code = Bytecodes::java_code_at(method, bcp);
assert(!Interpreter::bytecode_should_reexecute(code), "should not reexecute");
int bci = method->bci_from(bcp);
int length = -1; // initial value for debugging
// compute continuation length
- length = Bytecodes::length_at(bcp);
+ length = Bytecodes::length_at(method, bcp);
// compute result type
BasicType type = T_ILLEGAL;
@@ -303,7 +302,7 @@
Thread *thread = Thread::current();
ResourceMark rm(thread);
methodHandle mh(thread, method);
- type = Bytecode_invoke_at(mh, bci)->result_type(thread);
+ type = Bytecode_invoke(mh, bci).result_type(thread);
// since the cache entry might not be initialized:
// (NOT needed for the old calling convension)
if (!is_top_frame) {
@@ -317,7 +316,7 @@
Thread *thread = Thread::current();
ResourceMark rm(thread);
methodHandle mh(thread, method);
- type = Bytecode_invoke_at(mh, bci)->result_type(thread);
+ type = Bytecode_invoke(mh, bci).result_type(thread);
// since the cache entry might not be initialized:
// (NOT needed for the old calling convension)
if (!is_top_frame) {
@@ -334,7 +333,7 @@
Thread *thread = Thread::current();
ResourceMark rm(thread);
methodHandle mh(thread, method);
- type = Bytecode_loadconstant_at(mh, bci)->result_type();
+ type = Bytecode_loadconstant(mh, bci).result_type();
break;
}
@@ -356,7 +355,7 @@
// Interpreter::deopt_entry(vtos, 0) like others
address AbstractInterpreter::deopt_reexecute_entry(methodOop method, address bcp) {
assert(method->contains(bcp), "just checkin'");
- Bytecodes::Code code = Bytecodes::java_code_at(bcp);
+ Bytecodes::Code code = Bytecodes::java_code_at(method, bcp);
#ifdef COMPILER1
if(code == Bytecodes::_athrow ) {
return Interpreter::rethrow_exception_entry();
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -132,9 +132,9 @@
bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
ResourceMark rm(thread);
methodHandle m (thread, method(thread));
- Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(m, bci(thread));
- oop result = ldc->resolve_constant(THREAD);
- DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc->cache_index()));
+ Bytecode_loadconstant ldc(m, bci(thread));
+ oop result = ldc.resolve_constant(THREAD);
+ DEBUG_ONLY(ConstantPoolCacheEntry* cpce = m->constants()->cache()->entry_at(ldc.cache_index()));
assert(result == cpce->f1(), "expected result for assembly code");
}
IRT_END
@@ -672,8 +672,8 @@
if (bytecode == Bytecodes::_invokevirtual || bytecode == Bytecodes::_invokeinterface) {
ResourceMark rm(thread);
methodHandle m (thread, method(thread));
- Bytecode_invoke* call = Bytecode_invoke_at(m, bci(thread));
- symbolHandle signature (thread, call->signature());
+ Bytecode_invoke call(m, bci(thread));
+ symbolHandle signature (thread, call.signature());
receiver = Handle(thread,
thread->last_frame().interpreter_callee_receiver(signature));
assert(Universe::heap()->is_in_reserved_or_null(receiver()),
@@ -756,7 +756,7 @@
caller_bci = caller_method->bci_from(caller_bcp);
site_index = Bytes::get_native_u4(caller_bcp+1);
}
- assert(site_index == InterpreterRuntime::bytecode(thread)->get_index_u4(bytecode), "");
+ assert(site_index == InterpreterRuntime::bytecode(thread).get_index_u4(bytecode), "");
assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format");
// there is a second CPC entries that is of interest; it caches signature info:
int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
@@ -884,7 +884,7 @@
return mdo->bci_to_di(bci);
IRT_END
-IRT_ENTRY(jint, InterpreterRuntime::profile_method(JavaThread* thread, address cur_bcp))
+IRT_ENTRY(void, InterpreterRuntime::profile_method(JavaThread* thread))
// use UnlockFlagSaver to clear and restore the _do_not_unlock_if_synchronized
// flag, in case this method triggers classloading which will call into Java.
UnlockFlagSaver fs(thread);
@@ -893,16 +893,12 @@
frame fr = thread->last_frame();
assert(fr.is_interpreted_frame(), "must come from interpreter");
methodHandle method(thread, fr.interpreter_frame_method());
- int bci = method->bci_from(cur_bcp);
methodOopDesc::build_interpreter_method_data(method, THREAD);
if (HAS_PENDING_EXCEPTION) {
assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here");
CLEAR_PENDING_EXCEPTION;
// and fall through...
}
- methodDataOop mdo = method->method_data();
- if (mdo == NULL) return 0;
- return mdo->bci_to_di(bci);
IRT_END
@@ -1245,9 +1241,9 @@
assert(fr.is_interpreted_frame(), "");
jint bci = fr.interpreter_frame_bci();
methodHandle mh(thread, fr.interpreter_frame_method());
- Bytecode_invoke* invoke = Bytecode_invoke_at(mh, bci);
- ArgumentSizeComputer asc(invoke->signature());
- int size_of_arguments = (asc.size() + (invoke->has_receiver() ? 1 : 0)); // receiver
+ Bytecode_invoke invoke(mh, bci);
+ ArgumentSizeComputer asc(invoke.signature());
+ int size_of_arguments = (asc.size() + (invoke.has_receiver() ? 1 : 0)); // receiver
Copy::conjoint_jbytes(src_address, dest_address,
size_of_arguments * Interpreter::stackElementSize);
IRT_END
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -58,16 +58,16 @@
static void set_bcp_and_mdp(address bcp, JavaThread*thread);
static Bytecodes::Code code(JavaThread *thread) {
// pass method to avoid calling unsafe bcp_to_method (partial fix 4926272)
- return Bytecodes::code_at(bcp(thread), method(thread));
+ return Bytecodes::code_at(method(thread), bcp(thread));
}
static bool already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); }
- static Bytecode* bytecode(JavaThread *thread) { return Bytecode_at(bcp(thread)); }
+ static Bytecode bytecode(JavaThread *thread) { return Bytecode(method(thread), bcp(thread)); }
static int get_index_u1(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread)->get_index_u1(bc); }
+ { return bytecode(thread).get_index_u1(bc); }
static int get_index_u2(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread)->get_index_u2(bc); }
+ { return bytecode(thread).get_index_u2(bc); }
static int get_index_u2_cpcache(JavaThread *thread, Bytecodes::Code bc)
- { return bytecode(thread)->get_index_u2_cpcache(bc); }
+ { return bytecode(thread).get_index_u2_cpcache(bc); }
static int number_of_dimensions(JavaThread *thread) { return bcp(thread)[3]; }
static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); }
@@ -164,7 +164,7 @@
// Interpreter profiling support
static jint bcp_to_di(methodOopDesc* method, address cur_bcp);
- static jint profile_method(JavaThread* thread, address cur_bcp);
+ static void profile_method(JavaThread* thread);
static void update_mdp_for_ret(JavaThread* thread, int bci);
#ifdef ASSERT
static void verify_mdp(methodOopDesc* method, address bcp, address mdp);
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -221,7 +221,7 @@
// call to calculate the length.
bc_length = Bytecodes::length_for(c);
if (bc_length == 0) {
- bc_length = Bytecodes::length_at(bcp);
+ bc_length = Bytecodes::length_at(method, bcp);
// length_at will put us at the bytecode after the one modified
// by 'wide'. We don't currently examine any of the bytecodes
@@ -237,9 +237,9 @@
switch (c) {
case Bytecodes::_lookupswitch : {
#ifndef CC_INTERP
- Bytecode_lookupswitch* bc = Bytecode_lookupswitch_at(bcp);
+ Bytecode_lookupswitch bc(method, bcp);
(*bcp) = (
- bc->number_of_pairs() < BinarySwitchThreshold
+ bc.number_of_pairs() < BinarySwitchThreshold
? Bytecodes::_fast_linearswitch
: Bytecodes::_fast_binaryswitch
);
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -592,7 +592,7 @@
// that do not return "Interpreter::deopt_entry(vtos, 0)"
address TemplateInterpreter::deopt_reexecute_entry(methodOop method, address bcp) {
assert(method->contains(bcp), "just checkin'");
- Bytecodes::Code code = Bytecodes::java_code_at(bcp);
+ Bytecodes::Code code = Bytecodes::java_code_at(method, bcp);
if (code == Bytecodes::_return) {
// This is used for deopt during registration of finalizers
// during Object.<init>. We simply need to resume execution at
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -158,6 +158,7 @@
Threads::gc_epilogue();
CodeCache::gc_epilogue();
+ JvmtiExport::gc_epilogue();
if (PrintGC && !PrintGCDetails) {
gch->print_heap_change(gch_prev_used);
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -36,8 +36,8 @@
friend class VMStructs;
private:
int _dimension; // This is n'th-dimensional array.
- klassOop _higher_dimension; // Refers the (n+1)'th-dimensional array (if present).
- klassOop _lower_dimension; // Refers the (n-1)'th-dimensional array (if present).
+ volatile klassOop _higher_dimension; // Refers the (n+1)'th-dimensional array (if present).
+ volatile klassOop _lower_dimension; // Refers the (n-1)'th-dimensional array (if present).
int _vtable_len; // size of vtable for this klass
juint _alloc_size; // allocation profiling support
oop _component_mirror; // component type, as a java/lang/Class
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -535,23 +535,23 @@
(*jmpFct)(this, bcs->dest_w(), data);
break;
case Bytecodes::_tableswitch:
- { Bytecode_tableswitch *tableswitch = Bytecode_tableswitch_at(bcs->bcp());
- int len = tableswitch->length();
+ { Bytecode_tableswitch tableswitch(method(), bcs->bcp());
+ int len = tableswitch.length();
- (*jmpFct)(this, bci + tableswitch->default_offset(), data); /* Default. jump address */
+ (*jmpFct)(this, bci + tableswitch.default_offset(), data); /* Default. jump address */
while (--len >= 0) {
- (*jmpFct)(this, bci + tableswitch->dest_offset_at(len), data);
+ (*jmpFct)(this, bci + tableswitch.dest_offset_at(len), data);
}
break;
}
case Bytecodes::_lookupswitch:
- { Bytecode_lookupswitch *lookupswitch = Bytecode_lookupswitch_at(bcs->bcp());
- int npairs = lookupswitch->number_of_pairs();
- (*jmpFct)(this, bci + lookupswitch->default_offset(), data); /* Default. */
+ { Bytecode_lookupswitch lookupswitch(method(), bcs->bcp());
+ int npairs = lookupswitch.number_of_pairs();
+ (*jmpFct)(this, bci + lookupswitch.default_offset(), data); /* Default. */
while(--npairs >= 0) {
- LookupswitchPair *pair = lookupswitch->pair_at(npairs);
- (*jmpFct)(this, bci + pair->offset(), data);
+ LookupswitchPair pair = lookupswitch.pair_at(npairs);
+ (*jmpFct)(this, bci + pair.offset(), data);
}
break;
}
@@ -977,7 +977,7 @@
#ifdef ASSERT
if (blockNum + 1 < bbNo) {
address bcp = _method->bcp_from(bb->_end_bci);
- int bc_len = Bytecodes::java_length_at(bcp);
+ int bc_len = Bytecodes::java_length_at(_method(), bcp);
assert(bb->_end_bci + bc_len == bb[1]._bci, "unmatched bci info in basicblock");
}
#endif
@@ -985,7 +985,7 @@
#ifdef ASSERT
{ BasicBlock *bb = &_basic_blocks[bbNo-1];
address bcp = _method->bcp_from(bb->_end_bci);
- int bc_len = Bytecodes::java_length_at(bcp);
+ int bc_len = Bytecodes::java_length_at(_method(), bcp);
assert(bb->_end_bci + bc_len == _method->code_size(), "wrong end bci");
}
#endif
@@ -1837,14 +1837,14 @@
void GenerateOopMap::do_ldc(int bci) {
- Bytecode_loadconstant* ldc = Bytecode_loadconstant_at(method(), bci);
+ Bytecode_loadconstant ldc(method(), bci);
constantPoolOop cp = method()->constants();
- BasicType bt = ldc->result_type();
+ BasicType bt = ldc.result_type();
CellTypeState cts = (bt == T_OBJECT) ? CellTypeState::make_line_ref(bci) : valCTS;
// Make sure bt==T_OBJECT is the same as old code (is_pointer_entry).
// Note that CONSTANT_MethodHandle entries are u2 index pairs, not pointer-entries,
// and they are processed by _fast_aldc and the CP cache.
- assert((ldc->has_cache_index() || cp->is_pointer_entry(ldc->pool_index()))
+ assert((ldc.has_cache_index() || cp->is_pointer_entry(ldc.pool_index()))
? (bt == T_OBJECT) : true, "expected object type");
ppush1(cts);
}
@@ -2343,7 +2343,7 @@
bool GenerateOopMap::rewrite_load_or_store(BytecodeStream *bcs, Bytecodes::Code bcN, Bytecodes::Code bc0, unsigned int varNo) {
assert(bcN == Bytecodes::_astore || bcN == Bytecodes::_aload, "wrong argument (bcN)");
assert(bc0 == Bytecodes::_astore_0 || bc0 == Bytecodes::_aload_0, "wrong argument (bc0)");
- int ilen = Bytecodes::length_at(bcs->bcp());
+ int ilen = Bytecodes::length_at(_method(), bcs->bcp());
int newIlen;
if (ilen == 4) {
--- a/hotspot/src/share/vm/oops/methodDataOop.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/methodDataOop.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -417,11 +417,11 @@
int MultiBranchData::compute_cell_count(BytecodeStream* stream) {
int cell_count = 0;
if (stream->code() == Bytecodes::_tableswitch) {
- Bytecode_tableswitch* sw = Bytecode_tableswitch_at(stream->bcp());
- cell_count = 1 + per_case_cell_count * (1 + sw->length()); // 1 for default
+ Bytecode_tableswitch sw(stream->method()(), stream->bcp());
+ cell_count = 1 + per_case_cell_count * (1 + sw.length()); // 1 for default
} else {
- Bytecode_lookupswitch* sw = Bytecode_lookupswitch_at(stream->bcp());
- cell_count = 1 + per_case_cell_count * (sw->number_of_pairs() + 1); // 1 for default
+ Bytecode_lookupswitch sw(stream->method()(), stream->bcp());
+ cell_count = 1 + per_case_cell_count * (sw.number_of_pairs() + 1); // 1 for default
}
return cell_count;
}
@@ -434,35 +434,35 @@
int target_di;
int offset;
if (stream->code() == Bytecodes::_tableswitch) {
- Bytecode_tableswitch* sw = Bytecode_tableswitch_at(stream->bcp());
- int len = sw->length();
+ Bytecode_tableswitch sw(stream->method()(), stream->bcp());
+ int len = sw.length();
assert(array_len() == per_case_cell_count * (len + 1), "wrong len");
for (int count = 0; count < len; count++) {
- target = sw->dest_offset_at(count) + bci();
+ target = sw.dest_offset_at(count) + bci();
my_di = mdo->dp_to_di(dp());
target_di = mdo->bci_to_di(target);
offset = target_di - my_di;
set_displacement_at(count, offset);
}
- target = sw->default_offset() + bci();
+ target = sw.default_offset() + bci();
my_di = mdo->dp_to_di(dp());
target_di = mdo->bci_to_di(target);
offset = target_di - my_di;
set_default_displacement(offset);
} else {
- Bytecode_lookupswitch* sw = Bytecode_lookupswitch_at(stream->bcp());
- int npairs = sw->number_of_pairs();
+ Bytecode_lookupswitch sw(stream->method()(), stream->bcp());
+ int npairs = sw.number_of_pairs();
assert(array_len() == per_case_cell_count * (npairs + 1), "wrong len");
for (int count = 0; count < npairs; count++) {
- LookupswitchPair *pair = sw->pair_at(count);
- target = pair->offset() + bci();
+ LookupswitchPair pair = sw.pair_at(count);
+ target = pair.offset() + bci();
my_di = mdo->dp_to_di(dp());
target_di = mdo->bci_to_di(target);
offset = target_di - my_di;
set_displacement_at(count, offset);
}
- target = sw->default_offset() + bci();
+ target = sw.default_offset() + bci();
my_di = mdo->dp_to_di(dp());
target_di = mdo->bci_to_di(target);
offset = target_di - my_di;
--- a/hotspot/src/share/vm/oops/methodOop.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/methodOop.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -150,17 +150,6 @@
return -1;
}
-methodOop methodOopDesc::method_from_bcp(address bcp) {
- debug_only(static int count = 0; count++);
- assert(Universe::heap()->is_in_permanent(bcp), "bcp not in perm_gen");
- // TO DO: this may be unsafe in some configurations
- HeapWord* p = Universe::heap()->block_start(bcp);
- assert(Universe::heap()->block_is_obj(p), "must be obj");
- assert(oop(p)->is_constMethod(), "not a method");
- return constMethodOop(p)->method();
-}
-
-
void methodOopDesc::mask_for(int bci, InterpreterOopMap* mask) {
Thread* myThread = Thread::current();
@@ -469,11 +458,10 @@
bool methodOopDesc::is_accessor() const {
if (code_size() != 5) return false;
if (size_of_parameters() != 1) return false;
- methodOop m = (methodOop)this; // pass to code_at() to avoid method_from_bcp
- if (Bytecodes::java_code_at(code_base()+0, m) != Bytecodes::_aload_0 ) return false;
- if (Bytecodes::java_code_at(code_base()+1, m) != Bytecodes::_getfield) return false;
- if (Bytecodes::java_code_at(code_base()+4, m) != Bytecodes::_areturn &&
- Bytecodes::java_code_at(code_base()+4, m) != Bytecodes::_ireturn ) return false;
+ if (java_code_at(0) != Bytecodes::_aload_0 ) return false;
+ if (java_code_at(1) != Bytecodes::_getfield) return false;
+ if (java_code_at(4) != Bytecodes::_areturn &&
+ java_code_at(4) != Bytecodes::_ireturn ) return false;
return true;
}
@@ -1414,7 +1402,7 @@
}
-Bytecodes::Code methodOopDesc::orig_bytecode_at(int bci) {
+Bytecodes::Code methodOopDesc::orig_bytecode_at(int bci) const {
BreakpointInfo* bp = instanceKlass::cast(method_holder())->breakpoints();
for (; bp != NULL; bp = bp->next()) {
if (bp->match(this, bci)) {
--- a/hotspot/src/share/vm/oops/methodOop.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/methodOop.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -196,8 +196,15 @@
static char* name_and_sig_as_C_string(Klass* klass, symbolOop method_name, symbolOop signature);
static char* name_and_sig_as_C_string(Klass* klass, symbolOop method_name, symbolOop signature, char* buf, int size);
+ Bytecodes::Code java_code_at(int bci) const {
+ return Bytecodes::java_code_at(this, bcp_from(bci));
+ }
+ Bytecodes::Code code_at(int bci) const {
+ return Bytecodes::code_at(this, bcp_from(bci));
+ }
+
// JVMTI breakpoints
- Bytecodes::Code orig_bytecode_at(int bci);
+ Bytecodes::Code orig_bytecode_at(int bci) const;
void set_orig_bytecode_at(int bci, Bytecodes::Code code);
void set_breakpoint(int bci);
void clear_breakpoint(int bci);
@@ -655,8 +662,6 @@
void set_queued_for_compilation() { _access_flags.set_queued_for_compilation(); }
void clear_queued_for_compilation() { _access_flags.clear_queued_for_compilation(); }
- static methodOop method_from_bcp(address bcp);
-
// Resolve all classes in signature, return 'true' if successful
static bool load_signature_classes(methodHandle m, TRAPS);
@@ -787,11 +792,11 @@
void set_next(BreakpointInfo* n) { _next = n; }
// helps for searchers
- bool match(methodOop m, int bci) {
+ bool match(const methodOopDesc* m, int bci) {
return bci == _bci && match(m);
}
- bool match(methodOop m) {
+ bool match(const methodOopDesc* m) {
return _name_index == m->name_index() &&
_signature_index == m->signature_index();
}
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -235,8 +235,9 @@
objArrayKlassKlass::cast(Universe::objArrayKlassKlassObj())->
allocate_objArray_klass(dimension + 1, this_oop, CHECK_NULL);
ak = objArrayKlassHandle(THREAD, new_klass);
+ ak->set_lower_dimension(this_oop());
+ OrderAccess::storestore();
this_oop->set_higher_dimension(ak());
- ak->set_lower_dimension(this_oop());
assert(ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
}
}
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -179,6 +179,7 @@
dimension + 1, h_this, CHECK_NULL);
h_ak = objArrayKlassHandle(THREAD, oak);
h_ak->set_lower_dimension(h_this());
+ OrderAccess::storestore();
h_this->set_higher_dimension(h_ak());
assert(h_ak->oop_is_objArray(), "incorrect initialization of objArrayKlass");
}
--- a/hotspot/src/share/vm/opto/type.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/opto/type.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -2187,8 +2187,11 @@
case TypePtr::NotNull:
return this;
case TypePtr::Null:
- case TypePtr::Constant:
- return make( _bits+offset );
+ case TypePtr::Constant: {
+ address bits = _bits+offset;
+ if ( bits == 0 ) return TypePtr::NULL_PTR;
+ return make( bits );
+ }
default: ShouldNotReachHere();
}
return NULL; // Lint noise
--- a/hotspot/src/share/vm/prims/jvm.h Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvm.h Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1649,7 +1649,8 @@
* the new bit is also added in the main/baseline.
*/
unsigned int thread_park_blocker : 1;
- unsigned int : 31;
+ unsigned int post_vm_init_hook_enabled : 1;
+ unsigned int : 30;
unsigned int : 32;
unsigned int : 32;
} jdk_version_info;
--- a/hotspot/src/share/vm/prims/jvmti.xml Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmti.xml Fri Feb 18 12:04:36 2011 -0800
@@ -13048,8 +13048,8 @@
<event label="Garbage Collection Start"
id="GarbageCollectionStart" const="JVMTI_EVENT_GARBAGE_COLLECTION_START" num="81">
<description>
- A Garbage Collection Start event is sent when a full cycle
- garbage collection begins.
+ A Garbage Collection Start event is sent when a
+ garbage collection pause begins.
Only stop-the-world collections are reported--that is, collections during
which all threads cease to modify the state of the Java virtual machine.
This means that some collectors will never generate these events.
@@ -13075,8 +13075,8 @@
<event label="Garbage Collection Finish"
id="GarbageCollectionFinish" const="JVMTI_EVENT_GARBAGE_COLLECTION_FINISH" num="82">
<description>
- A Garbage Collection Finish event is sent when a full
- garbage collection cycle ends.
+ A Garbage Collection Finish event is sent when a
+ garbage collection pause ends.
This event is sent while the VM is still stopped, thus
the event handler must not use JNI functions and
must not use <jvmti/> functions except those which
--- a/hotspot/src/share/vm/prims/jvmtiEventController.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiEventController.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -667,14 +667,13 @@
JvmtiEventControllerPrivate::thread_ended(JavaThread *thread) {
// Removes the JvmtiThreadState associated with the specified thread.
// May be called after all environments have been disposed.
+ assert(JvmtiThreadState_lock->is_locked(), "sanity check");
EC_TRACE(("JVMTI [%s] # thread ended", JvmtiTrace::safe_get_thread_name(thread)));
JvmtiThreadState *state = thread->jvmti_thread_state();
- if (state != NULL) {
- MutexLocker mu(JvmtiThreadState_lock);
- delete state;
- }
+ assert(state != NULL, "else why are we here?");
+ delete state;
}
void JvmtiEventControllerPrivate::set_event_callbacks(JvmtiEnvBase *env,
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -2253,12 +2253,14 @@
void JvmtiExport::cleanup_thread(JavaThread* thread) {
assert(JavaThread::current() == thread, "thread is not current");
-
+ MutexLocker mu(JvmtiThreadState_lock);
- // This has to happen after the thread state is removed, which is
- // why it is not in post_thread_end_event like its complement
- // Maybe both these functions should be rolled into the posts?
- JvmtiEventController::thread_ended(thread);
+ if (thread->jvmti_thread_state() != NULL) {
+ // This has to happen after the thread state is removed, which is
+ // why it is not in post_thread_end_event like its complement
+ // Maybe both these functions should be rolled into the posts?
+ JvmtiEventController::thread_ended(thread);
+ }
}
void JvmtiExport::oops_do(OopClosure* f) {
@@ -2266,6 +2268,14 @@
JvmtiVMObjectAllocEventCollector::oops_do_for_all_threads(f);
}
+void JvmtiExport::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+ JvmtiTagMap::weak_oops_do(is_alive, f);
+}
+
+void JvmtiExport::gc_epilogue() {
+ JvmtiCurrentBreakpoints::gc_epilogue();
+}
+
// Onload raw monitor transition.
void JvmtiExport::transition_pending_onload_raw_monitors() {
JvmtiPendingMonitors::transition_raw_monitors();
@@ -2358,15 +2368,6 @@
}
#endif // SERVICES_KERNEL
-// CMS has completed referencing processing so may need to update
-// tag maps.
-void JvmtiExport::cms_ref_processing_epilogue() {
- if (JvmtiEnv::environments_might_exist()) {
- JvmtiTagMap::cms_ref_processing_epilogue();
- }
-}
-
-
////////////////////////////////////////////////////////////////////////////////////////////////
// Setup current current thread for event collection.
@@ -2536,36 +2537,20 @@
}
};
-JvmtiGCMarker::JvmtiGCMarker(bool full) : _full(full), _invocation_count(0) {
- assert(Thread::current()->is_VM_thread(), "wrong thread");
-
+JvmtiGCMarker::JvmtiGCMarker() {
// if there aren't any JVMTI environments then nothing to do
if (!JvmtiEnv::environments_might_exist()) {
return;
}
- if (ForceFullGCJVMTIEpilogues) {
- // force 'Full GC' was done semantics for JVMTI GC epilogues
- _full = true;
- }
-
- // GarbageCollectionStart event posted from VM thread - okay because
- // JVMTI is clear that the "world is stopped" and callback shouldn't
- // try to call into the VM.
if (JvmtiExport::should_post_garbage_collection_start()) {
JvmtiExport::post_garbage_collection_start();
}
- // if "full" is false it probably means this is a scavenge of the young
- // generation. However it could turn out that a "full" GC is required
- // so we record the number of collections so that it can be checked in
- // the destructor.
- if (!_full) {
- _invocation_count = Universe::heap()->total_full_collections();
+ if (SafepointSynchronize::is_at_safepoint()) {
+ // Do clean up tasks that need to be done at a safepoint
+ JvmtiEnvBase::check_for_periodic_clean_up();
}
-
- // Do clean up tasks that need to be done at a safepoint
- JvmtiEnvBase::check_for_periodic_clean_up();
}
JvmtiGCMarker::~JvmtiGCMarker() {
@@ -2578,21 +2563,5 @@
if (JvmtiExport::should_post_garbage_collection_finish()) {
JvmtiExport::post_garbage_collection_finish();
}
-
- // we might have initially started out doing a scavenge of the young
- // generation but could have ended up doing a "full" GC - check the
- // GC count to see.
- if (!_full) {
- _full = (_invocation_count != Universe::heap()->total_full_collections());
- }
-
- // Full collection probably means the perm generation has been GC'ed
- // so we clear the breakpoint cache.
- if (_full) {
- JvmtiCurrentBreakpoints::gc_epilogue();
- }
-
- // Notify heap/object tagging support
- JvmtiTagMap::gc_epilogue(_full);
}
#endif // JVMTI_KERNEL
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -346,6 +346,8 @@
static void cleanup_thread (JavaThread* thread) KERNEL_RETURN;
static void oops_do(OopClosure* f) KERNEL_RETURN;
+ static void weak_oops_do(BoolObjectClosure* b, OopClosure* f) KERNEL_RETURN;
+ static void gc_epilogue() KERNEL_RETURN;
static void transition_pending_onload_raw_monitors() KERNEL_RETURN;
@@ -356,9 +358,6 @@
// SetNativeMethodPrefix support
static char** get_all_native_method_prefixes(int* count_ptr);
-
- // call after CMS has completed referencing processing
- static void cms_ref_processing_epilogue() KERNEL_RETURN;
};
// Support class used by JvmtiDynamicCodeEventCollector and others. It
@@ -492,55 +491,11 @@
// Base class for reporting GC events to JVMTI.
class JvmtiGCMarker : public StackObj {
- private:
- bool _full; // marks a "full" GC
- unsigned int _invocation_count; // GC invocation count
- protected:
- JvmtiGCMarker(bool full) KERNEL_RETURN; // protected
- ~JvmtiGCMarker() KERNEL_RETURN; // protected
+ public:
+ JvmtiGCMarker() KERNEL_RETURN;
+ ~JvmtiGCMarker() KERNEL_RETURN;
};
-
-// Support class used to report GC events to JVMTI. The class is stack
-// allocated and should be placed in the doit() implementation of all
-// vm operations that do a stop-the-world GC for failed allocation.
-//
-// Usage :-
-//
-// void VM_GenCollectForAllocation::doit() {
-// JvmtiGCForAllocationMarker jgcm;
-// :
-// }
-//
-// If jvmti is not enabled the constructor and destructor is essentially
-// a no-op (no overhead).
-//
-class JvmtiGCForAllocationMarker : public JvmtiGCMarker {
- public:
- JvmtiGCForAllocationMarker() : JvmtiGCMarker(false) {
- }
-};
-
-// Support class used to report GC events to JVMTI. The class is stack
-// allocated and should be placed in the doit() implementation of all
-// vm operations that do a "full" stop-the-world GC. This class differs
-// from JvmtiGCForAllocationMarker in that this class assumes that a
-// "full" GC will happen.
-//
-// Usage :-
-//
-// void VM_GenCollectFull::doit() {
-// JvmtiGCFullMarker jgcm;
-// :
-// }
-//
-class JvmtiGCFullMarker : public JvmtiGCMarker {
- public:
- JvmtiGCFullMarker() : JvmtiGCMarker(true) {
- }
-};
-
-
// JvmtiHideSingleStepping is a helper class for hiding
// internal single step events.
class JvmtiHideSingleStepping : public StackObj {
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -217,7 +217,6 @@
void GrowableCache::gc_epilogue() {
int len = _elements->length();
- // recompute the new cache value after GC
for (int i=0; i<len; i++) {
_cache[i] = _elements->at(i)->getCacheValue();
}
@@ -401,7 +400,7 @@
_bps.oops_do(f);
}
-void JvmtiBreakpoints::gc_epilogue() {
+void JvmtiBreakpoints::gc_epilogue() {
_bps.gc_epilogue();
}
@@ -540,7 +539,6 @@
}
}
-
///////////////////////////////////////////////////////////////
//
// class VM_GetOrSetLocal
--- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -117,6 +117,7 @@
void clear();
// apply f to every element and update the cache
void oops_do(OopClosure* f);
+ // update the cache after a full gc
void gc_epilogue();
};
@@ -278,13 +279,13 @@
int length();
void oops_do(OopClosure* f);
- void gc_epilogue();
void print();
int set(JvmtiBreakpoint& bp);
int clear(JvmtiBreakpoint& bp);
void clearall_in_class_at_safepoint(klassOop klass);
void clearall();
+ void gc_epilogue();
};
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1458,7 +1458,7 @@
if (bc_length == 0) {
// More complicated bytecodes report a length of zero so
// we have to try again a slightly different way.
- bc_length = Bytecodes::length_at(bcp);
+ bc_length = Bytecodes::length_at(method(), bcp);
}
assert(bc_length != 0, "impossible bytecode length");
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -50,7 +50,7 @@
// JvmtiTagHashmapEntry
//
-// Each entry encapsulates a JNI weak reference to the tagged object
+// Each entry encapsulates a reference to the tagged object
// and the tag value. In addition an entry includes a next pointer which
// is used to chain entries together.
@@ -58,24 +58,25 @@
private:
friend class JvmtiTagMap;
- jweak _object; // JNI weak ref to tagged object
+ oop _object; // tagged object
jlong _tag; // the tag
JvmtiTagHashmapEntry* _next; // next on the list
- inline void init(jweak object, jlong tag) {
+ inline void init(oop object, jlong tag) {
_object = object;
_tag = tag;
_next = NULL;
}
// constructor
- JvmtiTagHashmapEntry(jweak object, jlong tag) { init(object, tag); }
+ JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
public:
// accessor methods
- inline jweak object() const { return _object; }
- inline jlong tag() const { return _tag; }
+ inline oop object() const { return _object; }
+ inline oop* object_addr() { return &_object; }
+ inline jlong tag() const { return _tag; }
inline void set_tag(jlong tag) {
assert(tag != 0, "can't be zero");
@@ -92,9 +93,7 @@
// A hashmap is essentially a table of pointers to entries. Entries
// are hashed to a location, or position in the table, and then
// chained from that location. The "key" for hashing is address of
-// the object, or oop. The "value" is the JNI weak reference to the
-// object and the tag value. Keys are not stored with the entry.
-// Instead the weak reference is resolved to obtain the key.
+// the object, or oop. The "value" is the tag value.
//
// A hashmap maintains a count of the number entries in the hashmap
// and resizes if the number of entries exceeds a given threshold.
@@ -206,7 +205,7 @@
JvmtiTagHashmapEntry* entry = _table[i];
while (entry != NULL) {
JvmtiTagHashmapEntry* next = entry->next();
- oop key = JNIHandles::resolve(entry->object());
+ oop key = entry->object();
assert(key != NULL, "jni weak reference cleared!!");
unsigned int h = hash(key, new_size);
JvmtiTagHashmapEntry* anchor = new_table[h];
@@ -299,14 +298,12 @@
unsigned int h = hash(key);
JvmtiTagHashmapEntry* entry = _table[h];
while (entry != NULL) {
- oop orig_key = JNIHandles::resolve(entry->object());
- assert(orig_key != NULL, "jni weak reference cleared!!");
- if (key == orig_key) {
- break;
+ if (entry->object() == key) {
+ return entry;
}
entry = entry->next();
}
- return entry;
+ return NULL;
}
@@ -343,9 +340,7 @@
JvmtiTagHashmapEntry* entry = _table[h];
JvmtiTagHashmapEntry* prev = NULL;
while (entry != NULL) {
- oop orig_key = JNIHandles::resolve(entry->object());
- assert(orig_key != NULL, "jni weak reference cleared!!");
- if (key == orig_key) {
+ if (key == entry->object()) {
break;
}
prev = entry;
@@ -418,54 +413,6 @@
}
}
-// memory region for young generation
-MemRegion JvmtiTagMap::_young_gen;
-
-// get the memory region used for the young generation
-void JvmtiTagMap::get_young_generation() {
- CollectedHeap* ch = Universe::heap();
- switch (ch->kind()) {
- case (CollectedHeap::GenCollectedHeap): {
- _young_gen = ((GenCollectedHeap*)ch)->get_gen(0)->reserved();
- break;
- }
-#ifndef SERIALGC
- case (CollectedHeap::ParallelScavengeHeap): {
- _young_gen = ((ParallelScavengeHeap*)ch)->young_gen()->reserved();
- break;
- }
- case (CollectedHeap::G1CollectedHeap): {
- // Until a more satisfactory solution is implemented, all
- // oops in the tag map will require rehash at each gc.
- // This is a correct, if extremely inefficient solution.
- // See RFE 6621729 for related commentary.
- _young_gen = ch->reserved_region();
- break;
- }
-#endif // !SERIALGC
- default:
- ShouldNotReachHere();
- }
-}
-
-// returns true if oop is in the young generation
-inline bool JvmtiTagMap::is_in_young(oop o) {
- assert(_young_gen.start() != NULL, "checking");
- void* p = (void*)o;
- bool in_young = _young_gen.contains(p);
- return in_young;
-}
-
-// returns the appropriate hashmap for a given object
-inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) {
- if (is_in_young(o)) {
- return _hashmap[0];
- } else {
- return _hashmap[1];
- }
-}
-
-
// create a JvmtiTagMap
JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
_env(env),
@@ -476,13 +423,7 @@
assert(JvmtiThreadState_lock->is_locked(), "sanity check");
assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
- // create the hashmaps
- for (int i=0; i<n_hashmaps; i++) {
- _hashmap[i] = new JvmtiTagHashmap();
- }
-
- // get the memory region used by the young generation
- get_young_generation();
+ _hashmap = new JvmtiTagHashmap();
// finally add us to the environment
((JvmtiEnvBase *)env)->set_tag_map(this);
@@ -496,25 +437,20 @@
// also being destroryed.
((JvmtiEnvBase *)_env)->set_tag_map(NULL);
- // iterate over the hashmaps and destroy each of the entries
- for (int i=0; i<n_hashmaps; i++) {
- JvmtiTagHashmap* hashmap = _hashmap[i];
- JvmtiTagHashmapEntry** table = hashmap->table();
- for (int j=0; j<hashmap->size(); j++) {
- JvmtiTagHashmapEntry *entry = table[j];
- while (entry != NULL) {
- JvmtiTagHashmapEntry* next = entry->next();
- jweak ref = entry->object();
- JNIHandles::destroy_weak_global(ref);
- delete entry;
- entry = next;
- }
+ JvmtiTagHashmapEntry** table = _hashmap->table();
+ for (int j = 0; j < _hashmap->size(); j++) {
+ JvmtiTagHashmapEntry* entry = table[j];
+ while (entry != NULL) {
+ JvmtiTagHashmapEntry* next = entry->next();
+ delete entry;
+ entry = next;
}
-
- // finally destroy the hashmap
- delete hashmap;
}
+ // finally destroy the hashmap
+ delete _hashmap;
+ _hashmap = NULL;
+
// remove any entries on the free list
JvmtiTagHashmapEntry* entry = _free_entries;
while (entry != NULL) {
@@ -522,12 +458,13 @@
delete entry;
entry = next;
}
+ _free_entries = NULL;
}
// create a hashmap entry
// - if there's an entry on the (per-environment) free list then this
// is returned. Otherwise an new entry is allocated.
-JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) {
+JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) {
assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
JvmtiTagHashmapEntry* entry;
if (_free_entries == NULL) {
@@ -558,10 +495,10 @@
// returns the tag map for the given environments. If the tag map
// doesn't exist then it is created.
JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
- JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
+ JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
if (tag_map == NULL) {
MutexLocker mu(JvmtiThreadState_lock);
- tag_map = ((JvmtiEnvBase *)env)->tag_map();
+ tag_map = ((JvmtiEnvBase*)env)->tag_map();
if (tag_map == NULL) {
tag_map = new JvmtiTagMap(env);
}
@@ -573,17 +510,13 @@
// iterate over all entries in the tag map.
void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
- for (int i=0; i<n_hashmaps; i++) {
- JvmtiTagHashmap* hashmap = _hashmap[i];
- hashmap->entry_iterate(closure);
- }
+ hashmap()->entry_iterate(closure);
}
// returns true if the hashmaps are empty
bool JvmtiTagMap::is_empty() {
assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
- assert(n_hashmaps == 2, "not implemented");
- return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0));
+ return hashmap()->entry_count() == 0;
}
@@ -591,7 +524,7 @@
// not tagged
//
static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) {
- JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o);
+ JvmtiTagHashmapEntry* entry = tag_map->hashmap()->find(o);
if (entry == NULL) {
return 0;
} else {
@@ -655,7 +588,7 @@
// record the context
_tag_map = tag_map;
- _hashmap = tag_map->hashmap_for(_o);
+ _hashmap = tag_map->hashmap();
_entry = _hashmap->find(_o);
// get object tag
@@ -694,23 +627,18 @@
if (obj_tag != 0) {
// callback has tagged the object
assert(Thread::current()->is_VM_thread(), "must be VMThread");
- HandleMark hm;
- Handle h(o);
- jweak ref = JNIHandles::make_weak_global(h);
- entry = tag_map()->create_entry(ref, obj_tag);
+ entry = tag_map()->create_entry(o, obj_tag);
hashmap->add(o, entry);
}
} else {
// object was previously tagged - the callback may have untagged
// the object or changed the tag value
if (obj_tag == 0) {
- jweak ref = entry->object();
JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o);
assert(entry_removed == entry, "checking");
tag_map()->destroy_entry(entry);
- JNIHandles::destroy_weak_global(ref);
} else {
if (obj_tag != entry->tag()) {
entry->set_tag(obj_tag);
@@ -760,7 +688,7 @@
// for Classes the klassOop is tagged
_referrer = klassOop_if_java_lang_Class(referrer);
// record the context
- _referrer_hashmap = tag_map->hashmap_for(_referrer);
+ _referrer_hashmap = tag_map->hashmap();
_referrer_entry = _referrer_hashmap->find(_referrer);
// get object tag
@@ -796,8 +724,7 @@
//
// This function is performance critical. If many threads attempt to tag objects
// around the same time then it's possible that the Mutex associated with the
-// tag map will be a hot lock. Eliminating this lock will not eliminate the issue
-// because creating a JNI weak reference requires acquiring a global lock also.
+// tag map will be a hot lock.
void JvmtiTagMap::set_tag(jobject object, jlong tag) {
MutexLocker ml(lock());
@@ -808,22 +735,14 @@
o = klassOop_if_java_lang_Class(o);
// see if the object is already tagged
- JvmtiTagHashmap* hashmap = hashmap_for(o);
+ JvmtiTagHashmap* hashmap = _hashmap;
JvmtiTagHashmapEntry* entry = hashmap->find(o);
// if the object is not already tagged then we tag it
if (entry == NULL) {
if (tag != 0) {
- HandleMark hm;
- Handle h(o);
- jweak ref = JNIHandles::make_weak_global(h);
-
- // the object may have moved because make_weak_global may
- // have blocked - thus it is necessary resolve the handle
- // and re-hash the object.
- o = h();
- entry = create_entry(ref, tag);
- hashmap_for(o)->add(o, entry);
+ entry = create_entry(o, tag);
+ hashmap->add(o, entry);
} else {
// no-op
}
@@ -831,13 +750,9 @@
// if the object is already tagged then we either update
// the tag (if a new tag value has been provided)
// or remove the object if the new tag value is 0.
- // Removing the object requires that we also delete the JNI
- // weak ref to the object.
if (tag == 0) {
- jweak ref = entry->object();
hashmap->remove(o);
destroy_entry(entry);
- JNIHandles::destroy_weak_global(ref);
} else {
entry->set_tag(tag);
}
@@ -1626,8 +1541,8 @@
void do_entry(JvmtiTagHashmapEntry* entry) {
for (int i=0; i<_tag_count; i++) {
if (_tags[i] == entry->tag()) {
- oop o = JNIHandles::resolve(entry->object());
- assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check");
+ oop o = entry->object();
+ assert(o != NULL, "sanity check");
// the mirror is tagged
if (o->is_klass()) {
@@ -3374,62 +3289,25 @@
}
-// called post-GC
-// - for each JVMTI environment with an object tag map, call its rehash
-// function to re-sync with the new object locations.
-void JvmtiTagMap::gc_epilogue(bool full) {
- assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
+void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
+ // No locks during VM bring-up (0 threads) and no safepoints after main
+ // thread creation and before VMThread creation (1 thread); initial GC
+ // verification can happen in that window which gets to here.
+ assert(Threads::number_of_threads() <= 1 ||
+ SafepointSynchronize::is_at_safepoint(),
+ "must be executed at a safepoint");
if (JvmtiEnv::environments_might_exist()) {
- // re-obtain the memory region for the young generation (might
- // changed due to adaptive resizing policy)
- get_young_generation();
-
JvmtiEnvIterator it;
for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
JvmtiTagMap* tag_map = env->tag_map();
if (tag_map != NULL && !tag_map->is_empty()) {
- TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging);
- if (full) {
- tag_map->rehash(0, n_hashmaps);
- } else {
- tag_map->rehash(0, 0); // tag map for young gen only
- }
+ tag_map->do_weak_oops(is_alive, f);
}
}
}
}
-// CMS has completed referencing processing so we may have JNI weak refs
-// to objects in the CMS generation that have been GC'ed.
-void JvmtiTagMap::cms_ref_processing_epilogue() {
- assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
- assert(UseConcMarkSweepGC, "should only be used with CMS");
- if (JvmtiEnv::environments_might_exist()) {
- JvmtiEnvIterator it;
- for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
- JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
- if (tag_map != NULL && !tag_map->is_empty()) {
- TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging);
- tag_map->rehash(1, n_hashmaps); // assume CMS not used in young gen
- }
- }
- }
-}
-
-
-// For each entry in the hashmaps 'start' to 'end' :
-//
-// 1. resolve the JNI weak reference
-//
-// 2. If it resolves to NULL it means the object has been freed so the entry
-// is removed, the weak reference destroyed, and the object free event is
-// posted (if enabled).
-//
-// 3. If the weak reference resolves to an object then we re-hash the object
-// to see if it has moved or has been promoted (from the young to the old
-// generation for example).
-//
-void JvmtiTagMap::rehash(int start, int end) {
+void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
// does this environment have the OBJECT_FREE event enabled
bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
@@ -3437,143 +3315,98 @@
// counters used for trace message
int freed = 0;
int moved = 0;
- int promoted = 0;
-
- // we assume there are two hashmaps - one for the young generation
- // and the other for all other spaces.
- assert(n_hashmaps == 2, "not implemented");
- JvmtiTagHashmap* young_hashmap = _hashmap[0];
- JvmtiTagHashmap* other_hashmap = _hashmap[1];
+
+ JvmtiTagHashmap* hashmap = this->hashmap();
// reenable sizing (if disabled)
- young_hashmap->set_resizing_enabled(true);
- other_hashmap->set_resizing_enabled(true);
-
- // when re-hashing the hashmap corresponding to the young generation we
- // collect the entries corresponding to objects that have been promoted.
- JvmtiTagHashmapEntry* promoted_entries = NULL;
-
- if (end >= n_hashmaps) {
- end = n_hashmaps - 1;
+ hashmap->set_resizing_enabled(true);
+
+ // if the hashmap is empty then we can skip it
+ if (hashmap->_entry_count == 0) {
+ return;
}
- for (int i=start; i <= end; i++) {
- JvmtiTagHashmap* hashmap = _hashmap[i];
-
- // if the hashmap is empty then we can skip it
- if (hashmap->_entry_count == 0) {
- continue;
- }
-
- // now iterate through each entry in the table
-
- JvmtiTagHashmapEntry** table = hashmap->table();
- int size = hashmap->size();
-
- for (int pos=0; pos<size; pos++) {
- JvmtiTagHashmapEntry* entry = table[pos];
- JvmtiTagHashmapEntry* prev = NULL;
-
- while (entry != NULL) {
- JvmtiTagHashmapEntry* next = entry->next();
-
- jweak ref = entry->object();
- oop oop = JNIHandles::resolve(ref);
-
- // has object been GC'ed
- if (oop == NULL) {
- // grab the tag
- jlong tag = entry->tag();
- guarantee(tag != 0, "checking");
-
- // remove GC'ed entry from hashmap and return the
- // entry to the free list
- hashmap->remove(prev, pos, entry);
- destroy_entry(entry);
-
- // destroy the weak ref
- JNIHandles::destroy_weak_global(ref);
-
- // post the event to the profiler
- if (post_object_free) {
- JvmtiExport::post_object_free(env(), tag);
+ // now iterate through each entry in the table
+
+ JvmtiTagHashmapEntry** table = hashmap->table();
+ int size = hashmap->size();
+
+ JvmtiTagHashmapEntry* delayed_add = NULL;
+
+ for (int pos = 0; pos < size; ++pos) {
+ JvmtiTagHashmapEntry* entry = table[pos];
+ JvmtiTagHashmapEntry* prev = NULL;
+
+ while (entry != NULL) {
+ JvmtiTagHashmapEntry* next = entry->next();
+
+ oop* obj = entry->object_addr();
+
+ // has object been GC'ed
+ if (!is_alive->do_object_b(entry->object())) {
+ // grab the tag
+ jlong tag = entry->tag();
+ guarantee(tag != 0, "checking");
+
+ // remove GC'ed entry from hashmap and return the
+ // entry to the free list
+ hashmap->remove(prev, pos, entry);
+ destroy_entry(entry);
+
+ // post the event to the profiler
+ if (post_object_free) {
+ JvmtiExport::post_object_free(env(), tag);
+ }
+
+ ++freed;
+ } else {
+ f->do_oop(entry->object_addr());
+ oop new_oop = entry->object();
+
+ // if the object has moved then re-hash it and move its
+ // entry to its new location.
+ unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size);
+ if (new_pos != (unsigned int)pos) {
+ if (prev == NULL) {
+ table[pos] = next;
+ } else {
+ prev->set_next(next);
}
-
- freed++;
- entry = next;
- continue;
- }
-
- // if this is the young hashmap then the object is either promoted
- // or moved.
- // if this is the other hashmap then the object is moved.
-
- bool same_gen;
- if (i == 0) {
- assert(hashmap == young_hashmap, "checking");
- same_gen = is_in_young(oop);
- } else {
- same_gen = true;
- }
-
-
- if (same_gen) {
- // if the object has moved then re-hash it and move its
- // entry to its new location.
- unsigned int new_pos = JvmtiTagHashmap::hash(oop, size);
- if (new_pos != (unsigned int)pos) {
- if (prev == NULL) {
- table[pos] = next;
- } else {
- prev->set_next(next);
- }
+ if (new_pos < (unsigned int)pos) {
entry->set_next(table[new_pos]);
table[new_pos] = entry;
- moved++;
} else {
- // object didn't move
- prev = entry;
+ // Delay adding this entry to it's new position as we'd end up
+ // hitting it again during this iteration.
+ entry->set_next(delayed_add);
+ delayed_add = entry;
}
+ moved++;
} else {
- // object has been promoted so remove the entry from the
- // young hashmap
- assert(hashmap == young_hashmap, "checking");
- hashmap->remove(prev, pos, entry);
-
- // move the entry to the promoted list
- entry->set_next(promoted_entries);
- promoted_entries = entry;
+ // object didn't move
+ prev = entry;
}
-
- entry = next;
}
+
+ entry = next;
}
}
-
- // add the entries, corresponding to the promoted objects, to the
- // other hashmap.
- JvmtiTagHashmapEntry* entry = promoted_entries;
- while (entry != NULL) {
- oop o = JNIHandles::resolve(entry->object());
- assert(hashmap_for(o) == other_hashmap, "checking");
- JvmtiTagHashmapEntry* next = entry->next();
- other_hashmap->add(o, entry);
- entry = next;
- promoted++;
+ // Re-add all the entries which were kept aside
+ while (delayed_add != NULL) {
+ JvmtiTagHashmapEntry* next = delayed_add->next();
+ unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
+ delayed_add->set_next(table[pos]);
+ table[pos] = delayed_add;
+ delayed_add = next;
}
// stats
if (TraceJVMTIObjectTagging) {
- int total_moves = promoted + moved;
-
- int post_total = 0;
- for (int i=0; i<n_hashmaps; i++) {
- post_total += _hashmap[i]->_entry_count;
- }
+ int post_total = hashmap->_entry_count;
int pre_total = post_total + freed;
- tty->print("(%d->%d, %d freed, %d promoted, %d total moves)",
- pre_total, post_total, freed, promoted, total_moves);
+ tty->print_cr("(%d->%d, %d freed, %d total moves)",
+ pre_total, post_total, freed, moved);
}
}
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -45,17 +45,12 @@
private:
enum{
- n_hashmaps = 2, // encapsulates 2 hashmaps
- max_free_entries = 4096 // maximum number of free entries per env
+ max_free_entries = 4096 // maximum number of free entries per env
};
- // memory region for young generation
- static MemRegion _young_gen;
- static void get_young_generation();
-
JvmtiEnv* _env; // the jvmti environment
Mutex _lock; // lock for this tag map
- JvmtiTagHashmap* _hashmap[n_hashmaps]; // the hashmaps
+ JvmtiTagHashmap* _hashmap; // the hashmap
JvmtiTagHashmapEntry* _free_entries; // free list for this environment
int _free_entries_count; // number of entries on the free list
@@ -67,11 +62,7 @@
inline Mutex* lock() { return &_lock; }
inline JvmtiEnv* env() const { return _env; }
- // rehash tags maps for generation start to end
- void rehash(int start, int end);
-
- // indicates if the object is in the young generation
- static bool is_in_young(oop o);
+ void do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f);
// iterate over all entries in this tag map
void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
@@ -81,11 +72,10 @@
// indicates if this tag map is locked
bool is_locked() { return lock()->is_locked(); }
- // return the appropriate hashmap for a given object
- JvmtiTagHashmap* hashmap_for(oop o);
+ JvmtiTagHashmap* hashmap() { return _hashmap; }
// create/destroy entries
- JvmtiTagHashmapEntry* create_entry(jweak ref, jlong tag);
+ JvmtiTagHashmapEntry* create_entry(oop ref, jlong tag);
void destroy_entry(JvmtiTagHashmapEntry* entry);
// returns true if the hashmaps are empty
@@ -134,11 +124,8 @@
jint* count_ptr, jobject** object_result_ptr,
jlong** tag_result_ptr);
- // call post-GC to rehash the tag maps.
- static void gc_epilogue(bool full);
-
- // call after referencing processing has completed (CMS)
- static void cms_ref_processing_epilogue();
+ static void weak_oops_do(
+ BoolObjectClosure* is_alive, OopClosure* f) KERNEL_RETURN;
};
#endif // SHARE_VM_PRIMS_JVMTITAGMAP_HPP
--- a/hotspot/src/share/vm/prims/methodComparator.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -194,10 +194,10 @@
case Bytecodes::_ldc : // fall through
case Bytecodes::_ldc_w : {
- Bytecode_loadconstant* ldc_old = Bytecode_loadconstant_at(_s_old->method(), _s_old->bci());
- Bytecode_loadconstant* ldc_new = Bytecode_loadconstant_at(_s_new->method(), _s_new->bci());
- int cpi_old = ldc_old->pool_index();
- int cpi_new = ldc_new->pool_index();
+ Bytecode_loadconstant ldc_old(_s_old->method(), _s_old->bci());
+ Bytecode_loadconstant ldc_new(_s_new->method(), _s_new->bci());
+ int cpi_old = ldc_old.pool_index();
+ int cpi_new = ldc_new.pool_index();
if (!pool_constants_same(cpi_old, cpi_new))
return false;
break;
@@ -267,8 +267,8 @@
case Bytecodes::_ifnonnull : // fall through
case Bytecodes::_ifnull : // fall through
case Bytecodes::_jsr : {
- int old_ofs = _s_old->bytecode()->get_offset_s2(c_old);
- int new_ofs = _s_new->bytecode()->get_offset_s2(c_new);
+ int old_ofs = _s_old->bytecode().get_offset_s2(c_old);
+ int new_ofs = _s_new->bytecode().get_offset_s2(c_new);
if (_switchable_test) {
int old_dest = _s_old->bci() + old_ofs;
int new_dest = _s_new->bci() + new_ofs;
@@ -304,8 +304,8 @@
case Bytecodes::_goto_w : // fall through
case Bytecodes::_jsr_w : {
- int old_ofs = _s_old->bytecode()->get_offset_s4(c_old);
- int new_ofs = _s_new->bytecode()->get_offset_s4(c_new);
+ int old_ofs = _s_old->bytecode().get_offset_s4(c_old);
+ int new_ofs = _s_new->bytecode().get_offset_s4(c_new);
if (_switchable_test) {
int old_dest = _s_old->bci() + old_ofs;
int new_dest = _s_new->bci() + new_ofs;
--- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -137,7 +137,6 @@
void MethodHandleChain::lose(const char* msg, TRAPS) {
- assert(false, "lose");
_lose_message = msg;
if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
// throw a preallocated exception
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -111,7 +111,7 @@
//------------------------------------------------------------------------------
// MethodHandles::generate_adapters
//
-void MethodHandles::generate_adapters(TRAPS) {
+void MethodHandles::generate_adapters() {
if (!EnableMethodHandles || SystemDictionary::MethodHandle_klass() == NULL) return;
assert(_adapter_code == NULL, "generate only once");
@@ -123,20 +123,20 @@
vm_exit_out_of_memory(_adapter_code_size, "CodeCache: no room for MethodHandles adapters");
CodeBuffer code(_adapter_code);
MethodHandlesAdapterGenerator g(&code);
- g.generate(CHECK);
+ g.generate();
}
//------------------------------------------------------------------------------
// MethodHandlesAdapterGenerator::generate
//
-void MethodHandlesAdapterGenerator::generate(TRAPS) {
+void MethodHandlesAdapterGenerator::generate() {
// Generate generic method handle adapters.
for (MethodHandles::EntryKind ek = MethodHandles::_EK_FIRST;
ek < MethodHandles::_EK_LIMIT;
ek = MethodHandles::EntryKind(1 + (int)ek)) {
StubCodeMark mark(this, "MethodHandle", MethodHandles::entry_name(ek));
- MethodHandles::generate_method_handle_stub(_masm, ek, CHECK);
+ MethodHandles::generate_method_handle_stub(_masm, ek);
}
}
@@ -2621,10 +2621,20 @@
warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
enable_MH = false;
}
+ } else {
+ enable_MH = false;
}
}
if (enable_MH) {
+ // We need to link the MethodHandleImpl klass before we generate
+ // the method handle adapters as the _raise_exception adapter uses
+ // one of its methods (and its c2i-adapter).
+ KlassHandle k = SystemDictionaryHandles::MethodHandleImpl_klass();
+ instanceKlass* ik = instanceKlass::cast(k());
+ ik->link_class(CHECK);
+
+ MethodHandles::generate_adapters();
MethodHandles::set_enabled(true);
}
@@ -2645,10 +2655,5 @@
MethodHandles::set_enabled(true);
}
}
-
- // Generate method handles adapters if enabled.
- if (MethodHandles::enabled()) {
- MethodHandles::generate_adapters(CHECK);
- }
}
JVM_END
--- a/hotspot/src/share/vm/prims/methodHandles.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -294,11 +294,11 @@
enum { _suppress_defc = 1, _suppress_name = 2, _suppress_type = 4 };
// Generate MethodHandles adapters.
- static void generate_adapters(TRAPS);
+ static void generate_adapters();
// Called from InterpreterGenerator and MethodHandlesAdapterGenerator.
static address generate_method_handle_interpreter_entry(MacroAssembler* _masm);
- static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek, TRAPS);
+ static void generate_method_handle_stub(MacroAssembler* _masm, EntryKind ek);
// argument list parsing
static int argument_slot(oop method_type, int arg);
@@ -530,7 +530,7 @@
public:
MethodHandlesAdapterGenerator(CodeBuffer* code) : StubCodeGenerator(code) {}
- void generate(TRAPS);
+ void generate();
};
#endif // SHARE_VM_PRIMS_METHODHANDLES_HPP
--- a/hotspot/src/share/vm/prims/unsafe.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -154,12 +154,11 @@
#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
oop p = JNIHandles::resolve(obj); \
- volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset)
+ volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
oop p = JNIHandles::resolve(obj); \
- *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \
- OrderAccess::fence();
+ OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
// Macros for oops that check UseCompressedOops
@@ -181,7 +180,8 @@
v = oopDesc::decode_heap_oop(n); \
} else { \
v = *(volatile oop*)index_oop_from_field_offset_long(p, offset); \
- }
+ } \
+ OrderAccess::acquire();
// Get/SetObject must be special-cased, since it works with handles.
@@ -248,14 +248,22 @@
UnsafeWrapper("Unsafe_SetObjectVolatile");
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
+ void* addr = index_oop_from_field_offset_long(p, offset);
+ OrderAccess::release();
if (UseCompressedOops) {
- oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
+ oop_store((narrowOop*)addr, x);
} else {
- oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
+ oop_store((oop*)addr, x);
}
OrderAccess::fence();
UNSAFE_END
+#if defined(SPARC) || defined(X86)
+// Sparc and X86 have atomic jlong (8 bytes) instructions
+
+#else
+// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions
+
// Volatile long versions must use locks if !VM_Version::supports_cx8().
// support_cx8 is a surrogate for 'supports atomic long memory ops'.
@@ -291,6 +299,7 @@
}
UNSAFE_END
+#endif // not SPARC and not X86
#define DEFINE_GETSETOOP(jboolean, Boolean) \
\
@@ -320,6 +329,16 @@
\
// END DEFINE_GETSETOOP.
+DEFINE_GETSETOOP(jboolean, Boolean)
+DEFINE_GETSETOOP(jbyte, Byte)
+DEFINE_GETSETOOP(jshort, Short);
+DEFINE_GETSETOOP(jchar, Char);
+DEFINE_GETSETOOP(jint, Int);
+DEFINE_GETSETOOP(jlong, Long);
+DEFINE_GETSETOOP(jfloat, Float);
+DEFINE_GETSETOOP(jdouble, Double);
+
+#undef DEFINE_GETSETOOP
#define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
\
@@ -336,47 +355,49 @@
\
// END DEFINE_GETSETOOP_VOLATILE.
-DEFINE_GETSETOOP(jboolean, Boolean)
-DEFINE_GETSETOOP(jbyte, Byte)
-DEFINE_GETSETOOP(jshort, Short);
-DEFINE_GETSETOOP(jchar, Char);
-DEFINE_GETSETOOP(jint, Int);
-DEFINE_GETSETOOP(jlong, Long);
-DEFINE_GETSETOOP(jfloat, Float);
-DEFINE_GETSETOOP(jdouble, Double);
-
DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
DEFINE_GETSETOOP_VOLATILE(jshort, Short);
DEFINE_GETSETOOP_VOLATILE(jchar, Char);
DEFINE_GETSETOOP_VOLATILE(jint, Int);
-// no long -- handled specially
DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
-#undef DEFINE_GETSETOOP
+#if defined(SPARC) || defined(X86)
+// Sparc and X86 have atomic jlong (8 bytes) instructions
+DEFINE_GETSETOOP_VOLATILE(jlong, Long);
+#endif
+
+#undef DEFINE_GETSETOOP_VOLATILE
// The non-intrinsified versions of setOrdered just use setVolatile
-UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \
- UnsafeWrapper("Unsafe_SetOrderedInt"); \
- SET_FIELD_VOLATILE(obj, offset, jint, x); \
+UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x))
+ UnsafeWrapper("Unsafe_SetOrderedInt");
+ SET_FIELD_VOLATILE(obj, offset, jint, x);
UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
UnsafeWrapper("Unsafe_SetOrderedObject");
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
+ void* addr = index_oop_from_field_offset_long(p, offset);
+ OrderAccess::release();
if (UseCompressedOops) {
- oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
+ oop_store((narrowOop*)addr, x);
} else {
- oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
+ oop_store((oop*)addr, x);
}
OrderAccess::fence();
UNSAFE_END
UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
UnsafeWrapper("Unsafe_SetOrderedLong");
+#if defined(SPARC) || defined(X86)
+ // Sparc and X86 have atomic jlong (8 bytes) instructions
+ SET_FIELD_VOLATILE(obj, offset, jlong, x);
+#else
+ // Keep old code for platforms which may not have atomic long (8 bytes) instructions
{
if (VM_Version::supports_cx8()) {
SET_FIELD_VOLATILE(obj, offset, jlong, x);
@@ -388,6 +409,7 @@
*addr = x;
}
}
+#endif
UNSAFE_END
////// Data in the C heap.
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -918,9 +918,7 @@
} else if (strcmp(key, "sun.java.command") == 0) {
_java_command = value;
- // don't add this property to the properties exposed to the java application
- FreeHeap(key);
- return true;
+ // Record value in Arguments, but let it get passed to Java.
} else if (strcmp(key, "sun.java.launcher.pid") == 0) {
// launcher.pid property is private and is processed
// in process_sun_java_launcher_properties();
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -395,8 +395,8 @@
{
HandleMark hm;
methodHandle method(thread, array->element(0)->method());
- Bytecode_invoke* invoke = Bytecode_invoke_at_check(method, array->element(0)->bci());
- return_type = (invoke != NULL) ? invoke->result_type(thread) : T_ILLEGAL;
+ Bytecode_invoke invoke = Bytecode_invoke_check(method, array->element(0)->bci());
+ return_type = invoke.is_valid() ? invoke.result_type(thread) : T_ILLEGAL;
}
// Compute information for handling adapters and adjusting the frame size of the caller.
@@ -600,8 +600,8 @@
cur_code == Bytecodes::_invokespecial ||
cur_code == Bytecodes::_invokestatic ||
cur_code == Bytecodes::_invokeinterface) {
- Bytecode_invoke* invoke = Bytecode_invoke_at(mh, iframe->interpreter_frame_bci());
- symbolHandle signature(thread, invoke->signature());
+ Bytecode_invoke invoke(mh, iframe->interpreter_frame_bci());
+ symbolHandle signature(thread, invoke.signature());
ArgumentSizeComputer asc(signature);
cur_invoke_parameter_size = asc.size();
if (cur_code != Bytecodes::_invokestatic) {
@@ -963,7 +963,7 @@
if (bci == SynchronizationEntryBCI) {
code_name = "sync entry";
} else {
- Bytecodes::Code code = Bytecodes::code_at(vf->method(), bci);
+ Bytecodes::Code code = vf->method()->code_at(bci);
code_name = Bytecodes::name(code);
}
tty->print(" - %s", code_name);
@@ -1224,7 +1224,7 @@
ScopeDesc* trap_scope = cvf->scope();
methodHandle trap_method = trap_scope->method();
int trap_bci = trap_scope->bci();
- Bytecodes::Code trap_bc = Bytecode_at(trap_method->bcp_from(trap_bci))->java_code();
+ Bytecodes::Code trap_bc = trap_method->java_code_at(trap_bci);
// Record this event in the histogram.
gather_statistics(reason, action, trap_bc);
--- a/hotspot/src/share/vm/runtime/frame.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/frame.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -930,10 +930,10 @@
// This is used sometimes for calling into the VM, not for another
// interpreted or compiled frame.
if (!m->is_native()) {
- Bytecode_invoke *call = Bytecode_invoke_at_check(m, bci);
- if (call != NULL) {
- signature = symbolHandle(thread, call->signature());
- has_receiver = call->has_receiver();
+ Bytecode_invoke call = Bytecode_invoke_check(m, bci);
+ if (call.is_valid()) {
+ signature = symbolHandle(thread, call.signature());
+ has_receiver = call.has_receiver();
if (map->include_argument_oops() &&
interpreter_frame_expression_stack_size() > 0) {
ResourceMark rm(thread); // is this right ???
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -1198,9 +1198,6 @@
product(ccstr, TraceJVMTI, NULL, \
"Trace flags for JVMTI functions and events") \
\
- product(bool, ForceFullGCJVMTIEpilogues, false, \
- "Force 'Full GC' was done semantics for JVMTI GC epilogues") \
- \
/* This option can change an EMCP method into an obsolete method. */ \
/* This can affect tests that except specific methods to be EMCP. */ \
/* This option should be used with caution. */ \
--- a/hotspot/src/share/vm/runtime/java.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/java.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -663,7 +663,8 @@
}
_current = JDK_Version(major, minor, micro, info.update_version,
info.special_update_version, build,
- info.thread_park_blocker == 1);
+ info.thread_park_blocker == 1,
+ info.post_vm_init_hook_enabled == 1);
}
}
--- a/hotspot/src/share/vm/runtime/java.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/java.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -92,6 +92,7 @@
bool _partially_initialized;
bool _thread_park_blocker;
+ bool _post_vm_init_hook_enabled;
bool is_valid() const {
return (_major != 0 || _partially_initialized);
@@ -113,14 +114,15 @@
JDK_Version() : _major(0), _minor(0), _micro(0), _update(0),
_special(0), _build(0), _partially_initialized(false),
- _thread_park_blocker(false) {}
+ _thread_park_blocker(false), _post_vm_init_hook_enabled(false) {}
JDK_Version(uint8_t major, uint8_t minor = 0, uint8_t micro = 0,
uint8_t update = 0, uint8_t special = 0, uint8_t build = 0,
- bool thread_park_blocker = false) :
+ bool thread_park_blocker = false, bool post_vm_init_hook_enabled = false) :
_major(major), _minor(minor), _micro(micro), _update(update),
_special(special), _build(build), _partially_initialized(false),
- _thread_park_blocker(thread_park_blocker) {}
+ _thread_park_blocker(thread_park_blocker),
+ _post_vm_init_hook_enabled(post_vm_init_hook_enabled) {}
// Returns the current running JDK version
static JDK_Version current() { return _current; }
@@ -144,6 +146,9 @@
bool supports_thread_park_blocker() const {
return _thread_park_blocker;
}
+ bool post_vm_init_hook_enabled() const {
+ return _post_vm_init_hook_enabled;
+ }
// Performs a full ordering comparison using all fields (update, build, etc.)
int compare(const JDK_Version& other) const;
--- a/hotspot/src/share/vm/runtime/jniHandles.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/jniHandles.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "oops/oop.inline.hpp"
+#include "prims/jvmtiExport.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutexLocker.hpp"
#ifdef TARGET_OS_FAMILY_linux
@@ -428,6 +429,12 @@
break;
}
}
+
+ /*
+ * JVMTI data structures may also contain weak oops. The iteration of them
+ * is placed here so that we don't need to add it to each of the collectors.
+ */
+ JvmtiExport::weak_oops_do(is_alive, f);
}
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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,8 +80,6 @@
Monitor* iCMS_lock = NULL;
Monitor* FullGCCount_lock = NULL;
Monitor* CMark_lock = NULL;
-Monitor* ZF_mon = NULL;
-Monitor* Cleanup_mon = NULL;
Mutex* CMRegionStack_lock = NULL;
Mutex* SATB_Q_FL_lock = NULL;
Monitor* SATB_Q_CBL_mon = NULL;
@@ -122,6 +120,9 @@
Mutex* PerfDataManager_lock = NULL;
Mutex* OopMapCacheAlloc_lock = NULL;
+Mutex* FreeList_lock = NULL;
+Monitor* SecondaryFreeList_lock = NULL;
+Mutex* OldSets_lock = NULL;
Mutex* MMUTracker_lock = NULL;
Mutex* HotCardCache_lock = NULL;
@@ -177,8 +178,6 @@
}
if (UseG1GC) {
def(CMark_lock , Monitor, nonleaf, true ); // coordinate concurrent mark thread
- def(ZF_mon , Monitor, leaf, true );
- def(Cleanup_mon , Monitor, nonleaf, true );
def(CMRegionStack_lock , Mutex, leaf, true );
def(SATB_Q_FL_lock , Mutex , special, true );
def(SATB_Q_CBL_mon , Monitor, nonleaf, true );
@@ -188,6 +187,9 @@
def(DirtyCardQ_CBL_mon , Monitor, nonleaf, true );
def(Shared_DirtyCardQ_lock , Mutex, nonleaf, true );
+ def(FreeList_lock , Mutex, leaf , true );
+ def(SecondaryFreeList_lock , Monitor, leaf , true );
+ def(OldSets_lock , Mutex , leaf , true );
def(MMUTracker_lock , Mutex , leaf , true );
def(HotCardCache_lock , Mutex , special , true );
def(EvacFailureStack_lock , Mutex , nonleaf , true );
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -76,8 +76,6 @@
extern Monitor* iCMS_lock; // CMS incremental mode start/stop notification
extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc
extern Monitor* CMark_lock; // used for concurrent mark thread coordination
-extern Monitor* ZF_mon; // used for G1 conc zero-fill.
-extern Monitor* Cleanup_mon; // used for G1 conc cleanup.
extern Mutex* CMRegionStack_lock; // used for protecting accesses to the CM region stack
extern Mutex* SATB_Q_FL_lock; // Protects SATB Q
// buffer free list.
@@ -125,6 +123,9 @@
extern Mutex* ParkerFreeList_lock;
extern Mutex* OopMapCacheAlloc_lock; // protects allocation of oop_map caches
+extern Mutex* FreeList_lock; // protects the free region list during safepoints
+extern Monitor* SecondaryFreeList_lock; // protects the secondary free region list
+extern Mutex* OldSets_lock; // protects the old region sets
extern Mutex* MMUTracker_lock; // protects the MMU
// tracker data structures
extern Mutex* HotCardCache_lock; // protects the hot card cache
--- a/hotspot/src/share/vm/runtime/relocator.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/relocator.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -106,7 +106,7 @@
// get the address of in the code_array
inline char* addr_at(int bci) const { return (char*) &code_array()[bci]; }
- int instruction_length_at(int bci) { return Bytecodes::length_at(code_array() + bci); }
+ int instruction_length_at(int bci) { return Bytecodes::length_at(NULL, code_array() + bci); }
// Helper methods
int align(int n) const { return (n+3) & ~3; }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -944,9 +944,9 @@
int bci = vfst.bci();
// Find bytecode
- Bytecode_invoke* bytecode = Bytecode_invoke_at(caller, bci);
- bc = bytecode->java_code();
- int bytecode_index = bytecode->index();
+ Bytecode_invoke bytecode(caller, bci);
+ bc = bytecode.java_code();
+ int bytecode_index = bytecode.index();
// Find receiver for non-static call
if (bc != Bytecodes::_invokestatic) {
@@ -957,7 +957,7 @@
// Caller-frame is a compiled frame
frame callerFrame = stubFrame.sender(®_map2);
- methodHandle callee = bytecode->static_target(CHECK_(nullHandle));
+ methodHandle callee = bytecode.static_target(CHECK_(nullHandle));
if (callee.is_null()) {
THROW_(vmSymbols::java_lang_NoSuchMethodException(), nullHandle);
}
@@ -1674,10 +1674,9 @@
// Get target class name from the checkcast instruction
vframeStream vfst(thread, true);
assert(!vfst.at_end(), "Java frame must exist");
- Bytecode_checkcast* cc = Bytecode_checkcast_at(
- vfst.method()->bcp_from(vfst.bci()));
+ Bytecode_checkcast cc(vfst.method(), vfst.method()->bcp_from(vfst.bci()));
Klass* targetKlass = Klass::cast(vfst.method()->constants()->klass_at(
- cc->index(), thread));
+ cc.index(), thread));
return generate_class_cast_message(objName, targetKlass->external_name());
}
@@ -1711,11 +1710,11 @@
const char* targetType = "the required signature";
vframeStream vfst(thread, true);
if (!vfst.at_end()) {
- Bytecode_invoke* call = Bytecode_invoke_at(vfst.method(), vfst.bci());
+ Bytecode_invoke call(vfst.method(), vfst.bci());
methodHandle target;
{
EXCEPTION_MARK;
- target = call->static_target(THREAD);
+ target = call.static_target(THREAD);
if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; }
}
if (target.not_null()
--- a/hotspot/src/share/vm/runtime/thread.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -31,6 +31,7 @@
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
+#include "jvmtifiles/jvmtiEnv.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
@@ -977,6 +978,19 @@
}
#endif // KERNEL
+// General purpose hook into Java code, run once when the VM is initialized.
+// The Java library method itself may be changed independently from the VM.
+static void call_postVMInitHook(TRAPS) {
+ klassOop k = SystemDictionary::sun_misc_PostVMInitHook_klass();
+ instanceKlassHandle klass (THREAD, k);
+ if (klass.not_null()) {
+ JavaValue result(T_VOID);
+ JavaCalls::call_static(&result, klass, vmSymbolHandles::run_method_name(),
+ vmSymbolHandles::void_method_signature(),
+ CHECK);
+ }
+}
+
static void reset_vm_info_property(TRAPS) {
// the vm info string
ResourceMark rm(THREAD);
@@ -1699,7 +1713,7 @@
tlab().make_parsable(true); // retire TLAB
}
- if (jvmti_thread_state() != NULL) {
+ if (JvmtiEnv::environments_might_exist()) {
JvmtiExport::cleanup_thread(this);
}
@@ -3345,6 +3359,14 @@
BiasedLocking::init();
+ if (JDK_Version::current().post_vm_init_hook_enabled()) {
+ call_postVMInitHook(THREAD);
+ // The Java side of PostVMInitHook.run must deal with all
+ // exceptions and provide means of diagnosis.
+ if (HAS_PENDING_EXCEPTION) {
+ CLEAR_PENDING_EXCEPTION;
+ }
+ }
// Start up the WatcherThread if there are any periodic tasks
// NOTE: All PeriodicTasks should be registered by now. If they
--- a/hotspot/src/share/vm/runtime/thread.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -809,7 +809,7 @@
//
// _vm_exited is a special value to cover the case of a JavaThread
// executing native code after the VM itself is terminated.
- TerminatedTypes _terminated;
+ volatile TerminatedTypes _terminated;
// suspend/resume support
volatile bool _suspend_equivalent; // Suspend equivalent condition
jint _in_deopt_handler; // count of deoptimization
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -399,7 +399,7 @@
} else if (TraceDeoptimization) {
tty->print(" ");
method()->print_value();
- Bytecodes::Code code = Bytecodes::java_code_at(bcp);
+ Bytecodes::Code code = Bytecodes::java_code_at(method(), bcp);
int bci = method()->bci_from(bcp);
tty->print(" - %s", Bytecodes::name(code));
tty->print(" @ bci %d ", bci);
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -219,8 +219,8 @@
volatile_nonstatic_field(oopDesc, _metadata._compressed_klass, narrowOop) \
static_field(oopDesc, _bs, BarrierSet*) \
nonstatic_field(arrayKlass, _dimension, int) \
- nonstatic_field(arrayKlass, _higher_dimension, klassOop) \
- nonstatic_field(arrayKlass, _lower_dimension, klassOop) \
+ volatile_nonstatic_field(arrayKlass, _higher_dimension, klassOop) \
+ volatile_nonstatic_field(arrayKlass, _lower_dimension, klassOop) \
nonstatic_field(arrayKlass, _vtable_len, int) \
nonstatic_field(arrayKlass, _alloc_size, juint) \
nonstatic_field(arrayKlass, _component_mirror, oop) \
--- a/hotspot/src/share/vm/services/heapDumper.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/services/heapDumper.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -453,7 +453,7 @@
DumpWriter::~DumpWriter() {
// flush and close dump file
- if (file_descriptor() >= 0) {
+ if (is_open()) {
close();
}
if (_buffer != NULL) os::free(_buffer);
@@ -463,9 +463,10 @@
// closes dump file (if open)
void DumpWriter::close() {
// flush and close dump file
- if (file_descriptor() >= 0) {
+ if (is_open()) {
flush();
::close(file_descriptor());
+ set_file_descriptor(-1);
}
}
@@ -1935,18 +1936,32 @@
void HeapDumper::dump_heap(bool oome) {
static char base_path[JVM_MAXPATHLEN] = {'\0'};
static uint dump_file_seq = 0;
- char my_path[JVM_MAXPATHLEN] = {'\0'};
+ char* my_path;
+ const int max_digit_chars = 20;
+
+ const char* dump_file_name = "java_pid";
+ const char* dump_file_ext = ".hprof";
// The dump file defaults to java_pid<pid>.hprof in the current working
// directory. HeapDumpPath=<file> can be used to specify an alternative
// dump file name or a directory where dump file is created.
if (dump_file_seq == 0) { // first time in, we initialize base_path
+ // Calculate potentially longest base path and check if we have enough
+ // allocated statically.
+ const size_t total_length =
+ (HeapDumpPath == NULL ? 0 : strlen(HeapDumpPath)) +
+ strlen(os::file_separator()) + max_digit_chars +
+ strlen(dump_file_name) + strlen(dump_file_ext) + 1;
+ if (total_length > sizeof(base_path)) {
+ warning("Cannot create heap dump file. HeapDumpPath is too long.");
+ return;
+ }
+
bool use_default_filename = true;
if (HeapDumpPath == NULL || HeapDumpPath[0] == '\0') {
// HeapDumpPath=<file> not specified
} else {
- assert(strlen(HeapDumpPath) < sizeof(base_path), "HeapDumpPath too long");
- strcpy(base_path, HeapDumpPath);
+ strncpy(base_path, HeapDumpPath, sizeof(base_path));
// check if the path is a directory (must exist)
DIR* dir = os::opendir(base_path);
if (dir == NULL) {
@@ -1960,8 +1975,6 @@
char* end = base_path;
end += (strlen(base_path) - fs_len);
if (strcmp(end, os::file_separator()) != 0) {
- assert(strlen(base_path) + strlen(os::file_separator()) < sizeof(base_path),
- "HeapDumpPath too long");
strcat(base_path, os::file_separator());
}
}
@@ -1969,21 +1982,26 @@
}
// If HeapDumpPath wasn't a file name then we append the default name
if (use_default_filename) {
- char fn[32];
- sprintf(fn, "java_pid%d", os::current_process_id());
- assert(strlen(base_path) + strlen(fn) + strlen(".hprof") < sizeof(base_path), "HeapDumpPath too long");
- strcat(base_path, fn);
- strcat(base_path, ".hprof");
+ const size_t dlen = strlen(base_path); // if heap dump dir specified
+ jio_snprintf(&base_path[dlen], sizeof(base_path)-dlen, "%s%d%s",
+ dump_file_name, os::current_process_id(), dump_file_ext);
}
- assert(strlen(base_path) < sizeof(my_path), "Buffer too small");
- strcpy(my_path, base_path);
+ const size_t len = strlen(base_path) + 1;
+ my_path = (char*)os::malloc(len);
+ if (my_path == NULL) {
+ warning("Cannot create heap dump file. Out of system memory.");
+ return;
+ }
+ strncpy(my_path, base_path, len);
} else {
// Append a sequence number id for dumps following the first
- char fn[33];
- sprintf(fn, ".%d", dump_file_seq);
- assert(strlen(base_path) + strlen(fn) < sizeof(my_path), "HeapDumpPath too long");
- strcpy(my_path, base_path);
- strcat(my_path, fn);
+ const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0
+ my_path = (char*)os::malloc(len);
+ if (my_path == NULL) {
+ warning("Cannot create heap dump file. Out of system memory.");
+ return;
+ }
+ jio_snprintf(my_path, len, "%s.%d", base_path, dump_file_seq);
}
dump_file_seq++; // increment seq number for next time we dump
@@ -1991,4 +2009,5 @@
true /* send to tty */,
oome /* pass along out-of-memory-error flag */);
dumper.dump(my_path);
+ os::free(my_path);
}
--- a/hotspot/src/share/vm/utilities/debug.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/utilities/debug.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -34,6 +34,7 @@
class FormatBuffer {
public:
inline FormatBuffer(const char * format, ...);
+ inline void append(const char* format, ...);
operator const char *() const { return _buf; }
private:
@@ -51,6 +52,19 @@
va_end(argp);
}
+template <size_t bufsz>
+void FormatBuffer<bufsz>::append(const char* format, ...) {
+ // Given that the constructor does a vsnprintf we can assume that
+ // _buf is already initialized.
+ size_t len = strlen(_buf);
+ char* buf_end = _buf + len;
+
+ va_list argp;
+ va_start(argp, format);
+ vsnprintf(buf_end, bufsz - len, format, argp);
+ va_end(argp);
+}
+
// Used to format messages for assert(), guarantee(), fatal(), etc.
typedef FormatBuffer<> err_msg;
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1179,6 +1179,8 @@
// '%d' formats to indicate a 64-bit quantity; commonly "l" (in LP64) or "ll"
// (in ILP32).
+#define BOOL_TO_STR(__b) (__b) ? "true" : "false"
+
// Format 32-bit quantities.
#define INT32_FORMAT "%d"
#define UINT32_FORMAT "%u"
--- a/hotspot/src/share/vm/utilities/vmError.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -874,11 +874,13 @@
}
if (fd == -1) {
- // try temp directory
const char * tmpdir = os::get_temp_directory();
- jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
- tmpdir, os::file_separator(), os::current_process_id());
- fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ // try temp directory if it exists.
+ if (tmpdir != NULL && tmpdir[0] != '\0') {
+ jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log",
+ tmpdir, os::file_separator(), os::current_process_id());
+ fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ }
}
if (fd != -1) {
--- a/jaxp/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/jaxp/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,5 @@
e2aedea6495d61557326928de20dbb2d78fdd9aa jdk7-b123
57ed1f3bec72924cdad102f9bf90f7449ea7bb83 jdk7-b124
6c9bdee0cc3a8912acc5189cc092b8cba6851f9d jdk7-b125
+2fde639439c1fb3fbc44f533d48bb2916e813312 jdk7-b126
+c532d6dbc8d18d55b5d693599ee5cd8250e16eb4 jdk7-b127
--- a/jaxws/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/jaxws/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,5 @@
5a8e43bcce56b7cd5576419067a929b74575ae71 jdk7-b123
86f60e5b3975840968f3147ddce047a27a9fc83e jdk7-b124
d72eea121c3bc2b649272a37b80d9417855b7146 jdk7-b125
+6d772c5119d5e247bc98a57ce8b1be121554ee0a jdk7-b126
+ef19f173578c804772d586a959fa3ab8a12c0598 jdk7-b127
--- a/jdk/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,6 @@
869190935eedee7750d955019ab2a1b80f0a13a8 jdk7-b123
1c72adc9d5f331cb882cf5354ba0dcb118a60b23 jdk7-b124
0a56bdd709d01c1663047e55201d19152ffd3d69 jdk7-b125
+8361ef97a0f90086c9048beaf7cea1a37216c4cd jdk7-b126
+29e09de1d0b4f84faea114cf10b3ec08b59acc4e jdk7-b127
+f08682e23279d6cccbdcafda1eb0647ba4900874 jdk7-b128
--- a/jdk/make/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -100,7 +100,6 @@
DEVTOOLS_PATH.desc = Directory containing zip and unzip
CUPS_HEADERS_PATH.desc = Include directory location for CUPS header files
DXSDK_PATH.desc = Root directory of DirectX SDK
-MSVCRT_DLL_PATH.desc = Directory containing mscvrt.dll
# Make variables to print out (description and value)
VARIABLE_PRINTVAL_LIST += \
@@ -133,12 +132,10 @@
ifeq ($(PLATFORM), windows)
VARIABLE_PRINTVAL_LIST += \
- DXSDK_PATH \
- MSVCRT_DLL_PATH
+ DXSDK_PATH
VARIABLE_CHECKDIR_LIST += \
- DXSDK_PATH \
- MSVCRT_DLL_PATH
+ DXSDK_PATH
endif
--- a/jdk/make/com/sun/java/pack/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/com/sun/java/pack/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -155,6 +155,7 @@
$(MT) /manifest $(OBJDIR)/unpack200$(EXE_SUFFIX).manifest /outputresource:$(TEMPDIR)/unpack200$(EXE_SUFFIX);#1
endif
$(CP) $(TEMPDIR)/unpack200$(EXE_SUFFIX) $(UNPACK_EXE)
+ @$(call binary_file_verification,$@)
$(install-module-file)
ifeq ($(PLATFORM), windows)
--- a/jdk/make/common/Defs-linux.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Defs-linux.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -75,15 +75,6 @@
CC_PROGRAM_OUTPUT_FLAG = -o #trailing blank required!
#
-# Default HPI libraries. Build will build only native, unless
-# overriden at the make command line. This makes it convenient for
-# people doing, say, a pthreads port -- they can create a posix
-# directory here, and say "gnumake HPIS=posix" at the top
-# level.
-#
-HPIS = native
-
-#
# Default optimization
#
--- a/jdk/make/common/Defs-solaris.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Defs-solaris.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -75,15 +75,6 @@
CC_PROGRAM_OUTPUT_FLAG = -o #trailing blank required!
#
-# Default HPI libraries. Build will build only native unless
-# overriden at the make command line. This makes it convenient for
-# people doing, say, a pthreads port -- they can create a posix
-# directory here, and say "gnumake HPIS=posix" at the top
-# level.
-#
-HPIS = native
-
-#
# Java default optimization (-x04/-O2) etc. Applies to the VM.
#
ifndef OPTIMIZATION_LEVEL
--- a/jdk/make/common/Defs-windows.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Defs-windows.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -43,7 +43,6 @@
# The suffix applied to scripts (.bat for windows, nothing for unix)
SCRIPT_SUFFIX = .bat
-HPIS = windows
# LIB_LOCATION, which for windows identifies where .exe files go, may be
# set by each GNUmakefile. The default is BINDIR.
ifndef LIB_LOCATION
@@ -68,28 +67,27 @@
# The following DLL's are considered MS runtime libraries and should
# not to be REBASEd, see deploy/make/common/Release.gmk.
-# msvcrt.dll, msvcrnn.dll [msvcr71 or msvcr80 or msvcr90] : Microsoft runtimes
-MS_RUNTIME_LIBRARIES = msvcrt.dll
+# msvcr*.dll: Microsoft runtimes
ifeq ($(ARCH_DATA_MODEL), 32)
ifeq ($(COMPILER_VERSION), VS2003)
MSVCRNN_DLL = msvcr71.dll
MSVCPNN_DLL = msvcp71.dll
- MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL)
+ MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL)
endif
ifeq ($(COMPILER_VERSION), VS2005)
MSVCRNN_DLL = msvcr80.dll
MSVCPNN_DLL = msvcp80.dll
- MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL)
+ MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL)
endif
ifeq ($(COMPILER_VERSION), VS2008)
MSVCRNN_DLL = msvcr90.dll
MSVCPNN_DLL = msvcp90.dll
- MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL)
+ MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL)
endif
ifeq ($(COMPILER_VERSION), VS2010)
MSVCRNN_DLL = msvcr100.dll
MSVCPNN_DLL = msvcp100.dll
- MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL)
+ MS_RUNTIME_LIBRARIES = $(MSVCRNN_DLL)
endif
endif
@@ -97,12 +95,12 @@
ifeq ($(COMPILER_VERSION), VS2008)
MSVCRNN_DLL = msvcr90.dll
MSVCPNN_DLL = msvcp90.dll
- MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL)
+ MS_RUNTIME_LIBRARIES = msvcrt.dll $(MSVCRNN_DLL)
endif
ifeq ($(COMPILER_VERSION), VS2010)
MSVCRNN_DLL = msvcr100.dll
MSVCPNN_DLL = msvcp100.dll
- MS_RUNTIME_LIBRARIES += $(MSVCRNN_DLL)
+ MS_RUNTIME_LIBRARIES = $(MSVCRNN_DLL)
endif
endif
@@ -284,7 +282,7 @@
MS_RUNTIME_OPTION=-MTd
else
# This MS debugging flag forces a dependence on the debug
- # version of the runtime library (MSVCRTD.DLL), as does -MDd.
+ # version of the runtime library (MSVCR*D.DLL), as does -MDd.
# We cannot re-distribute this debug runtime.
MS_RUNTIME_OPTION=-MDd
endif
--- a/jdk/make/common/Defs.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Defs.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -271,10 +271,9 @@
# An attempt is made to generate unique enough directories for the
# generated files to not have name collisisons. Most build units
# defines PRODUCT (except Release.gmk), but then they may or may
-# not define PACKAGE, THREADIR (only HPI uses this), PROGRAM, and
-# LIBRARY. This code chunk attempts to generate a unique
-# OBJDIR/CLASSHDRDIR for each build unit based on which of those
-# values are set within each build unit.
+# not define PACKAGE, PROGRAM, and LIBRARY. This code attempts to
+# generate a unique OBJDIR/CLASSHDRDIR for each build unit based
+# on which of those values are set within each build unit.
UNIQUE_LOCATION_STRING = tmp
@@ -298,10 +297,6 @@
endif
endif
-ifneq ($(THREADDIR),)
- UNIQUE_LOCATION_STRING += /$(THREADDIR)
-endif
-
#
# Build units may or may not define MODULE. Default to "other".
#
--- a/jdk/make/common/Demo.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Demo.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -73,8 +73,11 @@
# Destination "src" directory
DEMO_BUILD_SRCDIR = $(DEMO_BUILD_AREA)/src
-DEMO_BUILD_SRCZIP = $(DEMO_BUILD_AREA)/src.zip
-DEMO_SOURCE_ZIP = $(DEMO_DESTDIR)/src.zip
+
+ifndef DEMO_SKIP_SRCZIP
+ DEMO_BUILD_SRCZIP = $(DEMO_BUILD_AREA)/src.zip
+ DEMO_SOURCE_ZIP = $(DEMO_DESTDIR)/src.zip
+endif
# Place to hold the jar image we are creating
DEMO_JAR_IMAGE = $(DEMO_BUILD_AREA)/jar_image
@@ -258,14 +261,16 @@
endif
-# Create a src.zip file
-$(DEMO_BUILD_SRCZIP): $(DEMO_FULL_SOURCES)
+ifndef DEMO_SKIP_SRCZIP
+ # Create a src.zip file
+ $(DEMO_BUILD_SRCZIP): $(DEMO_FULL_SOURCES)
@$(prep-target)
$(CD) $(DEMO_BUILD_AREA)/src && $(ZIPEXE) -q -r ../$(@F) .
-# Install the destination src.zip file and create the src tree
-$(DEMO_SOURCE_ZIP): $(DEMO_BUILD_SRCZIP)
+ # Install the destination src.zip file and create the src tree
+ $(DEMO_SOURCE_ZIP): $(DEMO_BUILD_SRCZIP)
$(install-file)
+endif
# Native library building
ifdef DEMO_LIBRARY
@@ -289,6 +294,7 @@
@$(prep-target)
$(LINK.demo) $(SHARED_LIBRARY_FLAG) $(CC_PROGRAM_OUTPUT_FLAG)$@ \
$(DEMO_FULL_OBJECTS) $(LDLIBS.demo)
+ @$(call binary_file_verification,$@)
# Generation of any javah include file, make sure objects are dependent on it
ifdef DEMO_NATIVECLASS
@@ -362,7 +368,7 @@
$(RM) -r $(DEMO_BUILD_AREA)
$(RM) -r $(DEMO_DESTDIR)
-# This should not be needed, but some versions of GNU amke have a bug that
+# This should not be needed, but some versions of GNU make have a bug that
# sometimes deleted these files for some strange and unknown reason
# (GNU make version 3.78.1 has the problem, GNU make version 3.80 doesn't?)
.PRECIOUS: $(DEMO_FULL_SOURCES) $(DEMO_BUILD_SRCZIP) $(DEMO_SOURCE_ZIP)
--- a/jdk/make/common/Library.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Library.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -167,6 +167,7 @@
$(LFLAGS) @$(OBJDIR)/$(LIBRARY).lcf \
$(OTHER_LCF) $(JAVALIB) $(LDLIBS)
$(CP) $(OBJDIR)/$(@F) $@
+ @$(call binary_file_verification,$@)
$(install-module-file)
$(CP) $(OBJDIR)/$(LIBRARY).map $(@D)
$(CP) $(OBJDIR)/$(LIBRARY).pdb $(@D)
@@ -233,6 +234,7 @@
$(AR) -r $@ $(FILES_o)
else # LIBRARY
$(LINKER) $(SHARED_LIBRARY_FLAG) -o $@ $(FILES_o) $(LDLIBS)
+ @$(call binary_file_verification,$@)
$(install-module-file)
ifeq ($(WRITE_LIBVERSION),true)
$(MCS) -d -a "$(FULL_VERSION)" $@
--- a/jdk/make/common/Modules.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Modules.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -73,47 +73,20 @@
#
# Paths to these files we need
-JDK_MODULE_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
-JDK_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%64)
-JDK_MODULE_DOCFILES = $(OTHER_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
-
-JRE_MODULE_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
-JRE_MODULE_64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%64)
-JRE_MODULE_DOCFILES = $(OTHER_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
-JRE_MODULE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX))
+JDK_MODULE_DOCFILES = $(IMAGE_DOCLIST_JDK:%=$(JDK_MODULE_IMAGE_DIR)/%)
+JRE_MODULE_DOCFILES = $(IMAGE_DOCLIST_JRE:%=$(JRE_MODULE_IMAGE_DIR)/%)
###### RULES
# JDK files
$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%
$(process-doc-file)
-# Removes LICENSE_VERSION or not
-ifdef LICENSE_VERSION
-$(JDK_MODULE_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-else
-$(JDK_MODULE_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%
- $(process-doc-file)
-endif
# JRE files
$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%
$(process-doc-file)
-# Add $(TEXT_SUFFIX) suffix
-ifdef TEXT_SUFFIX
-$(JRE_MODULE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/%
- $(process-doc-file)
-endif
-# Removes LICENSE_VERSION or not
-ifdef LICENSE_VERSION
-$(JRE_MODULE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-else
-$(JRE_MODULE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%
+ifeq ($(PLATFORM), windows)
+$(JRE_MODULE_IMAGE_DIR)/README.txt: $(SHARE_JRE_DOC_SRC)/README
$(process-doc-file)
endif
@@ -157,8 +130,7 @@
$(MKDIR) -p $(JRE_MODULE_IMAGE_DIR)
# 64-bit solaris jre image contains only the 64-bit add-on files.
-initial-module-image-jre-sol64:: initial-module-image-jre-setup \
- $(JRE_MODULE_LICENSES) $(JRE_MODULE_64_LICENSES)
+initial-module-image-jre-sol64:: initial-module-image-jre-setup
@# Use tar instead of cp to preserve the symbolic links
for dir in bin lib ; do \
( $(CD) $(OUTPUTDIR) && \
@@ -174,7 +146,7 @@
# Construct an initial jre image (initial jdk jre) no trimming or stripping
initial-module-image-jre:: initial-module-image-jre-setup \
- $(JRE_LICENSES) $(JRE_MODULE_DOCFILES) \
+ $(JRE_MODULE_DOCFILES) \
$(BUILDMETAINDEX_JARFILE)
@# Copy in bin directory
$(CD) $(OUTPUTDIR) && $(FIND) bin -depth | $(CPIO) -pdum $(JRE_MODULE_IMAGE_DIR)
@@ -222,7 +194,7 @@
@# Remove certain *.lib files
$(CD) $(JRE_MODULE_IMAGE_DIR)/lib && \
$(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \
- hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX)
+ awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX)
ifeq ($(ARCH_DATA_MODEL), 32)
@# The Java Kernel JRE image ships with a special VM. It is not included
@# in the full JRE image, so remove it. Also, is it only for 32-bit windows.
@@ -310,8 +282,7 @@
# Solaris 64 bit image is special
initial-module-image-jdk-sol64:: initial-module-image-jdk-setup \
- initial-module-image-jdk64-bindemos \
- $(JDK_MODULE_LICENSES) $(JDK_MODULARLIZED_64_LICENSES)
+ initial-module-image-jdk64-bindemos
# DB files to add
ifeq ($(OPENJDK),true)
@@ -335,7 +306,7 @@
# Standard jdk image
initial-module-image-jdk:: initial-module-image-jdk-setup \
initial-module-image-jdk-db \
- $(JDK_MODULE_LICENSES) $(JDK_MODULE_DOCFILES)
+ $(JDK_MODULE_DOCFILES)
$(MKDIR) $(JDK_MODULE_IMAGE_DIR)/lib
@#
@# copy jdk modules to jdk/lib
@@ -415,8 +386,7 @@
trim-module-image-jdk::
@# Remove tools that should not be part of SDK.
for t in $(NOTJDKTOOLS); do \
- $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \
- $(JDK_MODULE_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \
+ $(RM) $(JDK_MODULE_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX); \
done
# Get list of Elf files in the jdk
--- a/jdk/make/common/Program.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Program.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -160,6 +160,7 @@
ifdef MT
$(MT) /manifest $(OBJDIR)/$(PROGRAM).exe.manifest /outputresource:$@;#1
endif
+ @$(call binary_file_verification,$@)
else # PLATFORM
@@ -184,6 +185,7 @@
@$(MKDIR) -p $(TEMPDIR)
$(LINK_PRE_CMD) $(CC) $(CC_OBJECT_OUTPUT_FLAG)$@ $(LDFLAGS) \
$(FILES_o) $(THREADLIBS) $(LDLIBS)
+ @$(call binary_file_verification,$@)
$(install-module-file)
endif # PLATFORM
--- a/jdk/make/common/Release.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/Release.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -26,6 +26,9 @@
include $(JDK_TOPDIR)/make/docs/CORE_PKGS.gmk
include $(JDK_TOPDIR)/make/docs/NON_CORE_PKGS.gmk
+# What jdk version are we building
+THIS_JDK_VERSION := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION)
+
#
# Perform release engineering tasks.
#
@@ -72,14 +75,6 @@
JTG_DOCS = $(JDK_TOPDIR)/src/solaris/doc
-#We use this for man page header
-jdkversion := $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION)
-
-# Text documents on windows use this suffix
-ifeq ($(PLATFORM), windows)
- TEXT_SUFFIX = .txt
-endif
-
# The base names of all the license and document files for the jdk and jre
# (These files get placed in the jdk and jre install images)
ifdef OPENJDK
@@ -87,53 +82,28 @@
SHARE_JDK_DOC_SRC = $(JDK_TOPDIR)
SHARE_JRE_DOC_SRC = $(JDK_TOPDIR)
# Same files for jdk and jre, no name changes
- LICENSE_DOCLIST_JDK = LICENSE ASSEMBLY_EXCEPTION
- LICENSE_DOCLIST_JRE = LICENSE ASSEMBLY_EXCEPTION
- OTHER_DOCLIST_JDK = THIRD_PARTY_README
- OTHER_DOCLIST_JRE = THIRD_PARTY_README
+ IMAGE_DOCLIST_JDK = LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README
+ IMAGE_DOCLIST_JRE = LICENSE ASSEMBLY_EXCEPTION THIRD_PARTY_README
else
# Where to find these files
SHARE_JDK_DOC_SRC = $(CLOSED_SHARE_SRC)/doc/jdk
SHARE_JRE_DOC_SRC = $(CLOSED_SHARE_SRC)/doc/jre
- # Select the pre-release or FCS license version based on the build milestone.
- LICENSE_VERSION=.pre
- ifeq ($(MILESTONE), fcs)
- LICENSE_VERSION=.fcs
- endif
+ IMAGE_DOCLIST_JDK = COPYRIGHT README.html THIRDPARTYLICENSEREADME.txt
+ IMAGE_DOCLIST_JRE = COPYRIGHT Welcome.html THIRDPARTYLICENSEREADME.txt
ifeq ($(PLATFORM), windows)
- LICENSE_DOCLIST_JDK = $(subst $(LICENSE_VERSION),,\
- $(shell $(CD) $(SHARE_JDK_DOC_SRC) && \
- $(LS) *LICENSE*$(LICENSE_VERSION)))
- LICENSE_DOCLIST_JRE = $(subst $(LICENSE_VERSION),,\
- $(shell $(CD) $(SHARE_JRE_DOC_SRC) && \
- $(LS) *LICENSE*$(LICENSE_VERSION)))
+ IMAGE_DOCLIST_JRE += README.txt
else
- LICENSE_DOCLIST_JDK = $(subst $(LICENSE_VERSION),,\
- $(shell $(CD) $(SHARE_JDK_DOC_SRC) && \
- $(LS) *LICENSE*$(LICENSE_VERSION) | $(GREP) -v rtf))
- LICENSE_DOCLIST_JRE = $(subst $(LICENSE_VERSION),,\
- $(shell $(CD) $(SHARE_JRE_DOC_SRC) && \
- $(LS) *LICENSE*$(LICENSE_VERSION) | $(GREP) -v rtf))
+ IMAGE_DOCLIST_JRE += README
endif
- OTHER_DOCLIST_JDK = COPYRIGHT README.html README_ja.html README_zh_CN.html
- OTHER_DOCLIST_JRE = COPYRIGHT Welcome.html
- JRE_NAMECHANGE_DOCLIST = README
endif
# Paths to these files we need
-JDK_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%)
-JDK64_LICENSES = $(LICENSE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%64)
-JDK_DOCFILES = $(OTHER_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%)
-
-JRE_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%)
-JRE64_LICENSES = $(LICENSE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%64)
-JRE_DOCFILES = $(OTHER_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%)
-JRE_DOCFILES += $(JRE_NAMECHANGE_DOCLIST:%=$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX))
+JDK_DOCFILES = $(IMAGE_DOCLIST_JDK:%=$(JDK_IMAGE_DIR)/%)
+JRE_DOCFILES = $(IMAGE_DOCLIST_JRE:%=$(JRE_IMAGE_DIR)/%)
# absolute directory names: note, these must exist prior to build
# time - they are created in the main Makefile.
JRE_IMAGE_BINDIR = $(JRE_IMAGE_DIR)/bin
-JRE_IMAGE_THREADIR = $(JRE_IMAGE_DIR)/bin/*/native_threads
MAINMANIFEST = $(JDK_TOPDIR)/make/tools/manifest.mf
BEANMANIFEST = $(JDK_TOPDIR)/make/javax/swing/beaninfo/manifest
@@ -214,7 +184,7 @@
$(MKDIR) -p $1/man/$${ja_dir}/man1; \
$(CAT) $${manbase}/ja/$${manpage} \
| $(NATIVE2ASCII) -encoding $(JA_SOURCE_ENCODING) \
- | $(SED) 's/@@VERSION@@/$(jdkversion)/g' \
+ | $(SED) 's/@@VERSION@@/$(THIS_JDK_VERSION)/g' \
| $(NATIVE2ASCII) -reverse -encoding $${ja_encoding} \
> $1/man/$${ja_dir}/man1/$${manpage}; \
done; \
@@ -244,6 +214,7 @@
initial-image-jre initial-image-jdk \
initial-image-jre-sol64 initial-image-jdk-sol64 \
trim-image-jre trim-image-jdk \
+identify-image-jre identify-image-jdk \
process-image-jre process-image-jdk \
compare-image \
sec-files sec-files-win jgss-files ::
@@ -253,11 +224,12 @@
images:: sanity-images post-sanity-images \
$(INITIAL_IMAGE_JRE) $(INITIAL_IMAGE_JDK) \
trim-image-jre trim-image-jdk \
+ identify-image-jre identify-image-jdk \
process-image-jre process-image-jdk sec-files sec-files-win jgss-files
# Don't use these
-image-jre:: initial-image-jre trim-image-jre process-image-jre
-image-jdk:: initial-image-jdk trim-image-jdk process-image-jdk
+image-jre:: initial-image-jre trim-image-jre identify-image-jre process-image-jre
+image-jdk:: initial-image-jdk trim-image-jdk identify-image-jdk process-image-jdk
#
# Sources we ship in the SDK.
@@ -504,33 +476,12 @@
# JDK files
$(JDK_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%
$(process-doc-file)
-# Removes LICENSE_VERSION or not
-ifdef LICENSE_VERSION
-$(JDK_IMAGE_DIR)/%: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-$(JDK_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-else
-$(JDK_IMAGE_DIR)/%64: $(SHARE_JDK_DOC_SRC)/%
- $(process-doc-file)
-endif
# JRE files
$(JRE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%
$(process-doc-file)
-# Add $(TEXT_SUFFIX) suffix
-ifdef TEXT_SUFFIX
-$(JRE_IMAGE_DIR)/%$(TEXT_SUFFIX): $(SHARE_JRE_DOC_SRC)/%
- $(process-doc-file)
-endif
-# Removes LICENSE_VERSION or not
-ifdef LICENSE_VERSION
-$(JRE_IMAGE_DIR)/%: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-$(JRE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%$(LICENSE_VERSION)
- $(process-doc-file)
-else
-$(JRE_IMAGE_DIR)/%64: $(SHARE_JRE_DOC_SRC)/%
+ifeq ($(PLATFORM), windows)
+$(JRE_IMAGE_DIR)/README.txt: $(SHARE_JRE_DOC_SRC)/README
$(process-doc-file)
endif
@@ -738,8 +689,7 @@
$(MKDIR) -p $(JRE_IMAGE_DIR)
# 64-bit solaris jre image contains only the 64-bit add-on files.
-initial-image-jre-sol64:: initial-image-jre-setup \
- $(JRE_LICENSES) $(JRE64_LICENSES)
+initial-image-jre-sol64:: initial-image-jre-setup
@# Use tar instead of cp to preserve the symbolic links
for dir in bin lib ; do \
( $(CD) $(OUTPUTDIR) && \
@@ -760,7 +710,7 @@
# See "initial-image-jdk-setup" for an explanation of the rm of
# drive names like C:
initial-image-jre:: initial-image-jre-setup \
- $(JRE_LICENSES) $(JRE_DOCFILES) \
+ $(JRE_DOCFILES) \
$(RT_JAR) $(RESOURCES_JAR) $(JSSE_JAR) \
$(BUILDMETAINDEX_JARFILE)
@# Copy in bin directory
@@ -802,7 +752,7 @@
@# Remove certain *.lib files
$(CD) $(JRE_IMAGE_DIR)/lib && \
$(RM) java.$(LIB_SUFFIX) jvm.$(LIB_SUFFIX) \
- hpi.$(LIB_SUFFIX) awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX)
+ awt.$(LIB_SUFFIX) jawt.$(LIB_SUFFIX)
ifeq ($(ARCH_DATA_MODEL), 32)
@# The Java Kernel JRE image ships with a special VM. It is not included
@# in the full JRE image, so remove it. Also, is it only for 32-bit windows.
@@ -836,11 +786,14 @@
endif
endif # PLATFORM
-# Get list of all Elf files in the jre
-JRE_ELF_LIST=$(TEMPDIR)/jre-elf-files.list
-$(JRE_ELF_LIST):
-ifneq ($(PLATFORM), windows)
+# Get list of all binary (COFF or Elf) files in the jre
+JRE_BIN_LIST=$(TEMPDIR)/jre-bin-files.list
+$(JRE_BIN_LIST):
$(RM) $@
+ifeq ($(PLATFORM), windows)
+ $(FIND) $(JRE_IMAGE_DIR)/bin -type f -name \*.exe \
+ -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" > $@
+else
$(FIND) $(JRE_IMAGE_DIR)/lib -type f -name \*.$(LIB_SUFFIX) >> $@
$(FILE) `$(FIND) $(JRE_IMAGE_DIR)/bin -type f -name \*$(EXE_SUFFIX)` \
| $(EGREP) 'ELF' | $(CUT) -d':' -f1 >> $@
@@ -848,9 +801,9 @@
# Post process the image (strips and mcs on Elf files we are shipping)
# (Note the jdk WILL want the jre image before this processing)
-process-image-jre:: $(JRE_ELF_LIST)
+process-image-jre:: $(JRE_BIN_LIST)
ifneq ($(POST_STRIP_PROCESS), )
- for f in `$(CAT) $(JRE_ELF_LIST)`; do \
+ @for f in `$(CAT) $(JRE_BIN_LIST)`; do \
$(CHMOD) u+w $${f}; \
$(ECHO) $(POST_STRIP_PROCESS) $${f}; \
$(POST_STRIP_PROCESS) $${f}; \
@@ -858,14 +811,17 @@
done
endif
ifneq ($(POST_MCS_PROCESS), )
- for f in `$(CAT) $(JRE_ELF_LIST)`; do \
+ @for f in `$(CAT) $(JRE_BIN_LIST)`; do \
$(CHMOD) u+w $${f}; \
$(ECHO) $(POST_MCS_PROCESS) $${f}; \
$(POST_MCS_PROCESS) $${f}; \
$(CHMOD) go-w $${f}; \
done
endif
- $(RM) $(JRE_ELF_LIST)
+ @for f in `$(CAT) $(JRE_BIN_LIST)`; do \
+ $(call binary_file_verification,$${f}); \
+ done
+ $(RM) $(JRE_BIN_LIST)
######################################################
# JDK Image
@@ -905,8 +861,7 @@
# Solaris 64 bit image is special
initial-image-jdk-sol64:: initial-image-jdk-setup \
- initial-image-jdk64-bindemos \
- $(JDK_LICENSES) $(JDK64_LICENSES)
+ initial-image-jdk64-bindemos
# DB files to add
ifdef OPENJDK
@@ -930,7 +885,7 @@
# Standard jdk image
initial-image-jdk:: initial-image-jdk-setup \
initial-image-jdk-db \
- $(JDK_LICENSES) $(JDK_DOCFILES)
+ $(JDK_DOCFILES)
$(MKDIR) $(JDK_IMAGE_DIR)/lib
@#
@# Copy in the jars in lib that only belong in the JDK
@@ -1089,14 +1044,18 @@
trim-image-jdk::
@# Remove tools that should not be part of SDK.
for t in $(NOTJDKTOOLS); do \
- $(RM) $(JDK_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX) \
- $(JDK_IMAGE_DIR)/bin/*/native_threads/$${t}$(EXE_SUFFIX); \
+ $(RM) $(JDK_IMAGE_DIR)/bin/$${t}$(EXE_SUFFIX); \
done
-# Get list of Elf files in the jdk
-JDK_ELF_LIST=$(TEMPDIR)/jdk-elf-files.list
-$(JDK_ELF_LIST):
-ifneq ($(PLATFORM), windows)
+# Get list of binary (COFF or Elf) files in the jdk
+JDK_BIN_LIST=$(TEMPDIR)/jdk-bin-files.list
+$(JDK_BIN_LIST):
+ifeq ($(PLATFORM), windows)
+ $(FIND) $(JDK_IMAGE_DIR)/jre/bin -type f -name \*.exe \
+ -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" > $@
+ $(FIND) $(JDK_IMAGE_DIR)/bin -type f -name \*.exe \
+ -o -name \*.dll | $(EGREP) -v -i "$(MSVCRNN_DLL)" >> $@
+else
$(RM) $@
$(FIND) $(JDK_IMAGE_DIR)/jre/lib -type f -name \*.$(LIB_SUFFIX) >> $@
$(FILE) `$(FIND) $(JDK_IMAGE_DIR)/jre/bin -type f -name \*$(EXE_SUFFIX)` \
@@ -1106,9 +1065,9 @@
endif
# Post process the image (strips and mcs on files we are shipping)
-process-image-jdk:: $(JDK_ELF_LIST)
+process-image-jdk:: $(JDK_BIN_LIST)
ifneq ($(POST_STRIP_PROCESS), )
- for f in `$(CAT) $(JDK_ELF_LIST)`; do \
+ @for f in `$(CAT) $(JDK_BIN_LIST)`; do \
$(CHMOD) u+w $${f}; \
$(ECHO) $(POST_STRIP_PROCESS) $${f}; \
$(POST_STRIP_PROCESS) $${f}; \
@@ -1116,14 +1075,56 @@
done
endif
ifneq ($(POST_MCS_PROCESS), )
- for f in `$(CAT) $(JDK_ELF_LIST)`; do \
+ @for f in `$(CAT) $(JDK_BIN_LIST)`; do \
$(CHMOD) u+w $${f}; \
$(ECHO) $(POST_MCS_PROCESS) $${f}; \
$(POST_MCS_PROCESS) $${f}; \
$(CHMOD) go-w $${f}; \
done
endif
- $(RM) $(JDK_ELF_LIST)
+ @for f in `$(CAT) $(JDK_BIN_LIST)`; do \
+ $(call binary_file_verification,$${f}); \
+ done
+ $(RM) $(JDK_BIN_LIST)
+
+###################################################################
+# What did we build
+###################################################################
+
+# The jdk text info file that lives at the root of the install image.
+
+JDK_INFO_FILE = $(JDK_IMAGE_DIR)/release
+JRE_INFO_FILE = $(JRE_IMAGE_DIR)/release
+
+# Common way to emit a line into the release or info file
+define info-file-item # name value
+$(PRINTF) "%s=\"%s\"\n" $1 $2 >> $@
+endef
+
+# Values to emit
+MINIMUM_OS_NAME := $(REQUIRED_OS_NAME)
+MINIMUM_OS_VERSION := $(REQUIRED_OS_VERSION)
+MINIMUM_OS_ARCH := $(ARCH)
+
+$(JDK_INFO_FILE): FRC
+ $(prep-target)
+ $(call info-file-item, "JAVA_VERSION", "$(THIS_JDK_VERSION)")
+ $(call info-file-item, "OS_NAME", "$(MINIMUM_OS_NAME)")
+ $(call info-file-item, "OS_VERSION", "$(MINIMUM_OS_VERSION)")
+ $(call info-file-item, "OS_ARCH", "$(MINIMUM_OS_ARCH)")
+
+# Create release file to identify this image
+identify-image-jdk:: $(JDK_INFO_FILE)
+
+$(JRE_INFO_FILE): FRC
+ $(prep-target)
+ $(call info-file-item, "JAVA_VERSION", "$(THIS_JDK_VERSION)")
+ $(call info-file-item, "OS_NAME", "$(MINIMUM_OS_NAME)")
+ $(call info-file-item, "OS_VERSION", "$(MINIMUM_OS_VERSION)")
+ $(call info-file-item, "OS_ARCH", "$(MINIMUM_OS_ARCH)")
+
+# Create release file to identify this image
+identify-image-jre:: $(JRE_INFO_FILE)
###################################################################
# What do we compare against
@@ -1278,6 +1279,7 @@
initial-image-jre-setup \
trim-image-jre trim-image-jdk \
process-image-jre process-image-jdk \
+ identify-image-jre identify-image-jdk \
install-previous-jre install-previous-jdk \
compare-image-jre compare-image-jdk \
compare-image compare-image-clobber \
--- a/jdk/make/common/shared/Compiler-msvc.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Compiler-msvc.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -35,6 +35,7 @@
LIBEXE = $(COMPILER_PATH)lib
LINK = $(COMPILER_PATH)link
LINK32 = $(LINK)
+ DUMPBIN = $(COMPILER_PATH)dumpbin.exe
# Fill in unknown values
COMPILER_NAME=Unknown MSVC Compiler
@@ -139,8 +140,8 @@
_OTHER_TOOLS_BIN = $(WINDOWSSDKDIR)/Bin/x64
endif
endif
- RC = $(_OTHER_TOOLS_BIN)/rc.exe
- REBASE = $(_OTHER_TOOLS_BIN)/rebase.exe
+ RC = $(_OTHER_TOOLS_BIN)/RC.Exe
+ REBASE = $(_OTHER_TOOLS_BIN)/ReBase.Exe
MT = $(_OTHER_TOOLS_BIN)/mt.exe
MTL = $(_OTHER_TOOLS_BIN)/midl.exe
endif
--- a/jdk/make/common/shared/Defs-control.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Defs-control.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -76,12 +76,9 @@
ABS_SRC_BUNDLEDIR = $(ABS_OUTPUTDIR)/source-bundles
BIN_BUNDLEDIR = $(OUTPUTDIR)/bundles
ABS_BIN_BUNDLEDIR = $(ABS_OUTPUTDIR)/bundles
-JRL_BUNDLEDIR = $(OUTPUTDIR)/java.net
-ABS_JRL_BUNDLEDIR = $(ABS_OUTPUTDIR)/java.net
dummy := $(shell $(MKDIR) -p $(BIN_BUNDLEDIR))
dummy := $(shell $(MKDIR) -p $(SRC_BUNDLEDIR) )
-dummy := $(shell $(MKDIR) -p $(JRL_BUNDLEDIR) )
TEMP_DIR = $(OUTPUTDIR)/tmp
ABS_TEMP_DIR = $(ABS_OUTPUTDIR)/tmp
--- a/jdk/make/common/shared/Defs-linux.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Defs-linux.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -177,3 +177,20 @@
endif
HOTSPOT_SERVER_PATH:=$(call AltCheckValue,HOTSPOT_SERVER_PATH)
+# Special define for checking the binaries
+
+# Macro to check it's input file for banned dependencies and verify the
+# binary built properly. Relies on process exit code.
+define binary_file_verification # binary_file
+( \
+ $(ECHO) "Checking for mapfile use in: $1" && \
+ if [ "`$(NM) -D -g --defined-only $1 | $(EGREP) 'SUNWprivate'`" = "" ] ; then \
+ $(ECHO) "WARNING: File was not built with a mapfile: $1"; \
+ fi && \
+ $(ECHO) "Library loads for: $1" && \
+ $(LDD) $1 && \
+ $(ECHO) "RUNPATH for: $1" && \
+ ( $(READELF) -d $1 | $(EGREP) 'NEEDED|RUNPATH|RPATH' ) \
+)
+endef
+
--- a/jdk/make/common/shared/Defs-solaris.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Defs-solaris.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -186,3 +186,20 @@
endif
HOTSPOT_SERVER_PATH:=$(call AltCheckValue,HOTSPOT_SERVER_PATH)
+# Special define for checking the binaries
+
+# Macro to check it's input file for banned dependencies and verify the
+# binary built properly. Relies on process exit code.
+define binary_file_verification # binary_file
+( \
+ $(ECHO) "Checking for mapfile use in: $1" && \
+ if [ "`$(NM) -g -D $1 | $(EGREP) -v 'UNDEF' | $(EGREP) 'SUNWprivate'`" = "" ] ; then \
+ $(ECHO) "WARNING: File was not built with a mapfile: $1"; \
+ fi && \
+ $(ECHO) "Library loads for: $1" && \
+ $(LDD) $1 && \
+ $(ECHO) "RUNPATH for: $1" && \
+ ( $(DUMP) -L -v $1 | $(EGREP) 'NEEDED|RUNPATH|RPATH' ) \
+)
+endef
+
--- a/jdk/make/common/shared/Defs-utils.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Defs-utils.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -85,6 +85,7 @@
DF = $(UTILS_COMMAND_PATH)df
DIFF = $(UTILS_USR_BIN_PATH)diff
DIRNAME = $(UTILS_USR_BIN_PATH)dirname
+DUMP = $(UTILS_CCS_BIN_PATH)dump
ECHO = $(UTILS_COMMAND_PATH)echo
EGREP = $(UTILS_COMMAND_PATH)egrep
EXPR = $(UTILS_USR_BIN_PATH)expr
@@ -99,6 +100,7 @@
ISAINFO = $(UTILS_COMMAND_PATH)isainfo
KSH = $(UTILS_COMMAND_PATH)ksh
LD = $(UTILS_CCS_BIN_PATH)ld
+LDD = $(UTILS_USR_BIN_PATH)ldd
LEX = $(UTILS_CCS_BIN_PATH)lex
LN = $(UTILS_COMMAND_PATH)ln
LS = $(UTILS_COMMAND_PATH)ls
@@ -114,6 +116,7 @@
PRINTF = $(UTILS_USR_BIN_PATH)printf
PWD = $(UTILS_COMMAND_PATH)pwd
RC = $(UTILS_COMMAND_PATH)rc
+READELF = $(UTILS_USR_BIN_PATH)readelf
RMDIR = $(UTILS_COMMAND_PATH)rmdir
RPM = $(UTILS_COMMAND_PATH)rpm
RPMBUILD = $(UTILS_COMMAND_PATH)rpmbuild
--- a/jdk/make/common/shared/Defs-versions.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Defs-versions.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -127,6 +127,7 @@
# Solaris specific
ifeq ($(PLATFORM), solaris)
+ REQUIRED_OS_NAME = SunOS
REQUIRED_OS_VERSION = 5.10
REQUIRED_OS_VARIANT_NAME = Solaris
REQUIRED_OS_VARIANT_VERSION = $(REQUIRED_OS_VERSION)
@@ -148,6 +149,7 @@
# Linux specific
ifeq ($(PLATFORM), linux)
+ REQUIRED_OS_NAME = Linux
REQUIRED_OS_VERSION = 2.6
REQUIRED_OS_VARIANT_NAME = Fedora
REQUIRED_OS_VARIANT_VERSION = 9
@@ -166,6 +168,7 @@
# Windows specific
ifeq ($(PLATFORM), windows)
+ REQUIRED_OS_NAME = Windows
ifeq ($(ARCH_DATA_MODEL),64)
REQUIRED_OS_VERSION = 5.2
REQUIRED_OS_VARIANT_NAME = Windows2003
--- a/jdk/make/common/shared/Defs-windows.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Defs-windows.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -288,8 +288,8 @@
xVS100COMNTOOLS :="$(_program_files32)/Microsoft Visual Studio 10.0/Common7/Tools/"
fVS100COMNTOOLS :=$(call FullPath,$(xVS100COMNTOOLS))
else
+ xVS100COMNTOOLS :="$(subst \,/,$(VS100COMNTOOLS))"
ifneq ($(word 2,$(VS100COMNTOOLS)),)
- xVS100COMNTOOLS :="$(subst \,/,$(VS100COMNTOOLS))"
fVS100COMNTOOLS :=$(call FullPath,$(xVS100COMNTOOLS))
else
fVS100COMNTOOLS :=$(xVS100COMNTOOLS)
@@ -551,18 +551,6 @@
_BOOTDIR3 =$(SLASH_JAVA)/re/jdk/$(PREVIOUS_JDK_VERSION)/archive/fcs/binaries/$(PLATFORM)-$(ARCH)
endif
-# 32 bit always needs 2 runtimes, 64 bit usually does too
-
-# MSVCRT_DLL_PATH: location of msvcrt.dll that will be re-distributed
-ifdef ALT_MSVCRT_DLL_PATH
- xALT_MSVCRT_DLL_PATH :="$(subst \,/,$(ALT_MSVCRT_DLL_PATH))"
- MSVCRT_DLL_PATH :=$(call FullPath,$(xALT_MSVCRT_DLL_PATH))
-else
- MSVCRT_DLL_PATH :=$(call FullPath,$(_system_root)/system32/)
-endif
-MSVCRT_DLL_PATH:=$(call AltCheckSpaces,MSVCRT_DLL_PATH)
-MSVCRT_DLL_PATH:=$(call AltCheckValue,MSVCRT_DLL_PATH)
-
# 32bit always needs the MSVCRNN runtime, 64bit does when using VS2008
ifeq ($(ARCH_DATA_MODEL), 32)
_NEEDS_MSVCRNN = true
@@ -641,15 +629,6 @@
endif
INSTALL_MSSDK:=$(call AltCheckSpaces,INSTALL_MSSDK)
-# INSTALL_MSIVAL2: Installation of MsiVal2 for this platform (for install)
-ifdef ALT_INSTALL_MSIVAL2
- xALT_INSTALL_MSIVAL2 :="$(subst \,/,$(ALT_INSTALL_MSIVAL2))"
- INSTALL_MSIVAL2 :=$(call FullPath,$(xALT_INSTALL_MSIVAL2))
-else
- INSTALL_MSIVAL2 :=$(_program_files32)/MsiVal2
-endif
-INSTALL_MSIVAL2:=$(call AltCheckSpaces,INSTALL_MSIVAL2)
-
# WSCRIPT: path to wscript.exe (used in creating install bundles)
ifdef ALT_WSCRIPT
xALT_WSCRIPT :="$(subst \,/,$(ALT_WSCRIPT))"
@@ -685,43 +664,6 @@
endif
CABARC:=$(call AltCheckSpaces,CABARC)
-# MSIVAL2: path to msival2.exe (used in validating install msi files)
-ifdef ALT_MSIVAL2
- xALT_MSIVAL2 :="$(subst \,/,$(ALT_MSIVAL2))"
- MSIVAL2 =$(xALT_MSIVAL2)
-else
- _MSIVAL2_1 :=$(INSTALL_MSIVAL2)/msival2.exe
- _MSIVAL2_2 :=$(DEVTOOLS_PATH)msival2.exe
- MSIVAL2 :=$(call FileExists,$(_MSIVAL2_1),$(_MSIVAL2_2))
-endif
-MSIVAL2:=$(call AltCheckSpaces,MSIVAL2)
-# suppress msival2 checks, as it hangs jprt builds
-ifdef SKIP_MSIVAL2
- MSIVAL2 := $(ECHO)
-endif
-
-# LOGOCUB: path to cub file for (used in validating install msi files)
-ifdef ALT_LOGOCUB
- xALT_LOGOCUB :="$(subst \,/,$(ALT_LOGOCUB))"
- LOGOCUB =$(xALT_LOGOCUB)
-else
- _LOGOCUB1 :=$(INSTALL_MSIVAL2)/logo.cub
- _LOGOCUB2 :=$(DEVTOOLS_PATH)logo.cub
- LOGOCUB :=$(call FileExists,$(_LOGOCUB1),$(_LOGOCUB2))
-endif
-LOGOCUB:=$(call AltCheckSpaces,LOGOCUB)
-
-# MSITRAN: path to msitran.exe (used in creating install bundles and sponsors)
-ifdef ALT_MSITRAN
- xALT_MSITRAN :="$(subst \,/,$(ALT_MSITRAN))"
- MSITRAN =$(xALT_MSITRAN)
-else
- _MSITRAN1 :=$(INSTALL_MSSDK)/Bin/msitran.exe
- _MSITRAN2 :=$(DEVTOOLS_PATH)msitran.exe
- MSITRAN :=$(call FileExists,$(_MSITRAN1),$(_MSITRAN2))
-endif
-MSITRAN:=$(call AltCheckSpaces,MSITRAN)
-
# MSICERT: path to msicert.exe (used in creating install bundles)
ifdef ALT_MSICERT
xALT_MSICERT :="$(subst \,/,$(ALT_MSICERT))"
@@ -798,3 +740,50 @@
endif
HOTSPOT_LIB_PATH:=$(call AltCheckSpaces,HOTSPOT_LIB_PATH)
HOTSPOT_LIB_PATH:=$(call AltCheckValue,HOTSPOT_LIB_PATH)
+
+# Special define for checking the binaries
+
+ifeq ($(VS2010_EXISTS),true)
+
+# All windows dll and exe files should have been built with /NXCOMPAT
+# and be setup for dynamic base addresses.
+# In addition, we should not be dependent on certain dll files that
+# we do not or cannot redistribute.
+
+# List of filenames we should NOT be dependent on
+BANNED_DLLS=msvcp100[.]dll|msvcr100d[.]dll|msvcrtd[.]dll
+
+# Macro to check it's input file for banned dependencies and verify the
+# binary was built properly. Relies on process exit code.
+define binary_file_verification # binary_file
+( \
+ $(ECHO) "Checking for /NXCOMPAT usage in: $1" && \
+ if [ "`$(DUMPBIN) /headers $1 | $(EGREP) -i 'NX compatible'`" = "" ] ; then \
+ $(ECHO) "ERROR: Did not find 'NX compatible' in headers: $1" ; \
+ $(DUMPBIN) /headers $1 ; \
+ exit 7 ; \
+ fi ; \
+ $(ECHO) "Checking for /DYNAMICBASE usage in: $1" && \
+ if [ "`$(DUMPBIN) /headers $1 | $(EGREP) -i 'Dynamic base'`" = "" ] ; then \
+ $(ECHO) "ERROR: Did not find 'Dynamic base' in headers: $1" ; \
+ $(DUMPBIN) /headers $1 ; \
+ exit 8 ; \
+ fi ; \
+ $(ECHO) "Checking for banned dependencies in: $1" && \
+ if [ "`$(DUMPBIN) /dependents $1 | $(EGREP) -i '$(BANNED_DLLS)'`" != "" ] ; then \
+ $(ECHO) "ERROR: Found us of $(BANNED_DLLS)"; \
+ $(DUMPBIN) /dependents $1 ; \
+ exit 9 ; \
+ fi ; \
+)
+endef
+
+else
+
+# Macro to check it's input file for banned dependencies and verify the
+# binary was built properly. Relies on process exit code.
+define binary_file_verification # binary_file
+endef
+
+endif
+
--- a/jdk/make/common/shared/Sanity-Settings.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Sanity-Settings.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -96,7 +96,6 @@
endif
endif
ifeq ($(PLATFORM),windows)
- ALL_SETTINGS+=$(call addAltSetting,MSVCRT_DLL_PATH)
ifneq ($(MSVCRNN_DLL),)
ALL_SETTINGS+=$(call addAltSetting,MSVCRNN_DLL_PATH)
endif
@@ -117,6 +116,9 @@
ALL_SETTINGS+=$(call addRequiredVersionSetting,UNZIP_VER)
ifeq ($(PLATFORM),windows)
ALL_SETTINGS+=$(call addRequiredVersionSetting,LINK_VER)
+ ALL_SETTINGS+=$(call addRequiredSetting,CC)
+ ALL_SETTINGS+=$(call addRequiredSetting,LINK)
+ ALL_SETTINGS+=$(call addRequiredSetting,DUMPBIN)
endif
ALL_SETTINGS+=$(call addRequiredVersionSetting,ANT_VER)
ALL_SETTINGS+=$(call addRequiredSetting,TEMPDIR)
@@ -226,13 +228,13 @@
ALL_SETTINGS+=$(call addAltSetting,DXSDK_INCLUDE_PATH)
ALL_SETTINGS+=$(call addAltSetting,DXSDK_LIB_PATH)
ALL_SETTINGS+=$(call addAltSetting,WINDOWSSDKDIR)
+ ALL_SETTINGS+=$(call addRequiredSetting,RC)
+ ALL_SETTINGS+=$(call addRequiredSetting,REBASE)
ifndef OPENJDK
ALL_SETTINGS+=$(call addAltSetting,DEPLOY_MSSDK)
ALL_SETTINGS+=$(call addAltSetting,INSTALL_MSSDK)
ALL_SETTINGS+=$(call addAltSetting,WSCRIPT)
ALL_SETTINGS+=$(call addAltSetting,MSICERT)
- ALL_SETTINGS+=$(call addAltSetting,MSITRAN)
- ALL_SETTINGS+=$(call addAltSetting,MSIVAL2)
endif
endif
ALL_SETTINGS+=$(call addAltSetting,CACERTS_FILE)
--- a/jdk/make/common/shared/Sanity.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/common/shared/Sanity.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -879,13 +879,6 @@
######################################################
sane-msvcrt_path:
ifeq ($(PLATFORM), windows)
- @if [ ! -r "$(MSVCRT_DLL_PATH)/msvcrt.dll" ]; then \
- $(ECHO) "ERROR: You do not have access to msvcrt.dll. \n" \
- " Please check your access to \n" \
- " $(MSVCRT_DLL_PATH) \n" \
- " and/or check your value of ALT_MSVCRT_DLL_PATH. \n" \
- "" >> $(ERROR_FILE) ; \
- fi
ifneq ($(MSVCRNN_DLL),)
@if [ ! -r "$(MSVCRNN_DLL_PATH)/$(MSVCRNN_DLL)" ]; then \
$(ECHO) "ERROR: You do not have access to $(MSVCRNN_DLL). \n" \
@@ -1018,6 +1011,22 @@
" and/or check your value of ALT_MSDEVTOOLS_PATH. \n" \
"" >> $(ERROR_FILE) ; \
fi
+ else
+ ifeq ($(wildcard $(REBASE)),)
+ @$(ECHO) "ERROR: Cannot find the REBASE utility from path: $(REBASE)\n" \
+ " This is normally obtained from the WINDOWSSDKDIR." \
+ "" >> $(ERROR_FILE)
+ endif
+ ifeq ($(wildcard $(RC)),)
+ @$(ECHO) "ERROR: Cannot find the RC utility from path: $(RC)\n" \
+ " This is normally obtained from the WINDOWSSDKDIR." \
+ "" >> $(ERROR_FILE)
+ endif
+ ifeq ($(wildcard $(DUMPBIN)),)
+ @$(ECHO) "ERROR: Cannot find the DUMPBIN utility from path: $(DUMPBIN)\n" \
+ " This is normally obtained from the WINDOWSSDKDIR." \
+ "" >> $(ERROR_FILE)
+ endif
endif
endif
@@ -1460,25 +1469,6 @@
endif
######################################################
-# Check for existence of INSTALL_MSIVAL2 on windows
-######################################################
-sane-install-msival2_path:
-ifeq ($(PLATFORM), windows)
- @if [ -z "$(INSTALL_MSIVAL2)" ]; then \
- $(ECHO) "WARNING: Your INSTALL_MSIVAL2 setting is empty.\n" \
- " It is recommended to set ALT_INSTALL_MSIVAL2.\n" \
- "" >> $(WARNING_FILE) ; \
- fi
- @if [ ! -r "$(INSTALL_MSIVAL2)" ]; then \
- $(ECHO) "ERROR: You do not have a valid INSTALL_MSIVAL2 setting. \n" \
- " Please check your access to \n" \
- " $(INSTALL_MSIVAL2) \n" \
- " and/or check your value of ALT_INSTALL_MSIVAL2. \n" \
- "" >> $(ERROR_FILE) ; \
- fi
-endif
-
-######################################################
# Check the GNU C++ compiler for OJI plugin
######################################################
sane-gcc-compiler:
--- a/jdk/make/java/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/java/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -34,7 +34,7 @@
#
# The order of subdirs here is important
#
-SUBDIRS += hpi version jvm redist verify fdlibm java sun_nio jli main zip
+SUBDIRS += version jvm redist verify fdlibm java sun_nio jli main zip
# Others
# Note: java_crw_demo java_hprof_demo are demos but must be delivered built in sdk
--- a/jdk/make/java/fdlibm/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/java/fdlibm/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -24,7 +24,7 @@
#
#
-# Makefile for native threads HPI.
+# Makefile for fdlibm
#
# Note:
# The fdlibm libraries are built using special rules in Library.gmk.
--- a/jdk/make/java/hpi/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-#
-# Copyright (c) 1998, 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. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-#
-# Build HPI (Host Porting Interface) libraries
-#
-
-BUILDDIR = ../..
-include $(BUILDDIR)/common/Defs.gmk
-
-#
-# Build specified the HPI implementations
-#
-SUBDIRS = $(HPIS)
-include $(BUILDDIR)/common/Subdirs.gmk
-
-all build clean clobber::
- $(SUBDIRS-loop)
-
--- a/jdk/make/java/hpi/hpi_common.gmk Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-#
-# Copyright (c) 1998, 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. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-#
-# Shared files between the different threads types on Solaris. Be
-# careful when including this, you must get your variables right.
-#
-
-#
-# Common files on Solaris.
-#
-ifneq ($(PLATFORM), windows)
-FILES_c += \
- interrupt.c \
- linker_md.c \
- memory_md.c \
- system_md.c \
- hpi.c
-endif
-
-#
-# Include paths can also be shared.
-#
-ifneq ($(PLATFORM), windows)
-OTHER_INCLUDES += \
- -I$(PLATFORM_SRC)/hpi/$(THREADDIR)/include \
- -I$(PLATFORM_SRC)/hpi/include \
- -I$(PLATFORM_SRC)/hpi/export \
- -I$(SHARE_SRC)/hpi/include \
- -I$(SHARE_SRC)/hpi/export
-else
-OTHER_INCLUDES += \
- -I$(PLATFORM_SRC)/hpi/include \
- -I$(PLATFORM_SRC)/hpi/export \
- -I$(SHARE_SRC)/hpi/include \
- -I$(SHARE_SRC)/hpi/export
-endif
-
-#
-# Add to the default C and assembly file search paths. Clear any initial
-# vpath settings to ensure that we don't look in unexpected places for HPI
-# files.
-#
-vpath %.c
-vpath %.c $(PLATFORM_SRC)/hpi/$(THREADDIR)/src
-vpath %.c $(PLATFORM_SRC)/hpi/src
-vpath %.c $(SHARE_SRC)/hpi/src
-
-vpath %.s
-vpath %.s $(PLATFORM_SRC)/hpi/$(THREADDIR)/src
-vpath %.s $(PLATFORM_SRC)/hpi/src
-
-#
-# By default leave out locking statistics
-#
-ifneq ($(PLATFORM), windows)
-LOCKSTATS = false
-ifeq ($(LOCKSTATS), true)
- CFLAGS_COMMON += -DLOCKSTATS
-endif
-endif
-
-#
-# Things that must be linked in.
-#
-ifneq ($(PLATFORM), windows)
-OTHER_LDLIBS += $(LIBSOCKET) $(LIBNSL) $(LIBM) -ldl
-endif
--- a/jdk/make/java/hpi/native/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#
-# Copyright (c) 1998, 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. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-#
-# Makefile for native threads HPI.
-#
-
-BUILDDIR = ../../..
-MODULE = base
-LIBRARY = hpi
-PRODUCT = java
-THREADDIR = native_threads
-LIB_LOCATION = $(LIBDIR)/$(LIBARCH)/$(THREADDIR)
-include $(BUILDDIR)/common/Defs.gmk
-
-#
-# Native threads specific C and .s files.
-#
-FILES_c = \
- monitor_md.c \
- threads_md.c \
- condvar_md.c \
- interrupt_md.c \
- mutex_md.c \
- sys_api_td.c \
- threads_$(PLATFORM).c
-
-#
-# Other files/flags shared between the HPIs.
-#
-include $(BUILDDIR)/java/hpi/hpi_common.gmk
-
-#
-# Rules for the .so file.
-#
-ifeq ($(PLATFORM), solaris)
- ifneq ($(ARCH), amd64)
- FILES_reorder += reorder-$(ARCH)
- endif
-endif
-include $(BUILDDIR)/common/Mapfile-vers.gmk
-include $(BUILDDIR)/common/Library.gmk
-
-#
-# HPI flags for native threads.
-#
-OTHER_CPPFLAGS += -D_REENTRANT -DNATIVE
-
-ifeq ($(USE_PTHREADS),true)
-OTHER_CPPFLAGS += -DUSE_PTHREADS
-ifeq ($(MOOT_PRIORITIES),true)
-OTHER_CPPFLAGS += -DMOOT_PRIORITIES
-endif
-LIBPOSIX4 = -lposix4
-OTHER_LDLIBS += -lpthread $(LIBPOSIX4)
-endif
-
-HAVE_GETHRVTIME=true
-ifeq ($(HAVE_GETHRVTIME),true)
-OTHER_CPPFLAGS += -DHAVE_GETHRVTIME
-endif
-
-HAVE_FILIOH=true
-ifeq ($(HAVE_FILIOH),true)
-OTHER_CPPFLAGS += -DHAVE_FILIOH
-endif
-
-ifeq ($(NO_INTERRUPTIBLE_IO),true)
-OTHER_CPPFLAGS += -DNO_INTERRUPTIBLE_IO
-endif
-
--- a/jdk/make/java/hpi/native/mapfile-vers Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-#
-# Copyright (c) 2000, 2002, 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. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-SUNWprivate_1.1 {
- global:
- DLL_Initialize;
-
- local:
- *;
-};
--- a/jdk/make/java/hpi/native/reorder-i586 Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-data = R0x2000;
-text = LOAD ?RXO;
-# Test Null
-text: .text%_init;
-text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj/threads_solaris.o;
-text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj/system_md.o;
-text: .text%DLL_Initialize;
-text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj/hpi.o;
-text: .text%sysBuildLibName;
-text: .text%sysLoadLibrary;
-text: .text%sysFindLibraryEntry;
-text: .text%sysNativePath;
-text: .text%sysOpen;
-text: .text%sysSeek;
-text: .text%lseek64_w;
-# Test Exit
-# Test Hello
-# Test Sleep
-# Test IntToString
-# Test LoadToolkit
-text: .text%sysAvailable;
-text: .text%sysFfileMode;
-text: .text%sysGetLastErrorString;
-# Test LoadFrame
-# Test LoadJFrame
-# Test JHello
-# SwingSet
--- a/jdk/make/java/hpi/native/reorder-sparc Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-data = R0x2000;
-text = LOAD ?RXO;
-# Test Null
-text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj/threads_solaris.o;
-text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj/system_md.o;
-text: .text%DLL_Initialize;
-text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj/hpi.o;
-text: .text%sysBuildLibName;
-text: .text%sysLoadLibrary;
-text: .text%sysFindLibraryEntry;
-text: .text%sysNativePath;
-text: .text%sysOpen;
-text: .text%sysFfileMode;
-text: .text%sysSeek;
-text: .text%lseek64_w;
-text: .text%sysAvailable;
-# Test Exit
-# Test Hello
-# Test Sleep
-# Test IntToString
-# Test LoadToolkit
-text: .text%sysGetLastErrorString;
-# Test LoadFrame
-# Test LoadJFrame
-# Test JHello
-# SwingSet
--- a/jdk/make/java/hpi/native/reorder-sparcv9 Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-data = R0x2000;
-text = LOAD ?RXO;
-# Test Null
-text: .text%checkForCorrectLibthread: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/threads_solaris.o;
-text: .text%init64IO: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/system_md.o;
-text: .text%DLL_Initialize;
-text: .text%GetInterface: OUTPUTDIR/tmp/java/hpi/native_threads/obj64/hpi.o;
-text: .text%sysBuildLibName;
-text: .text%sysLoadLibrary;
-text: .text%sysFindLibraryEntry;
-text: .text%sysNativePath;
-text: .text%sysOpen;
-text: .text%sysFfileMode;
-text: .text%sysSeek;
-text: .text%lseek64_w;
-text: .text%sysAvailable;
-# Test Exit
-# Test Hello
-# Test Sleep
-# Test IntToString
-# Test LoadToolkit
-text: .text%sysGetLastErrorString;
-# Test LoadFrame
-# Test LoadJFrame
-# Test JHello
-# SwingSet
--- a/jdk/make/java/hpi/windows/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-#
-# Copyright (c) 1999, 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. Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# 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.
-#
-
-#
-# Makefile for Windows HPI DLL
-#
-BUILDDIR = ../../..
-MODULE = base
-LIBRARY = hpi
-PRODUCT = java
-THREADDIR = windows_threads
-LIB_LOCATION = $(BINDIR)
-
-include $(BUILDDIR)/common/Defs.gmk
-
-# windows compiler flags
-ifeq ($(PLATFORM),windows)
- CPPFLAGS_DBG += -DLOGGING
-endif
-
-FILES_c = \
- linker_md.c \
- memory_md.c \
- monitor_md.c \
- path_md.c \
- socket_md.c \
- sys_api_md.c \
- system_md.c \
- threads_md.c \
- hpi.c # trailing blank required!
-
-JVMLIB =
-JAVALIB =
-OTHER_LCF = -export:DLL_Initialize
-EXTRA_LIBS =
-
-
-#
-# Other files/flags shared between the HPIs.
-#
-include $(BUILDDIR)/java/hpi/hpi_common.gmk
-
-#
-# Rules for the .so file.
-#
-include $(BUILDDIR)/common/Library.gmk
-
--- a/jdk/make/java/management/mapfile-vers Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/java/management/mapfile-vers Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 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
@@ -70,14 +70,18 @@
Java_sun_management_ThreadImpl_dumpThreads0;
Java_sun_management_ThreadImpl_findDeadlockedThreads0;
Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0;
- Java_sun_management_ThreadImpl_getThreadInfo0;
+ Java_sun_management_ThreadImpl_getThreadInfo1;
Java_sun_management_ThreadImpl_getThreads;
Java_sun_management_ThreadImpl_getThreadTotalCpuTime0;
+ Java_sun_management_ThreadImpl_getThreadTotalCpuTime1;
Java_sun_management_ThreadImpl_getThreadUserCpuTime0;
+ Java_sun_management_ThreadImpl_getThreadUserCpuTime1;
+ Java_sun_management_ThreadImpl_getThreadAllocatedMemory1;
Java_sun_management_ThreadImpl_resetContentionTimes0;
Java_sun_management_ThreadImpl_resetPeakThreadCount0;
Java_sun_management_ThreadImpl_setThreadContentionMonitoringEnabled0;
Java_sun_management_ThreadImpl_setThreadCpuTimeEnabled0;
+ Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0;
Java_sun_management_VMManagementImpl_getAvailableProcessors;
Java_sun_management_VMManagementImpl_getClassInitializationTime;
Java_sun_management_VMManagementImpl_getClassLoadingTime;
@@ -106,6 +110,7 @@
Java_sun_management_VMManagementImpl_initOptionalSupportFields;
Java_sun_management_VMManagementImpl_isThreadContentionMonitoringEnabled;
Java_sun_management_VMManagementImpl_isThreadCpuTimeEnabled;
+ Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled;
JNI_OnLoad;
local:
*;
--- a/jdk/make/java/nio/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/java/nio/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -296,7 +296,7 @@
OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread -ldl
endif
ifeq ($(PLATFORM), solaris)
-OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 -ldl \
+OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 -ldl -lsendfile \
-L$(LIBDIR)/$(LIBARCH) -ljava -lnet
endif # PLATFORM
--- a/jdk/make/java/redist/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/java/redist/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -93,10 +93,6 @@
IMPORT_LIST += $(MS_RUNTIME_LIBRARIES:%=$(BINDIR)/%)
-# NOTE: These might actually come from BUILDDIR, depends on the settings.
-$(BINDIR)/msvcrt.dll: $(MSVCRT_DLL_PATH)/msvcrt.dll
- $(install-import-file)
- $(call chmod-file, a+x)
$(BINDIR)/$(MSVCRNN_DLL): $(MSVCRNN_DLL_PATH)/$(MSVCRNN_DLL)
$(install-import-file)
$(call chmod-file, a+x)
@@ -223,12 +219,15 @@
$(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVM_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVM_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(KERNEL_LOCATION)/$(JVM_NAME): $(HOTSPOT_KERNEL_PATH)/$(JVM_NAME)
$(install-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(LIBJSIG_NAME): $(HOTSPOT_IMPORT_PATH)/$(ARCH_VM_SUBDIR)/$(LIBJSIG_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(CLIENT_LOCATION)/$(LIBJSIG_NAME) \
$(LIB_LOCATION)/$(SERVER_LOCATION)/$(LIBJSIG_NAME):
@@ -237,30 +236,39 @@
$(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMDB_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVMDB_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(CLIENT_LOCATION)/64/$(JVMDB_NAME): $(HOTSPOT_CLIENT_PATH)/64/$(JVMDB_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDB_NAME): $(HOTSPOT_SERVER_PATH)/$(JVMDB_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(SERVER_LOCATION)/64/$(JVMDB_NAME): $(HOTSPOT_SERVER_PATH)/64/$(JVMDB_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(CLIENT_LOCATION)/$(JVMDTRACE_NAME): $(HOTSPOT_CLIENT_PATH)/$(JVMDTRACE_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(CLIENT_LOCATION)/64/$(JVMDTRACE_NAME): $(HOTSPOT_CLIENT_PATH)/64/$(JVMDTRACE_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVMDTRACE_NAME): $(HOTSPOT_SERVER_PATH)/$(JVMDTRACE_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(SERVER_LOCATION)/64/$(JVMDTRACE_NAME): $(HOTSPOT_SERVER_PATH)/64/$(JVMDTRACE_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(SERVER_LOCATION)/$(JVM_NAME): $(HOTSPOT_SERVER_PATH)/$(JVM_NAME)
$(install-import-file)
+ @$(call binary_file_verification,$@)
$(LIB_LOCATION)/$(SERVER_LOCATION)/Xusage.txt : $(HOTSPOT_SERVER_PATH)/Xusage.txt
$(install-import-file)
--- a/jdk/make/jdk_generic_profile.sh Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/jdk_generic_profile.sh Fri Feb 18 12:04:36 2011 -0800
@@ -50,7 +50,7 @@
#
# Assumes basic unix utilities are in the PATH already (uname, hostname, etc.).
#
-# On Windows, assumes PROCESSOR_IDENTIFIER, VS71COMNTOOLS,
+# On Windows, assumes PROCESSOR_IDENTIFIER, VS100COMNTOOLS,
# SYSTEMROOT (or SystemRoot), COMPUTERNAME (or hostname works), and
# USERNAME is defined in the environment.
# This profile does not rely on using vcvars32.bat and 64bit Setup.bat.
@@ -81,8 +81,7 @@
# Windows Only:
# ALT_UNIXCOMMAND_PATH
# ALT_DXSDK_PATH
-# ALT_MSVCRT_DLL_PATH
-# ALT_MSVCR71_DLL_PATH
+# ALT_MSVCRNN_DLL_PATH
#
#############################################################################
#
@@ -213,78 +212,17 @@
# Compiler setup (nasty part)
# NOTE: You can use vcvars32.bat to set PATH, LIB, and INCLUDE.
# NOTE: CYGWIN has a link.exe too, make sure the compilers are first
- if [ "${windows_arch}" = i586 ] ; then
- # 32bit Windows compiler settings
- # VisualStudio .NET 2003 VC++ 7.1 (VS71COMNTOOLS should be defined)
- vs_root=$(${cygpath} "${VS71COMNTOOLS}/../..")
- # Fill in PATH, LIB, and INCLUDE (unset all others to make sure)
- vc7_root="${vs_root}/Vc7"
- compiler_path="${vc7_root}/bin"
- platform_sdk="${vc7_root}/PlatformSDK"
-
- # LIB and INCLUDE must use ; as a separator
- include4sdk="${vc7_root}/atlmfc/include"
- include4sdk="${include4sdk};${vc7_root}/include"
- include4sdk="${include4sdk};${platform_sdk}/include/prerelease"
- include4sdk="${include4sdk};${platform_sdk}/include"
- include4sdk="${include4sdk};${vs_root}/SDK/v1.1/include"
- lib4sdk="${lib4sdk};${vc7_root}/lib"
- lib4sdk="${lib4sdk};${platform_sdk}/lib/prerelease"
- lib4sdk="${lib4sdk};${platform_sdk}/lib"
- lib4sdk="${lib4sdk};${vs_root}/SDK/v1.1/lib"
- # Search path and DLL locating path
- # WARNING: CYGWIN has a link.exe too, make sure compilers are first
- path4sdk="${vs_root}/Common7/Tools/bin;${path4sdk}"
- path4sdk="${vs_root}/SDK/v1.1/bin;${path4sdk}"
- path4sdk="${vs_root}/Common7/Tools;${path4sdk}"
- path4sdk="${vs_root}/Common7/Tools/bin/prerelease;${path4sdk}"
- path4sdk="${vs_root}/Common7/IDE;${path4sdk}"
- path4sdk="${compiler_path};${path4sdk}"
- elif [ "${windows_arch}" = amd64 ] ; then
- # AMD64 64bit Windows compiler settings
- if [ "${ALT_DEPLOY_MSSDK}" != "" ] ; then
- platform_sdk=${ALT_DEPLOY_MSSDK}
- else
- platform_sdk=$(${cygpath} "C:/Program Files/Microsoft Platform SDK/")
- fi
- if [ "${ALT_COMPILER_PATH}" != "" ] ; then
- compiler_path=${ALT_COMPILER_PATH}
- if [ "${ALT_DEPLOY_MSSDK}" = "" ] ; then
- platform_sdk=${ALT_COMPILER_PATH}/../../../..
- fi
- else
- compiler_path="${platform_sdk}/Bin/win64/x86/AMD64"
- fi
- # LIB and INCLUDE must use ; as a separator
- include4sdk="${platform_sdk}/Include"
- include4sdk="${include4sdk};${platform_sdk}/Include/crt/sys"
- include4sdk="${include4sdk};${platform_sdk}/Include/mfc"
- include4sdk="${include4sdk};${platform_sdk}/Include/atl"
- include4sdk="${include4sdk};${platform_sdk}/Include/crt"
- lib4sdk="${platform_sdk}/Lib/AMD64"
- lib4sdk="${lib4sdk};${platform_sdk}/Lib/AMD64/atlmfc"
- # Search path and DLL locating path
- # WARNING: CYGWIN has a link.exe too, make sure compilers are first
- path4sdk="${platform_sdk}/bin;${path4sdk}"
- path4sdk="${compiler_path};${path4sdk}"
+
+ # Use supplied vsvars.sh
+ repo=`hg root`
+ if [ -f "${repo}/make/scripts/vsvars.sh" ] ; then
+ eval `sh ${repo}/make/scripts/vsvars.sh -v10`
+ elif [ -f "${repo}/../make/scripts/vsvars.sh" ] ; then
+ eval `sh ${repo}/../make/scripts/vsvars.sh -v10`
+ else
+ echo "WARNING: No make/scripts/vsvars.sh file found"
fi
- # Export LIB and INCLUDE
- unset lib
- unset Lib
- LIB="${lib4sdk}"
- export LIB
- unset include
- unset Include
- INCLUDE="${include4sdk}"
- export INCLUDE
- # Turn all \\ into /, remove duplicates and trailing /
- slash_path="$(echo ${path4sdk} | sed -e 's@\\\\@/@g' -e 's@//@/@g' -e 's@/$@@' -e 's@/;@;@g')"
- path4sdk="${slash_path}"
-
- # Convert path4sdk to cygwin style
- path4sdk="$(/usr/bin/cygpath -p ${path4sdk})"
-
fi
# Get the previous JDK to be used to bootstrap the build
--- a/jdk/make/mkdemo/jfc/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/mkdemo/jfc/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -43,7 +43,7 @@
# Some demos aren't currently included in OpenJDK
ifndef OPENJDK
- SUBDIRS += Java2D SwingSet2 Stylepad
+ SUBDIRS += Java2D SwingSet2 SwingSet3 Stylepad
endif
include $(BUILDDIR)/common/Subdirs.gmk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/mkdemo/jfc/SwingSet3/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,43 @@
+#
+# 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# 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.
+#
+
+#
+# Makefile to build the SwingSet3 demo.
+#
+
+BUILDDIR = ../../..
+PRODUCT = demo/jfc
+DEMONAME = SwingSet3
+include $(BUILDDIR)/common/Defs.gmk
+
+DEMO_ROOT = $(CLOSED_SRC)/share/demo/jfc/$(DEMONAME)
+DEMO_DESTDIR = $(DEMODIR)/jfc/$(DEMONAME)
+DEMO_TOPFILES = ./readme.html ./swingset3.png
+DEMO_SKIP_SRCZIP = true
+
+#
+# Demo jar building rules.
+#
+include $(BUILDDIR)/common/Demo.gmk
--- a/jdk/make/sun/jpeg/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/sun/jpeg/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -65,6 +65,19 @@
FILES_reorder += reorder-$(ARCH)
endif
endif
+
+ifeq ($(PLATFORM), linux)
+
+ # Suppress gcc warnings like "variable might be clobbered by 'longjmp'
+ # or 'vfork'": this warning indicates that some variable is placed to
+ # a register by optimized compiler and it's value might be lost on longjmp().
+ # Recommended way to avoid such warning is to declare the variable as
+ # volatile to prevent the optimization. However, this approach does not
+ # work because we have to declare all variables as volatile in result.
+
+ OTHER_CFLAGS += -Wno-clobbered
+endif
+
include $(BUILDDIR)/common/Mapfile-vers.gmk
include $(BUILDDIR)/common/Library.gmk
--- a/jdk/make/sun/jpeg/reorder-i586 Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/sun/jpeg/reorder-i586 Fri Feb 18 12:04:36 2011 -0800
@@ -22,7 +22,7 @@
text: .text%alloc_small: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o;
text: .text%reset_marker_reader: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%jIInCtlr;
-text: .text%GET_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o;
+# text: .text%GET_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o;
text: .text%jReadHeader;
text: .text%jConsumeInput;
text: .text%reset_input_controller: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
@@ -30,36 +30,36 @@
text: .text%sun_jpeg_init_source;
text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
-text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%sun_jpeg_fill_input_buffer;
-text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o;
-text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o;
+# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o;
-text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
-text: .text%examine_app0: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%examine_app0: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%skip_variable: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%sun_jpeg_skip_input_data;
-text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%examine_app14: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%jAlcQTable;
text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
-text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%jAlcHTable;
text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
-text: .text%initial_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
+# text: .text%initial_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
text: .text%jDivRound;
-text: .text%default_decompress_parms: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapimin.o;
+# text: .text%default_decompress_parms: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapimin.o;
text: .text%jHasMultScn;
text: .text%jStrtDecompress;
text: .text%jIDMaster;
-text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
+# text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%jCalcDimensions;
-text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
-text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
+# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
+# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%jIDColor;
-text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o;
+# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o;
text: .text%jIUpsampler;
text: .text%jRound;
text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o;
@@ -70,16 +70,16 @@
text: .text%jIHDecoder;
text: .text%jIDCoefC;
text: .text%jIDMainC;
-text: .text%alloc_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
+# text: .text%alloc_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
text: .text%realize_virt_arrays: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o;
text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
-text: .text%per_scan_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
-text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
+# text: .text%per_scan_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
+# text: .text%latch_quant_tables: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o;
text: .text%jMkDDerived;
text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
-text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
-text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o;
+# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
+# text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o;
text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jddctmgr.o;
text: .text%start_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
@@ -87,7 +87,7 @@
text: .text%start_pass_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o;
text: .text%start_pass_dpost: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdpostct.o;
text: .text%start_pass_main: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
-text: .text%make_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
+# text: .text%make_funny_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
text: .text%jReadScanlines;
text: .text%process_data_context_main: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
text: .text%decompress_onepass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
@@ -100,11 +100,11 @@
text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o;
text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o;
text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o;
-text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
-text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o;
+# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
+# text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o;
text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
-text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
+# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
text: .text%jFinDecompress;
text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%sun_jpeg_term_source;
--- a/jdk/make/sun/jpeg/reorder-sparc Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/sun/jpeg/reorder-sparc Fri Feb 18 12:04:36 2011 -0800
@@ -30,10 +30,10 @@
text: .text%sun_jpeg_init_source;
text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
-text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%sun_jpeg_fill_input_buffer;
text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jpegdecoder.o;
-text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jerror.o;
text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
@@ -44,7 +44,7 @@
text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%jAlcQTable;
text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
-text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
+# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%jAlcHTable;
text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
@@ -56,10 +56,10 @@
text: .text%jIDMaster;
text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%jCalcDimensions;
-text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
-text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
+# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
+# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%jIDColor;
-text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o;
+# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o;
text: .text%jIUpsampler;
text: .text%jRound;
text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jmemmgr.o;
@@ -78,7 +78,7 @@
text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o;
text: .text%jMkDDerived;
text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
-text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
+# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcoefct.o;
text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdapistd.o;
text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jddctmgr.o;
@@ -100,11 +100,11 @@
text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o;
text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdsample.o;
text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdcolor.o;
-text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
-text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o;
+# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
+#text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdhuff.o;
text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmarker.o;
text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdinput.o;
-text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
+# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmainct.o;
text: .text%jFinDecompress;
text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj/jdmaster.o;
text: .text%sun_jpeg_term_source;
--- a/jdk/make/sun/jpeg/reorder-sparcv9 Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/sun/jpeg/reorder-sparcv9 Fri Feb 18 12:04:36 2011 -0800
@@ -30,10 +30,10 @@
text: .text%sun_jpeg_init_source;
text: .text%consume_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o;
text: .text%read_markers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
-text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
+# text: .text%first_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%sun_jpeg_fill_input_buffer;
text: .text%RELEASE_ARRAYS: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jpegdecoder.o;
-text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
+# text: .text%get_soi: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%emit_message: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jerror.o;
text: .text%next_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%get_interesting_appn: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
@@ -44,7 +44,7 @@
text: .text%get_dqt: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%jAlcQTable;
text: .text%get_sof: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
-text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
+# text: .text%get_dri: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%get_dht: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%jAlcHTable;
text: .text%get_sos: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
@@ -56,10 +56,10 @@
text: .text%jIDMaster;
text: .text%master_selection: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
text: .text%jCalcDimensions;
-text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
-text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
+# text: .text%use_merged_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
+# text: .text%prepare_range_limit_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
text: .text%jIDColor;
-text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o;
+# text: .text%build_ycc_rgb_table: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o;
text: .text%jIUpsampler;
text: .text%jRound;
text: .text%alloc_sarray: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jmemmgr.o;
@@ -78,7 +78,7 @@
text: .text%start_pass_huff_decoder: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdhuff.o;
text: .text%jMkDDerived;
text: .text%start_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o;
-text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o;
+# text: .text%start_iMCU_row: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcoefct.o;
text: .text%output_pass_setup: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdapistd.o;
text: .text%prepare_for_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
text: .text%start_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jddctmgr.o;
@@ -100,11 +100,11 @@
text: .text%fullsize_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o;
text: .text%h2v2_fancy_upsample: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdsample.o;
text: .text%ycc_rgb_convert: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdcolor.o;
-text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o;
+# text: .text%set_wraparound_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o;
text: .text%process_restart: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdhuff.o;
text: .text%read_restart_marker: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmarker.o;
text: .text%finish_input_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdinput.o;
-text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o;
+# text: .text%set_bottom_pointers: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmainct.o;
text: .text%jFinDecompress;
text: .text%finish_output_pass: OUTPUTDIR/tmp/sun/sun.awt/jpeg/obj64/jdmaster.o;
text: .text%sun_jpeg_term_source;
--- a/jdk/make/sun/net/FILES_java.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/sun/net/FILES_java.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -33,6 +33,7 @@
sun/net/ProgressEvent.java \
sun/net/ProgressListener.java \
sun/net/ProgressMeteringPolicy.java \
+ sun/net/SocksProxy.java \
sun/net/TelnetInputStream.java \
sun/net/TelnetOutputStream.java \
sun/net/TelnetProtocolException.java \
--- a/jdk/make/tools/reorder/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/make/tools/reorder/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -85,7 +85,6 @@
libs.reorder :
ifeq ($(PLATFORM), solaris)
$(MAKE) LIBBLDDIR=java/zip LIBTMPDIR=sun/java.util.zip/zip reorder.lib
- $(MAKE) LIBBLDDIR=java/hpi/native LIBTMPDIR=java/hpi/native_threads reorder.lib
$(MAKE) LIBBLDDIR=java/java LIBTMPDIR=java/java.lang/java reorder.lib
$(MAKE) LIBBLDDIR=java/nio LIBTMPDIR=java/java.nio/nio reorder.lib
$(MAKE) LIBBLDDIR=sun/font LIBTMPDIR=sun/sun.awt.font/fontmanager reorder.lib
@@ -96,7 +95,6 @@
libs.copy:
ifeq ($(PLATFORM), solaris)
$(CP) $(OUTDIR)/reorder_java_zip-$(ARCH) ../../java/zip/reorder-$(ARCH)
- $(CP) $(OUTDIR)/reorder_java_hpi_native-$(ARCH) ../../java/hpi/native/reorder-$(ARCH)
$(CP) $(OUTDIR)/reorder_java_java-$(ARCH) ../../java/java/reorder-$(ARCH)
$(CP) $(OUTDIR)/reorder_sun_font-$(ARCH) ../../sun/font/reorder-$(ARCH)
$(CP) $(OUTDIR)/reorder_sun_jpeg-$(ARCH) ../../sun/jpeg/reorder-$(ARCH)
--- a/jdk/src/share/back/debugInit.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/back/debugInit.c Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -133,27 +133,60 @@
return error;
}
+typedef struct {
+ int major;
+ int minor;
+} version_type;
+
+typedef struct {
+ version_type runtime;
+ version_type compiletime;
+} compatible_versions_type;
+
+/*
+ * List of explicitly compatible JVMTI versions, specified as
+ * { runtime version, compile-time version } pairs. -1 is a wildcard.
+ */
+static int nof_compatible_versions = 3;
+static compatible_versions_type compatible_versions_list[] = {
+ /*
+ * FIXUP: Allow version 0 to be compatible with anything
+ * Special check for FCS of 1.0.
+ */
+ { { 0, -1 }, { -1, -1 } },
+ { { -1, -1 }, { 0, -1 } },
+ /*
+ * 1.2 is runtime compatible with 1.1 -- just make sure to check the
+ * version before using any new 1.2 features
+ */
+ { { 1, 1 }, { 1, 2 } }
+};
+
+
/* Logic to determine JVMTI version compatibility */
static jboolean
compatible_versions(jint major_runtime, jint minor_runtime,
jint major_compiletime, jint minor_compiletime)
{
-#if 1 /* FIXUP: We allow version 0 to be compatible with anything */
- /* Special check for FCS of 1.0. */
- if ( major_runtime == 0 || major_compiletime == 0 ) {
- return JNI_TRUE;
+ /*
+ * First check to see if versions are explicitly compatible via the
+ * list specified above.
+ */
+ int i;
+ for (i = 0; i < nof_compatible_versions; ++i) {
+ version_type runtime = compatible_versions_list[i].runtime;
+ version_type comptime = compatible_versions_list[i].compiletime;
+
+ if ((major_runtime == runtime.major || runtime.major == -1) &&
+ (minor_runtime == runtime.minor || runtime.minor == -1) &&
+ (major_compiletime == comptime.major || comptime.major == -1) &&
+ (minor_compiletime == comptime.minor || comptime.minor == -1)) {
+ return JNI_TRUE;
+ }
}
-#endif
- /* Runtime major version must match. */
- if ( major_runtime != major_compiletime ) {
- return JNI_FALSE;
- }
- /* Runtime minor version must be >= the version compiled with. */
- if ( minor_runtime < minor_compiletime ) {
- return JNI_FALSE;
- }
- /* Assumed compatible */
- return JNI_TRUE;
+
+ return major_runtime == major_compiletime &&
+ minor_runtime >= minor_compiletime;
}
/* OnLoad startup:
--- a/jdk/src/share/back/eventFilter.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/back/eventFilter.c Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -39,6 +39,7 @@
#include "stepControl.h"
#include "threadControl.h"
#include "SDE.h"
+#include "jvmti.h"
typedef struct ClassFilter {
jclass clazz;
@@ -275,6 +276,24 @@
}
}
+static jboolean isVersionGte12x() {
+ jint version;
+ jvmtiError err =
+ JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber)(gdata->jvmti, &version);
+
+ if (err == JVMTI_ERROR_NONE) {
+ jint major, minor;
+
+ major = (version & JVMTI_VERSION_MASK_MAJOR)
+ >> JVMTI_VERSION_SHIFT_MAJOR;
+ minor = (version & JVMTI_VERSION_MASK_MINOR)
+ >> JVMTI_VERSION_SHIFT_MINOR;
+ return (major > 1 || major == 1 && minor >= 2);
+ } else {
+ return JNI_FALSE;
+ }
+}
+
/* Return the object instance in which the event occurred */
/* Return NULL if static or if an error occurs */
static jobject
@@ -286,6 +305,14 @@
jint modifiers = 0;
jvmtiError error;
+ static jboolean got_version = JNI_FALSE;
+ static jboolean is_version_gte_12x = JNI_FALSE;
+
+ if (!got_version) {
+ is_version_gte_12x = isVersionGte12x();
+ got_version = JNI_TRUE;
+ }
+
switch (evinfo->ei) {
case EI_SINGLE_STEP:
case EI_BREAKPOINT:
@@ -314,11 +341,18 @@
/* fail if error or static (0x8) */
if (error == JVMTI_ERROR_NONE && thread!=NULL && (modifiers & 0x8) == 0) {
FrameNumber fnum = 0;
- /* get slot zero object "this" */
- error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
- (gdata->jvmti, thread, fnum, 0, &object);
- if (error != JVMTI_ERROR_NONE)
+ if (is_version_gte_12x) {
+ /* Use new 1.2.x function, GetLocalInstance */
+ error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalInstance)
+ (gdata->jvmti, thread, fnum, &object);
+ } else {
+ /* get slot zero object "this" */
+ error = JVMTI_FUNC_PTR(gdata->jvmti,GetLocalObject)
+ (gdata->jvmti, thread, fnum, 0, &object);
+ }
+ if (error != JVMTI_ERROR_NONE) {
object = NULL;
+ }
}
return object;
--- a/jdk/src/share/bin/java.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/bin/java.c Fri Feb 18 12:04:36 2011 -0800
@@ -94,15 +94,15 @@
* Prototypes for functions internal to launcher.
*/
static void SetClassPath(const char *s);
-static void SetModulesBootClassPath(const char *s);
static void SelectVersion(int argc, char **argv, char **main_class);
-static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile,
- char **pclassname, int *pret, const char *jvmpath);
+static jboolean ParseArguments(int *pargc, char ***pargv,
+ int *pmode, char **pwhat,
+ int *pret, const char *jrepath);
static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
InvocationFunctions *ifn);
static jstring NewPlatformString(JNIEnv *env, char *s);
static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
-static jclass LoadMainClass(JNIEnv *env, jboolean isJar, char *name);
+static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
@@ -158,18 +158,27 @@
* Running Java code in primordial thread caused many problems. We will
* create a new thread to invoke JVM. See 6316197 for more information.
*/
-static jlong threadStackSize = 0; /* stack size of the new thread */
+static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong maxHeapSize = 0; /* max heap size */
static jlong initialHeapSize = 0; /* inital heap size */
int JNICALL JavaMain(void * args); /* entry point */
+enum LaunchMode { // cf. sun.launcher.LauncherHelper
+ LM_UNKNOWN = 0,
+ LM_CLASS,
+ LM_JAR
+};
+
+static const char *launchModeNames[]
+ = { "Unknown", "Main class", "JAR file" };
+
typedef struct {
- int argc;
- char ** argv;
- char * jarfile;
- char * classname;
- InvocationFunctions ifn;
+ int argc;
+ char **argv;
+ int mode;
+ char *what;
+ InvocationFunctions ifn;
} JavaMainArgs;
/*
@@ -189,8 +198,8 @@
jint ergo /* ergonomics class policy */
)
{
- char *jarfile = 0;
- char *classname = 0;
+ int mode = LM_UNKNOWN;
+ char *what = NULL;
char *cpath = 0;
char *main_class = NULL;
int ret;
@@ -277,24 +286,21 @@
SetClassPath(cpath);
}
- /*
- * Parse command line options; if the return value of
- * ParseArguments is false, the program should exit.
+ /* Parse command line options; if the return value of
+ * ParseArguments is false, the program should exit.
*/
- if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) {
+ if (!ParseArguments(&argc, &argv, &mode, &what, &ret, jrepath))
+ {
return(ret);
}
- /* Set bootclasspath for modules */
- SetModulesBootClassPath(jrepath);
-
/* Override class path if -jar flag was specified */
- if (jarfile != 0) {
- SetClassPath(jarfile);
+ if (mode == LM_JAR) {
+ SetClassPath(what); /* Override class path */
}
/* set the -Dsun.java.command pseudo property */
- SetJavaCommandLineProp(classname, jarfile, argc, argv);
+ SetJavaCommandLineProp(what, argc, argv);
/* Set the -Dsun.java.launcher pseudo property */
SetJavaLauncherProp();
@@ -305,7 +311,7 @@
/* Show the splash screen if needed */
ShowSplashScreen();
- return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret);
+ return ContinueInNewThread(&ifn, argc, argv, mode, what, ret);
}
/*
@@ -353,13 +359,13 @@
JavaMainArgs *args = (JavaMainArgs *)_args;
int argc = args->argc;
char **argv = args->argv;
- char *jarfile = args->jarfile;
- char *classname = args->classname;
+ int mode = args->mode;
+ char *what = args->what;
InvocationFunctions ifn = args->ifn;
JavaVM *vm = 0;
JNIEnv *env = 0;
- jclass mainClass;
+ jclass mainClass = NULL;
jmethodID mainID;
jobjectArray mainArgs;
int ret = 0;
@@ -385,7 +391,7 @@
CHECK_EXCEPTION_LEAVE(1);
}
/* If the user specified neither a class name nor a JAR file */
- if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
+ if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) {
PrintUsage(env, printXUsage);
CHECK_EXCEPTION_LEAVE(1);
LEAVE();
@@ -399,11 +405,11 @@
(long)(jint)Counter2Micros(end-start));
}
- /* At this stage, argc/argv have the applications' arguments */
+ /* At this stage, argc/argv have the application's arguments */
if (JLI_IsTraceLauncher()){
int i;
- printf("Main-Class is '%s'\n", classname ? classname : "");
- printf("Apps' argc is %d\n", argc);
+ printf("%s is '%s'\n", launchModeNames[mode], what);
+ printf("App's argc is %d\n", argc);
for (i=0; i < argc; i++) {
printf(" argv[%2d] = '%s'\n", i, argv[i]);
}
@@ -431,11 +437,7 @@
* 2) Remove the vestages of maintaining main_class through
* the environment (and remove these comments).
*/
- if (jarfile != 0) {
- mainClass = LoadMainClass(env, JNI_TRUE, jarfile);
- } else {
- mainClass = LoadMainClass(env, JNI_FALSE, classname);
- }
+ mainClass = LoadMainClass(env, mode, what);
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
/*
@@ -697,7 +699,7 @@
if (JLI_StrCCmp(str, "-Xms") == 0) {
jlong tmp;
if (parse_size(str + 4, &tmp)) {
- initialHeapSize = tmp;
+ initialHeapSize = tmp;
}
}
}
@@ -719,44 +721,6 @@
}
/*
- * Set the bootclasspath for modules.
- * A temporary workaround until jigsaw is integrated into JDK 7.
- */
-static void
-SetModulesBootClassPath(const char *jrepath)
-{
- char *def, *s;
- char pathname[MAXPATHLEN];
- const char separator[] = { FILE_SEPARATOR, '\0' };
- const char *orig = jrepath;
- static const char format[] = "-Xbootclasspath/p:%s";
- struct stat statbuf;
-
- /* return if jre/lib/rt.jar exists */
- JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%srt.jar", jrepath, separator, separator);
- if (stat(pathname, &statbuf) == 0) {
- return;
- }
-
- /* return if jre/classes exists */
- JLI_Snprintf(pathname, sizeof(pathname), "%s%sclasses", jrepath, separator);
- if (stat(pathname, &statbuf) == 0) {
- return;
- }
-
- /* modularized jre */
- JLI_Snprintf(pathname, sizeof(pathname), "%s%slib%s*", jrepath, separator, separator);
- s = (char *) JLI_WildcardExpandClasspath(pathname);
- def = JLI_MemAlloc(sizeof(format)
- - 2 /* strlen("%s") */
- + JLI_StrLen(s));
- sprintf(def, format, s);
- AddOption(def, NULL);
- if (s != orig)
- JLI_MemFree((char *) s);
-}
-
-/*
* The SelectVersion() routine ensures that an appropriate version of
* the JRE is running. The specification for the appropriate version
* is obtained from either the manifest of a jar file (preferred) or
@@ -1000,16 +964,17 @@
/*
* Parses command line arguments. Returns JNI_FALSE if launcher
* should exit without starting vm, returns JNI_TRUE if vm needs
- * to be started to process given options. *pret (the launcher
+ * to be started to process given options. *pret (the launcher
* process return value) is set to 0 for a normal exit.
*/
static jboolean
-ParseArguments(int *pargc, char ***pargv, char **pjarfile,
- char **pclassname, int *pret, const char *jvmpath)
+ParseArguments(int *pargc, char ***pargv,
+ int *pmode, char **pwhat,
+ int *pret, const char *jrepath)
{
int argc = *pargc;
char **argv = *pargv;
- jboolean jarflag = JNI_FALSE;
+ int mode = LM_UNKNOWN;
char *arg;
*pret = 0;
@@ -1019,10 +984,11 @@
if (JLI_StrCmp(arg, "-classpath") == 0 || JLI_StrCmp(arg, "-cp") == 0) {
ARG_CHECK (argc, ARG_ERROR1, arg);
SetClassPath(*argv);
+ mode = LM_CLASS;
argv++; --argc;
} else if (JLI_StrCmp(arg, "-jar") == 0) {
ARG_CHECK (argc, ARG_ERROR2, arg);
- jarflag = JNI_TRUE;
+ mode = LM_JAR;
} else if (JLI_StrCmp(arg, "-help") == 0 ||
JLI_StrCmp(arg, "-h") == 0 ||
JLI_StrCmp(arg, "-?") == 0) {
@@ -1102,19 +1068,24 @@
}
if (--argc >= 0) {
- if (jarflag) {
- *pjarfile = *argv++;
- *pclassname = NULL;
- } else {
- *pjarfile = NULL;
- *pclassname = *argv++;
- }
+ *pwhat = *argv++;
+ }
+
+ if (*pwhat == NULL) {
+ *pret = 1;
+ } else if (mode == LM_UNKNOWN) {
+ /* default to LM_CLASS if -jar and -cp option are
+ * not specified */
+ mode = LM_CLASS;
+ }
+
+ if (argc >= 0) {
*pargc = argc;
*pargv = argv;
}
- if (*pjarfile == NULL && *pclassname == NULL) {
- *pret = 1;
- }
+
+ *pmode = mode;
+
return JNI_TRUE;
}
@@ -1263,7 +1234,7 @@
* call it for more details refer to the java implementation.
*/
static jclass
-LoadMainClass(JNIEnv *env, jboolean isJar, char *name)
+LoadMainClass(JNIEnv *env, int mode, char *name)
{
jclass cls;
jmethodID mid;
@@ -1276,9 +1247,9 @@
}
NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper"));
NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain",
- "(ZZLjava/lang/String;)Ljava/lang/Object;"));
+ "(ZILjava/lang/String;)Ljava/lang/Class;"));
str = (*env)->NewStringUTF(env, name);
- result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, isJar, str);
+ result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, mode, str);
if (JLI_IsTraceLauncher()) {
end = CounterGet();
@@ -1424,8 +1395,7 @@
* property is not exported by HotSpot to the Java layer.
*/
void
-SetJavaCommandLineProp(char *classname, char *jarfile,
- int argc, char **argv)
+SetJavaCommandLineProp(char *what, int argc, char **argv)
{
int i = 0;
@@ -1433,22 +1403,17 @@
char* javaCommand = NULL;
char* dashDstr = "-Dsun.java.command=";
- if (classname == NULL && jarfile == NULL) {
+ if (what == NULL) {
/* unexpected, one of these should be set. just return without
* setting the property
*/
return;
}
- /* if the class name is not set, then use the jarfile name */
- if (classname == NULL) {
- classname = jarfile;
- }
-
/* determine the amount of memory to allocate assuming
* the individual components will be space separated
*/
- len = JLI_StrLen(classname);
+ len = JLI_StrLen(what);
for (i = 0; i < argc; i++) {
len += JLI_StrLen(argv[i]) + 1;
}
@@ -1459,7 +1424,7 @@
/* build the -D string */
*javaCommand = '\0';
JLI_StrCat(javaCommand, dashDstr);
- JLI_StrCat(javaCommand, classname);
+ JLI_StrCat(javaCommand, what);
for (i = 0; i < argc; i++) {
/* the components of the string are space separated. In
@@ -1479,7 +1444,8 @@
* JVM would like to know if it's created by a standard Sun launcher, or by
* user native application, the following property indicates the former.
*/
-void SetJavaLauncherProp() {
+void
+SetJavaLauncherProp() {
AddOption("-Dsun.java.launcher=SUN_STANDARD", NULL);
}
@@ -1913,8 +1879,8 @@
}
static int
-ContinueInNewThread(InvocationFunctions* ifn, int argc,
- char **argv, char *jarfile, char *classname, int ret)
+ContinueInNewThread(InvocationFunctions* ifn, int argc, char **argv,
+ int mode, char *what, int ret)
{
/*
@@ -1938,8 +1904,8 @@
args.argc = argc;
args.argv = argv;
- args.jarfile = jarfile;
- args.classname = classname;
+ args.mode = mode;
+ args.what = what;
args.ifn = *ifn;
rslt = ContinueInNewThread0(JavaMain, threadStackSize, (void*)&args);
--- a/jdk/src/share/bin/java.h Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/bin/java.h Fri Feb 18 12:04:36 2011 -0800
@@ -153,7 +153,7 @@
/* sun.java.launcher.* platform properties. */
void SetJavaLauncherPlatformProps(void);
-void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv);
+void SetJavaCommandLineProp(char* what, int argc, char** argv);
void SetJavaLauncherProp(void);
/*
@@ -178,8 +178,9 @@
jboolean ServerClassMachine();
-static int ContinueInNewThread(InvocationFunctions* ifn, int argc, char** argv,
- char* jarfile, char* classname, int ret);
+static int ContinueInNewThread(InvocationFunctions* ifn,
+ int argc, char** argv,
+ int mode, char *what, int ret);
/*
* Initialize platform specific settings
--- a/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/BandStructure.java Fri Feb 18 12:04:36 2011 -0800
@@ -1704,7 +1704,7 @@
for (int i = 0; i < ATTR_CONTEXT_LIMIT; i++) {
assert(attrIndexLimit[i] == 0);
attrIndexLimit[i] = 32; // just for the sake of predefs.
- attrDefs.set(i, new ArrayList<>(Collections.nCopies(
+ attrDefs.set(i, new ArrayList<Attribute.Layout>(Collections.nCopies(
attrIndexLimit[i], (Attribute.Layout)null)));
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/management/ThreadMXBean.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,221 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.management;
+
+import java.util.Map;
+
+/**
+ * Platform-specific management interface for the thread system
+ * of the Java virtual machine.
+ * <p>
+ * This platform extension is only available to a thread
+ * implementation that supports this extension.
+ *
+ * @author Paul Hohensee
+ * @since 6u25
+ */
+
+public interface ThreadMXBean extends java.lang.management.ThreadMXBean {
+ /**
+ * Returns the total CPU time for each thread whose ID is
+ * in the input array {@code ids} in nanoseconds.
+ * The returned values are of nanoseconds precision but
+ * not necessarily nanoseconds accuracy.
+ * <p>
+ * This method is equivalent to calling the
+ * {@link ThreadMXBean#getThreadCpuTime(long)}
+ * method for each thread ID in the input array {@code ids} and setting the
+ * returned value in the corresponding element of the returned array.
+ *
+ * @param ids an array of thread IDs.
+ * @return an array of long values, each of which is the amount of CPU
+ * time the thread whose ID is in the corresponding element of the input
+ * array of IDs has used,
+ * if the thread of a specified ID exists, the thread is alive,
+ * and CPU time measurement is enabled;
+ * {@code -1} otherwise.
+ *
+ * @throws NullPointerException if {@code ids} is {@code null}
+ * @throws IllegalArgumentException if any element in the input array
+ * {@code ids} is {@code <=} {@code 0}.
+ * @throws java.lang.UnsupportedOperationException if the Java
+ * virtual machine implementation does not support CPU time
+ * measurement.
+ *
+ * @see ThreadMXBean#getThreadCpuTime(long)
+ * @see #getThreadUserTime
+ * @see ThreadMXBean#isThreadCpuTimeSupported
+ * @see ThreadMXBean#isThreadCpuTimeEnabled
+ * @see ThreadMXBean#setThreadCpuTimeEnabled
+ */
+ public long[] getThreadCpuTime(long[] ids);
+
+ /**
+ * Returns the CPU time that each thread whose ID is in the input array
+ * {@code ids} has executed in user mode in nanoseconds.
+ * The returned values are of nanoseconds precision but
+ * not necessarily nanoseconds accuracy.
+ * <p>
+ * This method is equivalent to calling the
+ * {@link ThreadMXBean#getThreadUserTime(long)}
+ * method for each thread ID in the input array {@code ids} and setting the
+ * returned value in the corresponding element of the returned array.
+ *
+ * @param ids an array of thread IDs.
+ * @return an array of long values, each of which is the amount of user
+ * mode CPU time the thread whose ID is in the corresponding element of
+ * the input array of IDs has used,
+ * if the thread of a specified ID exists, the thread is alive,
+ * and CPU time measurement is enabled;
+ * {@code -1} otherwise.
+ *
+ * @throws NullPointerException if {@code ids} is {@code null}
+ * @throws IllegalArgumentException if any element in the input array
+ * {@code ids} is {@code <=} {@code 0}.
+ * @throws java.lang.UnsupportedOperationException if the Java
+ * virtual machine implementation does not support CPU time
+ * measurement.
+ *
+ * @see ThreadMXBean#getThreadUserTime(long)
+ * @see #getThreadCpuTime
+ * @see ThreadMXBean#isThreadCpuTimeSupported
+ * @see ThreadMXBean#isThreadCpuTimeEnabled
+ * @see ThreadMXBean#setThreadCpuTimeEnabled
+ */
+ public long[] getThreadUserTime(long[] ids);
+
+ /**
+ * Returns an approximation of the total amount of memory, in bytes,
+ * allocated in heap memory for the thread of the specified ID.
+ * The returned value is an approximation because some Java virtual machine
+ * implementations may use object allocation mechanisms that result in a
+ * delay between the time an object is allocated and the time its size is
+ * recorded.
+ * <p>
+ * If the thread of the specified ID is not alive or does not exist,
+ * this method returns {@code -1}. If thread memory allocation measurement
+ * is disabled, this method returns {@code -1}.
+ * A thread is alive if it has been started and has not yet died.
+ * <p>
+ * If thread memory allocation measurement is enabled after the thread has
+ * started, the Java virtual machine implementation may choose any time up
+ * to and including the time that the capability is enabled as the point
+ * where thread memory allocation measurement starts.
+ *
+ * @param id the thread ID of a thread
+ * @return an approximation of the total memory allocated, in bytes, in
+ * heap memory for a thread of the specified ID
+ * if the thread of the specified ID exists, the thread is alive,
+ * and thread memory allocation measurement is enabled;
+ * {@code -1} otherwise.
+ *
+ * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}.
+ * @throws java.lang.UnsupportedOperationException if the Java virtual
+ * machine implementation does not support thread memory allocation
+ * measurement.
+ *
+ * @see #isThreadAllocatedMemorySupported
+ * @see #isThreadAllocatedMemoryEnabled
+ * @see #setThreadAllocatedMemoryEnabled
+ */
+ public long getThreadAllocatedBytes(long id);
+
+ /**
+ * Returns an approximation of the total amount of memory, in bytes,
+ * allocated in heap memory for each thread whose ID is in the input
+ * array {@code ids}.
+ * The returned values are approximations because some Java virtual machine
+ * implementations may use object allocation mechanisms that result in a
+ * delay between the time an object is allocated and the time its size is
+ * recorded.
+ * <p>
+ * This method is equivalent to calling the
+ * {@link #getThreadAllocatedBytes(long)}
+ * method for each thread ID in the input array {@code ids} and setting the
+ * returned value in the corresponding element of the returned array.
+ *
+ * @param ids an array of thread IDs.
+ * @return an array of long values, each of which is an approximation of
+ * the total memory allocated, in bytes, in heap memory for the thread
+ * whose ID is in the corresponding element of the input array of IDs.
+ *
+ * @throws NullPointerException if {@code ids} is {@code null}
+ * @throws IllegalArgumentException if any element in the input array
+ * {@code ids} is {@code <=} {@code 0}.
+ * @throws java.lang.UnsupportedOperationException if the Java virtual
+ * machine implementation does not support thread memory allocation
+ * measurement.
+ *
+ * @see #getThreadAllocatedBytes(long)
+ * @see #isThreadAllocatedMemorySupported
+ * @see #isThreadAllocatedMemoryEnabled
+ * @see #setThreadAllocatedMemoryEnabled
+ */
+ public long[] getThreadAllocatedBytes(long[] ids);
+
+ /**
+ * Tests if the Java virtual machine implementation supports thread memory
+ * allocation measurement.
+ *
+ * @return
+ * {@code true}
+ * if the Java virtual machine implementation supports thread memory
+ * allocation measurement;
+ * {@code false} otherwise.
+ */
+ public boolean isThreadAllocatedMemorySupported();
+
+ /**
+ * Tests if thread memory allocation measurement is enabled.
+ *
+ * @return {@code true} if thread memory allocation measurement is enabled;
+ * {@code false} otherwise.
+ *
+ * @throws java.lang.UnsupportedOperationException if the Java virtual
+ * machine does not support thread memory allocation measurement.
+ *
+ * @see #isThreadAllocatedMemorySupported
+ */
+ public boolean isThreadAllocatedMemoryEnabled();
+
+ /**
+ * Enables or disables thread memory allocation measurement. The default
+ * is platform dependent.
+ *
+ * @param enable {@code true} to enable;
+ * {@code false} to disable.
+ *
+ * @throws java.lang.UnsupportedOperationException if the Java virtual
+ * machine does not support thread memory allocation measurement.
+ *
+ * @throws java.lang.SecurityException if a security manager
+ * exists and the caller does not have
+ * ManagementPermission("control").
+ *
+ * @see #isThreadAllocatedMemorySupported
+ */
+ public void setThreadAllocatedMemoryEnabled(boolean enable);
+}
--- a/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java Fri Feb 18 12:04:36 2011 -0800
@@ -223,7 +223,9 @@
} catch (RhinoException re) {
if (DEBUG) re.printStackTrace();
int line = (line = re.lineNumber()) == 0 ? -1 : line;
- throw new ScriptException(re.toString(), re.sourceName(), line);
+ ScriptException se = new ScriptException(re.toString(), re.sourceName(), line);
+ se.initCause(re);
+ throw se;
} finally {
cx.exit();
}
@@ -257,6 +259,8 @@
" str = 'null'; \n" +
" } \n" +
" var out = context.getWriter(); \n" +
+ " if (!(out instanceof java.io.PrintWriter))\n" +
+ " out = new java.io.PrintWriter(out); \n" +
" out.print(String(str)); \n" +
" if (newline) out.print('\\n'); \n" +
" out.flush(); \n" +
--- a/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/PolicyFile.java Fri Feb 18 12:04:36 2011 -0800
@@ -1180,7 +1180,7 @@
// Done
return certs;
- ArrayList<Certificate> userCertList = new ArrayList<Certificate>();
+ ArrayList<Certificate> userCertList = new ArrayList<>();
i = 0;
while (i < certs.length) {
userCertList.add(certs[i]);
--- a/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/callback/DialogCallbackHandler.java Fri Feb 18 12:04:36 2011 -0800
@@ -99,10 +99,10 @@
throws UnsupportedCallbackException
{
/* Collect messages to display in the dialog */
- final List<Object> messages = new ArrayList<Object>(3);
+ final List<Object> messages = new ArrayList<>(3);
/* Collection actions to perform if the user clicks OK */
- final List<Action> okActions = new ArrayList<Action>(2);
+ final List<Action> okActions = new ArrayList<>(2);
ConfirmationInfo confirmation = new ConfirmationInfo();
--- a/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/login/ConfigFile.java Fri Feb 18 12:04:36 2011 -0800
@@ -152,7 +152,7 @@
// new configuration
HashMap<String, LinkedList<AppConfigurationEntry>> newConfig =
- new HashMap<String, LinkedList<AppConfigurationEntry>>();
+ new HashMap<>();
if (url != null) {
@@ -392,8 +392,7 @@
String moduleClass;
String sflag;
AppConfigurationEntry.LoginModuleControlFlag controlFlag;
- LinkedList<AppConfigurationEntry> configEntries =
- new LinkedList<AppConfigurationEntry>();
+ LinkedList<AppConfigurationEntry> configEntries = new LinkedList<>();
// application name
appName = st.sval;
@@ -433,7 +432,7 @@
}
// get the args
- HashMap<String, String> options = new HashMap<String, String>();
+ HashMap<String, String> options = new HashMap<>();
String key;
String value;
while (peek(";") == false) {
--- a/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/module/JndiLoginModule.java Fri Feb 18 12:04:36 2011 -0800
@@ -184,7 +184,7 @@
private UnixNumericUserPrincipal UIDPrincipal;
private UnixNumericGroupPrincipal GIDPrincipal;
private LinkedList<UnixNumericGroupPrincipal> supplementaryGroups =
- new LinkedList<UnixNumericGroupPrincipal>();
+ new LinkedList<>();
// initial state
private Subject subject;
--- a/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/module/KeyStoreLoginModule.java Fri Feb 18 12:04:36 2011 -0800
@@ -658,8 +658,7 @@
throw new FailedLoginException(
"Unable to find X.509 certificate chain in keystore");
} else {
- LinkedList<Certificate> certList =
- new LinkedList<Certificate>();
+ LinkedList<Certificate> certList = new LinkedList<>();
for (int i=0; i < fromKeyStore.length; i++) {
certList.add(fromKeyStore[i]);
}
--- a/jdk/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/module/SolarisLoginModule.java Fri Feb 18 12:04:36 2011 -0800
@@ -76,7 +76,7 @@
private SolarisNumericUserPrincipal UIDPrincipal;
private SolarisNumericGroupPrincipal GIDPrincipal;
private LinkedList<SolarisNumericGroupPrincipal> supplementaryGroups =
- new LinkedList<SolarisNumericGroupPrincipal>();
+ new LinkedList<>();
/**
* Initialize this <code>LoginModule</code>.
--- a/jdk/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/com/sun/security/auth/module/UnixLoginModule.java Fri Feb 18 12:04:36 2011 -0800
@@ -70,7 +70,7 @@
private UnixNumericUserPrincipal UIDPrincipal;
private UnixNumericGroupPrincipal GIDPrincipal;
private LinkedList<UnixNumericGroupPrincipal> supplementaryGroups =
- new LinkedList<UnixNumericGroupPrincipal>();
+ new LinkedList<>();
/**
* Initialize this <code>LoginModule</code>.
--- a/jdk/src/share/classes/java/io/ObjectStreamClass.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java Fri Feb 18 12:04:36 2011 -0800
@@ -329,7 +329,7 @@
entry = th;
}
if (future.set(entry)) {
- Caches.localDescs.put(key, new SoftReference<>(entry));
+ Caches.localDescs.put(key, new SoftReference<Object>(entry));
} else {
// nested lookup call already set future
entry = future.get();
@@ -2118,7 +2118,7 @@
entry = th;
}
future.set(entry);
- Caches.reflectors.put(key, new SoftReference<>(entry));
+ Caches.reflectors.put(key, new SoftReference<Object>(entry));
}
if (entry instanceof FieldReflector) {
--- a/jdk/src/share/classes/java/io/PrintStream.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/io/PrintStream.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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,7 +27,9 @@
import java.util.Formatter;
import java.util.Locale;
-
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
/**
* A <code>PrintStream</code> adds functionality to another output stream,
@@ -56,7 +58,7 @@
implements Appendable, Closeable
{
- private boolean autoFlush = false;
+ private final boolean autoFlush;
private boolean trouble = false;
private Formatter formatter;
@@ -68,6 +70,60 @@
private OutputStreamWriter charOut;
/**
+ * nonNull is explicitly declared here so as not to create an extra
+ * dependency on java.util.Objects.nonNull. PrintStream is loaded
+ * early during system initialization.
+ */
+ private static <T> T nonNull(T obj, String message) {
+ if (obj == null)
+ throw new NullPointerException(message);
+ return obj;
+ }
+
+ /**
+ * Returns a charset object for the given charset name.
+ * @throws NullPointerException is csn is null
+ * @throws UnsupportedEncodingException if the charset is not supported
+ */
+ private static Charset toCharset(String csn)
+ throws UnsupportedEncodingException
+ {
+ nonNull(csn, "charsetName");
+ try {
+ return Charset.forName(csn);
+ } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
+ // UnsupportedEncodingException should be thrown
+ throw new UnsupportedEncodingException(csn);
+ }
+ }
+
+ /* Private constructors */
+ private PrintStream(boolean autoFlush, OutputStream out) {
+ super(out);
+ this.autoFlush = autoFlush;
+ this.charOut = new OutputStreamWriter(this);
+ this.textOut = new BufferedWriter(charOut);
+ }
+
+ private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
+ super(out);
+ this.autoFlush = autoFlush;
+ this.charOut = new OutputStreamWriter(this, charset);
+ this.textOut = new BufferedWriter(charOut);
+ }
+
+ /* Variant of the private constructor so that the given charset name
+ * can be verified before evaluating the OutputStream argument. Used
+ * by constructors creating a FileOutputStream that also take a
+ * charset name.
+ */
+ private PrintStream(boolean autoFlush, Charset charset, OutputStream out)
+ throws UnsupportedEncodingException
+ {
+ this(autoFlush, out, charset);
+ }
+
+ /**
* Creates a new print stream. This stream will not flush automatically.
*
* @param out The output stream to which values and objects will be
@@ -79,27 +135,6 @@
this(out, false);
}
- /* Initialization is factored into a private constructor (note the swapped
- * parameters so that this one isn't confused with the public one) and a
- * separate init method so that the following two public constructors can
- * share code. We use a separate init method so that the constructor that
- * takes an encoding will throw an NPE for a null stream before it throws
- * an UnsupportedEncodingException for an unsupported encoding.
- */
-
- private PrintStream(boolean autoFlush, OutputStream out)
- {
- super(out);
- if (out == null)
- throw new NullPointerException("Null output stream");
- this.autoFlush = autoFlush;
- }
-
- private void init(OutputStreamWriter osw) {
- this.charOut = osw;
- this.textOut = new BufferedWriter(osw);
- }
-
/**
* Creates a new print stream.
*
@@ -113,8 +148,7 @@
* @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
*/
public PrintStream(OutputStream out, boolean autoFlush) {
- this(autoFlush, out);
- init(new OutputStreamWriter(this));
+ this(autoFlush, nonNull(out, "Null output stream"));
}
/**
@@ -138,8 +172,9 @@
public PrintStream(OutputStream out, boolean autoFlush, String encoding)
throws UnsupportedEncodingException
{
- this(autoFlush, out);
- init(new OutputStreamWriter(this, encoding));
+ this(autoFlush,
+ nonNull(out, "Null output stream"),
+ toCharset(encoding));
}
/**
@@ -171,7 +206,6 @@
*/
public PrintStream(String fileName) throws FileNotFoundException {
this(false, new FileOutputStream(fileName));
- init(new OutputStreamWriter(this));
}
/**
@@ -210,8 +244,8 @@
public PrintStream(String fileName, String csn)
throws FileNotFoundException, UnsupportedEncodingException
{
- this(false, new FileOutputStream(fileName));
- init(new OutputStreamWriter(this, csn));
+ // ensure charset is checked before the file is opened
+ this(false, toCharset(csn), new FileOutputStream(fileName));
}
/**
@@ -243,7 +277,6 @@
*/
public PrintStream(File file) throws FileNotFoundException {
this(false, new FileOutputStream(file));
- init(new OutputStreamWriter(this));
}
/**
@@ -282,8 +315,8 @@
public PrintStream(File file, String csn)
throws FileNotFoundException, UnsupportedEncodingException
{
- this(false, new FileOutputStream(file));
- init(new OutputStreamWriter(this, csn));
+ // ensure charset is checked before the file is opened
+ this(false, toCharset(csn), new FileOutputStream(file));
}
/** Check to make sure that the stream has not been closed */
--- a/jdk/src/share/classes/java/io/PrintWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/io/PrintWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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,8 +25,12 @@
package java.io;
+import java.util.Objects;
import java.util.Formatter;
import java.util.Locale;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
/**
* Prints formatted representations of objects to a text-output stream. This
@@ -59,7 +63,7 @@
*/
protected Writer out;
- private boolean autoFlush = false;
+ private final boolean autoFlush;
private boolean trouble = false;
private Formatter formatter;
private PrintStream psOut = null;
@@ -68,7 +72,24 @@
* Line separator string. This is the value of the line.separator
* property at the moment that the stream was created.
*/
- private String lineSeparator;
+ private final String lineSeparator;
+
+ /**
+ * Returns a charset object for the given charset name.
+ * @throws NullPointerException is csn is null
+ * @throws UnsupportedEncodingException if the charset is not supported
+ */
+ private static Charset toCharset(String csn)
+ throws UnsupportedEncodingException
+ {
+ Objects.nonNull(csn, "charsetName");
+ try {
+ return Charset.forName(csn);
+ } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
+ // UnsupportedEncodingException should be thrown
+ throw new UnsupportedEncodingException(csn);
+ }
+ }
/**
* Creates a new PrintWriter, without automatic line flushing.
@@ -164,6 +185,14 @@
false);
}
+ /* Private constructor */
+ private PrintWriter(Charset charset, File file)
+ throws FileNotFoundException
+ {
+ this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)),
+ false);
+ }
+
/**
* Creates a new PrintWriter, without automatic line flushing, with the
* specified file name and charset. This convenience constructor creates
@@ -200,8 +229,7 @@
public PrintWriter(String fileName, String csn)
throws FileNotFoundException, UnsupportedEncodingException
{
- this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),
- false);
+ this(toCharset(csn), new File(fileName));
}
/**
@@ -272,8 +300,7 @@
public PrintWriter(File file, String csn)
throws FileNotFoundException, UnsupportedEncodingException
{
- this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),
- false);
+ this(toCharset(csn), file);
}
/** Checks to make sure that the stream has not been closed */
--- a/jdk/src/share/classes/java/lang/AutoCloseable.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/lang/AutoCloseable.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -33,7 +33,7 @@
*/
public interface AutoCloseable {
/**
- * Close this resource, relinquishing any underlying resources.
+ * Closes this resource, relinquishing any underlying resources.
* This method is invoked automatically by the {@code
* try}-with-resources statement.
*
@@ -48,6 +48,10 @@
* visible side effect, unlike {@code Closeable.close} which is
* required to have no effect if called more than once.
*
+ * However, while not required to be idempotent, implementers of
+ * this interface are strongly encouraged to make their {@code
+ * close} methods idempotent.
+ *
* @throws Exception if this resource cannot be closed
*/
void close() throws Exception;
--- a/jdk/src/share/classes/java/lang/StringCoding.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/lang/StringCoding.java Fri Feb 18 12:04:36 2011 -0800
@@ -67,7 +67,7 @@
}
private static <T> void set(ThreadLocal<SoftReference<T>> tl, T ob) {
- tl.set(new SoftReference<>(ob));
+ tl.set(new SoftReference<T>(ob));
}
// Trim the given byte array to the given length
--- a/jdk/src/share/classes/java/lang/Throwable.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/lang/Throwable.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -809,7 +809,7 @@
native StackTraceElement getStackTraceElement(int index);
/**
- * Read a {@code Throwable} from a stream, enforcing
+ * Reads a {@code Throwable} from a stream, enforcing
* well-formedness constraints on fields. Null entries and
* self-pointers are not allowed in the list of {@code
* suppressedExceptions}. Null entries are not allowed for stack
@@ -865,9 +865,10 @@
}
/**
- * Adds the specified exception to the list of exceptions that
- * were suppressed, typically by the {@code try}-with-resources
- * statement, in order to deliver this exception.
+ * Appends the specified exception to the exceptions that were
+ * suppressed in order to deliver this exception. This method is
+ * typically called (automatically and implicitly) by the {@code
+ * try}-with-resources statement.
*
* If the first exception to be suppressed is {@code null}, that
* indicates suppressed exception information will <em>not</em> be
--- a/jdk/src/share/classes/java/net/InetAddress.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/net/InetAddress.java Fri Feb 18 12:04:36 2011 -0800
@@ -677,8 +677,7 @@
static InetAddressImpl impl;
- private static HashMap<String, InetAddress[]> lookupTable
- = new HashMap<String, InetAddress[]>();
+ private static final HashMap<String, Void> lookupTable = new HashMap<>();
/**
* Represents a cache entry
@@ -737,7 +736,7 @@
// As we iterate in insertion order we can
// terminate when a non-expired entry is found.
- LinkedList<String> expired = new LinkedList<String>();
+ LinkedList<String> expired = new LinkedList<>();
long now = System.currentTimeMillis();
for (String key : cache.keySet()) {
CacheEntry entry = cache.get(key);
@@ -1227,43 +1226,45 @@
// lookupTable and return null so the
// following code would do a lookup itself.
if ((addresses = checkLookupTable(host)) == null) {
- // This is the first thread which looks up the addresses
- // this host or the cache entry for this host has been
- // expired so this thread should do the lookup.
- for (NameService nameService : nameServices) {
- try {
- /*
- * Do not put the call to lookup() inside the
- * constructor. if you do you will still be
- * allocating space when the lookup fails.
- */
+ try {
+ // This is the first thread which looks up the addresses
+ // this host or the cache entry for this host has been
+ // expired so this thread should do the lookup.
+ for (NameService nameService : nameServices) {
+ try {
+ /*
+ * Do not put the call to lookup() inside the
+ * constructor. if you do you will still be
+ * allocating space when the lookup fails.
+ */
- addresses = nameService.lookupAllHostAddr(host);
- success = true;
- break;
- } catch (UnknownHostException uhe) {
- if (host.equalsIgnoreCase("localhost")) {
- InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
- addresses = local;
+ addresses = nameService.lookupAllHostAddr(host);
success = true;
break;
- }
- else {
- addresses = unknown_array;
- success = false;
- ex = uhe;
+ } catch (UnknownHostException uhe) {
+ if (host.equalsIgnoreCase("localhost")) {
+ InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
+ addresses = local;
+ success = true;
+ break;
+ }
+ else {
+ addresses = unknown_array;
+ success = false;
+ ex = uhe;
+ }
}
}
+
+ // Cache the addresses.
+ cacheAddresses(host, addresses, success);
+ if (!success && ex != null)
+ throw ex;
+ } finally {
+ // Delete host from the lookupTable and notify
+ // all threads waiting on the lookupTable monitor.
+ updateLookupTable(host);
}
-
- // Cache the addresses.
- cacheAddresses(host, addresses, success);
- // Delete the host from the lookupTable, and
- // notify all threads waiting for the monitor
- // for lookupTable.
- updateLookupTable(host);
- if (!success && ex != null)
- throw ex;
}
return addresses;
@@ -1271,16 +1272,13 @@
private static InetAddress[] checkLookupTable(String host) {
- // make sure addresses is null.
- InetAddress[] addresses = null;
-
synchronized (lookupTable) {
// If the host isn't in the lookupTable, add it in the
// lookuptable and return null. The caller should do
// the lookup.
if (lookupTable.containsKey(host) == false) {
lookupTable.put(host, null);
- return addresses;
+ return null;
}
// If the host is in the lookupTable, it means that another
@@ -1298,10 +1296,11 @@
// the host. This thread should retry to get the addresses
// from the addressCache. If it doesn't get the addresses from
// the cache, it will try to look up the addresses itself.
- addresses = getCachedAddresses(host);
+ InetAddress[] addresses = getCachedAddresses(host);
if (addresses == null) {
synchronized (lookupTable) {
lookupTable.put(host, null);
+ return null;
}
}
--- a/jdk/src/share/classes/java/net/NetworkInterface.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/net/NetworkInterface.java Fri Feb 18 12:04:36 2011 -0800
@@ -493,55 +493,44 @@
* @see java.net.InetAddress#getAddress()
*/
public boolean equals(Object obj) {
- if ((obj == null) || !(obj instanceof NetworkInterface)) {
+ if (!(obj instanceof NetworkInterface)) {
return false;
}
- NetworkInterface netIF = (NetworkInterface)obj;
- if (name != null ) {
- if (netIF.getName() != null) {
- if (!name.equals(netIF.getName())) {
- return false;
- }
- } else {
- return false;
- }
- } else {
- if (netIF.getName() != null) {
- return false;
- }
- }
- Enumeration newAddrs = netIF.getInetAddresses();
- int i = 0;
- for (i = 0; newAddrs.hasMoreElements();newAddrs.nextElement(), i++);
- if (addrs == null) {
- if (i != 0) {
+ NetworkInterface that = (NetworkInterface)obj;
+ if (this.name != null ) {
+ if (!this.name.equals(that.name)) {
return false;
}
} else {
- /*
- * Compare number of addresses (in the checked subset)
- */
- int count = 0;
- Enumeration e = getInetAddresses();
- for (; e.hasMoreElements(); count++) {
- e.nextElement();
- }
- if (i != count) {
+ if (that.name != null) {
return false;
}
}
- newAddrs = netIF.getInetAddresses();
- for (; newAddrs.hasMoreElements();) {
- boolean equal = false;
- Enumeration thisAddrs = getInetAddresses();
- InetAddress newAddr = (InetAddress)newAddrs.nextElement();
- for (; thisAddrs.hasMoreElements();) {
- InetAddress thisAddr = (InetAddress)thisAddrs.nextElement();
- if (thisAddr.equals(newAddr)) {
- equal = true;
+
+ if (this.addrs == null) {
+ return that.addrs == null;
+ } else if (that.addrs == null) {
+ return false;
+ }
+
+ /* Both addrs not null. Compare number of addresses */
+
+ if (this.addrs.length != that.addrs.length) {
+ return false;
+ }
+
+ InetAddress[] thatAddrs = that.addrs;
+ int count = thatAddrs.length;
+
+ for (int i=0; i<count; i++) {
+ boolean found = false;
+ for (int j=0; j<count; j++) {
+ if (addrs[i].equals(thatAddrs[j])) {
+ found = true;
+ break;
}
}
- if (!equal) {
+ if (!found) {
return false;
}
}
@@ -549,12 +538,7 @@
}
public int hashCode() {
- int count = name == null? 0: name.hashCode();
- Enumeration<InetAddress> addrs = getInetAddresses();
- while (addrs.hasMoreElements()) {
- count += addrs.nextElement().hashCode();
- }
- return count;
+ return name == null? 0: name.hashCode();
}
public String toString() {
--- a/jdk/src/share/classes/java/net/SocksSocketImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -29,6 +29,7 @@
import java.io.BufferedOutputStream;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
+import sun.net.SocksProxy;
import sun.net.www.ParseUtil;
/* import org.ietf.jgss.*; */
@@ -397,6 +398,11 @@
// Use getHostString() to avoid reverse lookups
server = ((InetSocketAddress) p.address()).getHostString();
serverPort = ((InetSocketAddress) p.address()).getPort();
+ if (p instanceof SocksProxy) {
+ if (((SocksProxy)p).protocolVersion() == 4) {
+ useV4 = true;
+ }
+ }
// Connects to the SOCKS server
try {
@@ -700,6 +706,11 @@
// Use getHostString() to avoid reverse lookups
server = ((InetSocketAddress) p.address()).getHostString();
serverPort = ((InetSocketAddress) p.address()).getPort();
+ if (p instanceof SocksProxy) {
+ if (((SocksProxy)p).protocolVersion() == 4) {
+ useV4 = true;
+ }
+ }
// Connects to the SOCKS server
try {
--- a/jdk/src/share/classes/java/net/URLClassLoader.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java Fri Feb 18 12:04:36 2011 -0800
@@ -27,19 +27,15 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.io.File;
-import java.io.FilePermission;
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.Closeable;
+import java.lang.ref.*;
+import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandlerFactory;
import java.util.Enumeration;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.StringTokenizer;
+import java.util.*;
import java.util.jar.Manifest;
+import java.util.jar.JarFile;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.security.CodeSigner;
@@ -194,6 +190,65 @@
acc = AccessController.getContext();
}
+ /* A map (used as a set) to keep track of closeable local resources
+ * (either JarFiles or FileInputStreams). We don't care about
+ * Http resources since they don't need to be closed.
+ *
+ * If the resource is coming from a jar file
+ * we keep a (weak) reference to the JarFile object which can
+ * be closed if URLClassLoader.close() called. Due to jar file
+ * caching there will typically be only one JarFile object
+ * per underlying jar file.
+ *
+ * For file resources, which is probably a less common situation
+ * we have to keep a weak reference to each stream.
+ */
+
+ private WeakHashMap<Closeable,Void>
+ closeables = new WeakHashMap<>();
+
+ /**
+ * Returns an input stream for reading the specified resource.
+ * If this loader is closed, then any resources opened by this method
+ * will be closed.
+ *
+ * <p> The search order is described in the documentation for {@link
+ * #getResource(String)}. </p>
+ *
+ * @param name
+ * The resource name
+ *
+ * @return An input stream for reading the resource, or <tt>null</tt>
+ * if the resource could not be found
+ *
+ * @since 1.7
+ */
+ public InputStream getResourceAsStream(String name) {
+ URL url = getResource(name);
+ try {
+ if (url == null) {
+ return null;
+ }
+ URLConnection urlc = url.openConnection();
+ InputStream is = urlc.getInputStream();
+ if (urlc instanceof JarURLConnection) {
+ JarURLConnection juc = (JarURLConnection)urlc;
+ JarFile jar = juc.getJarFile();
+ synchronized (closeables) {
+ if (!closeables.containsKey(jar)) {
+ closeables.put(jar, null);
+ }
+ }
+ } else if (urlc instanceof sun.net.www.protocol.file.FileURLConnection) {
+ synchronized (closeables) {
+ closeables.put(is, null);
+ }
+ }
+ return is;
+ } catch (IOException e) {
+ return null;
+ }
+ }
/**
* Closes this URLClassLoader, so that it can no longer be used to load
@@ -202,8 +257,8 @@
* delegation hierarchy are still accessible. Also, any classes or resources
* that are already loaded, are still accessible.
* <p>
- * In the case of jar: and file: URLs, it also closes any class files,
- * or JAR files that were opened by it. If another thread is loading a
+ * In the case of jar: and file: URLs, it also closes any files
+ * that were opened by it. If another thread is loading a
* class when the {@code close} method is invoked, then the result of
* that load is undefined.
* <p>
@@ -213,10 +268,10 @@
* loader has no effect.
* <p>
* @throws IOException if closing any file opened by this class loader
- * resulted in an IOException. Any such exceptions are caught, and a
- * single IOException is thrown after the last file has been closed.
- * If only one exception was thrown, it will be set as the <i>cause</i>
- * of this IOException.
+ * resulted in an IOException. Any such exceptions are caught internally.
+ * If only one is caught, then it is re-thrown. If more than one exception
+ * is caught, then the second and following exceptions are added
+ * as suppressed exceptions of the first one caught, which is then re-thrown.
*
* @throws SecurityException if a security manager is set, and it denies
* {@link RuntimePermission}<tt>("closeClassLoader")</tt>
@@ -229,21 +284,33 @@
security.checkPermission(new RuntimePermission("closeClassLoader"));
}
List<IOException> errors = ucp.closeLoaders();
+
+ // now close any remaining streams.
+
+ synchronized (closeables) {
+ Set<Closeable> keys = closeables.keySet();
+ for (Closeable c : keys) {
+ try {
+ c.close();
+ } catch (IOException ioex) {
+ errors.add(ioex);
+ }
+ }
+ closeables.clear();
+ }
+
if (errors.isEmpty()) {
return;
}
- if (errors.size() == 1) {
- throw new IOException (
- "Error closing URLClassLoader resource",
- errors.get(0)
- );
+
+ IOException firstex = errors.remove(0);
+
+ // Suppress any remaining exceptions
+
+ for (IOException error: errors) {
+ firstex.addSuppressed(error);
}
- // Several exceptions. So, just combine the error messages
- String errormsg = "Error closing resources: ";
- for (IOException error: errors) {
- errormsg = errormsg + "[" + error.toString() + "] ";
- }
- throw new IOException (errormsg);
+ throw firstex;
}
/**
--- a/jdk/src/share/classes/java/net/doc-files/net-properties.html Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html Fri Feb 18 12:04:36 2011 -0800
@@ -127,10 +127,15 @@
are specified. If SOCKS is supported by a Java SE implementation, the
following properties will be used:</P>
<UL>
- <LI><P><B>socksProxyHost</B> (default: <non>)<BR>
+ <LI><P><B>socksProxyHost</B> (default: <none>)<BR>
The hostname, or address, of the proxy server.</P>
<LI><P><B>socksProxyPort</B> (default: 1080)<BR>
The port number of the proxy server.</P>
+ <LI><P><B>socksProxyVersion</B> (default: 5)<BR>
+ The version of the SOCKS protocol supported by the server. The
+ default is <code>5</code> indicating SOCKS V5, alternatively
+ <code>4</code> can be specified for SOCKS V4. Setting the property
+ to values other than these leads to unspecified behavior.</P>
<LI><P><B>java.net.socks.username</B> (default: <none>)<BR>
Username to use if the SOCKSv5 server asks for authentication
and no java.net.Authenticator instance was found.</P>
--- a/jdk/src/share/classes/java/security/AccessControlContext.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/AccessControlContext.java Fri Feb 18 12:04:36 2011 -0800
@@ -121,7 +121,7 @@
this.context = null;
}
} else {
- List<ProtectionDomain> v = new ArrayList<ProtectionDomain>(context.length);
+ List<ProtectionDomain> v = new ArrayList<>(context.length);
for (int i =0; i< context.length; i++) {
if ((context[i] != null) && (!v.contains(context[i])))
v.add(context[i]);
--- a/jdk/src/share/classes/java/security/BasicPermission.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/BasicPermission.java Fri Feb 18 12:04:36 2011 -0800
@@ -515,7 +515,7 @@
// Copy perms into a Hashtable
Hashtable<String, Permission> permissions =
- new Hashtable<String, Permission>(perms.size()*2);
+ new Hashtable<>(perms.size()*2);
synchronized (this) {
permissions.putAll(perms);
--- a/jdk/src/share/classes/java/security/CodeSource.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/CodeSource.java Fri Feb 18 12:04:36 2011 -0800
@@ -188,7 +188,7 @@
} else if (signers != null) {
// Convert the code signers to certs
ArrayList<java.security.cert.Certificate> certChains =
- new ArrayList<java.security.cert.Certificate>();
+ new ArrayList<>();
for (int i = 0; i < signers.length; i++) {
certChains.addAll(
signers[i].getSignerCertPath().getCertificates());
@@ -606,10 +606,10 @@
// Iterate through all the certificates
int i = 0;
- List<CodeSigner> signers = new ArrayList<CodeSigner>();
+ List<CodeSigner> signers = new ArrayList<>();
while (i < certs.length) {
List<java.security.cert.Certificate> certChain =
- new ArrayList<java.security.cert.Certificate>();
+ new ArrayList<>();
certChain.add(certs[i++]); // first cert is an end-entity cert
int j = i;
--- a/jdk/src/share/classes/java/security/Permissions.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/Permissions.java Fri Feb 18 12:04:36 2011 -0800
@@ -362,7 +362,7 @@
// Copy perms into a Hashtable
Hashtable<Class<?>, PermissionCollection> perms =
- new Hashtable<Class<?>, PermissionCollection>(permsMap.size()*2); // no sync; estimate
+ new Hashtable<>(permsMap.size()*2); // no sync; estimate
synchronized (this) {
perms.putAll(permsMap);
}
@@ -567,7 +567,7 @@
// Copy perms into a Hashtable
Hashtable<Permission, Permission> perms =
- new Hashtable<Permission, Permission>(permsMap.size()*2);
+ new Hashtable<>(permsMap.size()*2);
synchronized (this) {
perms.putAll(permsMap);
}
--- a/jdk/src/share/classes/java/security/ProtectionDomain.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/ProtectionDomain.java Fri Feb 18 12:04:36 2011 -0800
@@ -336,8 +336,8 @@
int swag = 32;
int vcap = 8;
Enumeration<Permission> e;
- List<Permission> pdVector = new ArrayList<Permission>(vcap);
- List<Permission> plVector = new ArrayList<Permission>(swag);
+ List<Permission> pdVector = new ArrayList<>(vcap);
+ List<Permission> plVector = new ArrayList<>(swag);
//
// Build a vector of domain permissions for subsequent merge
--- a/jdk/src/share/classes/java/security/Provider.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/Provider.java Fri Feb 18 12:04:36 2011 -0800
@@ -437,7 +437,7 @@
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
- Map<Object,Object> copy = new HashMap<Object,Object>();
+ Map<Object,Object> copy = new HashMap<>();
for (Map.Entry<Object,Object> entry : super.entrySet()) {
copy.put(entry.getKey(), entry.getValue());
}
@@ -719,7 +719,7 @@
}
if (serviceSet == null) {
ensureLegacyParsed();
- Set<Service> set = new LinkedHashSet<Service>();
+ Set<Service> set = new LinkedHashSet<>();
if (serviceMap != null) {
set.addAll(serviceMap.values());
}
@@ -1395,7 +1395,7 @@
if (s != null) {
String[] classNames = s.split("\\|");
List<Class> classList =
- new ArrayList<Class>(classNames.length);
+ new ArrayList<>(classNames.length);
for (String className : classNames) {
Class clazz = getKeyClass(className);
if (clazz != null) {
--- a/jdk/src/share/classes/java/security/SecureClassLoader.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/SecureClassLoader.java Fri Feb 18 12:04:36 2011 -0800
@@ -50,7 +50,7 @@
// HashMap that maps CodeSource to ProtectionDomain
// @GuardedBy("pdcache")
private final HashMap<CodeSource, ProtectionDomain> pdcache =
- new HashMap<CodeSource, ProtectionDomain>(11);
+ new HashMap<>(11);
private static final Debug debug = Debug.getInstance("scl");
--- a/jdk/src/share/classes/java/security/Security.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/Security.java Fri Feb 18 12:04:36 2011 -0800
@@ -545,8 +545,7 @@
value = filter.substring(index + 1);
}
- Hashtable<String, String> hashtableFilter =
- new Hashtable<String, String>(1);
+ Hashtable<String, String> hashtableFilter = new Hashtable<>(1);
hashtableFilter.put(key, value);
return (getProviders(hashtableFilter));
@@ -606,7 +605,7 @@
// Then only return those providers who satisfy the selection criteria.
Provider[] allProviders = Security.getProviders();
Set<String> keySet = filter.keySet();
- LinkedHashSet<Provider> candidates = new LinkedHashSet<Provider>(5);
+ LinkedHashSet<Provider> candidates = new LinkedHashSet<>(5);
// Returns all installed providers
// if the selection criteria is null.
@@ -660,8 +659,7 @@
}
// Map containing cached Spi Class objects of the specified type
- private static final Map<String,Class> spiMap =
- new ConcurrentHashMap<String,Class>();
+ private static final Map<String, Class> spiMap = new ConcurrentHashMap<>();
/**
* Return the Class object for the given engine type
@@ -885,7 +883,7 @@
String attrName,
String filterValue,
Provider[] allProviders) {
- LinkedHashSet<Provider> candidates = new LinkedHashSet<Provider>(5);
+ LinkedHashSet<Provider> candidates = new LinkedHashSet<>(5);
for (int i = 0; i < allProviders.length; i++) {
if (isCriterionSatisfied(allProviders[i], serviceName,
algName,
@@ -1082,7 +1080,7 @@
return Collections.EMPTY_SET;
}
- HashSet<String> result = new HashSet<String>();
+ HashSet<String> result = new HashSet<>();
Provider[] providers = Security.getProviders();
for (int i = 0; i < providers.length; i++) {
--- a/jdk/src/share/classes/java/security/UnresolvedPermission.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/UnresolvedPermission.java Fri Feb 18 12:04:36 2011 -0800
@@ -198,7 +198,7 @@
if (this.certs == null) {
// extract the signer certs
ArrayList<java.security.cert.Certificate> signerCerts =
- new ArrayList<java.security.cert.Certificate>();
+ new ArrayList<>();
i = 0;
while (i < certs.length) {
signerCerts.add(certs[i]);
--- a/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/security/UnresolvedPermissionCollection.java Fri Feb 18 12:04:36 2011 -0800
@@ -119,7 +119,7 @@
public Enumeration<Permission> elements() {
List<Permission> results =
- new ArrayList<Permission>(); // where results are stored
+ new ArrayList<>(); // where results are stored
// Get iterator of Map values (which are lists of permissions)
synchronized (this) {
@@ -161,7 +161,7 @@
// Copy perms into a Hashtable
Hashtable<String, Vector<UnresolvedPermission>> permissions =
- new Hashtable<String, Vector<UnresolvedPermission>>(perms.size()*2);
+ new Hashtable<>(perms.size()*2);
// Convert each entry (List) into a Vector
synchronized (this) {
@@ -169,8 +169,7 @@
for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
// Convert list into Vector
List<UnresolvedPermission> list = e.getValue();
- Vector<UnresolvedPermission> vec =
- new Vector<UnresolvedPermission>(list.size());
+ Vector<UnresolvedPermission> vec = new Vector<>(list.size());
synchronized (list) {
vec.addAll(list);
}
@@ -207,8 +206,7 @@
for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
// Convert Vector into ArrayList
Vector<UnresolvedPermission> vec = e.getValue();
- List<UnresolvedPermission> list =
- new ArrayList<UnresolvedPermission>(vec.size());
+ List<UnresolvedPermission> list = new ArrayList<>(vec.size());
list.addAll(vec);
// Add to Hashtable being serialized
--- a/jdk/src/share/classes/java/sql/Timestamp.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/sql/Timestamp.java Fri Feb 18 12:04:36 2011 -0800
@@ -473,7 +473,9 @@
* @since 1.4
*/
public int compareTo(Timestamp ts) {
- int i = super.compareTo(ts);
+ long thisTime = this.getTime();
+ long anotherTime = ts.getTime();
+ int i = (thisTime<anotherTime ? -1 :(thisTime==anotherTime?0 :1));
if (i == 0) {
if (nanos > ts.nanos) {
return 1;
--- a/jdk/src/share/classes/java/util/Collections.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/Collections.java Fri Feb 18 12:04:36 2011 -0800
@@ -1452,10 +1452,10 @@
* when o is a Map.Entry, and calls o.setValue.
*/
public boolean containsAll(Collection<?> coll) {
- Iterator<?> it = coll.iterator();
- while (it.hasNext())
- if (!contains(it.next())) // Invokes safe contains() above
+ for (Object e : coll) {
+ if (!contains(e)) // Invokes safe contains() above
return false;
+ }
return true;
}
public boolean equals(Object o) {
@@ -3713,45 +3713,91 @@
}
/**
- * Returns <tt>true</tt> if the two specified collections have no
+ * Returns {@code true} if the two specified collections have no
* elements in common.
*
* <p>Care must be exercised if this method is used on collections that
- * do not comply with the general contract for <tt>Collection</tt>.
+ * do not comply with the general contract for {@code Collection}.
* Implementations may elect to iterate over either collection and test
* for containment in the other collection (or to perform any equivalent
* computation). If either collection uses a nonstandard equality test
- * (as does a {@link SortedSet} whose ordering is not <i>compatible with
- * equals</i>, or the key set of an {@link IdentityHashMap}), both
+ * (as does a {@link SortedSet} whose ordering is not <em>compatible with
+ * equals</em>, or the key set of an {@link IdentityHashMap}), both
* collections must use the same nonstandard equality test, or the
* result of this method is undefined.
*
+ * <p>Care must also be exercised when using collections that have
+ * restrictions on the elements that they may contain. Collection
+ * implementations are allowed to throw exceptions for any operation
+ * involving elements they deem ineligible. For absolute safety the
+ * specified collections should contain only elements which are
+ * eligible elements for both collections.
+ *
* <p>Note that it is permissible to pass the same collection in both
- * parameters, in which case the method will return true if and only if
- * the collection is empty.
+ * parameters, in which case the method will return {@code true} if and
+ * only if the collection is empty.
*
* @param c1 a collection
* @param c2 a collection
- * @throws NullPointerException if either collection is null
+ * @return {@code true} if the two specified collections have no
+ * elements in common.
+ * @throws NullPointerException if either collection is {@code null}.
+ * @throws NullPointerException if one collection contains a {@code null}
+ * element and {@code null} is not an eligible element for the other collection.
+ * (optional)
+ * @throws ClassCastException if one collection contains an element that is
+ * of a type which is ineligible for the other collection. (optional)
* @since 1.5
*/
public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
- /*
- * We're going to iterate through c1 and test for inclusion in c2.
- * If c1 is a Set and c2 isn't, swap the collections. Otherwise,
- * place the shorter collection in c1. Hopefully this heuristic
- * will minimize the cost of the operation.
- */
- if ((c1 instanceof Set) && !(c2 instanceof Set) ||
- (c1.size() > c2.size())) {
- Collection<?> tmp = c1;
- c1 = c2;
- c2 = tmp;
+ // The collection to be used for contains(). Preference is given to
+ // the collection who's contains() has lower O() complexity.
+ Collection<?> contains = c2;
+ // The collection to be iterated. If the collections' contains() impl
+ // are of different O() complexity, the collection with slower
+ // contains() will be used for iteration. For collections who's
+ // contains() are of the same complexity then best performance is
+ // achieved by iterating the smaller collection.
+ Collection<?> iterate = c1;
+
+ // Performance optimization cases. The heuristics:
+ // 1. Generally iterate over c1.
+ // 2. If c1 is a Set then iterate over c2.
+ // 3. If either collection is empty then result is always true.
+ // 4. Iterate over the smaller Collection.
+ if (c1 instanceof Set) {
+ // Use c1 for contains as a Set's contains() is expected to perform
+ // better than O(N/2)
+ iterate = c2;
+ contains = c1;
+ } else if (!(c2 instanceof Set)) {
+ // Both are mere Collections. Iterate over smaller collection.
+ // Example: If c1 contains 3 elements and c2 contains 50 elements and
+ // assuming contains() requires ceiling(N/2) comparisons then
+ // checking for all c1 elements in c2 would require 75 comparisons
+ // (3 * ceiling(50/2)) vs. checking all c2 elements in c1 requiring
+ // 100 comparisons (50 * ceiling(3/2)).
+ int c1size = c1.size();
+ int c2size = c2.size();
+ if (c1size == 0 || c2size == 0) {
+ // At least one collection is empty. Nothing will match.
+ return true;
+ }
+
+ if (c1size > c2size) {
+ iterate = c2;
+ contains = c1;
+ }
}
- for (Object e : c1)
- if (c2.contains(e))
+ for (Object e : iterate) {
+ if (contains.contains(e)) {
+ // Found a common element. Collections are not disjoint.
return false;
+ }
+ }
+
+ // No common elements were found.
return true;
}
--- a/jdk/src/share/classes/java/util/Formatter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/Formatter.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -41,6 +41,8 @@
import java.math.MathContext;
import java.math.RoundingMode;
import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
import java.text.DateFormatSymbols;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
@@ -1838,22 +1840,53 @@
*/
public final class Formatter implements Closeable, Flushable {
private Appendable a;
- private Locale l;
+ private final Locale l;
private IOException lastException;
- private char zero = '0';
+ private final char zero;
private static double scaleUp;
// 1 (sign) + 19 (max # sig digits) + 1 ('.') + 1 ('e') + 1 (sign)
// + 3 (max # exp digits) + 4 (error) = 30
private static final int MAX_FD_CHARS = 30;
- // Initialize internal data.
- private void init(Appendable a, Locale l) {
+ /**
+ * Returns a charset object for the given charset name.
+ * @throws NullPointerException is csn is null
+ * @throws UnsupportedEncodingException if the charset is not supported
+ */
+ private static Charset toCharset(String csn)
+ throws UnsupportedEncodingException
+ {
+ Objects.nonNull(csn, "charsetName");
+ try {
+ return Charset.forName(csn);
+ } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
+ // UnsupportedEncodingException should be thrown
+ throw new UnsupportedEncodingException(csn);
+ }
+ }
+
+ private static final Appendable nonNullAppendable(Appendable a) {
+ if (a == null)
+ return new StringBuilder();
+
+ return a;
+ }
+
+ /* Private constructors */
+ private Formatter(Locale l, Appendable a) {
this.a = a;
this.l = l;
- setZero();
+ this.zero = getZero(l);
+ }
+
+ private Formatter(Charset charset, Locale l, File file)
+ throws FileNotFoundException
+ {
+ this(l,
+ new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset)));
}
/**
@@ -1867,7 +1900,7 @@
* virtual machine.
*/
public Formatter() {
- init(new StringBuilder(), Locale.getDefault(Locale.Category.FORMAT));
+ this(Locale.getDefault(Locale.Category.FORMAT), new StringBuilder());
}
/**
@@ -1881,9 +1914,7 @@
* {@code null} then a {@link StringBuilder} will be created.
*/
public Formatter(Appendable a) {
- if (a == null)
- a = new StringBuilder();
- init(a, Locale.getDefault(Locale.Category.FORMAT));
+ this(Locale.getDefault(Locale.Category.FORMAT), nonNullAppendable(a));
}
/**
@@ -1900,7 +1931,7 @@
* is applied.
*/
public Formatter(Locale l) {
- init(new StringBuilder(), l);
+ this(l, new StringBuilder());
}
/**
@@ -1916,9 +1947,7 @@
* is applied.
*/
public Formatter(Appendable a, Locale l) {
- if (a == null)
- a = new StringBuilder();
- init(a, l);
+ this(l, nonNullAppendable(a));
}
/**
@@ -1949,8 +1978,8 @@
* creating the file
*/
public Formatter(String fileName) throws FileNotFoundException {
- init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
- Locale.getDefault(Locale.Category.FORMAT));
+ this(Locale.getDefault(Locale.Category.FORMAT),
+ new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))));
}
/**
@@ -2025,8 +2054,7 @@
public Formatter(String fileName, String csn, Locale l)
throws FileNotFoundException, UnsupportedEncodingException
{
- init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), csn)),
- l);
+ this(toCharset(csn), l, new File(fileName));
}
/**
@@ -2057,8 +2085,8 @@
* creating the file
*/
public Formatter(File file) throws FileNotFoundException {
- init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
- Locale.getDefault(Locale.Category.FORMAT));
+ this(Locale.getDefault(Locale.Category.FORMAT),
+ new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))));
}
/**
@@ -2133,8 +2161,7 @@
public Formatter(File file, String csn, Locale l)
throws FileNotFoundException, UnsupportedEncodingException
{
- init(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), csn)),
- l);
+ this(toCharset(csn), l, file);
}
/**
@@ -2151,9 +2178,8 @@
* The stream to use as the destination of this formatter.
*/
public Formatter(PrintStream ps) {
- if (ps == null)
- throw new NullPointerException();
- init((Appendable)ps, Locale.getDefault(Locale.Category.FORMAT));
+ this(Locale.getDefault(Locale.Category.FORMAT),
+ (Appendable)Objects.nonNull(ps));
}
/**
@@ -2171,8 +2197,8 @@
* The output will be buffered.
*/
public Formatter(OutputStream os) {
- init(new BufferedWriter(new OutputStreamWriter(os)),
- Locale.getDefault(Locale.Category.FORMAT));
+ this(Locale.getDefault(Locale.Category.FORMAT),
+ new BufferedWriter(new OutputStreamWriter(os)));
}
/**
@@ -2222,13 +2248,15 @@
public Formatter(OutputStream os, String csn, Locale l)
throws UnsupportedEncodingException
{
- init(new BufferedWriter(new OutputStreamWriter(os, csn)), l);
+ this(l, new BufferedWriter(new OutputStreamWriter(os, csn)));
}
- private void setZero() {
+ private static char getZero(Locale l) {
if ((l != null) && !l.equals(Locale.US)) {
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
- zero = dfs.getZeroDigit();
+ return dfs.getZeroDigit();
+ } else {
+ return '0';
}
}
--- a/jdk/src/share/classes/java/util/LinkedList.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/LinkedList.java Fri Feb 18 12:04:36 2011 -0800
@@ -26,9 +26,9 @@
package java.util;
/**
- * Linked list implementation of the {@link List} and {@link Deque} interfaces.
- * Implements all optional operations, and permits all elements (including
- * {@code null}).
+ * Doubly-linked list implementation of the {@code List} and {@code Deque}
+ * interfaces. Implements all optional list operations, and permits all
+ * elements (including {@code null}).
*
* <p>All of the operations perform as could be expected for a doubly-linked
* list. Operations that index into the list will traverse the list from
@@ -249,7 +249,7 @@
* @return the last element in this list
* @throws NoSuchElementException if this list is empty
*/
- public E getLast() {
+ public E getLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
--- a/jdk/src/share/classes/java/util/Scanner.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/Scanner.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -571,10 +571,8 @@
* @return A scanner with the specified source and pattern
*/
private Scanner(Readable source, Pattern pattern) {
- if (source == null)
- throw new NullPointerException("source");
- if (pattern == null)
- throw new NullPointerException("pattern");
+ assert source != null : "source should not be null";
+ assert pattern != null : "pattern should not be null";
this.source = source;
delimPattern = pattern;
buf = CharBuffer.allocate(BUFFER_SIZE);
@@ -593,7 +591,7 @@
* interface
*/
public Scanner(Readable source) {
- this(source, WHITESPACE_PATTERN);
+ this(Objects.nonNull(source, "source"), WHITESPACE_PATTERN);
}
/**
@@ -620,23 +618,27 @@
* does not exist
*/
public Scanner(InputStream source, String charsetName) {
- this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
+ this(makeReadable(Objects.nonNull(source, "source"), toCharset(charsetName)),
+ WHITESPACE_PATTERN);
}
- private static Readable makeReadable(InputStream source,
- String charsetName)
- {
- if (source == null)
- throw new NullPointerException("source");
- InputStreamReader isr = null;
+ /**
+ * Returns a charset object for the given charset name.
+ * @throws NullPointerException is csn is null
+ * @throws IllegalArgumentException if the charset is not supported
+ */
+ private static Charset toCharset(String csn) {
+ Objects.nonNull(csn, "charsetName");
try {
- isr = new InputStreamReader(source, charsetName);
- } catch (UnsupportedEncodingException uee) {
- IllegalArgumentException iae = new IllegalArgumentException();
- iae.initCause(uee);
- throw iae;
+ return Charset.forName(csn);
+ } catch (IllegalCharsetNameException|UnsupportedCharsetException e) {
+ // IllegalArgumentException should be thrown
+ throw new IllegalArgumentException(e);
}
- return isr;
+ }
+
+ private static Readable makeReadable(InputStream source, Charset charset) {
+ return new InputStreamReader(source, charset);
}
/**
@@ -648,9 +650,7 @@
* @param source A file to be scanned
* @throws FileNotFoundException if source is not found
*/
- public Scanner(File source)
- throws FileNotFoundException
- {
+ public Scanner(File source) throws FileNotFoundException {
this((ReadableByteChannel)(new FileInputStream(source).getChannel()));
}
@@ -669,8 +669,27 @@
public Scanner(File source, String charsetName)
throws FileNotFoundException
{
- this((ReadableByteChannel)(new FileInputStream(source).getChannel()),
- charsetName);
+ this(Objects.nonNull(source), toDecoder(charsetName));
+ }
+
+ private Scanner(File source, CharsetDecoder dec)
+ throws FileNotFoundException
+ {
+ this(makeReadable((ReadableByteChannel)(new FileInputStream(source).getChannel()), dec));
+ }
+
+ private static CharsetDecoder toDecoder(String charsetName) {
+ Objects.nonNull(charsetName, "charsetName");
+ try {
+ return Charset.forName(charsetName).newDecoder();
+ } catch (IllegalCharsetNameException|UnsupportedCharsetException unused) {
+ throw new IllegalArgumentException(charsetName);
+ }
+ }
+
+ private static Readable makeReadable(ReadableByteChannel source,
+ CharsetDecoder dec) {
+ return Channels.newReader(source, dec, -1);
}
/**
@@ -708,10 +727,12 @@
* if the specified encoding is not found
* @since 1.7
*/
- public Scanner(FileRef source, String charsetName)
- throws IOException
- {
- this(source.newInputStream(), charsetName);
+ public Scanner(FileRef source, String charsetName) throws IOException {
+ this(Objects.nonNull(source), toCharset(charsetName));
+ }
+
+ private Scanner(FileRef source, Charset charset) throws IOException {
+ this(makeReadable(source.newInputStream(), charset));
}
/**
@@ -733,16 +754,12 @@
* @param source A channel to scan
*/
public Scanner(ReadableByteChannel source) {
- this(makeReadable(source), WHITESPACE_PATTERN);
+ this(makeReadable(Objects.nonNull(source, "source")),
+ WHITESPACE_PATTERN);
}
private static Readable makeReadable(ReadableByteChannel source) {
- if (source == null)
- throw new NullPointerException("source");
- String defaultCharsetName =
- java.nio.charset.Charset.defaultCharset().name();
- return Channels.newReader(source,
- java.nio.charset.Charset.defaultCharset().name());
+ return makeReadable(source, Charset.defaultCharset().newDecoder());
}
/**
@@ -757,17 +774,8 @@
* does not exist
*/
public Scanner(ReadableByteChannel source, String charsetName) {
- this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
- }
-
- private static Readable makeReadable(ReadableByteChannel source,
- String charsetName)
- {
- if (source == null)
- throw new NullPointerException("source");
- if (!Charset.isSupported(charsetName))
- throw new IllegalArgumentException(charsetName);
- return Channels.newReader(source, charsetName);
+ this(makeReadable(Objects.nonNull(source, "source"), toDecoder(charsetName)),
+ WHITESPACE_PATTERN);
}
// Private primitives used to support scanning
--- a/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ArrayBlockingQueue.java Fri Feb 18 12:04:36 2011 -0800
@@ -49,14 +49,14 @@
* <p>This is a classic "bounded buffer", in which a
* fixed-sized array holds elements inserted by producers and
* extracted by consumers. Once created, the capacity cannot be
- * increased. Attempts to <tt>put</tt> an element into a full queue
- * will result in the operation blocking; attempts to <tt>take</tt> an
+ * changed. Attempts to {@code put} an element into a full queue
+ * will result in the operation blocking; attempts to {@code take} an
* element from an empty queue will similarly block.
*
- * <p> This class supports an optional fairness policy for ordering
+ * <p>This class supports an optional fairness policy for ordering
* waiting producer and consumer threads. By default, this ordering
* is not guaranteed. However, a queue constructed with fairness set
- * to <tt>true</tt> grants threads access in FIFO order. Fairness
+ * to {@code true} grants threads access in FIFO order. Fairness
* generally decreases throughput but reduces variability and avoids
* starvation.
*
@@ -83,14 +83,17 @@
*/
private static final long serialVersionUID = -817911632652898426L;
- /** The queued items */
- private final E[] items;
- /** items index for next take, poll or remove */
- private int takeIndex;
- /** items index for next put, offer, or add. */
- private int putIndex;
- /** Number of items in the queue */
- private int count;
+ /** The queued items */
+ final Object[] items;
+
+ /** items index for next take, poll, peek or remove */
+ int takeIndex;
+
+ /** items index for next put, offer, or add */
+ int putIndex;
+
+ /** Number of elements in the queue */
+ int count;
/*
* Concurrency control uses the classic two-condition algorithm
@@ -98,7 +101,7 @@
*/
/** Main lock guarding all access */
- private final ReentrantLock lock;
+ final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
@@ -110,7 +113,36 @@
* Circularly increment i.
*/
final int inc(int i) {
- return (++i == items.length)? 0 : i;
+ return (++i == items.length) ? 0 : i;
+ }
+
+ /**
+ * Circularly decrement i.
+ */
+ final int dec(int i) {
+ return ((i == 0) ? items.length : i) - 1;
+ }
+
+ @SuppressWarnings("unchecked")
+ static <E> E cast(Object item) {
+ return (E) item;
+ }
+
+ /**
+ * Returns item at index i.
+ */
+ final E itemAt(int i) {
+ return this.<E>cast(items[i]);
+ }
+
+ /**
+ * Throws NullPointerException if argument is null.
+ *
+ * @param v the element
+ */
+ private static void checkNotNull(Object v) {
+ if (v == null)
+ throw new NullPointerException();
}
/**
@@ -129,8 +161,8 @@
* Call only when holding lock.
*/
private E extract() {
- final E[] items = this.items;
- E x = items[takeIndex];
+ final Object[] items = this.items;
+ E x = this.<E>cast(items[takeIndex]);
items[takeIndex] = null;
takeIndex = inc(takeIndex);
--count;
@@ -139,11 +171,12 @@
}
/**
- * Utility for remove and iterator.remove: Delete item at position i.
+ * Deletes item at position i.
+ * Utility for remove and iterator.remove.
* Call only when holding lock.
*/
void removeAt(int i) {
- final E[] items = this.items;
+ final Object[] items = this.items;
// if removing front item, just advance
if (i == takeIndex) {
items[takeIndex] = null;
@@ -167,69 +200,82 @@
}
/**
- * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * Creates an {@code ArrayBlockingQueue} with the given (fixed)
* capacity and default access policy.
*
* @param capacity the capacity of this queue
- * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ * @throws IllegalArgumentException if {@code capacity < 1}
*/
public ArrayBlockingQueue(int capacity) {
this(capacity, false);
}
/**
- * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * Creates an {@code ArrayBlockingQueue} with the given (fixed)
* capacity and the specified access policy.
*
* @param capacity the capacity of this queue
- * @param fair if <tt>true</tt> then queue accesses for threads blocked
+ * @param fair if {@code true} then queue accesses for threads blocked
* on insertion or removal, are processed in FIFO order;
- * if <tt>false</tt> the access order is unspecified.
- * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+ * if {@code false} the access order is unspecified.
+ * @throws IllegalArgumentException if {@code capacity < 1}
*/
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
- this.items = (E[]) new Object[capacity];
+ this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
/**
- * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
+ * Creates an {@code ArrayBlockingQueue} with the given (fixed)
* capacity, the specified access policy and initially containing the
* elements of the given collection,
* added in traversal order of the collection's iterator.
*
* @param capacity the capacity of this queue
- * @param fair if <tt>true</tt> then queue accesses for threads blocked
+ * @param fair if {@code true} then queue accesses for threads blocked
* on insertion or removal, are processed in FIFO order;
- * if <tt>false</tt> the access order is unspecified.
+ * if {@code false} the access order is unspecified.
* @param c the collection of elements to initially contain
- * @throws IllegalArgumentException if <tt>capacity</tt> is less than
- * <tt>c.size()</tt>, or less than 1.
+ * @throws IllegalArgumentException if {@code capacity} is less than
+ * {@code c.size()}, or less than 1.
* @throws NullPointerException if the specified collection or any
* of its elements are null
*/
public ArrayBlockingQueue(int capacity, boolean fair,
Collection<? extends E> c) {
this(capacity, fair);
- if (capacity < c.size())
- throw new IllegalArgumentException();
- for (E e : c)
- add(e);
+ final ReentrantLock lock = this.lock;
+ lock.lock(); // Lock only for visibility, not mutual exclusion
+ try {
+ int i = 0;
+ try {
+ for (E e : c) {
+ checkNotNull(e);
+ items[i++] = e;
+ }
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ throw new IllegalArgumentException();
+ }
+ count = i;
+ putIndex = (i == capacity) ? 0 : i;
+ } finally {
+ lock.unlock();
+ }
}
/**
* Inserts the specified element at the tail of this queue if it is
* possible to do so immediately without exceeding the queue's capacity,
- * returning <tt>true</tt> upon success and throwing an
- * <tt>IllegalStateException</tt> if this queue is full.
+ * returning {@code true} upon success and throwing an
+ * {@code IllegalStateException} if this queue is full.
*
* @param e the element to add
- * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if this queue is full
* @throws NullPointerException if the specified element is null
*/
@@ -240,14 +286,14 @@
/**
* Inserts the specified element at the tail of this queue if it is
* possible to do so immediately without exceeding the queue's capacity,
- * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+ * returning {@code true} upon success and {@code false} if this queue
* is full. This method is generally preferable to method {@link #add},
* which can fail to insert an element only by throwing an exception.
*
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
- if (e == null) throw new NullPointerException();
+ checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -270,18 +316,12 @@
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
- if (e == null) throw new NullPointerException();
- final E[] items = this.items;
+ checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
- try {
- while (count == items.length)
- notFull.await();
- } catch (InterruptedException ie) {
- notFull.signal(); // propagate to non-interrupted thread
- throw ie;
- }
+ while (count == items.length)
+ notFull.await();
insert(e);
} finally {
lock.unlock();
@@ -299,25 +339,18 @@
public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
- if (e == null) throw new NullPointerException();
+ checkNotNull(e);
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
- for (;;) {
- if (count != items.length) {
- insert(e);
- return true;
- }
+ while (count == items.length) {
if (nanos <= 0)
return false;
- try {
- nanos = notFull.awaitNanos(nanos);
- } catch (InterruptedException ie) {
- notFull.signal(); // propagate to non-interrupted thread
- throw ie;
- }
+ nanos = notFull.awaitNanos(nanos);
}
+ insert(e);
+ return true;
} finally {
lock.unlock();
}
@@ -327,10 +360,7 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- if (count == 0)
- return null;
- E x = extract();
- return x;
+ return (count == 0) ? null : extract();
} finally {
lock.unlock();
}
@@ -340,15 +370,9 @@
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
- try {
- while (count == 0)
- notEmpty.await();
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
- E x = extract();
- return x;
+ while (count == 0)
+ notEmpty.await();
+ return extract();
} finally {
lock.unlock();
}
@@ -359,21 +383,12 @@
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
- for (;;) {
- if (count != 0) {
- E x = extract();
- return x;
- }
+ while (count == 0) {
if (nanos <= 0)
return null;
- try {
- nanos = notEmpty.awaitNanos(nanos);
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
-
+ nanos = notEmpty.awaitNanos(nanos);
}
+ return extract();
} finally {
lock.unlock();
}
@@ -383,7 +398,7 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return (count == 0) ? null : items[takeIndex];
+ return (count == 0) ? null : itemAt(takeIndex);
} finally {
lock.unlock();
}
@@ -412,10 +427,10 @@
* Returns the number of additional elements that this queue can ideally
* (in the absence of memory or resource constraints) accept without
* blocking. This is always equal to the initial capacity of this queue
- * less the current <tt>size</tt> of this queue.
+ * less the current {@code size} of this queue.
*
* <p>Note that you <em>cannot</em> always tell if an attempt to insert
- * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * an element will succeed by inspecting {@code remainingCapacity}
* because it may be the case that another thread is about to
* insert or remove an element.
*/
@@ -431,59 +446,56 @@
/**
* Removes a single instance of the specified element from this queue,
- * if it is present. More formally, removes an element <tt>e</tt> such
- * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * if it is present. More formally, removes an element {@code e} such
+ * that {@code o.equals(e)}, if this queue contains one or more such
* elements.
- * Returns <tt>true</tt> if this queue contained the specified element
+ * Returns {@code true} if this queue contained the specified element
* (or equivalently, if this queue changed as a result of the call).
*
+ * <p>Removal of interior elements in circular array based queues
+ * is an intrinsically slow and disruptive operation, so should
+ * be undertaken only in exceptional circumstances, ideally
+ * only when the queue is known not to be accessible by other
+ * threads.
+ *
* @param o element to be removed from this queue, if present
- * @return <tt>true</tt> if this queue changed as a result of the call
+ * @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
if (o == null) return false;
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- int i = takeIndex;
- int k = 0;
- for (;;) {
- if (k++ >= count)
- return false;
+ for (int i = takeIndex, k = count; k > 0; i = inc(i), k--) {
if (o.equals(items[i])) {
removeAt(i);
return true;
}
- i = inc(i);
}
-
+ return false;
} finally {
lock.unlock();
}
}
/**
- * Returns <tt>true</tt> if this queue contains the specified element.
- * More formally, returns <tt>true</tt> if and only if this queue contains
- * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ * Returns {@code true} if this queue contains the specified element.
+ * More formally, returns {@code true} if and only if this queue contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this queue
- * @return <tt>true</tt> if this queue contains the specified element
+ * @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
if (o == null) return false;
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- int i = takeIndex;
- int k = 0;
- while (k++ < count) {
+ for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
if (o.equals(items[i]))
return true;
- i = inc(i);
- }
return false;
} finally {
lock.unlock();
@@ -504,17 +516,14 @@
* @return an array containing all of the elements in this queue
*/
public Object[] toArray() {
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
+ final int count = this.count;
Object[] a = new Object[count];
- int k = 0;
- int i = takeIndex;
- while (k < count) {
- a[k++] = items[i];
- i = inc(i);
- }
+ for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
+ a[k] = items[i];
return a;
} finally {
lock.unlock();
@@ -531,22 +540,22 @@
* <p>If this queue fits in the specified array with room to spare
* (i.e., the array has more elements than this queue), the element in
* the array immediately following the end of the queue is set to
- * <tt>null</tt>.
+ * {@code null}.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
- * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+ * <p>Suppose {@code x} is a queue known to contain only strings.
* The following code can be used to dump the queue into a newly
- * allocated array of <tt>String</tt>:
+ * allocated array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
- * Note that <tt>toArray(new Object[0])</tt> is identical in function to
- * <tt>toArray()</tt>.
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
*
* @param a the array into which the elements of the queue are to
* be stored, if it is big enough; otherwise, a new array of the
@@ -557,24 +566,20 @@
* this queue
* @throws NullPointerException if the specified array is null
*/
+ @SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- if (a.length < count)
+ final int count = this.count;
+ final int len = a.length;
+ if (len < count)
a = (T[])java.lang.reflect.Array.newInstance(
- a.getClass().getComponentType(),
- count
- );
-
- int k = 0;
- int i = takeIndex;
- while (k < count) {
- a[k++] = (T)items[i];
- i = inc(i);
- }
- if (a.length > count)
+ a.getClass().getComponentType(), count);
+ for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
+ a[k] = (T) items[i];
+ if (len > count)
a[count] = null;
return a;
} finally {
@@ -586,7 +591,19 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return super.toString();
+ int k = count;
+ if (k == 0)
+ return "[]";
+
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int i = takeIndex; ; i = inc(i)) {
+ Object e = items[i];
+ sb.append(e == this ? "(this Collection)" : e);
+ if (--k == 0)
+ return sb.append(']').toString();
+ sb.append(',').append(' ');
+ }
} finally {
lock.unlock();
}
@@ -597,16 +614,12 @@
* The queue will be empty after this call returns.
*/
public void clear() {
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- int i = takeIndex;
- int k = count;
- while (k-- > 0) {
+ for (int i = takeIndex, k = count; k > 0; i = inc(i), k--)
items[i] = null;
- i = inc(i);
- }
count = 0;
putIndex = 0;
takeIndex = 0;
@@ -623,11 +636,10 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c) {
- if (c == null)
- throw new NullPointerException();
+ checkNotNull(c);
if (c == this)
throw new IllegalArgumentException();
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
@@ -635,7 +647,7 @@
int n = 0;
int max = count;
while (n < max) {
- c.add(items[i]);
+ c.add(this.<E>cast(items[i]));
items[i] = null;
i = inc(i);
++n;
@@ -659,22 +671,20 @@
* @throws IllegalArgumentException {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
- if (c == null)
- throw new NullPointerException();
+ checkNotNull(c);
if (c == this)
throw new IllegalArgumentException();
if (maxElements <= 0)
return 0;
- final E[] items = this.items;
+ final Object[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lock();
try {
int i = takeIndex;
int n = 0;
- int sz = count;
- int max = (maxElements < count)? maxElements : count;
+ int max = (maxElements < count) ? maxElements : count;
while (n < max) {
- c.add(items[i]);
+ c.add(this.<E>cast(items[i]));
items[i] = null;
i = inc(i);
++n;
@@ -690,11 +700,13 @@
}
}
-
/**
* Returns an iterator over the elements in this queue in proper sequence.
- * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
- * will never throw {@link ConcurrentModificationException},
+ * The elements will be returned in order from first (head) to last (tail).
+ *
+ * <p>The returned {@code Iterator} is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
* reflect any modifications subsequent to construction.
@@ -702,83 +714,65 @@
* @return an iterator over the elements in this queue in proper sequence
*/
public Iterator<E> iterator() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- return new Itr();
- } finally {
- lock.unlock();
- }
+ return new Itr();
}
/**
- * Iterator for ArrayBlockingQueue
+ * Iterator for ArrayBlockingQueue. To maintain weak consistency
+ * with respect to puts and takes, we (1) read ahead one slot, so
+ * as to not report hasNext true but then not have an element to
+ * return -- however we later recheck this slot to use the most
+ * current value; (2) ensure that each array slot is traversed at
+ * most once (by tracking "remaining" elements); (3) skip over
+ * null slots, which can occur if takes race ahead of iterators.
+ * However, for circular array-based queues, we cannot rely on any
+ * well established definition of what it means to be weakly
+ * consistent with respect to interior removes since these may
+ * require slot overwrites in the process of sliding elements to
+ * cover gaps. So we settle for resiliency, operating on
+ * established apparent nexts, which may miss some elements that
+ * have moved between calls to next.
*/
private class Itr implements Iterator<E> {
- /**
- * Index of element to be returned by next,
- * or a negative number if no such.
- */
- private int nextIndex;
-
- /**
- * nextItem holds on to item fields because once we claim
- * that an element exists in hasNext(), we must return it in
- * the following next() call even if it was in the process of
- * being removed when hasNext() was called.
- */
- private E nextItem;
-
- /**
- * Index of element returned by most recent call to next.
- * Reset to -1 if this element is deleted by a call to remove.
- */
- private int lastRet;
+ private int remaining; // Number of elements yet to be returned
+ private int nextIndex; // Index of element to be returned by next
+ private E nextItem; // Element to be returned by next call to next
+ private E lastItem; // Element returned by last call to next
+ private int lastRet; // Index of last element returned, or -1 if none
Itr() {
- lastRet = -1;
- if (count == 0)
- nextIndex = -1;
- else {
- nextIndex = takeIndex;
- nextItem = items[takeIndex];
+ final ReentrantLock lock = ArrayBlockingQueue.this.lock;
+ lock.lock();
+ try {
+ lastRet = -1;
+ if ((remaining = count) > 0)
+ nextItem = itemAt(nextIndex = takeIndex);
+ } finally {
+ lock.unlock();
}
}
public boolean hasNext() {
- /*
- * No sync. We can return true by mistake here
- * only if this iterator passed across threads,
- * which we don't support anyway.
- */
- return nextIndex >= 0;
- }
-
- /**
- * Checks whether nextIndex is valid; if so setting nextItem.
- * Stops iterator when either hits putIndex or sees null item.
- */
- private void checkNext() {
- if (nextIndex == putIndex) {
- nextIndex = -1;
- nextItem = null;
- } else {
- nextItem = items[nextIndex];
- if (nextItem == null)
- nextIndex = -1;
- }
+ return remaining > 0;
}
public E next() {
final ReentrantLock lock = ArrayBlockingQueue.this.lock;
lock.lock();
try {
- if (nextIndex < 0)
+ if (remaining <= 0)
throw new NoSuchElementException();
lastRet = nextIndex;
- E x = nextItem;
- nextIndex = inc(nextIndex);
- checkNext();
+ E x = itemAt(nextIndex); // check for fresher value
+ if (x == null) {
+ x = nextItem; // we are forced to report old value
+ lastItem = null; // but ensure remove fails
+ }
+ else
+ lastItem = x;
+ while (--remaining > 0 && // skip over nulls
+ (nextItem = itemAt(nextIndex = inc(nextIndex))) == null)
+ ;
return x;
} finally {
lock.unlock();
@@ -793,15 +787,19 @@
if (i == -1)
throw new IllegalStateException();
lastRet = -1;
-
- int ti = takeIndex;
- removeAt(i);
- // back up cursor (reset to front if was first element)
- nextIndex = (i == ti) ? takeIndex : i;
- checkNext();
+ E x = lastItem;
+ lastItem = null;
+ // only remove if item still at index
+ if (x != null && x == items[i]) {
+ boolean removingHead = (i == takeIndex);
+ removeAt(i);
+ if (!removingHead)
+ nextIndex = dec(nextIndex);
+ }
} finally {
lock.unlock();
}
}
}
+
}
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Fri Feb 18 12:04:36 2011 -0800
@@ -869,6 +869,8 @@
/**
* Inserts the specified element at the front of this deque.
+ * As the deque is unbounded, this method will never throw
+ * {@link IllegalStateException}.
*
* @throws NullPointerException if the specified element is null
*/
@@ -878,6 +880,8 @@
/**
* Inserts the specified element at the end of this deque.
+ * As the deque is unbounded, this method will never throw
+ * {@link IllegalStateException}.
*
* <p>This method is equivalent to {@link #add}.
*
@@ -889,8 +893,9 @@
/**
* Inserts the specified element at the front of this deque.
+ * As the deque is unbounded, this method will never return {@code false}.
*
- * @return {@code true} always
+ * @return {@code true} (as specified by {@link Deque#offerFirst})
* @throws NullPointerException if the specified element is null
*/
public boolean offerFirst(E e) {
@@ -900,10 +905,11 @@
/**
* Inserts the specified element at the end of this deque.
+ * As the deque is unbounded, this method will never return {@code false}.
*
* <p>This method is equivalent to {@link #add}.
*
- * @return {@code true} always
+ * @return {@code true} (as specified by {@link Deque#offerLast})
* @throws NullPointerException if the specified element is null
*/
public boolean offerLast(E e) {
@@ -983,6 +989,7 @@
/**
* Inserts the specified element at the tail of this deque.
+ * As the deque is unbounded, this method will never return {@code false}.
*
* @return {@code true} (as specified by {@link Queue#offer})
* @throws NullPointerException if the specified element is null
@@ -993,6 +1000,8 @@
/**
* Inserts the specified element at the tail of this deque.
+ * As the deque is unbounded, this method will never throw
+ * {@link IllegalStateException} or return {@code false}.
*
* @return {@code true} (as specified by {@link Collection#add})
* @throws NullPointerException if the specified element is null
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Fri Feb 18 12:04:36 2011 -0800
@@ -269,6 +269,8 @@
/**
* Inserts the specified element at the tail of this queue.
+ * As the queue is unbounded, this method will never throw
+ * {@link IllegalStateException} or return {@code false}.
*
* @return {@code true} (as specified by {@link Collection#add})
* @throws NullPointerException if the specified element is null
@@ -298,6 +300,7 @@
/**
* Inserts the specified element at the tail of this queue.
+ * As the queue is unbounded, this method will never return {@code false}.
*
* @return {@code true} (as specified by {@link Queue#offer})
* @throws NullPointerException if the specified element is null
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListMap.java Fri Feb 18 12:04:36 2011 -0800
@@ -374,17 +374,11 @@
null, null, 1);
}
- /** Updater for casHead */
- private static final
- AtomicReferenceFieldUpdater<ConcurrentSkipListMap, HeadIndex>
- headUpdater = AtomicReferenceFieldUpdater.newUpdater
- (ConcurrentSkipListMap.class, HeadIndex.class, "head");
-
/**
* compareAndSet head node
*/
private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
- return headUpdater.compareAndSet(this, cmp, val);
+ return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
}
/* ---------------- Nodes -------------- */
@@ -423,28 +417,18 @@
this.next = next;
}
- /** Updater for casNext */
- static final AtomicReferenceFieldUpdater<Node, Node>
- nextUpdater = AtomicReferenceFieldUpdater.newUpdater
- (Node.class, Node.class, "next");
-
- /** Updater for casValue */
- static final AtomicReferenceFieldUpdater<Node, Object>
- valueUpdater = AtomicReferenceFieldUpdater.newUpdater
- (Node.class, Object.class, "value");
-
/**
* compareAndSet value field
*/
boolean casValue(Object cmp, Object val) {
- return valueUpdater.compareAndSet(this, cmp, val);
+ return UNSAFE.compareAndSwapObject(this, valueOffset, cmp, val);
}
/**
* compareAndSet next field
*/
boolean casNext(Node<K,V> cmp, Node<K,V> val) {
- return nextUpdater.compareAndSet(this, cmp, val);
+ return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
/**
@@ -522,6 +506,14 @@
return null;
return new AbstractMap.SimpleImmutableEntry<K,V>(key, v);
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long valueOffset =
+ objectFieldOffset(UNSAFE, "value", Node.class);
+ private static final long nextOffset =
+ objectFieldOffset(UNSAFE, "next", Node.class);
+
}
/* ---------------- Indexing -------------- */
@@ -547,16 +539,11 @@
this.right = right;
}
- /** Updater for casRight */
- static final AtomicReferenceFieldUpdater<Index, Index>
- rightUpdater = AtomicReferenceFieldUpdater.newUpdater
- (Index.class, Index.class, "right");
-
/**
* compareAndSet right field
*/
final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
- return rightUpdater.compareAndSet(this, cmp, val);
+ return UNSAFE.compareAndSwapObject(this, rightOffset, cmp, val);
}
/**
@@ -591,6 +578,12 @@
final boolean unlink(Index<K,V> succ) {
return !indexesDeletedNode() && casRight(succ, succ.right);
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long rightOffset =
+ objectFieldOffset(UNSAFE, "right", Index.class);
+
}
/* ---------------- Head nodes -------------- */
@@ -640,7 +633,8 @@
* cast key as Comparable, which may cause ClassCastException,
* which is propagated back to caller.
*/
- private Comparable<? super K> comparable(Object key) throws ClassCastException {
+ private Comparable<? super K> comparable(Object key)
+ throws ClassCastException {
if (key == null)
throw new NullPointerException();
if (comparator != null)
@@ -799,68 +793,12 @@
}
/**
- * Specialized variant of findNode to perform Map.get. Does a weak
- * traversal, not bothering to fix any deleted index nodes,
- * returning early if it happens to see key in index, and passing
- * over any deleted base nodes, falling back to getUsingFindNode
- * only if it would otherwise return value from an ongoing
- * deletion. Also uses "bound" to eliminate need for some
- * comparisons (see Pugh Cookbook). Also folds uses of null checks
- * and node-skipping because markers have null keys.
+ * Gets value for key using findNode.
* @param okey the key
* @return the value, or null if absent
*/
private V doGet(Object okey) {
Comparable<? super K> key = comparable(okey);
- Node<K,V> bound = null;
- Index<K,V> q = head;
- Index<K,V> r = q.right;
- Node<K,V> n;
- K k;
- int c;
- for (;;) {
- Index<K,V> d;
- // Traverse rights
- if (r != null && (n = r.node) != bound && (k = n.key) != null) {
- if ((c = key.compareTo(k)) > 0) {
- q = r;
- r = r.right;
- continue;
- } else if (c == 0) {
- Object v = n.value;
- return (v != null)? (V)v : getUsingFindNode(key);
- } else
- bound = n;
- }
-
- // Traverse down
- if ((d = q.down) != null) {
- q = d;
- r = d.right;
- } else
- break;
- }
-
- // Traverse nexts
- for (n = q.node.next; n != null; n = n.next) {
- if ((k = n.key) != null) {
- if ((c = key.compareTo(k)) == 0) {
- Object v = n.value;
- return (v != null)? (V)v : getUsingFindNode(key);
- } else if (c < 0)
- break;
- }
- }
- return null;
- }
-
- /**
- * Performs map.get via findNode. Used as a backup if doGet
- * encounters an in-progress deletion.
- * @param key the key
- * @return the value, or null if absent
- */
- private V getUsingFindNode(Comparable<? super K> key) {
/*
* Loop needed here and elsewhere in case value field goes
* null just as it is about to be returned, in which case we
@@ -943,7 +881,7 @@
x ^= x << 13;
x ^= x >>> 17;
randomSeed = x ^= x << 5;
- if ((x & 0x8001) != 0) // test highest and lowest bits
+ if ((x & 0x80000001) != 0) // test highest and lowest bits
return 0;
int level = 1;
while (((x >>>= 1) & 1) != 0) ++level;
@@ -1256,7 +1194,7 @@
Node<K,V> n = b.next;
for (;;) {
if (n == null)
- return (b.isBaseHeader())? null : b;
+ return b.isBaseHeader() ? null : b;
Node<K,V> f = n.next; // inconsistent read
if (n != b.next)
break;
@@ -1374,7 +1312,7 @@
Node<K,V> n = b.next;
for (;;) {
if (n == null)
- return ((rel & LT) == 0 || b.isBaseHeader())? null : b;
+ return ((rel & LT) == 0 || b.isBaseHeader()) ? null : b;
Node<K,V> f = n.next;
if (n != b.next) // inconsistent read
break;
@@ -1390,7 +1328,7 @@
(c < 0 && (rel & LT) == 0))
return n;
if ( c <= 0 && (rel & LT) != 0)
- return (b.isBaseHeader())? null : b;
+ return b.isBaseHeader() ? null : b;
b = n;
n = f;
}
@@ -1744,7 +1682,7 @@
if (n.getValidValue() != null)
++count;
}
- return (count >= Integer.MAX_VALUE)? Integer.MAX_VALUE : (int)count;
+ return (count >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) count;
}
/**
@@ -2099,7 +2037,7 @@
*/
public K lowerKey(K key) {
Node<K,V> n = findNear(key, LT);
- return (n == null)? null : n.key;
+ return (n == null) ? null : n.key;
}
/**
@@ -2123,7 +2061,7 @@
*/
public K floorKey(K key) {
Node<K,V> n = findNear(key, LT|EQ);
- return (n == null)? null : n.key;
+ return (n == null) ? null : n.key;
}
/**
@@ -2145,7 +2083,7 @@
*/
public K ceilingKey(K key) {
Node<K,V> n = findNear(key, GT|EQ);
- return (n == null)? null : n.key;
+ return (n == null) ? null : n.key;
}
/**
@@ -2169,7 +2107,7 @@
*/
public K higherKey(K key) {
Node<K,V> n = findNear(key, GT);
- return (n == null)? null : n.key;
+ return (n == null) ? null : n.key;
}
/**
@@ -2342,7 +2280,8 @@
return list;
}
- static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {
+ static final class KeySet<E>
+ extends AbstractSet<E> implements NavigableSet<E> {
private final ConcurrentNavigableMap<E,Object> m;
KeySet(ConcurrentNavigableMap<E,Object> map) { m = map; }
public int size() { return m.size(); }
@@ -2359,11 +2298,11 @@
public E last() { return m.lastKey(); }
public E pollFirst() {
Map.Entry<E,Object> e = m.pollFirstEntry();
- return e == null? null : e.getKey();
+ return (e == null) ? null : e.getKey();
}
public E pollLast() {
Map.Entry<E,Object> e = m.pollLastEntry();
- return e == null? null : e.getKey();
+ return (e == null) ? null : e.getKey();
}
public Iterator<E> iterator() {
if (m instanceof ConcurrentSkipListMap)
@@ -2710,9 +2649,9 @@
rel &= ~m.LT;
}
if (tooLow(key))
- return ((rel & m.LT) != 0)? null : lowestEntry();
+ return ((rel & m.LT) != 0) ? null : lowestEntry();
if (tooHigh(key))
- return ((rel & m.LT) != 0)? highestEntry() : null;
+ return ((rel & m.LT) != 0) ? highestEntry() : null;
for (;;) {
Node<K,V> n = m.findNear(key, rel);
if (n == null || !inBounds(n.key))
@@ -2783,7 +2722,7 @@
public V remove(Object key) {
K k = (K)key;
- return (!inBounds(k))? null : m.remove(k);
+ return (!inBounds(k)) ? null : m.remove(k);
}
public int size() {
@@ -2794,7 +2733,7 @@
if (n.getValidValue() != null)
++count;
}
- return count >= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)count;
+ return count >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)count;
}
public boolean isEmpty() {
@@ -2972,27 +2911,27 @@
}
public K firstKey() {
- return isDescending? highestKey() : lowestKey();
+ return isDescending ? highestKey() : lowestKey();
}
public K lastKey() {
- return isDescending? lowestKey() : highestKey();
+ return isDescending ? lowestKey() : highestKey();
}
public Map.Entry<K,V> firstEntry() {
- return isDescending? highestEntry() : lowestEntry();
+ return isDescending ? highestEntry() : lowestEntry();
}
public Map.Entry<K,V> lastEntry() {
- return isDescending? lowestEntry() : highestEntry();
+ return isDescending ? lowestEntry() : highestEntry();
}
public Map.Entry<K,V> pollFirstEntry() {
- return isDescending? removeHighest() : removeLowest();
+ return isDescending ? removeHighest() : removeLowest();
}
public Map.Entry<K,V> pollLastEntry() {
- return isDescending? removeLowest() : removeHighest();
+ return isDescending ? removeLowest() : removeHighest();
}
/* ---------------- Submap Views -------------- */
@@ -3141,4 +3080,22 @@
}
}
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long headOffset =
+ objectFieldOffset(UNSAFE, "head", ConcurrentSkipListMap.class);
+
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
+ }
+
}
--- a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Fri Feb 18 12:04:36 2011 -0800
@@ -832,7 +832,7 @@
}
/**
- * Save the state of the list to a stream (i.e., serialize it).
+ * Saves the state of the list to a stream (that is, serializes it).
*
* @serialData The length of the array backing the list is emitted
* (int), followed by all of its elements (each an Object)
@@ -842,27 +842,25 @@
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
- // Write out element count, and any hidden stuff
s.defaultWriteObject();
Object[] elements = getArray();
- int len = elements.length;
// Write out array length
- s.writeInt(len);
+ s.writeInt(elements.length);
// Write out all elements in the proper order.
- for (int i = 0; i < len; i++)
- s.writeObject(elements[i]);
+ for (Object element : elements)
+ s.writeObject(element);
}
/**
- * Reconstitute the list from a stream (i.e., deserialize it).
+ * Reconstitutes the list from a stream (that is, deserializes it).
+ *
* @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
- // Read in size, and any hidden stuff
s.defaultReadObject();
// bind to new lock
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinPool.java Fri Feb 18 12:04:36 2011 -0800
@@ -525,8 +525,8 @@
*/
private volatile long eventWaiters;
- private static final int EVENT_COUNT_SHIFT = 32;
- private static final long WAITER_ID_MASK = (1L << 16) - 1L;
+ private static final int EVENT_COUNT_SHIFT = 32;
+ private static final int WAITER_ID_MASK = (1 << 16) - 1;
/**
* A counter for events that may wake up worker threads:
@@ -615,7 +615,7 @@
// are usually manually inlined by callers
/**
- * Increments running count part of workerCounts
+ * Increments running count part of workerCounts.
*/
final void incrementRunningCount() {
int c;
@@ -625,7 +625,17 @@
}
/**
- * Tries to decrement running count unless already zero
+ * Tries to increment running count part of workerCounts.
+ */
+ final boolean tryIncrementRunningCount() {
+ int c;
+ return UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+ c = workerCounts,
+ c + ONE_RUNNING);
+ }
+
+ /**
+ * Tries to decrement running count unless already zero.
*/
final boolean tryDecrementRunningCount() {
int wc = workerCounts;
@@ -698,10 +708,11 @@
for (k = 0; k < n && ws[k] != null; ++k)
;
if (k == n)
- ws = Arrays.copyOf(ws, n << 1);
+ ws = workers = Arrays.copyOf(ws, n << 1);
}
ws[k] = w;
- workers = ws; // volatile array write ensures slot visibility
+ int c = eventCount; // advance event count to ensure visibility
+ UNSAFE.compareAndSwapInt(this, eventCountOffset, c, c+1);
} finally {
lock.unlock();
}
@@ -734,7 +745,7 @@
*/
final void workerTerminated(ForkJoinWorkerThread w) {
forgetWorker(w);
- decrementWorkerCounts(w.isTrimmed()? 0 : ONE_RUNNING, ONE_TOTAL);
+ decrementWorkerCounts(w.isTrimmed() ? 0 : ONE_RUNNING, ONE_TOTAL);
while (w.stealCount != 0) // collect final count
tryAccumulateStealCount(w);
tryTerminate(false);
@@ -746,24 +757,23 @@
* Releases workers blocked on a count not equal to current count.
* Normally called after precheck that eventWaiters isn't zero to
* avoid wasted array checks. Gives up upon a change in count or
- * upon releasing two workers, letting others take over.
+ * upon releasing four workers, letting others take over.
*/
private void releaseEventWaiters() {
ForkJoinWorkerThread[] ws = workers;
int n = ws.length;
long h = eventWaiters;
int ec = eventCount;
- boolean releasedOne = false;
+ int releases = 4;
ForkJoinWorkerThread w; int id;
- while ((id = ((int)(h & WAITER_ID_MASK)) - 1) >= 0 &&
+ while ((id = (((int)h) & WAITER_ID_MASK) - 1) >= 0 &&
(int)(h >>> EVENT_COUNT_SHIFT) != ec &&
id < n && (w = ws[id]) != null) {
if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
h, w.nextWaiter)) {
LockSupport.unpark(w);
- if (releasedOne) // exit on second release
+ if (--releases == 0)
break;
- releasedOne = true;
}
if (eventCount != ec)
break;
@@ -793,7 +803,7 @@
long nh = (((long)ec) << EVENT_COUNT_SHIFT) | ((long)(w.poolIndex+1));
long h;
while ((runState < SHUTDOWN || !tryTerminate(false)) &&
- (((int)((h = eventWaiters) & WAITER_ID_MASK)) == 0 ||
+ (((int)(h = eventWaiters) & WAITER_ID_MASK) == 0 ||
(int)(h >>> EVENT_COUNT_SHIFT) == ec) &&
eventCount == ec) {
if (UNSAFE.compareAndSwapLong(this, eventWaitersOffset,
@@ -820,9 +830,9 @@
if (tryAccumulateStealCount(w)) { // transfer while idle
boolean untimed = (w.nextWaiter != 0L ||
(workerCounts & RUNNING_COUNT_MASK) <= 1);
- long startTime = untimed? 0 : System.nanoTime();
+ long startTime = untimed ? 0 : System.nanoTime();
Thread.interrupted(); // clear/ignore interrupt
- if (eventCount != ec || w.isTerminating())
+ if (w.isTerminating() || eventCount != ec)
break; // recheck after clear
if (untimed)
LockSupport.park(w);
@@ -860,7 +870,8 @@
if ((sw = spareWaiters) != 0 &&
(id = (sw & SPARE_ID_MASK) - 1) >= 0 &&
id < n && (w = ws[id]) != null &&
- (workerCounts & RUNNING_COUNT_MASK) < parallelism &&
+ (runState >= TERMINATING ||
+ (workerCounts & RUNNING_COUNT_MASK) < parallelism) &&
spareWaiters == sw &&
UNSAFE.compareAndSwapInt(this, spareWaitersOffset,
sw, w.nextSpare)) {
@@ -914,12 +925,8 @@
break;
}
w.start(recordWorker(w), ueh);
- if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc) {
- int c; // advance event count
- UNSAFE.compareAndSwapInt(this, eventCountOffset,
- c = eventCount, c+1);
+ if ((workerCounts >>> TOTAL_COUNT_SHIFT) >= pc)
break; // add at most one unless total below target
- }
}
}
if (eventWaiters != 0L)
@@ -955,7 +962,7 @@
}
else if ((h = eventWaiters) != 0L) {
long nh;
- int id = ((int)(h & WAITER_ID_MASK)) - 1;
+ int id = (((int)h) & WAITER_ID_MASK) - 1;
if (id >= 0 && id < n && (w = ws[id]) != null &&
(nh = w.nextWaiter) != 0L && // keep at least one worker
UNSAFE.compareAndSwapLong(this, eventWaitersOffset, h, nh))
@@ -1003,24 +1010,31 @@
int pc = parallelism;
while (w.runState == 0) {
int rs = runState;
- if (rs >= TERMINATING) { // propagate shutdown
+ if (rs >= TERMINATING) { // propagate shutdown
w.shutdown();
break;
}
if ((inactivate || (active && (rs & ACTIVE_COUNT_MASK) >= pc)) &&
- UNSAFE.compareAndSwapInt(this, runStateOffset, rs, rs - 1))
+ UNSAFE.compareAndSwapInt(this, runStateOffset, rs, --rs)) {
inactivate = active = w.active = false;
- int wc = workerCounts;
+ if (rs == SHUTDOWN) { // all inactive and shut down
+ tryTerminate(false);
+ continue;
+ }
+ }
+ int wc = workerCounts; // try to suspend as spare
if ((wc & RUNNING_COUNT_MASK) > pc) {
if (!(inactivate |= active) && // must inactivate to suspend
- workerCounts == wc && // try to suspend as spare
+ workerCounts == wc &&
UNSAFE.compareAndSwapInt(this, workerCountsOffset,
wc, wc - ONE_RUNNING))
w.suspendAsSpare();
}
else if ((wc >>> TOTAL_COUNT_SHIFT) < pc)
helpMaintainParallelism(); // not enough workers
- else if (!ran) {
+ else if (ran)
+ break;
+ else {
long h = eventWaiters;
int ec = eventCount;
if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != ec)
@@ -1032,8 +1046,6 @@
else if (!(inactivate |= active))
eventSync(w, wec); // must inactivate before sync
}
- else
- break;
}
}
@@ -1043,35 +1055,67 @@
*
* @param joinMe the task to join
* @param worker the current worker thread
+ * @param timed true if wait should time out
+ * @param nanos timeout value if timed
*/
- final void awaitJoin(ForkJoinTask<?> joinMe, ForkJoinWorkerThread worker) {
+ final void awaitJoin(ForkJoinTask<?> joinMe, ForkJoinWorkerThread worker,
+ boolean timed, long nanos) {
+ long startTime = timed ? System.nanoTime() : 0L;
int retries = 2 + (parallelism >> 2); // #helpJoins before blocking
+ boolean running = true; // false when count decremented
while (joinMe.status >= 0) {
- int wc;
- worker.helpJoinTask(joinMe);
+ if (runState >= TERMINATING) {
+ joinMe.cancelIgnoringExceptions();
+ break;
+ }
+ running = worker.helpJoinTask(joinMe, running);
if (joinMe.status < 0)
break;
- else if (retries > 0)
+ if (retries > 0) {
--retries;
- else if (((wc = workerCounts) & RUNNING_COUNT_MASK) != 0 &&
- UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - ONE_RUNNING)) {
- int stat, c; long h;
- while ((stat = joinMe.status) >= 0 &&
- (h = eventWaiters) != 0L && // help release others
- (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
+ continue;
+ }
+ int wc = workerCounts;
+ if ((wc & RUNNING_COUNT_MASK) != 0) {
+ if (running) {
+ if (!UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+ wc, wc - ONE_RUNNING))
+ continue;
+ running = false;
+ }
+ long h = eventWaiters;
+ if (h != 0L && (int)(h >>> EVENT_COUNT_SHIFT) != eventCount)
releaseEventWaiters();
- if (stat >= 0 &&
- ((workerCounts & RUNNING_COUNT_MASK) == 0 ||
- (stat =
- joinMe.internalAwaitDone(JOIN_TIMEOUT_MILLIS)) >= 0))
- helpMaintainParallelism(); // timeout or no running workers
- do {} while (!UNSAFE.compareAndSwapInt
- (this, workerCountsOffset,
- c = workerCounts, c + ONE_RUNNING));
- if (stat < 0)
- break; // else restart
+ if ((workerCounts & RUNNING_COUNT_MASK) != 0) {
+ long ms; int ns;
+ if (!timed) {
+ ms = JOIN_TIMEOUT_MILLIS;
+ ns = 0;
+ }
+ else { // at most JOIN_TIMEOUT_MILLIS per wait
+ long nt = nanos - (System.nanoTime() - startTime);
+ if (nt <= 0L)
+ break;
+ ms = nt / 1000000;
+ if (ms > JOIN_TIMEOUT_MILLIS) {
+ ms = JOIN_TIMEOUT_MILLIS;
+ ns = 0;
+ }
+ else
+ ns = (int) (nt % 1000000);
+ }
+ joinMe.internalAwaitDone(ms, ns);
+ }
+ if (joinMe.status < 0)
+ break;
}
+ helpMaintainParallelism();
+ }
+ if (!running) {
+ int c;
+ do {} while (!UNSAFE.compareAndSwapInt
+ (this, workerCountsOffset,
+ c = workerCounts, c + ONE_RUNNING));
}
}
@@ -1082,9 +1126,10 @@
throws InterruptedException {
while (!blocker.isReleasable()) {
int wc = workerCounts;
- if ((wc & RUNNING_COUNT_MASK) != 0 &&
- UNSAFE.compareAndSwapInt(this, workerCountsOffset,
- wc, wc - ONE_RUNNING)) {
+ if ((wc & RUNNING_COUNT_MASK) == 0)
+ helpMaintainParallelism();
+ else if (UNSAFE.compareAndSwapInt(this, workerCountsOffset,
+ wc, wc - ONE_RUNNING)) {
try {
while (!blocker.isReleasable()) {
long h = eventWaiters;
@@ -1129,12 +1174,11 @@
// Finish now if all threads terminated; else in some subsequent call
if ((workerCounts >>> TOTAL_COUNT_SHIFT) == 0) {
advanceRunLevel(TERMINATED);
- termination.arrive();
+ termination.forceTermination();
}
return true;
}
-
/**
* Actions on transition to TERMINATING
*
@@ -1325,17 +1369,13 @@
// Execution methods
/**
- * Common code for execute, invoke and submit
+ * Submits task and creates, starts, or resumes some workers if necessary
*/
private <T> void doSubmit(ForkJoinTask<T> task) {
- if (task == null)
- throw new NullPointerException();
- if (runState >= SHUTDOWN)
- throw new RejectedExecutionException();
submissionQueue.offer(task);
int c; // try to increment event count -- CAS failure OK
UNSAFE.compareAndSwapInt(this, eventCountOffset, c = eventCount, c+1);
- helpMaintainParallelism(); // create, start, or resume some workers
+ helpMaintainParallelism();
}
/**
@@ -1348,8 +1388,33 @@
* scheduled for execution
*/
public <T> T invoke(ForkJoinTask<T> task) {
- doSubmit(task);
- return task.join();
+ if (task == null)
+ throw new NullPointerException();
+ if (runState >= SHUTDOWN)
+ throw new RejectedExecutionException();
+ Thread t = Thread.currentThread();
+ if ((t instanceof ForkJoinWorkerThread) &&
+ ((ForkJoinWorkerThread)t).pool == this)
+ return task.invoke(); // bypass submit if in same pool
+ else {
+ doSubmit(task);
+ return task.join();
+ }
+ }
+
+ /**
+ * Unless terminating, forks task if within an ongoing FJ
+ * computation in the current pool, else submits as external task.
+ */
+ private <T> void forkOrSubmit(ForkJoinTask<T> task) {
+ if (runState >= SHUTDOWN)
+ throw new RejectedExecutionException();
+ Thread t = Thread.currentThread();
+ if ((t instanceof ForkJoinWorkerThread) &&
+ ((ForkJoinWorkerThread)t).pool == this)
+ task.fork();
+ else
+ doSubmit(task);
}
/**
@@ -1361,7 +1426,9 @@
* scheduled for execution
*/
public void execute(ForkJoinTask<?> task) {
- doSubmit(task);
+ if (task == null)
+ throw new NullPointerException();
+ forkOrSubmit(task);
}
// AbstractExecutorService methods
@@ -1372,12 +1439,14 @@
* scheduled for execution
*/
public void execute(Runnable task) {
+ if (task == null)
+ throw new NullPointerException();
ForkJoinTask<?> job;
if (task instanceof ForkJoinTask<?>) // avoid re-wrap
job = (ForkJoinTask<?>) task;
else
job = ForkJoinTask.adapt(task, null);
- doSubmit(job);
+ forkOrSubmit(job);
}
/**
@@ -1390,7 +1459,9 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
- doSubmit(task);
+ if (task == null)
+ throw new NullPointerException();
+ forkOrSubmit(task);
return task;
}
@@ -1400,8 +1471,10 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(Callable<T> task) {
+ if (task == null)
+ throw new NullPointerException();
ForkJoinTask<T> job = ForkJoinTask.adapt(task);
- doSubmit(job);
+ forkOrSubmit(job);
return job;
}
@@ -1411,8 +1484,10 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(Runnable task, T result) {
+ if (task == null)
+ throw new NullPointerException();
ForkJoinTask<T> job = ForkJoinTask.adapt(task, result);
- doSubmit(job);
+ forkOrSubmit(job);
return job;
}
@@ -1422,12 +1497,14 @@
* scheduled for execution
*/
public ForkJoinTask<?> submit(Runnable task) {
+ if (task == null)
+ throw new NullPointerException();
ForkJoinTask<?> job;
if (task instanceof ForkJoinTask<?>) // avoid re-wrap
job = (ForkJoinTask<?>) task;
else
job = ForkJoinTask.adapt(task, null);
- doSubmit(job);
+ forkOrSubmit(job);
return job;
}
@@ -1725,8 +1802,11 @@
* commenced but not yet completed. This method may be useful for
* debugging. A return of {@code true} reported a sufficient
* period after shutdown may indicate that submitted tasks have
- * ignored or suppressed interruption, causing this executor not
- * to properly terminate.
+ * ignored or suppressed interruption, or are waiting for IO,
+ * causing this executor not to properly terminate. (See the
+ * advisory notes for class {@link ForkJoinTask} stating that
+ * tasks should not normally entail blocking operations. But if
+ * they do, they must abort them on interrupt.)
*
* @return {@code true} if terminating but not yet terminated
*/
@@ -1764,10 +1844,11 @@
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
try {
- return termination.awaitAdvanceInterruptibly(0, timeout, unit) > 0;
+ termination.awaitAdvanceInterruptibly(0, timeout, unit);
} catch (TimeoutException ex) {
return false;
}
+ return true;
}
/**
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinTask.java Fri Feb 18 12:04:36 2011 -0800
@@ -42,6 +42,16 @@
import java.util.RandomAccess;
import java.util.Map;
import java.util.WeakHashMap;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -129,6 +139,16 @@
* result in exceptions or errors, possibly including
* {@code ClassCastException}.
*
+ * <p>Method {@link #join} and its variants are appropriate for use
+ * only when completion dependencies are acyclic; that is, the
+ * parallel computation can be described as a directed acyclic graph
+ * (DAG). Otherwise, executions may encounter a form of deadlock as
+ * tasks cyclically wait for each other. However, this framework
+ * supports other methods and techniques (for example the use of
+ * {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
+ * may be of use in constructing custom subclasses for problems that
+ * are not statically structured as DAGs.
+ *
* <p>Most base support methods are {@code final}, to prevent
* overriding of implementations that are intrinsically tied to the
* underlying lightweight task scheduling framework. Developers
@@ -143,9 +163,10 @@
* computation. Large tasks should be split into smaller subtasks,
* usually via recursive decomposition. As a very rough rule of thumb,
* a task should perform more than 100 and less than 10000 basic
- * computational steps. If tasks are too big, then parallelism cannot
- * improve throughput. If too small, then memory and internal task
- * maintenance overhead may overwhelm processing.
+ * computational steps, and should avoid indefinite looping. If tasks
+ * are too big, then parallelism cannot improve throughput. If too
+ * small, then memory and internal task maintenance overhead may
+ * overwhelm processing.
*
* <p>This class provides {@code adapt} methods for {@link Runnable}
* and {@link Callable}, that may be of use when mixing execution of
@@ -242,17 +263,20 @@
}
/**
- * Blocks a worker thread until completion. Called only by
- * pool. Currently unused -- pool-based waits use timeout
- * version below.
+ * Blocks a worker thread until completed or timed out. Called
+ * only by pool.
*/
- final void internalAwaitDone() {
- int s; // the odd construction reduces lock bias effects
- while ((s = status) >= 0) {
- try {
+ final void internalAwaitDone(long millis, int nanos) {
+ int s = status;
+ if ((s == 0 &&
+ UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL)) ||
+ s > 0) {
+ try { // the odd construction reduces lock bias effects
synchronized (this) {
- if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
- wait();
+ if (status > 0)
+ wait(millis, nanos);
+ else
+ notifyAll();
}
} catch (InterruptedException ie) {
cancelIfTerminating();
@@ -261,46 +285,61 @@
}
/**
- * Blocks a worker thread until completed or timed out. Called
- * only by pool.
- *
- * @return status on exit
- */
- final int internalAwaitDone(long millis) {
- int s;
- if ((s = status) >= 0) {
- try {
- synchronized (this) {
- if (UNSAFE.compareAndSwapInt(this, statusOffset, s,SIGNAL))
- wait(millis, 0);
- }
- } catch (InterruptedException ie) {
- cancelIfTerminating();
- }
- s = status;
- }
- return s;
- }
-
- /**
* Blocks a non-worker-thread until completion.
*/
private void externalAwaitDone() {
- int s;
- while ((s = status) >= 0) {
+ if (status >= 0) {
+ boolean interrupted = false;
synchronized (this) {
- if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)){
- boolean interrupted = false;
- while (status >= 0) {
+ for (;;) {
+ int s = status;
+ if (s == 0)
+ UNSAFE.compareAndSwapInt(this, statusOffset,
+ 0, SIGNAL);
+ else if (s < 0) {
+ notifyAll();
+ break;
+ }
+ else {
try {
wait();
} catch (InterruptedException ie) {
interrupted = true;
}
}
- if (interrupted)
- Thread.currentThread().interrupt();
- break;
+ }
+ }
+ if (interrupted)
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ /**
+ * Blocks a non-worker-thread until completion or interruption or timeout.
+ */
+ private void externalInterruptibleAwaitDone(boolean timed, long nanos)
+ throws InterruptedException {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ if (status >= 0) {
+ long startTime = timed ? System.nanoTime() : 0L;
+ synchronized (this) {
+ for (;;) {
+ long nt;
+ int s = status;
+ if (s == 0)
+ UNSAFE.compareAndSwapInt(this, statusOffset,
+ 0, SIGNAL);
+ else if (s < 0) {
+ notifyAll();
+ break;
+ }
+ else if (!timed)
+ wait();
+ else if ((nt = nanos - (System.nanoTime()-startTime)) > 0L)
+ wait(nt / 1000000, (int)(nt % 1000000));
+ else
+ break;
}
}
}
@@ -335,7 +374,7 @@
* #isDone} returning {@code true}.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -349,10 +388,13 @@
}
/**
- * Returns the result of the computation when it {@link #isDone is done}.
- * This method differs from {@link #get()} in that
+ * Returns the result of the computation when it {@link #isDone is
+ * done}. This method differs from {@link #get()} in that
* abnormal completion results in {@code RuntimeException} or
- * {@code Error}, not {@code ExecutionException}.
+ * {@code Error}, not {@code ExecutionException}, and that
+ * interrupts of the calling thread do <em>not</em> cause the
+ * method to abruptly return by throwing {@code
+ * InterruptedException}.
*
* @return the computed result
*/
@@ -394,7 +436,7 @@
* unprocessed.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -422,7 +464,7 @@
* normally or exceptionally, or left unprocessed.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -477,7 +519,7 @@
* unprocessed.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -529,25 +571,28 @@
/**
* Attempts to cancel execution of this task. This attempt will
- * fail if the task has already completed, has already been
- * cancelled, or could not be cancelled for some other reason. If
- * successful, and this task has not started when cancel is
- * called, execution of this task is suppressed, {@link
- * #isCancelled} will report true, and {@link #join} will result
- * in a {@code CancellationException} being thrown.
+ * fail if the task has already completed or could not be
+ * cancelled for some other reason. If successful, and this task
+ * has not started when {@code cancel} is called, execution of
+ * this task is suppressed. After this method returns
+ * successfully, unless there is an intervening call to {@link
+ * #reinitialize}, subsequent calls to {@link #isCancelled},
+ * {@link #isDone}, and {@code cancel} will return {@code true}
+ * and calls to {@link #join} and related methods will result in
+ * {@code CancellationException}.
*
* <p>This method may be overridden in subclasses, but if so, must
- * still ensure that these minimal properties hold. In particular,
- * the {@code cancel} method itself must not throw exceptions.
+ * still ensure that these properties hold. In particular, the
+ * {@code cancel} method itself must not throw exceptions.
*
* <p>This method is designed to be invoked by <em>other</em>
* tasks. To terminate the current task, you can just return or
* throw an unchecked exception from its computation method, or
* invoke {@link #completeExceptionally}.
*
- * @param mayInterruptIfRunning this value is ignored in the
- * default implementation because tasks are not
- * cancelled via interruption
+ * @param mayInterruptIfRunning this value has no effect in the
+ * default implementation because interrupts are not used to
+ * control cancellation.
*
* @return {@code true} if this task is now cancelled
*/
@@ -681,23 +726,13 @@
* member of a ForkJoinPool and was interrupted while waiting
*/
public final V get() throws InterruptedException, ExecutionException {
- int s;
- if (Thread.currentThread() instanceof ForkJoinWorkerThread) {
+ Thread t = Thread.currentThread();
+ if (t instanceof ForkJoinWorkerThread)
quietlyJoin();
- s = status;
- }
- else {
- while ((s = status) >= 0) {
- synchronized (this) { // interruptible form of awaitDone
- if (UNSAFE.compareAndSwapInt(this, statusOffset,
- s, SIGNAL)) {
- while (status >= 0)
- wait();
- }
- }
- }
- }
- if (s < NORMAL) {
+ else
+ externalInterruptibleAwaitDone(false, 0L);
+ int s = status;
+ if (s != NORMAL) {
Throwable ex;
if (s == CANCELLED)
throw new CancellationException();
@@ -723,72 +758,18 @@
*/
public final V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
+ long nanos = unit.toNanos(timeout);
Thread t = Thread.currentThread();
- ForkJoinPool pool;
- if (t instanceof ForkJoinWorkerThread) {
- ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
- if (status >= 0 && w.unpushTask(this))
- quietlyExec();
- pool = w.pool;
- }
+ if (t instanceof ForkJoinWorkerThread)
+ ((ForkJoinWorkerThread)t).joinTask(this, true, nanos);
else
- pool = null;
- /*
- * Timed wait loop intermixes cases for FJ (pool != null) and
- * non FJ threads. For FJ, decrement pool count but don't try
- * for replacement; increment count on completion. For non-FJ,
- * deal with interrupts. This is messy, but a little less so
- * than is splitting the FJ and nonFJ cases.
- */
- boolean interrupted = false;
- boolean dec = false; // true if pool count decremented
- long nanos = unit.toNanos(timeout);
- for (;;) {
- if (pool == null && Thread.interrupted()) {
- interrupted = true;
- break;
- }
- int s = status;
- if (s < 0)
- break;
- if (UNSAFE.compareAndSwapInt(this, statusOffset, s, SIGNAL)) {
- long startTime = System.nanoTime();
- long nt; // wait time
- while (status >= 0 &&
- (nt = nanos - (System.nanoTime() - startTime)) > 0) {
- if (pool != null && !dec)
- dec = pool.tryDecrementRunningCount();
- else {
- long ms = nt / 1000000;
- int ns = (int) (nt % 1000000);
- try {
- synchronized (this) {
- if (status >= 0)
- wait(ms, ns);
- }
- } catch (InterruptedException ie) {
- if (pool != null)
- cancelIfTerminating();
- else {
- interrupted = true;
- break;
- }
- }
- }
- }
- break;
- }
- }
- if (pool != null && dec)
- pool.incrementRunningCount();
- if (interrupted)
- throw new InterruptedException();
- int es = status;
- if (es != NORMAL) {
+ externalInterruptibleAwaitDone(true, nanos);
+ int s = status;
+ if (s != NORMAL) {
Throwable ex;
- if (es == CANCELLED)
+ if (s == CANCELLED)
throw new CancellationException();
- if (es == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
+ if (s == EXCEPTIONAL && (ex = exceptionMap.get(this)) != null)
throw new ExecutionException(ex);
throw new TimeoutException();
}
@@ -819,7 +800,7 @@
return;
}
}
- w.joinTask(this);
+ w.joinTask(this, false, 0L);
}
}
else
@@ -855,7 +836,7 @@
* processed.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -874,6 +855,12 @@
* under any other usage conditions are not guaranteed.
* This method may be useful when executing
* pre-constructed trees of subtasks in loops.
+ *
+ * <p>Upon completion of this method, {@code isDone()} reports
+ * {@code false}, and {@code getException()} reports {@code
+ * null}. However, the value returned by {@code getRawResult} is
+ * unaffected. To clear this value, you can invoke {@code
+ * setRawResult(null)}.
*/
public void reinitialize() {
if (status == EXCEPTIONAL)
@@ -895,11 +882,12 @@
}
/**
- * Returns {@code true} if the current thread is executing as a
- * ForkJoinPool computation.
+ * Returns {@code true} if the current thread is a {@link
+ * ForkJoinWorkerThread} executing as a ForkJoinPool computation.
*
- * @return {@code true} if the current thread is executing as a
- * ForkJoinPool computation, or false otherwise
+ * @return {@code true} if the current thread is a {@link
+ * ForkJoinWorkerThread} executing as a ForkJoinPool computation,
+ * or {@code false} otherwise
*/
public static boolean inForkJoinPool() {
return Thread.currentThread() instanceof ForkJoinWorkerThread;
@@ -914,7 +902,7 @@
* were not, stolen.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -933,7 +921,7 @@
* fork other tasks.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -956,7 +944,7 @@
* exceeded.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -1014,7 +1002,7 @@
* otherwise.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -1033,7 +1021,7 @@
* be useful otherwise.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
@@ -1056,7 +1044,7 @@
* otherwise.
*
* <p>This method may be invoked only from within {@code
- * ForkJoinTask} computations (as may be determined using method
+ * ForkJoinPool} computations (as may be determined using method
* {@link #inForkJoinPool}). Attempts to invoke in other contexts
* result in exceptions or errors, possibly including {@code
* ClassCastException}.
--- a/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ForkJoinWorkerThread.java Fri Feb 18 12:04:36 2011 -0800
@@ -38,16 +38,18 @@
import java.util.Random;
import java.util.Collection;
import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.RejectedExecutionException;
/**
- * A thread managed by a {@link ForkJoinPool}. This class is
- * subclassable solely for the sake of adding functionality -- there
- * are no overridable methods dealing with scheduling or execution.
- * However, you can override initialization and termination methods
- * surrounding the main task processing loop. If you do create such a
- * subclass, you will also need to supply a custom {@link
- * ForkJoinPool.ForkJoinWorkerThreadFactory} to use it in a {@code
- * ForkJoinPool}.
+ * A thread managed by a {@link ForkJoinPool}, which executes
+ * {@link ForkJoinTask}s.
+ * This class is subclassable solely for the sake of adding
+ * functionality -- there are no overridable methods dealing with
+ * scheduling or execution. However, you can override initialization
+ * and termination methods surrounding the main task processing loop.
+ * If you do create such a subclass, you will also need to supply a
+ * custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it
+ * in a {@code ForkJoinPool}.
*
* @since 1.7
* @author Doug Lea
@@ -376,7 +378,7 @@
/**
* Initializes internal state after construction but before
* processing any tasks. If you override this method, you must
- * invoke @code{super.onStart()} at the beginning of the method.
+ * invoke {@code super.onStart()} at the beginning of the method.
* Initialization requires care: Most fields must have legal
* default values, to ensure that attempted accesses from other
* threads work correctly even before this thread starts
@@ -384,7 +386,7 @@
*/
protected void onStart() {
int rs = seedGenerator.nextInt();
- seed = rs == 0? 1 : rs; // seed must be nonzero
+ seed = (rs == 0) ? 1 : rs; // seed must be nonzero
// Allocate name string and arrays in this thread
String pid = Integer.toString(pool.getPoolNumber());
@@ -426,7 +428,7 @@
/**
* This method is required to be public, but should never be
* called explicitly. It performs the main run loop to execute
- * ForkJoinTasks.
+ * {@link ForkJoinTask}s.
*/
public void run() {
Throwable exception = null;
@@ -628,6 +630,19 @@
if (t == null) // lost to stealer
break;
if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ /*
+ * Note: here and in related methods, as a
+ * performance (not correctness) issue, we'd like
+ * to encourage compiler not to arbitrarily
+ * postpone setting sp after successful CAS.
+ * Currently there is no intrinsic for arranging
+ * this, but using Unsafe putOrderedInt may be a
+ * preferable strategy on some compilers even
+ * though its main effect is a pre-, not post-
+ * fence. To simplify possible changes, the option
+ * is left in comments next to the associated
+ * assignments.
+ */
sp = s; // putOrderedInt may encourage more timely write
// UNSAFE.putOrderedInt(this, spOffset, s);
return t;
@@ -777,10 +792,10 @@
// Run State management
// status check methods used mainly by ForkJoinPool
- final boolean isRunning() { return runState == 0; }
- final boolean isTerminated() { return (runState & TERMINATED) != 0; }
- final boolean isSuspended() { return (runState & SUSPENDED) != 0; }
- final boolean isTrimmed() { return (runState & TRIMMED) != 0; }
+ final boolean isRunning() { return runState == 0; }
+ final boolean isTerminated() { return (runState & TERMINATED) != 0; }
+ final boolean isSuspended() { return (runState & SUSPENDED) != 0; }
+ final boolean isTrimmed() { return (runState & TRIMMED) != 0; }
final boolean isTerminating() {
if ((runState & TERMINATING) != 0)
@@ -884,8 +899,7 @@
*/
final void cancelTasks() {
ForkJoinTask<?> cj = currentJoin; // try to cancel ongoing tasks
- if (cj != null) {
- currentJoin = null;
+ if (cj != null && cj.status >= 0) {
cj.cancelIgnoringExceptions();
try {
this.interrupt(); // awaken wait
@@ -893,10 +907,8 @@
}
}
ForkJoinTask<?> cs = currentSteal;
- if (cs != null) {
- currentSteal = null;
+ if (cs != null && cs.status >= 0)
cs.cancelIgnoringExceptions();
- }
while (base != sp) {
ForkJoinTask<?> t = deqTask();
if (t != null)
@@ -959,57 +971,23 @@
* Possibly runs some tasks and/or blocks, until task is done.
*
* @param joinMe the task to join
+ * @param timed true if use timed wait
+ * @param nanos wait time if timed
*/
- final void joinTask(ForkJoinTask<?> joinMe) {
+ final void joinTask(ForkJoinTask<?> joinMe, boolean timed, long nanos) {
// currentJoin only written by this thread; only need ordered store
ForkJoinTask<?> prevJoin = currentJoin;
UNSAFE.putOrderedObject(this, currentJoinOffset, joinMe);
- if (sp != base)
- localHelpJoinTask(joinMe);
- if (joinMe.status >= 0)
- pool.awaitJoin(joinMe, this);
+ pool.awaitJoin(joinMe, this, timed, nanos);
UNSAFE.putOrderedObject(this, currentJoinOffset, prevJoin);
}
/**
- * Run tasks in local queue until given task is done.
- *
- * @param joinMe the task to join
- */
- private void localHelpJoinTask(ForkJoinTask<?> joinMe) {
- int s;
- ForkJoinTask<?>[] q;
- while (joinMe.status >= 0 && (s = sp) != base && (q = queue) != null) {
- int i = (q.length - 1) & --s;
- long u = (i << qShift) + qBase; // raw offset
- ForkJoinTask<?> t = q[i];
- if (t == null) // lost to a stealer
- break;
- if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
- /*
- * This recheck (and similarly in helpJoinTask)
- * handles cases where joinMe is independently
- * cancelled or forced even though there is other work
- * available. Back out of the pop by putting t back
- * into slot before we commit by writing sp.
- */
- if (joinMe.status < 0) {
- UNSAFE.putObjectVolatile(q, u, t);
- break;
- }
- sp = s;
- // UNSAFE.putOrderedInt(this, spOffset, s);
- t.quietlyExec();
- }
- }
- }
-
- /**
- * Unless terminating, tries to locate and help perform tasks for
- * a stealer of the given task, or in turn one of its stealers.
- * Traces currentSteal->currentJoin links looking for a thread
- * working on a descendant of the given task and with a non-empty
- * queue to steal back and execute tasks from.
+ * Tries to locate and help perform tasks for a stealer of the
+ * given task, or in turn one of its stealers. Traces
+ * currentSteal->currentJoin links looking for a thread working on
+ * a descendant of the given task and with a non-empty queue to
+ * steal back and execute tasks from.
*
* The implementation is very branchy to cope with potential
* inconsistencies or loops encountering chains that are stale,
@@ -1019,77 +997,127 @@
* don't work out.
*
* @param joinMe the task to join
+ * @param running if false, then must update pool count upon
+ * running a task
+ * @return value of running on exit
*/
- final void helpJoinTask(ForkJoinTask<?> joinMe) {
- ForkJoinWorkerThread[] ws;
- int n;
- if (joinMe.status < 0) // already done
- return;
- if ((runState & TERMINATING) != 0) { // cancel if shutting down
- joinMe.cancelIgnoringExceptions();
- return;
- }
- if ((ws = pool.workers) == null || (n = ws.length) <= 1)
- return; // need at least 2 workers
-
- ForkJoinTask<?> task = joinMe; // base of chain
- ForkJoinWorkerThread thread = this; // thread with stolen task
- for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length
- // Try to find v, the stealer of task, by first using hint
- ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)];
- if (v == null || v.currentSteal != task) {
- for (int j = 0; ; ++j) { // search array
- if (j < n) {
- ForkJoinTask<?> vs;
- if ((v = ws[j]) != null &&
- (vs = v.currentSteal) != null) {
- if (joinMe.status < 0 || task.status < 0)
- return; // stale or done
- if (vs == task) {
- thread.stealHint = j;
- break; // save hint for next time
- }
- }
- }
- else
- return; // no stealer
+ final boolean helpJoinTask(ForkJoinTask<?> joinMe, boolean running) {
+ /*
+ * Initial checks to (1) abort if terminating; (2) clean out
+ * old cancelled tasks from local queue; (3) if joinMe is next
+ * task, run it; (4) omit scan if local queue nonempty (since
+ * it may contain non-descendents of joinMe).
+ */
+ ForkJoinPool p = pool;
+ for (;;) {
+ ForkJoinTask<?>[] q;
+ int s;
+ if (joinMe.status < 0)
+ return running;
+ else if ((runState & TERMINATING) != 0) {
+ joinMe.cancelIgnoringExceptions();
+ return running;
+ }
+ else if ((s = sp) == base || (q = queue) == null)
+ break; // queue empty
+ else {
+ int i = (q.length - 1) & --s;
+ long u = (i << qShift) + qBase; // raw offset
+ ForkJoinTask<?> t = q[i];
+ if (t == null)
+ break; // lost to a stealer
+ else if (t != joinMe && t.status >= 0)
+ return running; // cannot safely help
+ else if ((running ||
+ (running = p.tryIncrementRunningCount())) &&
+ UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ sp = s; // putOrderedInt may encourage more timely write
+ // UNSAFE.putOrderedInt(this, spOffset, s);
+ t.quietlyExec();
}
}
- for (;;) { // Try to help v, using specialized form of deqTask
- if (joinMe.status < 0)
- return;
- int b = v.base;
- ForkJoinTask<?>[] q = v.queue;
- if (b == v.sp || q == null)
- break;
- int i = (q.length - 1) & b;
- long u = (i << qShift) + qBase;
- ForkJoinTask<?> t = q[i];
- int pid = poolIndex;
- ForkJoinTask<?> ps = currentSteal;
- if (task.status < 0)
- return; // stale or done
- if (t != null && v.base == b++ &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- if (joinMe.status < 0) {
- UNSAFE.putObjectVolatile(q, u, t);
- return; // back out on cancel
+ }
+
+ int n; // worker array size
+ ForkJoinWorkerThread[] ws = p.workers;
+ if (ws != null && (n = ws.length) > 1) { // need at least 2 workers
+ ForkJoinTask<?> task = joinMe; // base of chain
+ ForkJoinWorkerThread thread = this; // thread with stolen task
+
+ outer:for (int d = 0; d < MAX_HELP_DEPTH; ++d) { // chain length
+ // Try to find v, the stealer of task, by first using hint
+ ForkJoinWorkerThread v = ws[thread.stealHint & (n - 1)];
+ if (v == null || v.currentSteal != task) {
+ for (int j = 0; ; ++j) { // search array
+ if (j < n) {
+ ForkJoinTask<?> vs;
+ if ((v = ws[j]) != null &&
+ (vs = v.currentSteal) != null) {
+ if (joinMe.status < 0)
+ break outer;
+ if (vs == task) {
+ if (task.status < 0)
+ break outer; // stale
+ thread.stealHint = j;
+ break; // save hint for next time
+ }
+ }
+ }
+ else
+ break outer; // no stealer
}
- v.base = b;
- v.stealHint = pid;
- UNSAFE.putOrderedObject(this, currentStealOffset, t);
- t.quietlyExec();
- UNSAFE.putOrderedObject(this, currentStealOffset, ps);
}
+
+ // Try to help v, using specialized form of deqTask
+ for (;;) {
+ if (joinMe.status < 0)
+ break outer;
+ int b = v.base;
+ ForkJoinTask<?>[] q = v.queue;
+ if (b == v.sp || q == null)
+ break; // empty
+ int i = (q.length - 1) & b;
+ long u = (i << qShift) + qBase;
+ ForkJoinTask<?> t = q[i];
+ if (task.status < 0)
+ break outer; // stale
+ if (t != null &&
+ (running ||
+ (running = p.tryIncrementRunningCount())) &&
+ v.base == b++ &&
+ UNSAFE.compareAndSwapObject(q, u, t, null)) {
+ if (t != joinMe && joinMe.status < 0) {
+ UNSAFE.putObjectVolatile(q, u, t);
+ break outer; // joinMe cancelled; back out
+ }
+ v.base = b;
+ if (t.status >= 0) {
+ ForkJoinTask<?> ps = currentSteal;
+ int pid = poolIndex;
+ v.stealHint = pid;
+ UNSAFE.putOrderedObject(this,
+ currentStealOffset, t);
+ t.quietlyExec();
+ UNSAFE.putOrderedObject(this,
+ currentStealOffset, ps);
+ }
+ }
+ else if ((runState & TERMINATING) != 0) {
+ joinMe.cancelIgnoringExceptions();
+ break outer;
+ }
+ }
+
+ // Try to descend to find v's stealer
+ ForkJoinTask<?> next = v.currentJoin;
+ if (task.status < 0 || next == null || next == task ||
+ joinMe.status < 0)
+ break; // done, stale, dead-end, or cyclic
+ task = next;
+ thread = v;
}
- // Try to descend to find v's stealer
- ForkJoinTask<?> next = v.currentJoin;
- if (task.status < 0 || next == null || next == task ||
- joinMe.status < 0)
- return;
- task = next;
- thread = v;
}
+ return running;
}
/**
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java Fri Feb 18 12:04:36 2011 -0800
@@ -1029,6 +1029,8 @@
* elements as they existed upon construction of the iterator, and
* may (but is not guaranteed to) reflect any modifications
* subsequent to construction.
+ *
+ * @return an iterator over the elements in this deque in reverse order
*/
public Iterator<E> descendingIterator() {
return new DescendingItr();
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java Fri Feb 18 12:04:36 2011 -0800
@@ -189,14 +189,14 @@
}
/**
- * Creates a node and links it at end of queue.
+ * Links node at end of queue.
*
- * @param x the item
+ * @param node the node
*/
- private void enqueue(E x) {
+ private void enqueue(Node<E> node) {
// assert putLock.isHeldByCurrentThread();
// assert last.next == null;
- last = last.next = new Node<E>(x);
+ last = last.next = node;
}
/**
@@ -282,7 +282,7 @@
throw new NullPointerException();
if (n == capacity)
throw new IllegalStateException("Queue full");
- enqueue(e);
+ enqueue(new Node<E>(e));
++n;
}
count.set(n);
@@ -332,6 +332,7 @@
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
+ Node<E> node = new Node(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
@@ -347,7 +348,7 @@
while (count.get() == capacity) {
notFull.await();
}
- enqueue(e);
+ enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
@@ -382,7 +383,7 @@
return false;
nanos = notFull.awaitNanos(nanos);
}
- enqueue(e);
+ enqueue(new Node<E>(e));
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
@@ -411,11 +412,12 @@
if (count.get() == capacity)
return false;
int c = -1;
+ Node<E> node = new Node(e);
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
if (count.get() < capacity) {
- enqueue(e);
+ enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
@@ -560,6 +562,27 @@
}
/**
+ * Returns {@code true} if this queue contains the specified element.
+ * More formally, returns {@code true} if and only if this queue contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return {@code true} if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ fullyLock();
+ try {
+ for (Node<E> p = head.next; p != null; p = p.next)
+ if (o.equals(p.item))
+ return true;
+ return false;
+ } finally {
+ fullyUnlock();
+ }
+ }
+
+ /**
* Returns an array containing all of the elements in this queue, in
* proper sequence.
*
@@ -645,7 +668,20 @@
public String toString() {
fullyLock();
try {
- return super.toString();
+ Node<E> p = head.next;
+ if (p == null)
+ return "[]";
+
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (;;) {
+ E e = p.item;
+ sb.append(e == this ? "(this Collection)" : e);
+ p = p.next;
+ if (p == null)
+ return sb.append(']').toString();
+ sb.append(',').append(' ');
+ }
} finally {
fullyUnlock();
}
@@ -727,12 +763,14 @@
/**
* Returns an iterator over the elements in this queue in proper sequence.
- * The returned {@code Iterator} is a "weakly consistent" iterator that
+ * The elements will be returned in order from first (head) to last (tail).
+ *
+ * <p>The returned iterator is a "weakly consistent" iterator that
* will never throw {@link java.util.ConcurrentModificationException
- * ConcurrentModificationException},
- * and guarantees to traverse elements as they existed upon
- * construction of the iterator, and may (but is not guaranteed to)
- * reflect any modifications subsequent to construction.
+ * ConcurrentModificationException}, and guarantees to traverse
+ * elements as they existed upon construction of the iterator, and
+ * may (but is not guaranteed to) reflect any modifications
+ * subsequent to construction.
*
* @return an iterator over the elements in this queue in proper sequence
*/
--- a/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java Fri Feb 18 12:04:36 2011 -0800
@@ -37,10 +37,10 @@
import java.util.AbstractQueue;
import java.util.Collection;
-import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
@@ -450,7 +450,7 @@
}
final boolean casItem(Object cmp, Object val) {
- // assert cmp == null || cmp.getClass() != Node.class;
+ // assert cmp == null || cmp.getClass() != Node.class;
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
}
@@ -516,7 +516,7 @@
* Tries to artificially match a data node -- used by remove.
*/
final boolean tryMatchData() {
- // assert isData;
+ // assert isData;
Object x = item;
if (x != null && x != this && casItem(x, null)) {
LockSupport.unpark(waiter);
@@ -569,7 +569,7 @@
@SuppressWarnings("unchecked")
static <E> E cast(Object item) {
- // assert item == null || item.getClass() != Node.class;
+ // assert item == null || item.getClass() != Node.class;
return (E) item;
}
@@ -588,7 +588,8 @@
throw new NullPointerException();
Node s = null; // the node to append, if needed
- retry: for (;;) { // restart on append race
+ retry:
+ for (;;) { // restart on append race
for (Node h = head, p = h; p != null;) { // find & match first node
boolean isData = p.isData;
@@ -599,7 +600,7 @@
if (p.casItem(item, e)) { // match
for (Node q = p; q != h;) {
Node n = q.next; // update by 2 unless singleton
- if (head == h && casHead(h, n == null? q : n)) {
+ if (head == h && casHead(h, n == null ? q : n)) {
h.forgetNext();
break;
} // advance and retry
@@ -684,7 +685,7 @@
for (;;) {
Object item = s.item;
if (item != e) { // matched
- // assert item != s;
+ // assert item != s;
s.forgetContents(); // avoid garbage
return this.<E>cast(item);
}
@@ -809,22 +810,61 @@
* Moves to next node after prev, or first node if prev null.
*/
private void advance(Node prev) {
- lastPred = lastRet;
- lastRet = prev;
- for (Node p = (prev == null) ? head : succ(prev);
- p != null; p = succ(p)) {
- Object item = p.item;
- if (p.isData) {
- if (item != null && item != p) {
- nextItem = LinkedTransferQueue.this.<E>cast(item);
- nextNode = p;
+ /*
+ * To track and avoid buildup of deleted nodes in the face
+ * of calls to both Queue.remove and Itr.remove, we must
+ * include variants of unsplice and sweep upon each
+ * advance: Upon Itr.remove, we may need to catch up links
+ * from lastPred, and upon other removes, we might need to
+ * skip ahead from stale nodes and unsplice deleted ones
+ * found while advancing.
+ */
+
+ Node r, b; // reset lastPred upon possible deletion of lastRet
+ if ((r = lastRet) != null && !r.isMatched())
+ lastPred = r; // next lastPred is old lastRet
+ else if ((b = lastPred) == null || b.isMatched())
+ lastPred = null; // at start of list
+ else {
+ Node s, n; // help with removal of lastPred.next
+ while ((s = b.next) != null &&
+ s != b && s.isMatched() &&
+ (n = s.next) != null && n != s)
+ b.casNext(s, n);
+ }
+
+ this.lastRet = prev;
+
+ for (Node p = prev, s, n;;) {
+ s = (p == null) ? head : p.next;
+ if (s == null)
+ break;
+ else if (s == p) {
+ p = null;
+ continue;
+ }
+ Object item = s.item;
+ if (s.isData) {
+ if (item != null && item != s) {
+ nextItem = LinkedTransferQueue.<E>cast(item);
+ nextNode = s;
return;
}
}
else if (item == null)
break;
+ // assert s.isMatched();
+ if (p == null)
+ p = s;
+ else if ((n = s.next) == null)
+ break;
+ else if (s == n)
+ p = null;
+ else
+ p.casNext(s, n);
}
nextNode = null;
+ nextItem = null;
}
Itr() {
@@ -844,10 +884,12 @@
}
public final void remove() {
- Node p = lastRet;
- if (p == null) throw new IllegalStateException();
- if (p.tryMatchData())
- unsplice(lastPred, p);
+ final Node lastRet = this.lastRet;
+ if (lastRet == null)
+ throw new IllegalStateException();
+ this.lastRet = null;
+ if (lastRet.tryMatchData())
+ unsplice(lastPred, lastRet);
}
}
@@ -997,8 +1039,7 @@
* Inserts the specified element at the tail of this queue.
* As the queue is unbounded, this method will never return {@code false}.
*
- * @return {@code true} (as specified by
- * {@link BlockingQueue#offer(Object) BlockingQueue.offer})
+ * @return {@code true} (as specified by {@link Queue#offer})
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
@@ -1130,15 +1171,15 @@
}
/**
- * Returns an iterator over the elements in this queue in proper
- * sequence, from head to tail.
+ * Returns an iterator over the elements in this queue in proper sequence.
+ * The elements will be returned in order from first (head) to last (tail).
*
* <p>The returned iterator is a "weakly consistent" iterator that
- * will never throw
- * {@link ConcurrentModificationException ConcurrentModificationException},
- * and guarantees to traverse elements as they existed upon
- * construction of the iterator, and may (but is not guaranteed
- * to) reflect any modifications subsequent to construction.
+ * will never throw {@link java.util.ConcurrentModificationException
+ * ConcurrentModificationException}, and guarantees to traverse
+ * elements as they existed upon construction of the iterator, and
+ * may (but is not guaranteed to) reflect any modifications
+ * subsequent to construction.
*
* @return an iterator over the elements in this queue in proper sequence
*/
@@ -1203,6 +1244,28 @@
}
/**
+ * Returns {@code true} if this queue contains the specified element.
+ * More formally, returns {@code true} if and only if this queue contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
+ *
+ * @param o object to be checked for containment in this queue
+ * @return {@code true} if this queue contains the specified element
+ */
+ public boolean contains(Object o) {
+ if (o == null) return false;
+ for (Node p = head; p != null; p = succ(p)) {
+ Object item = p.item;
+ if (p.isData) {
+ if (item != null && item != p && o.equals(item))
+ return true;
+ }
+ else if (item == null)
+ break;
+ }
+ return false;
+ }
+
+ /**
* Always returns {@code Integer.MAX_VALUE} because a
* {@code LinkedTransferQueue} is not capacity constrained.
*
--- a/jdk/src/share/classes/java/util/concurrent/Phaser.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/Phaser.java Fri Feb 18 12:04:36 2011 -0800
@@ -35,6 +35,8 @@
package java.util.concurrent;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
@@ -61,38 +63,38 @@
* Phaser} may be repeatedly awaited. Method {@link
* #arriveAndAwaitAdvance} has effect analogous to {@link
* java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each
- * generation of a {@code Phaser} has an associated phase number. The
- * phase number starts at zero, and advances when all parties arrive
- * at the barrier, wrapping around to zero after reaching {@code
+ * generation of a phaser has an associated phase number. The phase
+ * number starts at zero, and advances when all parties arrive at the
+ * phaser, wrapping around to zero after reaching {@code
* Integer.MAX_VALUE}. The use of phase numbers enables independent
- * control of actions upon arrival at a barrier and upon awaiting
+ * control of actions upon arrival at a phaser and upon awaiting
* others, via two kinds of methods that may be invoked by any
* registered party:
*
* <ul>
*
* <li> <b>Arrival.</b> Methods {@link #arrive} and
- * {@link #arriveAndDeregister} record arrival at a
- * barrier. These methods do not block, but return an associated
- * <em>arrival phase number</em>; that is, the phase number of
- * the barrier to which the arrival applied. When the final
- * party for a given phase arrives, an optional barrier action
- * is performed and the phase advances. Barrier actions,
- * performed by the party triggering a phase advance, are
- * arranged by overriding method {@link #onAdvance(int, int)},
- * which also controls termination. Overriding this method is
- * similar to, but more flexible than, providing a barrier
- * action to a {@code CyclicBarrier}.
+ * {@link #arriveAndDeregister} record arrival. These methods
+ * do not block, but return an associated <em>arrival phase
+ * number</em>; that is, the phase number of the phaser to which
+ * the arrival applied. When the final party for a given phase
+ * arrives, an optional action is performed and the phase
+ * advances. These actions are performed by the party
+ * triggering a phase advance, and are arranged by overriding
+ * method {@link #onAdvance(int, int)}, which also controls
+ * termination. Overriding this method is similar to, but more
+ * flexible than, providing a barrier action to a {@code
+ * CyclicBarrier}.
*
* <li> <b>Waiting.</b> Method {@link #awaitAdvance} requires an
* argument indicating an arrival phase number, and returns when
- * the barrier advances to (or is already at) a different phase.
+ * the phaser advances to (or is already at) a different phase.
* Unlike similar constructions using {@code CyclicBarrier},
* method {@code awaitAdvance} continues to wait even if the
* waiting thread is interrupted. Interruptible and timeout
* versions are also available, but exceptions encountered while
* tasks wait interruptibly or with timeout do not change the
- * state of the barrier. If necessary, you can perform any
+ * state of the phaser. If necessary, you can perform any
* associated recovery within handlers of those exceptions,
* often after invoking {@code forceTermination}. Phasers may
* also be used by tasks executing in a {@link ForkJoinPool},
@@ -101,26 +103,39 @@
*
* </ul>
*
- * <p> <b>Termination.</b> A {@code Phaser} may enter a
- * <em>termination</em> state in which all synchronization methods
- * immediately return without updating phaser state or waiting for
- * advance, and indicating (via a negative phase value) that execution
- * is complete. Termination is triggered when an invocation of {@code
- * onAdvance} returns {@code true}. As illustrated below, when
- * phasers control actions with a fixed number of iterations, it is
- * often convenient to override this method to cause termination when
- * the current phase number reaches a threshold. Method {@link
- * #forceTermination} is also available to abruptly release waiting
- * threads and allow them to terminate.
+ * <p> <b>Termination.</b> A phaser may enter a <em>termination</em>
+ * state, that may be checked using method {@link #isTerminated}. Upon
+ * termination, all synchronization methods immediately return without
+ * waiting for advance, as indicated by a negative return value.
+ * Similarly, attempts to register upon termination have no effect.
+ * Termination is triggered when an invocation of {@code onAdvance}
+ * returns {@code true}. The default implementation returns {@code
+ * true} if a deregistration has caused the number of registered
+ * parties to become zero. As illustrated below, when phasers control
+ * actions with a fixed number of iterations, it is often convenient
+ * to override this method to cause termination when the current phase
+ * number reaches a threshold. Method {@link #forceTermination} is
+ * also available to abruptly release waiting threads and allow them
+ * to terminate.
*
- * <p> <b>Tiering.</b> Phasers may be <em>tiered</em> (i.e., arranged
- * in tree structures) to reduce contention. Phasers with large
- * numbers of parties that would otherwise experience heavy
+ * <p> <b>Tiering.</b> Phasers may be <em>tiered</em> (i.e.,
+ * constructed in tree structures) to reduce contention. Phasers with
+ * large numbers of parties that would otherwise experience heavy
* synchronization contention costs may instead be set up so that
* groups of sub-phasers share a common parent. This may greatly
* increase throughput even though it incurs greater per-operation
* overhead.
*
+ * <p>In a tree of tiered phasers, registration and deregistration of
+ * child phasers with their parent are managed automatically.
+ * Whenever the number of registered parties of a child phaser becomes
+ * non-zero (as established in the {@link #Phaser(Phaser,int)}
+ * constructor, {@link #register}, or {@link #bulkRegister}), the
+ * child phaser is registered with its parent. Whenever the number of
+ * registered parties becomes zero as the result of an invocation of
+ * {@link #arriveAndDeregister}, the child phaser is deregistered
+ * from its parent.
+ *
* <p><b>Monitoring.</b> While synchronization methods may be invoked
* only by registered parties, the current state of a phaser may be
* monitored by any caller. At any given moment there are {@link
@@ -136,9 +151,9 @@
* <p><b>Sample usages:</b>
*
* <p>A {@code Phaser} may be used instead of a {@code CountDownLatch}
- * to control a one-shot action serving a variable number of
- * parties. The typical idiom is for the method setting this up to
- * first register, then start the actions, then deregister, as in:
+ * to control a one-shot action serving a variable number of parties.
+ * The typical idiom is for the method setting this up to first
+ * register, then start the actions, then deregister, as in:
*
* <pre> {@code
* void runTasks(List<Runnable> tasks) {
@@ -208,34 +223,32 @@
* }}</pre>
*
*
- * <p>To create a set of tasks using a tree of phasers,
- * you could use code of the following form, assuming a
- * Task class with a constructor accepting a phaser that
- * it registers for upon construction:
+ * <p>To create a set of {@code n} tasks using a tree of phasers, you
+ * could use code of the following form, assuming a Task class with a
+ * constructor accepting a {@code Phaser} that it registers with upon
+ * construction. After invocation of {@code build(new Task[n], 0, n,
+ * new Phaser())}, these tasks could then be started, for example by
+ * submitting to a pool:
*
* <pre> {@code
- * void build(Task[] actions, int lo, int hi, Phaser ph) {
+ * void build(Task[] tasks, int lo, int hi, Phaser ph) {
* if (hi - lo > TASKS_PER_PHASER) {
* for (int i = lo; i < hi; i += TASKS_PER_PHASER) {
* int j = Math.min(i + TASKS_PER_PHASER, hi);
- * build(actions, i, j, new Phaser(ph));
+ * build(tasks, i, j, new Phaser(ph));
* }
* } else {
* for (int i = lo; i < hi; ++i)
- * actions[i] = new Task(ph);
+ * tasks[i] = new Task(ph);
* // assumes new Task(ph) performs ph.register()
* }
- * }
- * // .. initially called, for n tasks via
- * build(new Task[n], 0, n, new Phaser());}</pre>
+ * }}</pre>
*
* The best value of {@code TASKS_PER_PHASER} depends mainly on
- * expected barrier synchronization rates. A value as low as four may
- * be appropriate for extremely small per-barrier task bodies (thus
+ * expected synchronization rates. A value as low as four may
+ * be appropriate for extremely small per-phase task bodies (thus
* high rates), or up to hundreds for extremely large ones.
*
- * </pre>
- *
* <p><b>Implementation notes</b>: This implementation restricts the
* maximum number of parties to 65535. Attempts to register additional
* parties result in {@code IllegalStateException}. However, you can and
@@ -253,60 +266,66 @@
*/
/**
- * Barrier state representation. Conceptually, a barrier contains
- * four values:
+ * Primary state representation, holding four bit-fields:
*
- * * parties -- the number of parties to wait (16 bits)
- * * unarrived -- the number of parties yet to hit barrier (16 bits)
- * * phase -- the generation of the barrier (31 bits)
- * * terminated -- set if barrier is terminated (1 bit)
+ * unarrived -- the number of parties yet to hit barrier (bits 0-15)
+ * parties -- the number of parties to wait (bits 16-31)
+ * phase -- the generation of the barrier (bits 32-62)
+ * terminated -- set if barrier is terminated (bit 63 / sign)
+ *
+ * Except that a phaser with no registered parties is
+ * distinguished by the otherwise illegal state of having zero
+ * parties and one unarrived parties (encoded as EMPTY below).
*
- * However, to efficiently maintain atomicity, these values are
- * packed into a single (atomic) long. Termination uses the sign
- * bit of 32 bit representation of phase, so phase is set to -1 on
- * termination. Good performance relies on keeping state decoding
- * and encoding simple, and keeping race windows short.
+ * To efficiently maintain atomicity, these values are packed into
+ * a single (atomic) long. Good performance relies on keeping
+ * state decoding and encoding simple, and keeping race windows
+ * short.
*
- * Note: there are some cheats in arrive() that rely on unarrived
- * count being lowest 16 bits.
+ * All state updates are performed via CAS except initial
+ * registration of a sub-phaser (i.e., one with a non-null
+ * parent). In this (relatively rare) case, we use built-in
+ * synchronization to lock while first registering with its
+ * parent.
+ *
+ * The phase of a subphaser is allowed to lag that of its
+ * ancestors until it is actually accessed -- see method
+ * reconcileState.
*/
private volatile long state;
- private static final int ushortMask = 0xffff;
- private static final int phaseMask = 0x7fffffff;
+ private static final int MAX_PARTIES = 0xffff;
+ private static final int MAX_PHASE = Integer.MAX_VALUE;
+ private static final int PARTIES_SHIFT = 16;
+ private static final int PHASE_SHIFT = 32;
+ private static final int UNARRIVED_MASK = 0xffff; // to mask ints
+ private static final long PARTIES_MASK = 0xffff0000L; // to mask longs
+ private static final long TERMINATION_BIT = 1L << 63;
+
+ // some special values
+ private static final int ONE_ARRIVAL = 1;
+ private static final int ONE_PARTY = 1 << PARTIES_SHIFT;
+ private static final int EMPTY = 1;
+
+ // The following unpacking methods are usually manually inlined
private static int unarrivedOf(long s) {
- return (int) (s & ushortMask);
+ int counts = (int)s;
+ return (counts == EMPTY) ? 0 : counts & UNARRIVED_MASK;
}
private static int partiesOf(long s) {
- return ((int) s) >>> 16;
+ return (int)s >>> PARTIES_SHIFT;
}
private static int phaseOf(long s) {
- return (int) (s >>> 32);
+ return (int)(s >>> PHASE_SHIFT);
}
private static int arrivedOf(long s) {
- return partiesOf(s) - unarrivedOf(s);
- }
-
- private static long stateFor(int phase, int parties, int unarrived) {
- return ((((long) phase) << 32) | (((long) parties) << 16) |
- (long) unarrived);
- }
-
- private static long trippedStateFor(int phase, int parties) {
- long lp = (long) parties;
- return (((long) phase) << 32) | (lp << 16) | lp;
- }
-
- /**
- * Returns message string for bad bounds exceptions.
- */
- private static String badBounds(int parties, int unarrived) {
- return ("Attempt to set " + unarrived +
- " unarrived of " + parties + " parties");
+ int counts = (int)s;
+ return (counts == EMPTY) ? 0 :
+ (counts >>> PARTIES_SHIFT) - (counts & UNARRIVED_MASK);
}
/**
@@ -315,70 +334,180 @@
private final Phaser parent;
/**
- * The root of phaser tree. Equals this if not in a tree. Used to
- * support faster state push-down.
+ * The root of phaser tree. Equals this if not in a tree.
*/
private final Phaser root;
- // Wait queues
-
/**
* Heads of Treiber stacks for waiting threads. To eliminate
- * contention while releasing some threads while adding others, we
+ * contention when releasing some threads while adding others, we
* use two of them, alternating across even and odd phases.
+ * Subphasers share queues with root to speed up releases.
*/
- private final AtomicReference<QNode> evenQ = new AtomicReference<QNode>();
- private final AtomicReference<QNode> oddQ = new AtomicReference<QNode>();
+ private final AtomicReference<QNode> evenQ;
+ private final AtomicReference<QNode> oddQ;
private AtomicReference<QNode> queueFor(int phase) {
return ((phase & 1) == 0) ? evenQ : oddQ;
}
/**
- * Returns current state, first resolving lagged propagation from
- * root if necessary.
+ * Returns message string for bounds exceptions on arrival.
+ */
+ private String badArrive(long s) {
+ return "Attempted arrival of unregistered party for " +
+ stateToString(s);
+ }
+
+ /**
+ * Returns message string for bounds exceptions on registration.
+ */
+ private String badRegister(long s) {
+ return "Attempt to register more than " +
+ MAX_PARTIES + " parties for " + stateToString(s);
+ }
+
+ /**
+ * Main implementation for methods arrive and arriveAndDeregister.
+ * Manually tuned to speed up and minimize race windows for the
+ * common case of just decrementing unarrived field.
+ *
+ * @param deregister false for arrive, true for arriveAndDeregister
*/
- private long getReconciledState() {
- return (parent == null) ? state : reconcileState();
+ private int doArrive(boolean deregister) {
+ int adj = deregister ? ONE_ARRIVAL|ONE_PARTY : ONE_ARRIVAL;
+ final Phaser root = this.root;
+ for (;;) {
+ long s = (root == this) ? state : reconcileState();
+ int phase = (int)(s >>> PHASE_SHIFT);
+ int counts = (int)s;
+ int unarrived = (counts & UNARRIVED_MASK) - 1;
+ if (phase < 0)
+ return phase;
+ else if (counts == EMPTY || unarrived < 0) {
+ if (root == this || reconcileState() == s)
+ throw new IllegalStateException(badArrive(s));
+ }
+ else if (UNSAFE.compareAndSwapLong(this, stateOffset, s, s-=adj)) {
+ if (unarrived == 0) {
+ long n = s & PARTIES_MASK; // base of next state
+ int nextUnarrived = (int)n >>> PARTIES_SHIFT;
+ if (root != this)
+ return parent.doArrive(nextUnarrived == 0);
+ if (onAdvance(phase, nextUnarrived))
+ n |= TERMINATION_BIT;
+ else if (nextUnarrived == 0)
+ n |= EMPTY;
+ else
+ n |= nextUnarrived;
+ n |= (long)((phase + 1) & MAX_PHASE) << PHASE_SHIFT;
+ UNSAFE.compareAndSwapLong(this, stateOffset, s, n);
+ releaseWaiters(phase);
+ }
+ return phase;
+ }
+ }
}
/**
- * Recursively resolves state.
+ * Implementation of register, bulkRegister
+ *
+ * @param registrations number to add to both parties and
+ * unarrived fields. Must be greater than zero.
*/
- private long reconcileState() {
- Phaser p = parent;
- long s = state;
- if (p != null) {
- while (unarrivedOf(s) == 0 && phaseOf(s) != phaseOf(root.state)) {
- long parentState = p.getReconciledState();
- int parentPhase = phaseOf(parentState);
- int phase = phaseOf(s = state);
- if (phase != parentPhase) {
- long next = trippedStateFor(parentPhase, partiesOf(s));
- if (casState(s, next)) {
- releaseWaiters(phase);
- s = next;
+ private int doRegister(int registrations) {
+ // adjustment to state
+ long adj = ((long)registrations << PARTIES_SHIFT) | registrations;
+ final Phaser parent = this.parent;
+ int phase;
+ for (;;) {
+ long s = state;
+ int counts = (int)s;
+ int parties = counts >>> PARTIES_SHIFT;
+ int unarrived = counts & UNARRIVED_MASK;
+ if (registrations > MAX_PARTIES - parties)
+ throw new IllegalStateException(badRegister(s));
+ else if ((phase = (int)(s >>> PHASE_SHIFT)) < 0)
+ break;
+ else if (counts != EMPTY) { // not 1st registration
+ if (parent == null || reconcileState() == s) {
+ if (unarrived == 0) // wait out advance
+ root.internalAwaitAdvance(phase, null);
+ else if (UNSAFE.compareAndSwapLong(this, stateOffset,
+ s, s + adj))
+ break;
+ }
+ }
+ else if (parent == null) { // 1st root registration
+ long next = ((long)phase << PHASE_SHIFT) | adj;
+ if (UNSAFE.compareAndSwapLong(this, stateOffset, s, next))
+ break;
+ }
+ else {
+ synchronized (this) { // 1st sub registration
+ if (state == s) { // recheck under lock
+ parent.doRegister(1);
+ do { // force current phase
+ phase = (int)(root.state >>> PHASE_SHIFT);
+ // assert phase < 0 || (int)state == EMPTY;
+ } while (!UNSAFE.compareAndSwapLong
+ (this, stateOffset, state,
+ ((long)phase << PHASE_SHIFT) | adj));
+ break;
}
}
}
}
+ return phase;
+ }
+
+ /**
+ * Resolves lagged phase propagation from root if necessary.
+ * Reconciliation normally occurs when root has advanced but
+ * subphasers have not yet done so, in which case they must finish
+ * their own advance by setting unarrived to parties (or if
+ * parties is zero, resetting to unregistered EMPTY state).
+ * However, this method may also be called when "floating"
+ * subphasers with possibly some unarrived parties are merely
+ * catching up to current phase, in which case counts are
+ * unaffected.
+ *
+ * @return reconciled state
+ */
+ private long reconcileState() {
+ final Phaser root = this.root;
+ long s = state;
+ if (root != this) {
+ int phase, u, p;
+ // CAS root phase with current parties; possibly trip unarrived
+ while ((phase = (int)(root.state >>> PHASE_SHIFT)) !=
+ (int)(s >>> PHASE_SHIFT) &&
+ !UNSAFE.compareAndSwapLong
+ (this, stateOffset, s,
+ s = (((long)phase << PHASE_SHIFT) |
+ (s & PARTIES_MASK) |
+ ((p = (int)s >>> PARTIES_SHIFT) == 0 ? EMPTY :
+ (u = (int)s & UNARRIVED_MASK) == 0 ? p : u))))
+ s = state;
+ }
return s;
}
/**
- * Creates a new phaser without any initially registered parties,
- * initial phase number 0, and no parent. Any thread using this
+ * Creates a new phaser with no initially registered parties, no
+ * parent, and initial phase number 0. Any thread using this
* phaser will need to first register for it.
*/
public Phaser() {
- this(null);
+ this(null, 0);
}
/**
- * Creates a new phaser with the given numbers of registered
- * unarrived parties, initial phase number 0, and no parent.
+ * Creates a new phaser with the given number of registered
+ * unarrived parties, no parent, and initial phase number 0.
*
- * @param parties the number of parties required to trip barrier
+ * @param parties the number of parties required to advance to the
+ * next phase
* @throws IllegalArgumentException if parties less than zero
* or greater than the maximum number of parties supported
*/
@@ -387,54 +516,62 @@
}
/**
- * Creates a new phaser with the given parent, without any
- * initially registered parties. If parent is non-null this phaser
- * is registered with the parent and its initial phase number is
- * the same as that of parent phaser.
+ * Equivalent to {@link #Phaser(Phaser, int) Phaser(parent, 0)}.
*
* @param parent the parent phaser
*/
public Phaser(Phaser parent) {
- int phase = 0;
- this.parent = parent;
- if (parent != null) {
- this.root = parent.root;
- phase = parent.register();
- }
- else
- this.root = this;
- this.state = trippedStateFor(phase, 0);
+ this(parent, 0);
}
/**
- * Creates a new phaser with the given parent and numbers of
- * registered unarrived parties. If parent is non-null, this phaser
- * is registered with the parent and its initial phase number is
- * the same as that of parent phaser.
+ * Creates a new phaser with the given parent and number of
+ * registered unarrived parties. When the given parent is non-null
+ * and the given number of parties is greater than zero, this
+ * child phaser is registered with its parent.
*
* @param parent the parent phaser
- * @param parties the number of parties required to trip barrier
+ * @param parties the number of parties required to advance to the
+ * next phase
* @throws IllegalArgumentException if parties less than zero
* or greater than the maximum number of parties supported
*/
public Phaser(Phaser parent, int parties) {
- if (parties < 0 || parties > ushortMask)
+ if (parties >>> PARTIES_SHIFT != 0)
throw new IllegalArgumentException("Illegal number of parties");
int phase = 0;
this.parent = parent;
if (parent != null) {
- this.root = parent.root;
- phase = parent.register();
+ final Phaser root = parent.root;
+ this.root = root;
+ this.evenQ = root.evenQ;
+ this.oddQ = root.oddQ;
+ if (parties != 0)
+ phase = parent.doRegister(1);
}
- else
+ else {
this.root = this;
- this.state = trippedStateFor(phase, parties);
+ this.evenQ = new AtomicReference<QNode>();
+ this.oddQ = new AtomicReference<QNode>();
+ }
+ this.state = (parties == 0) ? (long)EMPTY :
+ ((long)phase << PHASE_SHIFT) |
+ ((long)parties << PARTIES_SHIFT) |
+ ((long)parties);
}
/**
- * Adds a new unarrived party to this phaser.
+ * Adds a new unarrived party to this phaser. If an ongoing
+ * invocation of {@link #onAdvance} is in progress, this method
+ * may await its completion before returning. If this phaser has
+ * a parent, and this phaser previously had no registered parties,
+ * this child phaser is also registered with its parent. If
+ * this phaser is terminated, the attempt to register has
+ * no effect, and a negative value is returned.
*
- * @return the arrival phase number to which this registration applied
+ * @return the arrival phase number to which this registration
+ * applied. If this value is negative, then this phaser has
+ * terminated, in which case registration has no effect.
* @throws IllegalStateException if attempting to register more
* than the maximum supported number of parties
*/
@@ -444,11 +581,22 @@
/**
* Adds the given number of new unarrived parties to this phaser.
+ * If an ongoing invocation of {@link #onAdvance} is in progress,
+ * this method may await its completion before returning. If this
+ * phaser has a parent, and the given number of parties is greater
+ * than zero, and this phaser previously had no registered
+ * parties, this child phaser is also registered with its parent.
+ * If this phaser is terminated, the attempt to register has no
+ * effect, and a negative value is returned.
*
- * @param parties the number of parties required to trip barrier
- * @return the arrival phase number to which this registration applied
+ * @param parties the number of additional parties required to
+ * advance to the next phase
+ * @return the arrival phase number to which this registration
+ * applied. If this value is negative, then this phaser has
+ * terminated, in which case registration has no effect.
* @throws IllegalStateException if attempting to register more
* than the maximum supported number of parties
+ * @throws IllegalArgumentException if {@code parties < 0}
*/
public int bulkRegister(int parties) {
if (parties < 0)
@@ -459,258 +607,210 @@
}
/**
- * Shared code for register, bulkRegister
- */
- private int doRegister(int registrations) {
- int phase;
- for (;;) {
- long s = getReconciledState();
- phase = phaseOf(s);
- int unarrived = unarrivedOf(s) + registrations;
- int parties = partiesOf(s) + registrations;
- if (phase < 0)
- break;
- if (parties > ushortMask || unarrived > ushortMask)
- throw new IllegalStateException(badBounds(parties, unarrived));
- if (phase == phaseOf(root.state) &&
- casState(s, stateFor(phase, parties, unarrived)))
- break;
- }
- return phase;
- }
-
- /**
- * Arrives at the barrier, but does not wait for others. (You can
- * in turn wait for others via {@link #awaitAdvance}). It is an
- * unenforced usage error for an unregistered party to invoke this
- * method.
+ * Arrives at this phaser, without waiting for others to arrive.
+ *
+ * <p>It is a usage error for an unregistered party to invoke this
+ * method. However, this error may result in an {@code
+ * IllegalStateException} only upon some subsequent operation on
+ * this phaser, if ever.
*
* @return the arrival phase number, or a negative value if terminated
* @throws IllegalStateException if not terminated and the number
* of unarrived parties would become negative
*/
public int arrive() {
- int phase;
- for (;;) {
- long s = state;
- phase = phaseOf(s);
- if (phase < 0)
- break;
- int parties = partiesOf(s);
- int unarrived = unarrivedOf(s) - 1;
- if (unarrived > 0) { // Not the last arrival
- if (casState(s, s - 1)) // s-1 adds one arrival
- break;
- }
- else if (unarrived == 0) { // the last arrival
- Phaser par = parent;
- if (par == null) { // directly trip
- if (casState
- (s,
- trippedStateFor(onAdvance(phase, parties) ? -1 :
- ((phase + 1) & phaseMask), parties))) {
- releaseWaiters(phase);
- break;
- }
- }
- else { // cascade to parent
- if (casState(s, s - 1)) { // zeroes unarrived
- par.arrive();
- reconcileState();
- break;
- }
- }
- }
- else if (phase != phaseOf(root.state)) // or if unreconciled
- reconcileState();
- else
- throw new IllegalStateException(badBounds(parties, unarrived));
- }
- return phase;
+ return doArrive(false);
}
/**
- * Arrives at the barrier and deregisters from it without waiting
- * for others. Deregistration reduces the number of parties
- * required to trip the barrier in future phases. If this phaser
+ * Arrives at this phaser and deregisters from it without waiting
+ * for others to arrive. Deregistration reduces the number of
+ * parties required to advance in future phases. If this phaser
* has a parent, and deregistration causes this phaser to have
- * zero parties, this phaser also arrives at and is deregistered
- * from its parent. It is an unenforced usage error for an
- * unregistered party to invoke this method.
+ * zero parties, this phaser is also deregistered from its parent.
+ *
+ * <p>It is a usage error for an unregistered party to invoke this
+ * method. However, this error may result in an {@code
+ * IllegalStateException} only upon some subsequent operation on
+ * this phaser, if ever.
*
* @return the arrival phase number, or a negative value if terminated
* @throws IllegalStateException if not terminated and the number
* of registered or unarrived parties would become negative
*/
public int arriveAndDeregister() {
- // similar code to arrive, but too different to merge
- Phaser par = parent;
- int phase;
- for (;;) {
- long s = state;
- phase = phaseOf(s);
- if (phase < 0)
- break;
- int parties = partiesOf(s) - 1;
- int unarrived = unarrivedOf(s) - 1;
- if (parties >= 0) {
- if (unarrived > 0 || (unarrived == 0 && par != null)) {
- if (casState
- (s,
- stateFor(phase, parties, unarrived))) {
- if (unarrived == 0) {
- par.arriveAndDeregister();
- reconcileState();
- }
- break;
- }
- continue;
- }
- if (unarrived == 0) {
- if (casState
- (s,
- trippedStateFor(onAdvance(phase, parties) ? -1 :
- ((phase + 1) & phaseMask), parties))) {
- releaseWaiters(phase);
- break;
- }
- continue;
- }
- if (par != null && phase != phaseOf(root.state)) {
- reconcileState();
- continue;
- }
- }
- throw new IllegalStateException(badBounds(parties, unarrived));
- }
- return phase;
+ return doArrive(true);
}
/**
- * Arrives at the barrier and awaits others. Equivalent in effect
+ * Arrives at this phaser and awaits others. Equivalent in effect
* to {@code awaitAdvance(arrive())}. If you need to await with
* interruption or timeout, you can arrange this with an analogous
- * construction using one of the other forms of the awaitAdvance
- * method. If instead you need to deregister upon arrival use
- * {@code arriveAndDeregister}. It is an unenforced usage error
- * for an unregistered party to invoke this method.
+ * construction using one of the other forms of the {@code
+ * awaitAdvance} method. If instead you need to deregister upon
+ * arrival, use {@code awaitAdvance(arriveAndDeregister())}.
*
- * @return the arrival phase number, or a negative number if terminated
+ * <p>It is a usage error for an unregistered party to invoke this
+ * method. However, this error may result in an {@code
+ * IllegalStateException} only upon some subsequent operation on
+ * this phaser, if ever.
+ *
+ * @return the arrival phase number, or the (negative)
+ * {@linkplain #getPhase() current phase} if terminated
* @throws IllegalStateException if not terminated and the number
* of unarrived parties would become negative
*/
public int arriveAndAwaitAdvance() {
- return awaitAdvance(arrive());
+ // Specialization of doArrive+awaitAdvance eliminating some reads/paths
+ final Phaser root = this.root;
+ for (;;) {
+ long s = (root == this) ? state : reconcileState();
+ int phase = (int)(s >>> PHASE_SHIFT);
+ int counts = (int)s;
+ int unarrived = (counts & UNARRIVED_MASK) - 1;
+ if (phase < 0)
+ return phase;
+ else if (counts == EMPTY || unarrived < 0) {
+ if (reconcileState() == s)
+ throw new IllegalStateException(badArrive(s));
+ }
+ else if (UNSAFE.compareAndSwapLong(this, stateOffset, s,
+ s -= ONE_ARRIVAL)) {
+ if (unarrived != 0)
+ return root.internalAwaitAdvance(phase, null);
+ if (root != this)
+ return parent.arriveAndAwaitAdvance();
+ long n = s & PARTIES_MASK; // base of next state
+ int nextUnarrived = (int)n >>> PARTIES_SHIFT;
+ if (onAdvance(phase, nextUnarrived))
+ n |= TERMINATION_BIT;
+ else if (nextUnarrived == 0)
+ n |= EMPTY;
+ else
+ n |= nextUnarrived;
+ int nextPhase = (phase + 1) & MAX_PHASE;
+ n |= (long)nextPhase << PHASE_SHIFT;
+ if (!UNSAFE.compareAndSwapLong(this, stateOffset, s, n))
+ return (int)(state >>> PHASE_SHIFT); // terminated
+ releaseWaiters(phase);
+ return nextPhase;
+ }
+ }
}
/**
- * Awaits the phase of the barrier to advance from the given phase
- * value, returning immediately if the current phase of the
- * barrier is not equal to the given phase value or this barrier
- * is terminated. It is an unenforced usage error for an
- * unregistered party to invoke this method.
+ * Awaits the phase of this phaser to advance from the given phase
+ * value, returning immediately if the current phase is not equal
+ * to the given phase value or this phaser is terminated.
*
* @param phase an arrival phase number, or negative value if
* terminated; this argument is normally the value returned by a
- * previous call to {@code arrive} or its variants
- * @return the next arrival phase number, or a negative value
- * if terminated or argument is negative
+ * previous call to {@code arrive} or {@code arriveAndDeregister}.
+ * @return the next arrival phase number, or the argument if it is
+ * negative, or the (negative) {@linkplain #getPhase() current phase}
+ * if terminated
*/
public int awaitAdvance(int phase) {
+ final Phaser root = this.root;
+ long s = (root == this) ? state : reconcileState();
+ int p = (int)(s >>> PHASE_SHIFT);
if (phase < 0)
return phase;
- long s = getReconciledState();
- int p = phaseOf(s);
- if (p != phase)
- return p;
- if (unarrivedOf(s) == 0 && parent != null)
- parent.awaitAdvance(phase);
- // Fall here even if parent waited, to reconcile and help release
- return untimedWait(phase);
+ if (p == phase)
+ return root.internalAwaitAdvance(phase, null);
+ return p;
}
/**
- * Awaits the phase of the barrier to advance from the given phase
+ * Awaits the phase of this phaser to advance from the given phase
* value, throwing {@code InterruptedException} if interrupted
- * while waiting, or returning immediately if the current phase of
- * the barrier is not equal to the given phase value or this
- * barrier is terminated. It is an unenforced usage error for an
- * unregistered party to invoke this method.
+ * while waiting, or returning immediately if the current phase is
+ * not equal to the given phase value or this phaser is
+ * terminated.
*
* @param phase an arrival phase number, or negative value if
* terminated; this argument is normally the value returned by a
- * previous call to {@code arrive} or its variants
- * @return the next arrival phase number, or a negative value
- * if terminated or argument is negative
+ * previous call to {@code arrive} or {@code arriveAndDeregister}.
+ * @return the next arrival phase number, or the argument if it is
+ * negative, or the (negative) {@linkplain #getPhase() current phase}
+ * if terminated
* @throws InterruptedException if thread interrupted while waiting
*/
public int awaitAdvanceInterruptibly(int phase)
throws InterruptedException {
+ final Phaser root = this.root;
+ long s = (root == this) ? state : reconcileState();
+ int p = (int)(s >>> PHASE_SHIFT);
if (phase < 0)
return phase;
- long s = getReconciledState();
- int p = phaseOf(s);
- if (p != phase)
- return p;
- if (unarrivedOf(s) == 0 && parent != null)
- parent.awaitAdvanceInterruptibly(phase);
- return interruptibleWait(phase);
+ if (p == phase) {
+ QNode node = new QNode(this, phase, true, false, 0L);
+ p = root.internalAwaitAdvance(phase, node);
+ if (node.wasInterrupted)
+ throw new InterruptedException();
+ }
+ return p;
}
/**
- * Awaits the phase of the barrier to advance from the given phase
+ * Awaits the phase of this phaser to advance from the given phase
* value or the given timeout to elapse, throwing {@code
* InterruptedException} if interrupted while waiting, or
- * returning immediately if the current phase of the barrier is
- * not equal to the given phase value or this barrier is
- * terminated. It is an unenforced usage error for an
- * unregistered party to invoke this method.
+ * returning immediately if the current phase is not equal to the
+ * given phase value or this phaser is terminated.
*
* @param phase an arrival phase number, or negative value if
* terminated; this argument is normally the value returned by a
- * previous call to {@code arrive} or its variants
+ * previous call to {@code arrive} or {@code arriveAndDeregister}.
* @param timeout how long to wait before giving up, in units of
* {@code unit}
* @param unit a {@code TimeUnit} determining how to interpret the
* {@code timeout} parameter
- * @return the next arrival phase number, or a negative value
- * if terminated or argument is negative
+ * @return the next arrival phase number, or the argument if it is
+ * negative, or the (negative) {@linkplain #getPhase() current phase}
+ * if terminated
* @throws InterruptedException if thread interrupted while waiting
* @throws TimeoutException if timed out while waiting
*/
public int awaitAdvanceInterruptibly(int phase,
long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
+ long nanos = unit.toNanos(timeout);
+ final Phaser root = this.root;
+ long s = (root == this) ? state : reconcileState();
+ int p = (int)(s >>> PHASE_SHIFT);
if (phase < 0)
return phase;
- long s = getReconciledState();
- int p = phaseOf(s);
- if (p != phase)
- return p;
- if (unarrivedOf(s) == 0 && parent != null)
- parent.awaitAdvanceInterruptibly(phase, timeout, unit);
- return timedWait(phase, unit.toNanos(timeout));
+ if (p == phase) {
+ QNode node = new QNode(this, phase, true, true, nanos);
+ p = root.internalAwaitAdvance(phase, node);
+ if (node.wasInterrupted)
+ throw new InterruptedException();
+ else if (p == phase)
+ throw new TimeoutException();
+ }
+ return p;
}
/**
- * Forces this barrier to enter termination state. Counts of
- * arrived and registered parties are unaffected. If this phaser
- * has a parent, it too is terminated. This method may be useful
- * for coordinating recovery after one or more tasks encounter
+ * Forces this phaser to enter termination state. Counts of
+ * registered parties are unaffected. If this phaser is a member
+ * of a tiered set of phasers, then all of the phasers in the set
+ * are terminated. If this phaser is already terminated, this
+ * method has no effect. This method may be useful for
+ * coordinating recovery after one or more tasks encounter
* unexpected exceptions.
*/
public void forceTermination() {
- for (;;) {
- long s = getReconciledState();
- int phase = phaseOf(s);
- int parties = partiesOf(s);
- int unarrived = unarrivedOf(s);
- if (phase < 0 ||
- casState(s, stateFor(-1, parties, unarrived))) {
+ // Only need to change root state
+ final Phaser root = this.root;
+ long s;
+ while ((s = root.state) >= 0) {
+ if (UNSAFE.compareAndSwapLong(root, stateOffset,
+ s, s | TERMINATION_BIT)) {
+ // signal all threads
releaseWaiters(0);
releaseWaiters(1);
- if (parent != null)
- parent.forceTermination();
return;
}
}
@@ -719,16 +819,18 @@
/**
* Returns the current phase number. The maximum phase number is
* {@code Integer.MAX_VALUE}, after which it restarts at
- * zero. Upon termination, the phase number is negative.
+ * zero. Upon termination, the phase number is negative,
+ * in which case the prevailing phase prior to termination
+ * may be obtained via {@code getPhase() + Integer.MIN_VALUE}.
*
* @return the phase number, or a negative value if terminated
*/
public final int getPhase() {
- return phaseOf(getReconciledState());
+ return (int)(root.state >>> PHASE_SHIFT);
}
/**
- * Returns the number of parties registered at this barrier.
+ * Returns the number of parties registered at this phaser.
*
* @return the number of parties
*/
@@ -738,22 +840,24 @@
/**
* Returns the number of registered parties that have arrived at
- * the current phase of this barrier.
+ * the current phase of this phaser. If this phaser has terminated,
+ * the returned value is meaningless and arbitrary.
*
* @return the number of arrived parties
*/
public int getArrivedParties() {
- return arrivedOf(state);
+ return arrivedOf(reconcileState());
}
/**
* Returns the number of registered parties that have not yet
- * arrived at the current phase of this barrier.
+ * arrived at the current phase of this phaser. If this phaser has
+ * terminated, the returned value is meaningless and arbitrary.
*
* @return the number of unarrived parties
*/
public int getUnarrivedParties() {
- return unarrivedOf(state);
+ return unarrivedOf(reconcileState());
}
/**
@@ -776,52 +880,56 @@
}
/**
- * Returns {@code true} if this barrier has been terminated.
+ * Returns {@code true} if this phaser has been terminated.
*
- * @return {@code true} if this barrier has been terminated
+ * @return {@code true} if this phaser has been terminated
*/
public boolean isTerminated() {
- return getPhase() < 0;
+ return root.state < 0L;
}
/**
* Overridable method to perform an action upon impending phase
* advance, and to control termination. This method is invoked
- * upon arrival of the party tripping the barrier (when all other
+ * upon arrival of the party advancing this phaser (when all other
* waiting parties are dormant). If this method returns {@code
- * true}, then, rather than advance the phase number, this barrier
- * will be set to a final termination state, and subsequent calls
- * to {@link #isTerminated} will return true. Any (unchecked)
- * Exception or Error thrown by an invocation of this method is
- * propagated to the party attempting to trip the barrier, in
- * which case no advance occurs.
+ * true}, this phaser will be set to a final termination state
+ * upon advance, and subsequent calls to {@link #isTerminated}
+ * will return true. Any (unchecked) Exception or Error thrown by
+ * an invocation of this method is propagated to the party
+ * attempting to advance this phaser, in which case no advance
+ * occurs.
*
* <p>The arguments to this method provide the state of the phaser
- * prevailing for the current transition. (When called from within
- * an implementation of {@code onAdvance} the values returned by
- * methods such as {@code getPhase} may or may not reliably
- * indicate the state to which this transition applies.)
+ * prevailing for the current transition. The effects of invoking
+ * arrival, registration, and waiting methods on this phaser from
+ * within {@code onAdvance} are unspecified and should not be
+ * relied on.
*
- * <p>The default version returns {@code true} when the number of
- * registered parties is zero. Normally, overrides that arrange
- * termination for other reasons should also preserve this
- * property.
+ * <p>If this phaser is a member of a tiered set of phasers, then
+ * {@code onAdvance} is invoked only for its root phaser on each
+ * advance.
*
- * <p>You may override this method to perform an action with side
- * effects visible to participating tasks, but it is only sensible
- * to do so in designs where all parties register before any
- * arrive, and all {@link #awaitAdvance} at each phase.
- * Otherwise, you cannot ensure lack of interference from other
- * parties during the invocation of this method. Additionally,
- * method {@code onAdvance} may be invoked more than once per
- * transition if registrations are intermixed with arrivals.
+ * <p>To support the most common use cases, the default
+ * implementation of this method returns {@code true} when the
+ * number of registered parties has become zero as the result of a
+ * party invoking {@code arriveAndDeregister}. You can disable
+ * this behavior, thus enabling continuation upon future
+ * registrations, by overriding this method to always return
+ * {@code false}:
*
- * @param phase the phase number on entering the barrier
+ * <pre> {@code
+ * Phaser phaser = new Phaser() {
+ * protected boolean onAdvance(int phase, int parties) { return false; }
+ * }}</pre>
+ *
+ * @param phase the current phase number on entry to this method,
+ * before this phaser is advanced
* @param registeredParties the current number of registered parties
- * @return {@code true} if this barrier should terminate
+ * @return {@code true} if this phaser should terminate
*/
protected boolean onAdvance(int phase, int registeredParties) {
- return registeredParties <= 0;
+ return registeredParties == 0;
}
/**
@@ -831,17 +939,138 @@
* followed by the number of registered parties, and {@code
* "arrived = "} followed by the number of arrived parties.
*
- * @return a string identifying this barrier, as well as its state
+ * @return a string identifying this phaser, as well as its state
*/
public String toString() {
- long s = getReconciledState();
+ return stateToString(reconcileState());
+ }
+
+ /**
+ * Implementation of toString and string-based error messages
+ */
+ private String stateToString(long s) {
return super.toString() +
"[phase = " + phaseOf(s) +
" parties = " + partiesOf(s) +
" arrived = " + arrivedOf(s) + "]";
}
- // methods for waiting
+ // Waiting mechanics
+
+ /**
+ * Removes and signals threads from queue for phase.
+ */
+ private void releaseWaiters(int phase) {
+ QNode q; // first element of queue
+ Thread t; // its thread
+ AtomicReference<QNode> head = (phase & 1) == 0 ? evenQ : oddQ;
+ while ((q = head.get()) != null &&
+ q.phase != (int)(root.state >>> PHASE_SHIFT)) {
+ if (head.compareAndSet(q, q.next) &&
+ (t = q.thread) != null) {
+ q.thread = null;
+ LockSupport.unpark(t);
+ }
+ }
+ }
+
+ /**
+ * Variant of releaseWaiters that additionally tries to remove any
+ * nodes no longer waiting for advance due to timeout or
+ * interrupt. Currently, nodes are removed only if they are at
+ * head of queue, which suffices to reduce memory footprint in
+ * most usages.
+ *
+ * @return current phase on exit
+ */
+ private int abortWait(int phase) {
+ AtomicReference<QNode> head = (phase & 1) == 0 ? evenQ : oddQ;
+ for (;;) {
+ Thread t;
+ QNode q = head.get();
+ int p = (int)(root.state >>> PHASE_SHIFT);
+ if (q == null || ((t = q.thread) != null && q.phase == p))
+ return p;
+ if (head.compareAndSet(q, q.next) && t != null) {
+ q.thread = null;
+ LockSupport.unpark(t);
+ }
+ }
+ }
+
+ /** The number of CPUs, for spin control */
+ private static final int NCPU = Runtime.getRuntime().availableProcessors();
+
+ /**
+ * The number of times to spin before blocking while waiting for
+ * advance, per arrival while waiting. On multiprocessors, fully
+ * blocking and waking up a large number of threads all at once is
+ * usually a very slow process, so we use rechargeable spins to
+ * avoid it when threads regularly arrive: When a thread in
+ * internalAwaitAdvance notices another arrival before blocking,
+ * and there appear to be enough CPUs available, it spins
+ * SPINS_PER_ARRIVAL more times before blocking. The value trades
+ * off good-citizenship vs big unnecessary slowdowns.
+ */
+ static final int SPINS_PER_ARRIVAL = (NCPU < 2) ? 1 : 1 << 8;
+
+ /**
+ * Possibly blocks and waits for phase to advance unless aborted.
+ * Call only from root node.
+ *
+ * @param phase current phase
+ * @param node if non-null, the wait node to track interrupt and timeout;
+ * if null, denotes noninterruptible wait
+ * @return current phase
+ */
+ private int internalAwaitAdvance(int phase, QNode node) {
+ releaseWaiters(phase-1); // ensure old queue clean
+ boolean queued = false; // true when node is enqueued
+ int lastUnarrived = 0; // to increase spins upon change
+ int spins = SPINS_PER_ARRIVAL;
+ long s;
+ int p;
+ while ((p = (int)((s = state) >>> PHASE_SHIFT)) == phase) {
+ if (node == null) { // spinning in noninterruptible mode
+ int unarrived = (int)s & UNARRIVED_MASK;
+ if (unarrived != lastUnarrived &&
+ (lastUnarrived = unarrived) < NCPU)
+ spins += SPINS_PER_ARRIVAL;
+ boolean interrupted = Thread.interrupted();
+ if (interrupted || --spins < 0) { // need node to record intr
+ node = new QNode(this, phase, false, false, 0L);
+ node.wasInterrupted = interrupted;
+ }
+ }
+ else if (node.isReleasable()) // done or aborted
+ break;
+ else if (!queued) { // push onto queue
+ AtomicReference<QNode> head = (phase & 1) == 0 ? evenQ : oddQ;
+ QNode q = node.next = head.get();
+ if ((q == null || q.phase == phase) &&
+ (int)(state >>> PHASE_SHIFT) == phase) // avoid stale enq
+ queued = head.compareAndSet(q, node);
+ }
+ else {
+ try {
+ ForkJoinPool.managedBlock(node);
+ } catch (InterruptedException ie) {
+ node.wasInterrupted = true;
+ }
+ }
+ }
+
+ if (node != null) {
+ if (node.thread != null)
+ node.thread = null; // avoid need for unpark()
+ if (node.wasInterrupted && !node.interruptible)
+ Thread.currentThread().interrupt();
+ if (p == phase && (p = (int)(state >>> PHASE_SHIFT)) == phase)
+ return abortWait(phase); // possibly clean up on abort
+ }
+ releaseWaiters(phase);
+ return p;
+ }
/**
* Wait nodes for Treiber stack representing wait queue
@@ -849,174 +1078,61 @@
static final class QNode implements ForkJoinPool.ManagedBlocker {
final Phaser phaser;
final int phase;
- final long startTime;
- final long nanos;
+ final boolean interruptible;
final boolean timed;
- final boolean interruptible;
- volatile boolean wasInterrupted = false;
+ boolean wasInterrupted;
+ long nanos;
+ long lastTime;
volatile Thread thread; // nulled to cancel wait
QNode next;
+
QNode(Phaser phaser, int phase, boolean interruptible,
- boolean timed, long startTime, long nanos) {
+ boolean timed, long nanos) {
this.phaser = phaser;
this.phase = phase;
+ this.interruptible = interruptible;
+ this.nanos = nanos;
this.timed = timed;
- this.interruptible = interruptible;
- this.startTime = startTime;
- this.nanos = nanos;
+ this.lastTime = timed ? System.nanoTime() : 0L;
thread = Thread.currentThread();
}
- public boolean isReleasable() {
- return (thread == null ||
- phaser.getPhase() != phase ||
- (interruptible && wasInterrupted) ||
- (timed && (nanos - (System.nanoTime() - startTime)) <= 0));
- }
- public boolean block() {
- if (Thread.interrupted()) {
- wasInterrupted = true;
- if (interruptible)
- return true;
- }
- if (!timed)
- LockSupport.park(this);
- else {
- long waitTime = nanos - (System.nanoTime() - startTime);
- if (waitTime <= 0)
- return true;
- LockSupport.parkNanos(this, waitTime);
- }
- return isReleasable();
- }
- void signal() {
- Thread t = thread;
- if (t != null) {
- thread = null;
- LockSupport.unpark(t);
- }
- }
- boolean doWait() {
- if (thread != null) {
- try {
- ForkJoinPool.managedBlock(this);
- } catch (InterruptedException ie) {
- }
- }
- return wasInterrupted;
- }
- }
-
- /**
- * Removes and signals waiting threads from wait queue.
- */
- private void releaseWaiters(int phase) {
- AtomicReference<QNode> head = queueFor(phase);
- QNode q;
- while ((q = head.get()) != null) {
- if (head.compareAndSet(q, q.next))
- q.signal();
+ public boolean isReleasable() {
+ if (thread == null)
+ return true;
+ if (phaser.getPhase() != phase) {
+ thread = null;
+ return true;
+ }
+ if (Thread.interrupted())
+ wasInterrupted = true;
+ if (wasInterrupted && interruptible) {
+ thread = null;
+ return true;
+ }
+ if (timed) {
+ if (nanos > 0L) {
+ long now = System.nanoTime();
+ nanos -= now - lastTime;
+ lastTime = now;
+ }
+ if (nanos <= 0L) {
+ thread = null;
+ return true;
+ }
+ }
+ return false;
}
- }
-
- /**
- * Tries to enqueue given node in the appropriate wait queue.
- *
- * @return true if successful
- */
- private boolean tryEnqueue(QNode node) {
- AtomicReference<QNode> head = queueFor(node.phase);
- return head.compareAndSet(node.next = head.get(), node);
- }
-
- /**
- * Enqueues node and waits unless aborted or signalled.
- *
- * @return current phase
- */
- private int untimedWait(int phase) {
- QNode node = null;
- boolean queued = false;
- boolean interrupted = false;
- int p;
- while ((p = getPhase()) == phase) {
- if (Thread.interrupted())
- interrupted = true;
- else if (node == null)
- node = new QNode(this, phase, false, false, 0, 0);
- else if (!queued)
- queued = tryEnqueue(node);
- else
- interrupted = node.doWait();
- }
- if (node != null)
- node.thread = null;
- releaseWaiters(phase);
- if (interrupted)
- Thread.currentThread().interrupt();
- return p;
- }
- /**
- * Interruptible version
- * @return current phase
- */
- private int interruptibleWait(int phase) throws InterruptedException {
- QNode node = null;
- boolean queued = false;
- boolean interrupted = false;
- int p;
- while ((p = getPhase()) == phase && !interrupted) {
- if (Thread.interrupted())
- interrupted = true;
- else if (node == null)
- node = new QNode(this, phase, true, false, 0, 0);
- else if (!queued)
- queued = tryEnqueue(node);
- else
- interrupted = node.doWait();
+ public boolean block() {
+ if (isReleasable())
+ return true;
+ else if (!timed)
+ LockSupport.park(this);
+ else if (nanos > 0)
+ LockSupport.parkNanos(this, nanos);
+ return isReleasable();
}
- if (node != null)
- node.thread = null;
- if (p != phase || (p = getPhase()) != phase)
- releaseWaiters(phase);
- if (interrupted)
- throw new InterruptedException();
- return p;
- }
-
- /**
- * Timeout version.
- * @return current phase
- */
- private int timedWait(int phase, long nanos)
- throws InterruptedException, TimeoutException {
- long startTime = System.nanoTime();
- QNode node = null;
- boolean queued = false;
- boolean interrupted = false;
- int p;
- while ((p = getPhase()) == phase && !interrupted) {
- if (Thread.interrupted())
- interrupted = true;
- else if (nanos - (System.nanoTime() - startTime) <= 0)
- break;
- else if (node == null)
- node = new QNode(this, phase, true, true, startTime, nanos);
- else if (!queued)
- queued = tryEnqueue(node);
- else
- interrupted = node.doWait();
- }
- if (node != null)
- node.thread = null;
- if (p != phase || (p = getPhase()) != phase)
- releaseWaiters(phase);
- if (interrupted)
- throw new InterruptedException();
- if (p == phase)
- throw new TimeoutException();
- return p;
}
// Unsafe mechanics
@@ -1025,10 +1141,6 @@
private static final long stateOffset =
objectFieldOffset("state", Phaser.class);
- private final boolean casState(long cmp, long val) {
- return UNSAFE.compareAndSwapLong(this, stateOffset, cmp, val);
- }
-
private static long objectFieldOffset(String field, Class<?> klazz) {
try {
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
--- a/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/PriorityBlockingQueue.java Fri Feb 18 12:04:36 2011 -0800
@@ -43,11 +43,11 @@
* the same ordering rules as class {@link PriorityQueue} and supplies
* blocking retrieval operations. While this queue is logically
* unbounded, attempted additions may fail due to resource exhaustion
- * (causing <tt>OutOfMemoryError</tt>). This class does not permit
- * <tt>null</tt> elements. A priority queue relying on {@linkplain
+ * (causing {@code OutOfMemoryError}). This class does not permit
+ * {@code null} elements. A priority queue relying on {@linkplain
* Comparable natural ordering} also does not permit insertion of
* non-comparable objects (doing so results in
- * <tt>ClassCastException</tt>).
+ * {@code ClassCastException}).
*
* <p>This class and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
@@ -55,7 +55,7 @@
* #iterator()} is <em>not</em> guaranteed to traverse the elements of
* the PriorityBlockingQueue in any particular order. If you need
* ordered traversal, consider using
- * <tt>Arrays.sort(pq.toArray())</tt>. Also, method <tt>drainTo</tt>
+ * {@code Arrays.sort(pq.toArray())}. Also, method {@code drainTo}
* can be used to <em>remove</em> some or all elements in priority
* order and place them in another collection.
*
@@ -65,12 +65,12 @@
* secondary key to break ties in primary priority values. For
* example, here is a class that applies first-in-first-out
* tie-breaking to comparable elements. To use it, you would insert a
- * <tt>new FIFOEntry(anEntry)</tt> instead of a plain entry object.
+ * {@code new FIFOEntry(anEntry)} instead of a plain entry object.
*
- * <pre>
- * class FIFOEntry<E extends Comparable<? super E>>
- * implements Comparable<FIFOEntry<E>> {
- * final static AtomicLong seq = new AtomicLong();
+ * <pre> {@code
+ * class FIFOEntry<E extends Comparable<? super E>>
+ * implements Comparable<FIFOEntry<E>> {
+ * static final AtomicLong seq = new AtomicLong(0);
* final long seqNum;
* final E entry;
* public FIFOEntry(E entry) {
@@ -78,13 +78,13 @@
* this.entry = entry;
* }
* public E getEntry() { return entry; }
- * public int compareTo(FIFOEntry<E> other) {
+ * public int compareTo(FIFOEntry<E> other) {
* int res = entry.compareTo(other.entry);
- * if (res == 0 && other.entry != this.entry)
- * res = (seqNum < other.seqNum ? -1 : 1);
+ * if (res == 0 && other.entry != this.entry)
+ * res = (seqNum < other.seqNum ? -1 : 1);
* return res;
* }
- * }</pre>
+ * }}</pre>
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
@@ -98,34 +98,102 @@
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = 5595510919245408276L;
- private final PriorityQueue<E> q;
- private final ReentrantLock lock = new ReentrantLock(true);
- private final Condition notEmpty = lock.newCondition();
+ /*
+ * The implementation uses an array-based binary heap, with public
+ * operations protected with a single lock. However, allocation
+ * during resizing uses a simple spinlock (used only while not
+ * holding main lock) in order to allow takes to operate
+ * concurrently with allocation. This avoids repeated
+ * postponement of waiting consumers and consequent element
+ * build-up. The need to back away from lock during allocation
+ * makes it impossible to simply wrap delegated
+ * java.util.PriorityQueue operations within a lock, as was done
+ * in a previous version of this class. To maintain
+ * interoperability, a plain PriorityQueue is still used during
+ * serialization, which maintains compatibility at the espense of
+ * transiently doubling overhead.
+ */
+
+ /**
+ * Default array capacity.
+ */
+ private static final int DEFAULT_INITIAL_CAPACITY = 11;
+
+ /**
+ * The maximum size of array to allocate.
+ * Some VMs reserve some header words in an array.
+ * Attempts to allocate larger arrays may result in
+ * OutOfMemoryError: Requested array size exceeds VM limit
+ */
+ private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
- * Creates a <tt>PriorityBlockingQueue</tt> with the default
+ * Priority queue represented as a balanced binary heap: the two
+ * children of queue[n] are queue[2*n+1] and queue[2*(n+1)]. The
+ * priority queue is ordered by comparator, or by the elements'
+ * natural ordering, if comparator is null: For each node n in the
+ * heap and each descendant d of n, n <= d. The element with the
+ * lowest value is in queue[0], assuming the queue is nonempty.
+ */
+ private transient Object[] queue;
+
+ /**
+ * The number of elements in the priority queue.
+ */
+ private transient int size;
+
+ /**
+ * The comparator, or null if priority queue uses elements'
+ * natural ordering.
+ */
+ private transient Comparator<? super E> comparator;
+
+ /**
+ * Lock used for all public operations
+ */
+ private final ReentrantLock lock;
+
+ /**
+ * Condition for blocking when empty
+ */
+ private final Condition notEmpty;
+
+ /**
+ * Spinlock for allocation, acquired via CAS.
+ */
+ private transient volatile int allocationSpinLock;
+
+ /**
+ * A plain PriorityQueue used only for serialization,
+ * to maintain compatibility with previous versions
+ * of this class. Non-null only during serialization/deserialization.
+ */
+ private PriorityQueue q;
+
+ /**
+ * Creates a {@code PriorityBlockingQueue} with the default
* initial capacity (11) that orders its elements according to
* their {@linkplain Comparable natural ordering}.
*/
public PriorityBlockingQueue() {
- q = new PriorityQueue<E>();
+ this(DEFAULT_INITIAL_CAPACITY, null);
}
/**
- * Creates a <tt>PriorityBlockingQueue</tt> with the specified
+ * Creates a {@code PriorityBlockingQueue} with the specified
* initial capacity that orders its elements according to their
* {@linkplain Comparable natural ordering}.
*
* @param initialCapacity the initial capacity for this priority queue
- * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
+ * @throws IllegalArgumentException if {@code initialCapacity} is less
* than 1
*/
public PriorityBlockingQueue(int initialCapacity) {
- q = new PriorityQueue<E>(initialCapacity, null);
+ this(initialCapacity, null);
}
/**
- * Creates a <tt>PriorityBlockingQueue</tt> with the specified initial
+ * Creates a {@code PriorityBlockingQueue} with the specified initial
* capacity that orders its elements according to the specified
* comparator.
*
@@ -133,16 +201,21 @@
* @param comparator the comparator that will be used to order this
* priority queue. If {@code null}, the {@linkplain Comparable
* natural ordering} of the elements will be used.
- * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
+ * @throws IllegalArgumentException if {@code initialCapacity} is less
* than 1
*/
public PriorityBlockingQueue(int initialCapacity,
Comparator<? super E> comparator) {
- q = new PriorityQueue<E>(initialCapacity, comparator);
+ if (initialCapacity < 1)
+ throw new IllegalArgumentException();
+ this.lock = new ReentrantLock();
+ this.notEmpty = lock.newCondition();
+ this.comparator = comparator;
+ this.queue = new Object[initialCapacity];
}
/**
- * Creates a <tt>PriorityBlockingQueue</tt> containing the elements
+ * Creates a {@code PriorityBlockingQueue} containing the elements
* in the specified collection. If the specified collection is a
* {@link SortedSet} or a {@link PriorityQueue}, this
* priority queue will be ordered according to the same ordering.
@@ -158,14 +231,215 @@
* of its elements are null
*/
public PriorityBlockingQueue(Collection<? extends E> c) {
- q = new PriorityQueue<E>(c);
+ this.lock = new ReentrantLock();
+ this.notEmpty = lock.newCondition();
+ boolean heapify = true; // true if not known to be in heap order
+ boolean screen = true; // true if must screen for nulls
+ if (c instanceof SortedSet<?>) {
+ SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
+ this.comparator = (Comparator<? super E>) ss.comparator();
+ heapify = false;
+ }
+ else if (c instanceof PriorityBlockingQueue<?>) {
+ PriorityBlockingQueue<? extends E> pq =
+ (PriorityBlockingQueue<? extends E>) c;
+ this.comparator = (Comparator<? super E>) pq.comparator();
+ screen = false;
+ if (pq.getClass() == PriorityBlockingQueue.class) // exact match
+ heapify = false;
+ }
+ Object[] a = c.toArray();
+ int n = a.length;
+ // If c.toArray incorrectly doesn't return Object[], copy it.
+ if (a.getClass() != Object[].class)
+ a = Arrays.copyOf(a, n, Object[].class);
+ if (screen && (n == 1 || this.comparator != null)) {
+ for (int i = 0; i < n; ++i)
+ if (a[i] == null)
+ throw new NullPointerException();
+ }
+ this.queue = a;
+ this.size = n;
+ if (heapify)
+ heapify();
+ }
+
+ /**
+ * Tries to grow array to accommodate at least one more element
+ * (but normally expand by about 50%), giving up (allowing retry)
+ * on contention (which we expect to be rare). Call only while
+ * holding lock.
+ *
+ * @param array the heap array
+ * @param oldCap the length of the array
+ */
+ private void tryGrow(Object[] array, int oldCap) {
+ lock.unlock(); // must release and then re-acquire main lock
+ Object[] newArray = null;
+ if (allocationSpinLock == 0 &&
+ UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset,
+ 0, 1)) {
+ try {
+ int newCap = oldCap + ((oldCap < 64) ?
+ (oldCap + 2) : // grow faster if small
+ (oldCap >> 1));
+ if (newCap - MAX_ARRAY_SIZE > 0) { // possible overflow
+ int minCap = oldCap + 1;
+ if (minCap < 0 || minCap > MAX_ARRAY_SIZE)
+ throw new OutOfMemoryError();
+ newCap = MAX_ARRAY_SIZE;
+ }
+ if (newCap > oldCap && queue == array)
+ newArray = new Object[newCap];
+ } finally {
+ allocationSpinLock = 0;
+ }
+ }
+ if (newArray == null) // back off if another thread is allocating
+ Thread.yield();
+ lock.lock();
+ if (newArray != null && queue == array) {
+ queue = newArray;
+ System.arraycopy(array, 0, newArray, 0, oldCap);
+ }
+ }
+
+ /**
+ * Mechanics for poll(). Call only while holding lock.
+ */
+ private E extract() {
+ E result;
+ int n = size - 1;
+ if (n < 0)
+ result = null;
+ else {
+ Object[] array = queue;
+ result = (E) array[0];
+ E x = (E) array[n];
+ array[n] = null;
+ Comparator<? super E> cmp = comparator;
+ if (cmp == null)
+ siftDownComparable(0, x, array, n);
+ else
+ siftDownUsingComparator(0, x, array, n, cmp);
+ size = n;
+ }
+ return result;
+ }
+
+ /**
+ * Inserts item x at position k, maintaining heap invariant by
+ * promoting x up the tree until it is greater than or equal to
+ * its parent, or is the root.
+ *
+ * To simplify and speed up coercions and comparisons. the
+ * Comparable and Comparator versions are separated into different
+ * methods that are otherwise identical. (Similarly for siftDown.)
+ * These methods are static, with heap state as arguments, to
+ * simplify use in light of possible comparator exceptions.
+ *
+ * @param k the position to fill
+ * @param x the item to insert
+ * @param array the heap array
+ * @param n heap size
+ */
+ private static <T> void siftUpComparable(int k, T x, Object[] array) {
+ Comparable<? super T> key = (Comparable<? super T>) x;
+ while (k > 0) {
+ int parent = (k - 1) >>> 1;
+ Object e = array[parent];
+ if (key.compareTo((T) e) >= 0)
+ break;
+ array[k] = e;
+ k = parent;
+ }
+ array[k] = key;
+ }
+
+ private static <T> void siftUpUsingComparator(int k, T x, Object[] array,
+ Comparator<? super T> cmp) {
+ while (k > 0) {
+ int parent = (k - 1) >>> 1;
+ Object e = array[parent];
+ if (cmp.compare(x, (T) e) >= 0)
+ break;
+ array[k] = e;
+ k = parent;
+ }
+ array[k] = x;
+ }
+
+ /**
+ * Inserts item x at position k, maintaining heap invariant by
+ * demoting x down the tree repeatedly until it is less than or
+ * equal to its children or is a leaf.
+ *
+ * @param k the position to fill
+ * @param x the item to insert
+ * @param array the heap array
+ * @param n heap size
+ */
+ private static <T> void siftDownComparable(int k, T x, Object[] array,
+ int n) {
+ Comparable<? super T> key = (Comparable<? super T>)x;
+ int half = n >>> 1; // loop while a non-leaf
+ while (k < half) {
+ int child = (k << 1) + 1; // assume left child is least
+ Object c = array[child];
+ int right = child + 1;
+ if (right < n &&
+ ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
+ c = array[child = right];
+ if (key.compareTo((T) c) <= 0)
+ break;
+ array[k] = c;
+ k = child;
+ }
+ array[k] = key;
+ }
+
+ private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
+ int n,
+ Comparator<? super T> cmp) {
+ int half = n >>> 1;
+ while (k < half) {
+ int child = (k << 1) + 1;
+ Object c = array[child];
+ int right = child + 1;
+ if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
+ c = array[child = right];
+ if (cmp.compare(x, (T) c) <= 0)
+ break;
+ array[k] = c;
+ k = child;
+ }
+ array[k] = x;
+ }
+
+ /**
+ * Establishes the heap invariant (described above) in the entire tree,
+ * assuming nothing about the order of the elements prior to the call.
+ */
+ private void heapify() {
+ Object[] array = queue;
+ int n = size;
+ int half = (n >>> 1) - 1;
+ Comparator<? super E> cmp = comparator;
+ if (cmp == null) {
+ for (int i = half; i >= 0; i--)
+ siftDownComparable(i, (E) array[i], array, n);
+ }
+ else {
+ for (int i = half; i >= 0; i--)
+ siftDownUsingComparator(i, (E) array[i], array, n, cmp);
+ }
}
/**
* Inserts the specified element into this priority queue.
*
* @param e the element to add
- * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @return {@code true} (as specified by {@link Collection#add})
* @throws ClassCastException if the specified element cannot be compared
* with elements currently in the priority queue according to the
* priority queue's ordering
@@ -177,30 +451,41 @@
/**
* Inserts the specified element into this priority queue.
+ * As the queue is unbounded, this method will never return {@code false}.
*
* @param e the element to add
- * @return <tt>true</tt> (as specified by {@link Queue#offer})
+ * @return {@code true} (as specified by {@link Queue#offer})
* @throws ClassCastException if the specified element cannot be compared
* with elements currently in the priority queue according to the
* priority queue's ordering
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
+ if (e == null)
+ throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
+ int n, cap;
+ Object[] array;
+ while ((n = size) >= (cap = (array = queue).length))
+ tryGrow(array, cap);
try {
- boolean ok = q.offer(e);
- assert ok;
+ Comparator<? super E> cmp = comparator;
+ if (cmp == null)
+ siftUpComparable(n, e, array);
+ else
+ siftUpUsingComparator(n, e, array, cmp);
+ size = n + 1;
notEmpty.signal();
- return true;
} finally {
lock.unlock();
}
+ return true;
}
/**
- * Inserts the specified element into this priority queue. As the queue is
- * unbounded this method will never block.
+ * Inserts the specified element into this priority queue.
+ * As the queue is unbounded, this method will never block.
*
* @param e the element to add
* @throws ClassCastException if the specified element cannot be compared
@@ -213,13 +498,15 @@
}
/**
- * Inserts the specified element into this priority queue. As the queue is
- * unbounded this method will never block.
+ * Inserts the specified element into this priority queue.
+ * As the queue is unbounded, this method will never block or
+ * return {@code false}.
*
* @param e the element to add
* @param timeout This parameter is ignored as the method never blocks
* @param unit This parameter is ignored as the method never blocks
- * @return <tt>true</tt>
+ * @return {@code true} (as specified by
+ * {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
* @throws ClassCastException if the specified element cannot be compared
* with elements currently in the priority queue according to the
* priority queue's ordering
@@ -232,95 +519,121 @@
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
+ E result;
try {
- return q.poll();
+ result = extract();
} finally {
lock.unlock();
}
+ return result;
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
+ E result;
try {
- try {
- while (q.size() == 0)
- notEmpty.await();
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
- E x = q.poll();
- assert x != null;
- return x;
+ while ( (result = extract()) == null)
+ notEmpty.await();
} finally {
lock.unlock();
}
+ return result;
}
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
+ E result;
try {
- for (;;) {
- E x = q.poll();
- if (x != null)
- return x;
- if (nanos <= 0)
- return null;
- try {
- nanos = notEmpty.awaitNanos(nanos);
- } catch (InterruptedException ie) {
- notEmpty.signal(); // propagate to non-interrupted thread
- throw ie;
- }
- }
+ while ( (result = extract()) == null && nanos > 0)
+ nanos = notEmpty.awaitNanos(nanos);
} finally {
lock.unlock();
}
+ return result;
}
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
+ E result;
try {
- return q.peek();
+ result = size > 0 ? (E) queue[0] : null;
+ } finally {
+ lock.unlock();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the comparator used to order the elements in this queue,
+ * or {@code null} if this queue uses the {@linkplain Comparable
+ * natural ordering} of its elements.
+ *
+ * @return the comparator used to order the elements in this queue,
+ * or {@code null} if this queue uses the natural
+ * ordering of its elements
+ */
+ public Comparator<? super E> comparator() {
+ return comparator;
+ }
+
+ public int size() {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ return size;
} finally {
lock.unlock();
}
}
/**
- * Returns the comparator used to order the elements in this queue,
- * or <tt>null</tt> if this queue uses the {@linkplain Comparable
- * natural ordering} of its elements.
- *
- * @return the comparator used to order the elements in this queue,
- * or <tt>null</tt> if this queue uses the natural
- * ordering of its elements
+ * Always returns {@code Integer.MAX_VALUE} because
+ * a {@code PriorityBlockingQueue} is not capacity constrained.
+ * @return {@code Integer.MAX_VALUE} always
*/
- public Comparator<? super E> comparator() {
- return q.comparator();
+ public int remainingCapacity() {
+ return Integer.MAX_VALUE;
}
- public int size() {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- return q.size();
- } finally {
- lock.unlock();
+ private int indexOf(Object o) {
+ if (o != null) {
+ Object[] array = queue;
+ int n = size;
+ for (int i = 0; i < n; i++)
+ if (o.equals(array[i]))
+ return i;
}
+ return -1;
}
/**
- * Always returns <tt>Integer.MAX_VALUE</tt> because
- * a <tt>PriorityBlockingQueue</tt> is not capacity constrained.
- * @return <tt>Integer.MAX_VALUE</tt>
+ * Removes the ith element from queue.
*/
- public int remainingCapacity() {
- return Integer.MAX_VALUE;
+ private void removeAt(int i) {
+ Object[] array = queue;
+ int n = size - 1;
+ if (n == i) // removed last element
+ array[i] = null;
+ else {
+ E moved = (E) array[n];
+ array[n] = null;
+ Comparator<? super E> cmp = comparator;
+ if (cmp == null)
+ siftDownComparable(i, moved, array, n);
+ else
+ siftDownUsingComparator(i, moved, array, n, cmp);
+ if (array[i] == moved) {
+ if (cmp == null)
+ siftUpComparable(i, moved, array);
+ else
+ siftUpUsingComparator(i, moved, array, cmp);
+ }
+ }
+ size = n;
}
/**
@@ -332,13 +645,40 @@
* result of the call).
*
* @param o element to be removed from this queue, if present
- * @return <tt>true</tt> if this queue changed as a result of the call
+ * @return {@code true} if this queue changed as a result of the call
*/
public boolean remove(Object o) {
+ boolean removed = false;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return q.remove(o);
+ int i = indexOf(o);
+ if (i != -1) {
+ removeAt(i);
+ removed = true;
+ }
+ } finally {
+ lock.unlock();
+ }
+ return removed;
+ }
+
+
+ /**
+ * Identity-based version for use in Itr.remove
+ */
+ private void removeEQ(Object o) {
+ final ReentrantLock lock = this.lock;
+ lock.lock();
+ try {
+ Object[] array = queue;
+ int n = size;
+ for (int i = 0; i < n; i++) {
+ if (o == array[i]) {
+ removeAt(i);
+ break;
+ }
+ }
} finally {
lock.unlock();
}
@@ -350,16 +690,18 @@
* at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this queue
- * @return <tt>true</tt> if this queue contains the specified element
+ * @return {@code true} if this queue contains the specified element
*/
public boolean contains(Object o) {
+ int index;
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return q.contains(o);
+ index = indexOf(o);
} finally {
lock.unlock();
}
+ return index != -1;
}
/**
@@ -379,7 +721,7 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return q.toArray();
+ return Arrays.copyOf(queue, size);
} finally {
lock.unlock();
}
@@ -390,7 +732,18 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return q.toString();
+ int n = size;
+ if (n == 0)
+ return "[]";
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int i = 0; i < n; ++i) {
+ E e = (E)queue[i];
+ sb.append(e == this ? "(this Collection)" : e);
+ if (i != n - 1)
+ sb.append(',').append(' ');
+ }
+ return sb.append(']').toString();
} finally {
lock.unlock();
}
@@ -412,7 +765,7 @@
try {
int n = 0;
E e;
- while ( (e = q.poll()) != null) {
+ while ( (e = extract()) != null) {
c.add(e);
++n;
}
@@ -440,7 +793,7 @@
try {
int n = 0;
E e;
- while (n < maxElements && (e = q.poll()) != null) {
+ while (n < maxElements && (e = extract()) != null) {
c.add(e);
++n;
}
@@ -458,7 +811,11 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- q.clear();
+ Object[] array = queue;
+ int n = size;
+ size = 0;
+ for (int i = 0; i < n; i++)
+ array[i] = null;
} finally {
lock.unlock();
}
@@ -475,22 +832,22 @@
* <p>If this queue fits in the specified array with room to spare
* (i.e., the array has more elements than this queue), the element in
* the array immediately following the end of the queue is set to
- * <tt>null</tt>.
+ * {@code null}.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
- * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+ * <p>Suppose {@code x} is a queue known to contain only strings.
* The following code can be used to dump the queue into a newly
- * allocated array of <tt>String</tt>:
+ * allocated array of {@code String}:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
- * Note that <tt>toArray(new Object[0])</tt> is identical in function to
- * <tt>toArray()</tt>.
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
*
* @param a the array into which the elements of the queue are to
* be stored, if it is big enough; otherwise, a new array of the
@@ -505,7 +862,14 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return q.toArray(a);
+ int n = size;
+ if (a.length < n)
+ // Make a new array of a's runtime type, but my contents:
+ return (T[]) Arrays.copyOf(queue, size, a.getClass());
+ System.arraycopy(queue, 0, a, 0, n);
+ if (a.length > n)
+ a[n] = null;
+ return a;
} finally {
lock.unlock();
}
@@ -514,8 +878,9 @@
/**
* Returns an iterator over the elements in this queue. The
* iterator does not return the elements in any particular order.
- * The returned <tt>Iterator</tt> is a "weakly consistent"
- * iterator that will never throw {@link
+ *
+ * <p>The returned iterator is a "weakly consistent" iterator that
+ * will never throw {@link java.util.ConcurrentModificationException
* ConcurrentModificationException}, and guarantees to traverse
* elements as they existed upon construction of the iterator, and
* may (but is not guaranteed to) reflect any modifications
@@ -530,7 +895,7 @@
/**
* Snapshot iterator that works off copy of underlying q array.
*/
- private class Itr implements Iterator<E> {
+ final class Itr implements Iterator<E> {
final Object[] array; // Array of all elements
int cursor; // index of next element to return;
int lastRet; // index of last element, or -1 if no such
@@ -554,39 +919,65 @@
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
- Object x = array[lastRet];
+ removeEQ(array[lastRet]);
lastRet = -1;
- // Traverse underlying queue to find == element,
- // not just a .equals element.
- lock.lock();
- try {
- for (Iterator it = q.iterator(); it.hasNext(); ) {
- if (it.next() == x) {
- it.remove();
- return;
- }
- }
- } finally {
- lock.unlock();
- }
}
}
/**
- * Saves the state to a stream (that is, serializes it). This
- * merely wraps default serialization within lock. The
- * serialization strategy for items is left to underlying
- * Queue. Note that locking is not needed on deserialization, so
- * readObject is not defined, just relying on default.
+ * Saves the state to a stream (that is, serializes it). For
+ * compatibility with previous version of this class,
+ * elements are first copied to a java.util.PriorityQueue,
+ * which is then serialized.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
lock.lock();
try {
+ int n = size; // avoid zero capacity argument
+ q = new PriorityQueue<E>(n == 0 ? 1 : n, comparator);
+ q.addAll(this);
s.defaultWriteObject();
} finally {
+ q = null;
lock.unlock();
}
}
+ /**
+ * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream
+ * (that is, deserializes it).
+ *
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException {
+ try {
+ s.defaultReadObject();
+ this.queue = new Object[q.size()];
+ comparator = q.comparator();
+ addAll(q);
+ } finally {
+ q = null;
+ }
+ }
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long allocationSpinLockOffset =
+ objectFieldOffset(UNSAFE, "allocationSpinLock",
+ PriorityBlockingQueue.class);
+
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
+ }
+
}
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Fri Feb 18 12:04:36 2011 -0800
@@ -360,8 +360,12 @@
getExecuteExistingDelayedTasksAfterShutdownPolicy();
boolean keepPeriodic =
getContinueExistingPeriodicTasksAfterShutdownPolicy();
- if (!keepDelayed && !keepPeriodic)
+ if (!keepDelayed && !keepPeriodic) {
+ for (Object e : q.toArray())
+ if (e instanceof RunnableScheduledFuture<?>)
+ ((RunnableScheduledFuture<?>) e).cancel(false);
q.clear();
+ }
else {
// Traverse snapshot to avoid iterator exceptions
for (Object e : q.toArray()) {
--- a/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/SynchronousQueue.java Fri Feb 18 12:04:36 2011 -0800
@@ -163,7 +163,7 @@
/**
* Shared internal API for dual stacks and queues.
*/
- static abstract class Transferer {
+ abstract static class Transferer {
/**
* Performs a put or take.
*
@@ -190,7 +190,7 @@
* seems not to vary with number of CPUs (beyond 2) so is just
* a constant.
*/
- static final int maxTimedSpins = (NCPUS < 2)? 0 : 32;
+ static final int maxTimedSpins = (NCPUS < 2) ? 0 : 32;
/**
* The number of times to spin before blocking in untimed waits.
@@ -241,19 +241,11 @@
this.item = item;
}
- static final AtomicReferenceFieldUpdater<SNode, SNode>
- nextUpdater = AtomicReferenceFieldUpdater.newUpdater
- (SNode.class, SNode.class, "next");
-
boolean casNext(SNode cmp, SNode val) {
- return (cmp == next &&
- nextUpdater.compareAndSet(this, cmp, val));
+ return cmp == next &&
+ UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
- static final AtomicReferenceFieldUpdater<SNode, SNode>
- matchUpdater = AtomicReferenceFieldUpdater.newUpdater
- (SNode.class, SNode.class, "match");
-
/**
* Tries to match node s to this node, if so, waking up thread.
* Fulfillers call tryMatch to identify their waiters.
@@ -264,7 +256,7 @@
*/
boolean tryMatch(SNode s) {
if (match == null &&
- matchUpdater.compareAndSet(this, null, s)) {
+ UNSAFE.compareAndSwapObject(this, matchOffset, null, s)) {
Thread w = waiter;
if (w != null) { // waiters need at most one unpark
waiter = null;
@@ -279,23 +271,28 @@
* Tries to cancel a wait by matching node to itself.
*/
void tryCancel() {
- matchUpdater.compareAndSet(this, null, this);
+ UNSAFE.compareAndSwapObject(this, matchOffset, null, this);
}
boolean isCancelled() {
return match == this;
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long nextOffset =
+ objectFieldOffset(UNSAFE, "next", SNode.class);
+ private static final long matchOffset =
+ objectFieldOffset(UNSAFE, "match", SNode.class);
+
}
/** The head (top) of the stack */
volatile SNode head;
- static final AtomicReferenceFieldUpdater<TransferStack, SNode>
- headUpdater = AtomicReferenceFieldUpdater.newUpdater
- (TransferStack.class, SNode.class, "head");
-
boolean casHead(SNode h, SNode nh) {
- return h == head && headUpdater.compareAndSet(this, h, nh);
+ return h == head &&
+ UNSAFE.compareAndSwapObject(this, headOffset, h, nh);
}
/**
@@ -338,7 +335,7 @@
*/
SNode s = null; // constructed/reused as needed
- int mode = (e == null)? REQUEST : DATA;
+ int mode = (e == null) ? REQUEST : DATA;
for (;;) {
SNode h = head;
@@ -356,7 +353,7 @@
}
if ((h = head) != null && h.next == s)
casHead(h, s.next); // help s's fulfiller
- return mode == REQUEST? m.item : s.item;
+ return (mode == REQUEST) ? m.item : s.item;
}
} else if (!isFulfilling(h.mode)) { // try to fulfill
if (h.isCancelled()) // already cancelled
@@ -372,7 +369,7 @@
SNode mn = m.next;
if (m.tryMatch(s)) {
casHead(s, mn); // pop both s and m
- return (mode == REQUEST)? m.item : s.item;
+ return (mode == REQUEST) ? m.item : s.item;
} else // lost match
s.casNext(m, mn); // help unlink
}
@@ -423,11 +420,11 @@
* and don't wait at all, so are trapped in transfer
* method rather than calling awaitFulfill.
*/
- long lastTime = (timed)? System.nanoTime() : 0;
+ long lastTime = timed ? System.nanoTime() : 0;
Thread w = Thread.currentThread();
SNode h = head;
- int spins = (shouldSpin(s)?
- (timed? maxTimedSpins : maxUntimedSpins) : 0);
+ int spins = (shouldSpin(s) ?
+ (timed ? maxTimedSpins : maxUntimedSpins) : 0);
for (;;) {
if (w.isInterrupted())
s.tryCancel();
@@ -444,7 +441,7 @@
}
}
if (spins > 0)
- spins = shouldSpin(s)? (spins-1) : 0;
+ spins = shouldSpin(s) ? (spins-1) : 0;
else if (s.waiter == null)
s.waiter = w; // establish waiter so can park next iter
else if (!timed)
@@ -499,6 +496,12 @@
p = n;
}
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long headOffset =
+ objectFieldOffset(UNSAFE, "head", TransferStack.class);
+
}
/** Dual Queue */
@@ -524,29 +527,21 @@
this.isData = isData;
}
- static final AtomicReferenceFieldUpdater<QNode, QNode>
- nextUpdater = AtomicReferenceFieldUpdater.newUpdater
- (QNode.class, QNode.class, "next");
-
boolean casNext(QNode cmp, QNode val) {
- return (next == cmp &&
- nextUpdater.compareAndSet(this, cmp, val));
+ return next == cmp &&
+ UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
- static final AtomicReferenceFieldUpdater<QNode, Object>
- itemUpdater = AtomicReferenceFieldUpdater.newUpdater
- (QNode.class, Object.class, "item");
-
boolean casItem(Object cmp, Object val) {
- return (item == cmp &&
- itemUpdater.compareAndSet(this, cmp, val));
+ return item == cmp &&
+ UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
}
/**
* Tries to cancel by CAS'ing ref to this as item.
*/
void tryCancel(Object cmp) {
- itemUpdater.compareAndSet(this, cmp, this);
+ UNSAFE.compareAndSwapObject(this, itemOffset, cmp, this);
}
boolean isCancelled() {
@@ -561,6 +556,13 @@
boolean isOffList() {
return next == this;
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long nextOffset =
+ objectFieldOffset(UNSAFE, "next", QNode.class);
+ private static final long itemOffset =
+ objectFieldOffset(UNSAFE, "item", QNode.class);
}
/** Head of queue */
@@ -580,41 +582,30 @@
tail = h;
}
- static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
- headUpdater = AtomicReferenceFieldUpdater.newUpdater
- (TransferQueue.class, QNode.class, "head");
-
/**
* Tries to cas nh as new head; if successful, unlink
* old head's next node to avoid garbage retention.
*/
void advanceHead(QNode h, QNode nh) {
- if (h == head && headUpdater.compareAndSet(this, h, nh))
+ if (h == head &&
+ UNSAFE.compareAndSwapObject(this, headOffset, h, nh))
h.next = h; // forget old next
}
- static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
- tailUpdater = AtomicReferenceFieldUpdater.newUpdater
- (TransferQueue.class, QNode.class, "tail");
-
/**
* Tries to cas nt as new tail.
*/
void advanceTail(QNode t, QNode nt) {
if (tail == t)
- tailUpdater.compareAndSet(this, t, nt);
+ UNSAFE.compareAndSwapObject(this, tailOffset, t, nt);
}
- static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
- cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater
- (TransferQueue.class, QNode.class, "cleanMe");
-
/**
* Tries to CAS cleanMe slot.
*/
boolean casCleanMe(QNode cmp, QNode val) {
- return (cleanMe == cmp &&
- cleanMeUpdater.compareAndSet(this, cmp, val));
+ return cleanMe == cmp &&
+ UNSAFE.compareAndSwapObject(this, cleanMeOffset, cmp, val);
}
/**
@@ -683,7 +674,7 @@
s.item = s;
s.waiter = null;
}
- return (x != null)? x : e;
+ return (x != null) ? x : e;
} else { // complementary-mode
QNode m = h.next; // node to fulfill
@@ -700,7 +691,7 @@
advanceHead(h, m); // successfully fulfilled
LockSupport.unpark(m.waiter);
- return (x != null)? x : e;
+ return (x != null) ? x : e;
}
}
}
@@ -716,10 +707,10 @@
*/
Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
/* Same idea as TransferStack.awaitFulfill */
- long lastTime = (timed)? System.nanoTime() : 0;
+ long lastTime = timed ? System.nanoTime() : 0;
Thread w = Thread.currentThread();
int spins = ((head.next == s) ?
- (timed? maxTimedSpins : maxUntimedSpins) : 0);
+ (timed ? maxTimedSpins : maxUntimedSpins) : 0);
for (;;) {
if (w.isInterrupted())
s.tryCancel(e);
@@ -799,6 +790,16 @@
return; // Postpone cleaning s
}
}
+
+ // unsafe mechanics
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long headOffset =
+ objectFieldOffset(UNSAFE, "head", TransferQueue.class);
+ private static final long tailOffset =
+ objectFieldOffset(UNSAFE, "tail", TransferQueue.class);
+ private static final long cleanMeOffset =
+ objectFieldOffset(UNSAFE, "cleanMe", TransferQueue.class);
+
}
/**
@@ -824,7 +825,7 @@
* access; otherwise the order is unspecified.
*/
public SynchronousQueue(boolean fair) {
- transferer = (fair)? new TransferQueue() : new TransferStack();
+ transferer = fair ? new TransferQueue() : new TransferStack();
}
/**
@@ -1141,4 +1142,17 @@
transferer = new TransferStack();
}
+ // Unsafe mechanics
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
+ }
+
}
--- a/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/ThreadPoolExecutor.java Fri Feb 18 12:04:36 2011 -0800
@@ -1841,6 +1841,43 @@
}
}
+ /**
+ * Returns a string identifying this pool, as well as its state,
+ * including indications of run state and estimated worker and
+ * task counts.
+ *
+ * @return a string identifying this pool, as well as its state
+ */
+ public String toString() {
+ long ncompleted;
+ int nworkers, nactive;
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ ncompleted = completedTaskCount;
+ nactive = 0;
+ nworkers = workers.size();
+ for (Worker w : workers) {
+ ncompleted += w.completedTasks;
+ if (w.isLocked())
+ ++nactive;
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ int c = ctl.get();
+ String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
+ (runStateAtLeast(c, TERMINATED) ? "Terminated" :
+ "Shutting down"));
+ return super.toString() +
+ "[" + rs +
+ ", pool size = " + nworkers +
+ ", active threads = " + nactive +
+ ", queued tasks = " + workQueue.size() +
+ ", completed tasks = " + ncompleted +
+ "]";
+ }
+
/* Extension hooks */
/**
@@ -1961,7 +1998,9 @@
* @throws RejectedExecutionException always.
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
- throw new RejectedExecutionException();
+ throw new RejectedExecutionException("Task " + r.toString() +
+ " rejected from " +
+ e.toString());
}
}
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java Fri Feb 18 12:04:36 2011 -0800
@@ -48,28 +48,37 @@
public class AtomicIntegerArray implements java.io.Serializable {
private static final long serialVersionUID = 2862133569453604235L;
- // setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(int[].class);
- private static final int scale = unsafe.arrayIndexScale(int[].class);
+ private static final int shift;
private final int[] array;
- private long rawIndex(int i) {
+ static {
+ int scale = unsafe.arrayIndexScale(int[].class);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ shift = 31 - Integer.numberOfLeadingZeros(scale);
+ }
+
+ private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- return base + (long) i * scale;
+
+ return byteOffset(i);
+ }
+
+ private static long byteOffset(int i) {
+ return ((long) i << shift) + base;
}
/**
- * Creates a new AtomicIntegerArray of given length.
+ * Creates a new AtomicIntegerArray of the given length, with all
+ * elements initially zero.
*
* @param length the length of the array
*/
public AtomicIntegerArray(int length) {
array = new int[length];
- // must perform at least one volatile write to conform to JMM
- if (length > 0)
- unsafe.putIntVolatile(array, rawIndex(0), 0);
}
/**
@@ -80,17 +89,8 @@
* @throws NullPointerException if array is null
*/
public AtomicIntegerArray(int[] array) {
- if (array == null)
- throw new NullPointerException();
- int length = array.length;
- this.array = new int[length];
- if (length > 0) {
- int last = length-1;
- for (int i = 0; i < last; ++i)
- this.array[i] = array[i];
- // Do the last write as volatile
- unsafe.putIntVolatile(this.array, rawIndex(last), array[last]);
- }
+ // Visibility guaranteed by final field guarantees
+ this.array = array.clone();
}
/**
@@ -109,7 +109,11 @@
* @return the current value
*/
public final int get(int i) {
- return unsafe.getIntVolatile(array, rawIndex(i));
+ return getRaw(checkedByteOffset(i));
+ }
+
+ private int getRaw(long offset) {
+ return unsafe.getIntVolatile(array, offset);
}
/**
@@ -119,7 +123,7 @@
* @param newValue the new value
*/
public final void set(int i, int newValue) {
- unsafe.putIntVolatile(array, rawIndex(i), newValue);
+ unsafe.putIntVolatile(array, checkedByteOffset(i), newValue);
}
/**
@@ -130,7 +134,7 @@
* @since 1.6
*/
public final void lazySet(int i, int newValue) {
- unsafe.putOrderedInt(array, rawIndex(i), newValue);
+ unsafe.putOrderedInt(array, checkedByteOffset(i), newValue);
}
/**
@@ -142,9 +146,10 @@
* @return the previous value
*/
public final int getAndSet(int i, int newValue) {
+ long offset = checkedByteOffset(i);
while (true) {
- int current = get(i);
- if (compareAndSet(i, current, newValue))
+ int current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, newValue))
return current;
}
}
@@ -160,8 +165,11 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, int expect, int update) {
- return unsafe.compareAndSwapInt(array, rawIndex(i),
- expect, update);
+ return compareAndSetRaw(checkedByteOffset(i), expect, update);
+ }
+
+ private boolean compareAndSetRaw(long offset, int expect, int update) {
+ return unsafe.compareAndSwapInt(array, offset, expect, update);
}
/**
@@ -188,12 +196,7 @@
* @return the previous value
*/
public final int getAndIncrement(int i) {
- while (true) {
- int current = get(i);
- int next = current + 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, 1);
}
/**
@@ -203,12 +206,7 @@
* @return the previous value
*/
public final int getAndDecrement(int i) {
- while (true) {
- int current = get(i);
- int next = current - 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, -1);
}
/**
@@ -219,10 +217,10 @@
* @return the previous value
*/
public final int getAndAdd(int i, int delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- int current = get(i);
- int next = current + delta;
- if (compareAndSet(i, current, next))
+ int current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, current + delta))
return current;
}
}
@@ -234,12 +232,7 @@
* @return the updated value
*/
public final int incrementAndGet(int i) {
- while (true) {
- int current = get(i);
- int next = current + 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, 1);
}
/**
@@ -249,12 +242,7 @@
* @return the updated value
*/
public final int decrementAndGet(int i) {
- while (true) {
- int current = get(i);
- int next = current - 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, -1);
}
/**
@@ -265,22 +253,32 @@
* @return the updated value
*/
public final int addAndGet(int i, int delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- int current = get(i);
+ int current = getRaw(offset);
int next = current + delta;
- if (compareAndSet(i, current, next))
+ if (compareAndSetRaw(offset, current, next))
return next;
}
}
/**
* Returns the String representation of the current values of array.
- * @return the String representation of the current values of array.
+ * @return the String representation of the current values of array
*/
public String toString() {
- if (array.length > 0) // force volatile read
- get(0);
- return Arrays.toString(array);
+ int iMax = array.length - 1;
+ if (iMax == -1)
+ return "[]";
+
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(getRaw(byteOffset(i)));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(',').append(' ');
+ }
}
}
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongArray.java Fri Feb 18 12:04:36 2011 -0800
@@ -47,28 +47,37 @@
public class AtomicLongArray implements java.io.Serializable {
private static final long serialVersionUID = -2308431214976778248L;
- // setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(long[].class);
- private static final int scale = unsafe.arrayIndexScale(long[].class);
+ private static final int shift;
private final long[] array;
- private long rawIndex(int i) {
+ static {
+ int scale = unsafe.arrayIndexScale(long[].class);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ shift = 31 - Integer.numberOfLeadingZeros(scale);
+ }
+
+ private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- return base + (long) i * scale;
+
+ return byteOffset(i);
+ }
+
+ private static long byteOffset(int i) {
+ return ((long) i << shift) + base;
}
/**
- * Creates a new AtomicLongArray of given length.
+ * Creates a new AtomicLongArray of the given length, with all
+ * elements initially zero.
*
* @param length the length of the array
*/
public AtomicLongArray(int length) {
array = new long[length];
- // must perform at least one volatile write to conform to JMM
- if (length > 0)
- unsafe.putLongVolatile(array, rawIndex(0), 0);
}
/**
@@ -79,17 +88,8 @@
* @throws NullPointerException if array is null
*/
public AtomicLongArray(long[] array) {
- if (array == null)
- throw new NullPointerException();
- int length = array.length;
- this.array = new long[length];
- if (length > 0) {
- int last = length-1;
- for (int i = 0; i < last; ++i)
- this.array[i] = array[i];
- // Do the last write as volatile
- unsafe.putLongVolatile(this.array, rawIndex(last), array[last]);
- }
+ // Visibility guaranteed by final field guarantees
+ this.array = array.clone();
}
/**
@@ -108,7 +108,11 @@
* @return the current value
*/
public final long get(int i) {
- return unsafe.getLongVolatile(array, rawIndex(i));
+ return getRaw(checkedByteOffset(i));
+ }
+
+ private long getRaw(long offset) {
+ return unsafe.getLongVolatile(array, offset);
}
/**
@@ -118,7 +122,7 @@
* @param newValue the new value
*/
public final void set(int i, long newValue) {
- unsafe.putLongVolatile(array, rawIndex(i), newValue);
+ unsafe.putLongVolatile(array, checkedByteOffset(i), newValue);
}
/**
@@ -129,7 +133,7 @@
* @since 1.6
*/
public final void lazySet(int i, long newValue) {
- unsafe.putOrderedLong(array, rawIndex(i), newValue);
+ unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
}
@@ -142,16 +146,17 @@
* @return the previous value
*/
public final long getAndSet(int i, long newValue) {
+ long offset = checkedByteOffset(i);
while (true) {
- long current = get(i);
- if (compareAndSet(i, current, newValue))
+ long current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, newValue))
return current;
}
}
/**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
+ * Atomically sets the element at position {@code i} to the given
+ * updated value if the current value {@code ==} the expected value.
*
* @param i the index
* @param expect the expected value
@@ -160,13 +165,16 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, long expect, long update) {
- return unsafe.compareAndSwapLong(array, rawIndex(i),
- expect, update);
+ return compareAndSetRaw(checkedByteOffset(i), expect, update);
+ }
+
+ private boolean compareAndSetRaw(long offset, long expect, long update) {
+ return unsafe.compareAndSwapLong(array, offset, expect, update);
}
/**
- * Atomically sets the value to the given updated value
- * if the current value {@code ==} the expected value.
+ * Atomically sets the element at position {@code i} to the given
+ * updated value if the current value {@code ==} the expected value.
*
* <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
@@ -188,12 +196,7 @@
* @return the previous value
*/
public final long getAndIncrement(int i) {
- while (true) {
- long current = get(i);
- long next = current + 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, 1);
}
/**
@@ -203,12 +206,7 @@
* @return the previous value
*/
public final long getAndDecrement(int i) {
- while (true) {
- long current = get(i);
- long next = current - 1;
- if (compareAndSet(i, current, next))
- return current;
- }
+ return getAndAdd(i, -1);
}
/**
@@ -219,10 +217,10 @@
* @return the previous value
*/
public final long getAndAdd(int i, long delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- long current = get(i);
- long next = current + delta;
- if (compareAndSet(i, current, next))
+ long current = getRaw(offset);
+ if (compareAndSetRaw(offset, current, current + delta))
return current;
}
}
@@ -234,12 +232,7 @@
* @return the updated value
*/
public final long incrementAndGet(int i) {
- while (true) {
- long current = get(i);
- long next = current + 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, 1);
}
/**
@@ -249,12 +242,7 @@
* @return the updated value
*/
public final long decrementAndGet(int i) {
- while (true) {
- long current = get(i);
- long next = current - 1;
- if (compareAndSet(i, current, next))
- return next;
- }
+ return addAndGet(i, -1);
}
/**
@@ -265,22 +253,32 @@
* @return the updated value
*/
public long addAndGet(int i, long delta) {
+ long offset = checkedByteOffset(i);
while (true) {
- long current = get(i);
+ long current = getRaw(offset);
long next = current + delta;
- if (compareAndSet(i, current, next))
+ if (compareAndSetRaw(offset, current, next))
return next;
}
}
/**
* Returns the String representation of the current values of array.
- * @return the String representation of the current values of array.
+ * @return the String representation of the current values of array
*/
public String toString() {
- if (array.length > 0) // force volatile read
- get(0);
- return Arrays.toString(array);
+ int iMax = array.length - 1;
+ if (iMax == -1)
+ return "[]";
+
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(getRaw(byteOffset(i)));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(',').append(' ');
+ }
}
}
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java Fri Feb 18 12:04:36 2011 -0800
@@ -38,8 +38,8 @@
/**
* An {@code AtomicMarkableReference} maintains an object reference
* along with a mark bit, that can be updated atomically.
- * <p>
- * <p> Implementation note. This implementation maintains markable
+ *
+ * <p>Implementation note: This implementation maintains markable
* references by creating internal objects representing "boxed"
* [reference, boolean] pairs.
*
@@ -47,17 +47,21 @@
* @author Doug Lea
* @param <V> The type of object referred to by this reference
*/
-public class AtomicMarkableReference<V> {
+public class AtomicMarkableReference<V> {
- private static class ReferenceBooleanPair<T> {
- private final T reference;
- private final boolean bit;
- ReferenceBooleanPair(T r, boolean i) {
- reference = r; bit = i;
+ private static class Pair<T> {
+ final T reference;
+ final boolean mark;
+ private Pair(T reference, boolean mark) {
+ this.reference = reference;
+ this.mark = mark;
+ }
+ static <T> Pair<T> of(T reference, boolean mark) {
+ return new Pair<T>(reference, mark);
}
}
- private final AtomicReference<ReferenceBooleanPair<V>> atomicRef;
+ private volatile Pair<V> pair;
/**
* Creates a new {@code AtomicMarkableReference} with the given
@@ -67,7 +71,7 @@
* @param initialMark the initial mark
*/
public AtomicMarkableReference(V initialRef, boolean initialMark) {
- atomicRef = new AtomicReference<ReferenceBooleanPair<V>> (new ReferenceBooleanPair<V>(initialRef, initialMark));
+ pair = Pair.of(initialRef, initialMark);
}
/**
@@ -76,7 +80,7 @@
* @return the current value of the reference
*/
public V getReference() {
- return atomicRef.get().reference;
+ return pair.reference;
}
/**
@@ -85,7 +89,7 @@
* @return the current value of the mark
*/
public boolean isMarked() {
- return atomicRef.get().bit;
+ return pair.mark;
}
/**
@@ -97,9 +101,9 @@
* @return the current value of the reference
*/
public V get(boolean[] markHolder) {
- ReferenceBooleanPair<V> p = atomicRef.get();
- markHolder[0] = p.bit;
- return p.reference;
+ Pair<V> pair = this.pair;
+ markHolder[0] = pair.mark;
+ return pair.reference;
}
/**
@@ -122,13 +126,8 @@
V newReference,
boolean expectedMark,
boolean newMark) {
- ReferenceBooleanPair<V> current = atomicRef.get();
- return expectedReference == current.reference &&
- expectedMark == current.bit &&
- ((newReference == current.reference && newMark == current.bit) ||
- atomicRef.weakCompareAndSet(current,
- new ReferenceBooleanPair<V>(newReference,
- newMark)));
+ return compareAndSet(expectedReference, newReference,
+ expectedMark, newMark);
}
/**
@@ -147,13 +146,13 @@
V newReference,
boolean expectedMark,
boolean newMark) {
- ReferenceBooleanPair<V> current = atomicRef.get();
- return expectedReference == current.reference &&
- expectedMark == current.bit &&
- ((newReference == current.reference && newMark == current.bit) ||
- atomicRef.compareAndSet(current,
- new ReferenceBooleanPair<V>(newReference,
- newMark)));
+ Pair<V> current = pair;
+ return
+ expectedReference == current.reference &&
+ expectedMark == current.mark &&
+ ((newReference == current.reference &&
+ newMark == current.mark) ||
+ casPair(current, Pair.of(newReference, newMark)));
}
/**
@@ -163,9 +162,9 @@
* @param newMark the new value for the mark
*/
public void set(V newReference, boolean newMark) {
- ReferenceBooleanPair<V> current = atomicRef.get();
- if (newReference != current.reference || newMark != current.bit)
- atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark));
+ Pair<V> current = pair;
+ if (newReference != current.reference || newMark != current.mark)
+ this.pair = Pair.of(newReference, newMark);
}
/**
@@ -182,11 +181,32 @@
* @return true if successful
*/
public boolean attemptMark(V expectedReference, boolean newMark) {
- ReferenceBooleanPair<V> current = atomicRef.get();
- return expectedReference == current.reference &&
- (newMark == current.bit ||
- atomicRef.compareAndSet
- (current, new ReferenceBooleanPair<V>(expectedReference,
- newMark)));
+ Pair<V> current = pair;
+ return
+ expectedReference == current.reference &&
+ (newMark == current.mark ||
+ casPair(current, Pair.of(expectedReference, newMark)));
+ }
+
+ // Unsafe mechanics
+
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long pairOffset =
+ objectFieldOffset(UNSAFE, "pair", AtomicMarkableReference.class);
+
+ private boolean casPair(Pair<V> cmp, Pair<V> val) {
+ return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
+ }
+
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
}
}
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Fri Feb 18 12:04:36 2011 -0800
@@ -51,24 +51,35 @@
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final int base = unsafe.arrayBaseOffset(Object[].class);
- private static final int scale = unsafe.arrayIndexScale(Object[].class);
+ private static final int shift;
private final Object[] array;
- private long rawIndex(int i) {
+ static {
+ int scale = unsafe.arrayIndexScale(Object[].class);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ shift = 31 - Integer.numberOfLeadingZeros(scale);
+ }
+
+ private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException("index " + i);
- return base + (long) i * scale;
+
+ return byteOffset(i);
+ }
+
+ private static long byteOffset(int i) {
+ return ((long) i << shift) + base;
}
/**
- * Creates a new AtomicReferenceArray of given length.
+ * Creates a new AtomicReferenceArray of the given length, with all
+ * elements initially null.
+ *
* @param length the length of the array
*/
public AtomicReferenceArray(int length) {
array = new Object[length];
- // must perform at least one volatile write to conform to JMM
- if (length > 0)
- unsafe.putObjectVolatile(array, rawIndex(0), null);
}
/**
@@ -79,18 +90,8 @@
* @throws NullPointerException if array is null
*/
public AtomicReferenceArray(E[] array) {
- if (array == null)
- throw new NullPointerException();
- int length = array.length;
- this.array = new Object[length];
- if (length > 0) {
- int last = length-1;
- for (int i = 0; i < last; ++i)
- this.array[i] = array[i];
- // Do the last write as volatile
- E e = array[last];
- unsafe.putObjectVolatile(this.array, rawIndex(last), e);
- }
+ // Visibility guaranteed by final field guarantees
+ this.array = array.clone();
}
/**
@@ -109,7 +110,11 @@
* @return the current value
*/
public final E get(int i) {
- return (E) unsafe.getObjectVolatile(array, rawIndex(i));
+ return getRaw(checkedByteOffset(i));
+ }
+
+ private E getRaw(long offset) {
+ return (E) unsafe.getObjectVolatile(array, offset);
}
/**
@@ -119,7 +124,7 @@
* @param newValue the new value
*/
public final void set(int i, E newValue) {
- unsafe.putObjectVolatile(array, rawIndex(i), newValue);
+ unsafe.putObjectVolatile(array, checkedByteOffset(i), newValue);
}
/**
@@ -130,7 +135,7 @@
* @since 1.6
*/
public final void lazySet(int i, E newValue) {
- unsafe.putOrderedObject(array, rawIndex(i), newValue);
+ unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
}
@@ -143,9 +148,10 @@
* @return the previous value
*/
public final E getAndSet(int i, E newValue) {
+ long offset = checkedByteOffset(i);
while (true) {
- E current = get(i);
- if (compareAndSet(i, current, newValue))
+ E current = (E) getRaw(offset);
+ if (compareAndSetRaw(offset, current, newValue))
return current;
}
}
@@ -153,6 +159,7 @@
/**
* Atomically sets the element at position {@code i} to the given
* updated value if the current value {@code ==} the expected value.
+ *
* @param i the index
* @param expect the expected value
* @param update the new value
@@ -160,8 +167,11 @@
* the actual value was not equal to the expected value.
*/
public final boolean compareAndSet(int i, E expect, E update) {
- return unsafe.compareAndSwapObject(array, rawIndex(i),
- expect, update);
+ return compareAndSetRaw(checkedByteOffset(i), expect, update);
+ }
+
+ private boolean compareAndSetRaw(long offset, E expect, E update) {
+ return unsafe.compareAndSwapObject(array, offset, expect, update);
}
/**
@@ -183,12 +193,21 @@
/**
* Returns the String representation of the current values of array.
- * @return the String representation of the current values of array.
+ * @return the String representation of the current values of array
*/
public String toString() {
- if (array.length > 0) // force volatile read
- get(0);
- return Arrays.toString(array);
+ int iMax = array.length - 1;
+ if (iMax == -1)
+ return "[]";
+
+ StringBuilder b = new StringBuilder();
+ b.append('[');
+ for (int i = 0; ; i++) {
+ b.append(getRaw(byteOffset(i)));
+ if (i == iMax)
+ return b.append(']').toString();
+ b.append(',').append(' ');
+ }
}
}
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java Fri Feb 18 12:04:36 2011 -0800
@@ -39,7 +39,7 @@
* An {@code AtomicStampedReference} maintains an object reference
* along with an integer "stamp", that can be updated atomically.
*
- * <p> Implementation note. This implementation maintains stamped
+ * <p>Implementation note: This implementation maintains stamped
* references by creating internal objects representing "boxed"
* [reference, integer] pairs.
*
@@ -47,17 +47,21 @@
* @author Doug Lea
* @param <V> The type of object referred to by this reference
*/
-public class AtomicStampedReference<V> {
+public class AtomicStampedReference<V> {
- private static class ReferenceIntegerPair<T> {
- private final T reference;
- private final int integer;
- ReferenceIntegerPair(T r, int i) {
- reference = r; integer = i;
+ private static class Pair<T> {
+ final T reference;
+ final int stamp;
+ private Pair(T reference, int stamp) {
+ this.reference = reference;
+ this.stamp = stamp;
+ }
+ static <T> Pair<T> of(T reference, int stamp) {
+ return new Pair<T>(reference, stamp);
}
}
- private final AtomicReference<ReferenceIntegerPair<V>> atomicRef;
+ private volatile Pair<V> pair;
/**
* Creates a new {@code AtomicStampedReference} with the given
@@ -67,8 +71,7 @@
* @param initialStamp the initial stamp
*/
public AtomicStampedReference(V initialRef, int initialStamp) {
- atomicRef = new AtomicReference<ReferenceIntegerPair<V>>
- (new ReferenceIntegerPair<V>(initialRef, initialStamp));
+ pair = Pair.of(initialRef, initialStamp);
}
/**
@@ -77,7 +80,7 @@
* @return the current value of the reference
*/
public V getReference() {
- return atomicRef.get().reference;
+ return pair.reference;
}
/**
@@ -86,7 +89,7 @@
* @return the current value of the stamp
*/
public int getStamp() {
- return atomicRef.get().integer;
+ return pair.stamp;
}
/**
@@ -98,9 +101,9 @@
* @return the current value of the reference
*/
public V get(int[] stampHolder) {
- ReferenceIntegerPair<V> p = atomicRef.get();
- stampHolder[0] = p.integer;
- return p.reference;
+ Pair<V> pair = this.pair;
+ stampHolder[0] = pair.stamp;
+ return pair.reference;
}
/**
@@ -119,18 +122,12 @@
* @param newStamp the new value for the stamp
* @return true if successful
*/
- public boolean weakCompareAndSet(V expectedReference,
- V newReference,
- int expectedStamp,
- int newStamp) {
- ReferenceIntegerPair<V> current = atomicRef.get();
- return expectedReference == current.reference &&
- expectedStamp == current.integer &&
- ((newReference == current.reference &&
- newStamp == current.integer) ||
- atomicRef.weakCompareAndSet(current,
- new ReferenceIntegerPair<V>(newReference,
- newStamp)));
+ public boolean weakCompareAndSet(V expectedReference,
+ V newReference,
+ int expectedStamp,
+ int newStamp) {
+ return compareAndSet(expectedReference, newReference,
+ expectedStamp, newStamp);
}
/**
@@ -145,18 +142,17 @@
* @param newStamp the new value for the stamp
* @return true if successful
*/
- public boolean compareAndSet(V expectedReference,
- V newReference,
- int expectedStamp,
- int newStamp) {
- ReferenceIntegerPair<V> current = atomicRef.get();
- return expectedReference == current.reference &&
- expectedStamp == current.integer &&
+ public boolean compareAndSet(V expectedReference,
+ V newReference,
+ int expectedStamp,
+ int newStamp) {
+ Pair<V> current = pair;
+ return
+ expectedReference == current.reference &&
+ expectedStamp == current.stamp &&
((newReference == current.reference &&
- newStamp == current.integer) ||
- atomicRef.compareAndSet(current,
- new ReferenceIntegerPair<V>(newReference,
- newStamp)));
+ newStamp == current.stamp) ||
+ casPair(current, Pair.of(newReference, newStamp)));
}
@@ -167,9 +163,9 @@
* @param newStamp the new value for the stamp
*/
public void set(V newReference, int newStamp) {
- ReferenceIntegerPair<V> current = atomicRef.get();
- if (newReference != current.reference || newStamp != current.integer)
- atomicRef.set(new ReferenceIntegerPair<V>(newReference, newStamp));
+ Pair<V> current = pair;
+ if (newReference != current.reference || newStamp != current.stamp)
+ this.pair = Pair.of(newReference, newStamp);
}
/**
@@ -186,11 +182,32 @@
* @return true if successful
*/
public boolean attemptStamp(V expectedReference, int newStamp) {
- ReferenceIntegerPair<V> current = atomicRef.get();
- return expectedReference == current.reference &&
- (newStamp == current.integer ||
- atomicRef.compareAndSet(current,
- new ReferenceIntegerPair<V>(expectedReference,
- newStamp)));
+ Pair<V> current = pair;
+ return
+ expectedReference == current.reference &&
+ (newStamp == current.stamp ||
+ casPair(current, Pair.of(expectedReference, newStamp)));
+ }
+
+ // Unsafe mechanics
+
+ private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+ private static final long pairOffset =
+ objectFieldOffset(UNSAFE, "pair", AtomicStampedReference.class);
+
+ private boolean casPair(Pair<V> cmp, Pair<V> val) {
+ return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
+ }
+
+ static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+ String field, Class<?> klazz) {
+ try {
+ return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+ } catch (NoSuchFieldException e) {
+ // Convert Exception to corresponding Error
+ NoSuchFieldError error = new NoSuchFieldError(field);
+ error.initCause(e);
+ throw error;
+ }
}
}
--- a/jdk/src/share/classes/java/util/concurrent/locks/Condition.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/concurrent/locks/Condition.java Fri Feb 18 12:04:36 2011 -0800
@@ -308,18 +308,21 @@
* condition still does not hold. Typical uses of this method take
* the following form:
*
- * <pre>
- * synchronized boolean aMethod(long timeout, TimeUnit unit) {
- * long nanosTimeout = unit.toNanos(timeout);
- * while (!conditionBeingWaitedFor) {
- * if (nanosTimeout > 0)
- * nanosTimeout = theCondition.awaitNanos(nanosTimeout);
- * else
- * return false;
+ * <pre> {@code
+ * boolean aMethod(long timeout, TimeUnit unit) {
+ * long nanos = unit.toNanos(timeout);
+ * lock.lock();
+ * try {
+ * while (!conditionBeingWaitedFor()) {
+ * if (nanos <= 0L)
+ * return false;
+ * nanos = theCondition.awaitNanos(nanos);
+ * }
+ * // ...
+ * } finally {
+ * lock.unlock();
* }
- * // ...
- * }
- * </pre>
+ * }}</pre>
*
* <p> Design note: This method requires a nanosecond argument so
* as to avoid truncation errors in reporting remaining times.
@@ -408,18 +411,21 @@
*
* <p>The return value indicates whether the deadline has elapsed,
* which can be used as follows:
- * <pre>
- * synchronized boolean aMethod(Date deadline) {
+ * <pre> {@code
+ * boolean aMethod(Date deadline) {
* boolean stillWaiting = true;
- * while (!conditionBeingWaitedFor) {
- * if (stillWaiting)
- * stillWaiting = theCondition.awaitUntil(deadline);
- * else
- * return false;
+ * lock.lock();
+ * try {
+ * while (!conditionBeingWaitedFor()) {
+ * if (!stillWaiting)
+ * return false;
+ * stillWaiting = theCondition.awaitUntil(deadline);
+ * }
+ * // ...
+ * } finally {
+ * lock.unlock();
* }
- * // ...
- * }
- * </pre>
+ * }}</pre>
*
* <p><b>Implementation Considerations</b>
*
@@ -450,6 +456,15 @@
* <p>If any threads are waiting on this condition then one
* is selected for waking up. That thread must then re-acquire the
* lock before returning from {@code await}.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>An implementation may (and typically does) require that the
+ * current thread hold the lock associated with this {@code
+ * Condition} when this method is called. Implementations must
+ * document this precondition and any actions taken if the lock is
+ * not held. Typically, an exception such as {@link
+ * IllegalMonitorStateException} will be thrown.
*/
void signal();
@@ -459,6 +474,15 @@
* <p>If any threads are waiting on this condition then they are
* all woken up. Each thread must re-acquire the lock before it can
* return from {@code await}.
+ *
+ * <p><b>Implementation Considerations</b>
+ *
+ * <p>An implementation may (and typically does) require that the
+ * current thread hold the lock associated with this {@code
+ * Condition} when this method is called. Implementations must
+ * document this precondition and any actions taken if the lock is
+ * not held. Typically, an exception such as {@link
+ * IllegalMonitorStateException} will be thrown.
*/
void signalAll();
}
--- a/jdk/src/share/classes/java/util/logging/Logger.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Fri Feb 18 12:04:36 2011 -0800
@@ -1426,7 +1426,7 @@
// we didn't have a previous parent
ref = manager.new LoggerWeakRef(this);
}
- ref.setParentRef(new WeakReference<>(parent));
+ ref.setParentRef(new WeakReference<Logger>(parent));
parent.kids.add(ref);
// As a result of the reparenting, the effective level
--- a/jdk/src/share/classes/javax/script/CompiledScript.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/script/CompiledScript.java Fri Feb 18 12:04:36 2011 -0800
@@ -107,7 +107,7 @@
}
/**
- * Returns the <code>ScriptEngine</code> wbose <code>compile</code> method created this <code>CompiledScript</code>.
+ * Returns the <code>ScriptEngine</code> whose <code>compile</code> method created this <code>CompiledScript</code>.
* The <code>CompiledScript</code> will execute in this engine.
*
* @return The <code>ScriptEngine</code> that created this <code>CompiledScript</code>
--- a/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/security/auth/PrivateCredentialPermission.java Fri Feb 18 12:04:36 2011 -0800
@@ -329,7 +329,7 @@
throw new IllegalArgumentException("invalid empty name");
}
- ArrayList<CredOwner> pList = new ArrayList<CredOwner>();
+ ArrayList<CredOwner> pList = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(name, " ", true);
String principalClass = null;
String principalName = null;
--- a/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/security/auth/SubjectDomainCombiner.java Fri Feb 18 12:04:36 2011 -0800
@@ -48,7 +48,7 @@
private Subject subject;
private WeakKeyValueMap<ProtectionDomain, ProtectionDomain> cachedPDs =
- new WeakKeyValueMap<ProtectionDomain, ProtectionDomain>();
+ new WeakKeyValueMap<>();
private Set<Principal> principalSet;
private Principal[] principals;
--- a/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/DelegationPermission.java Fri Feb 18 12:04:36 2011 -0800
@@ -361,7 +361,7 @@
// Don't call out.defaultWriteObject()
// Write out Vector
- Vector<Permission> permissions = new Vector<Permission>(perms.size());
+ Vector<Permission> permissions = new Vector<>(perms.size());
synchronized (this) {
permissions.addAll(perms);
--- a/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/security/auth/kerberos/ServicePermission.java Fri Feb 18 12:04:36 2011 -0800
@@ -569,7 +569,7 @@
// Don't call out.defaultWriteObject()
// Write out Vector
- Vector<Permission> permissions = new Vector<Permission>(perms.size());
+ Vector<Permission> permissions = new Vector<>(perms.size());
synchronized (this) {
permissions.addAll(perms);
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialJavaObject.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2006, 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,9 +25,7 @@
package javax.sql.rowset.serial;
-import java.sql.*;
import java.io.*;
-import java.util.Map;
import java.lang.reflect.*;
import javax.sql.rowset.RowSetWarning;
@@ -51,7 +49,7 @@
/**
* Placeholder for object to be serialized.
*/
- private Object obj;
+ private final Object obj;
/**
@@ -64,8 +62,7 @@
* <p>
*
* @param obj the Java <code>Object</code> to be serialized
- * @throws SerialException if the object is found
- * to be unserializable
+ * @throws SerialException if the object is found not to be serializable
*/
public SerialJavaObject(Object obj) throws SerialException {
@@ -74,16 +71,11 @@
// get Class. Object instance should always be available
- Class c = obj.getClass();
+ Class<?> c = obj.getClass();
// determine if object implements Serializable i/f
- boolean serializableImpl = false;
- Class[] theIf = c.getInterfaces();
- for (int i = 0; i < theIf.length; i++) {
- String ifName = theIf[i].getName();
- if (ifName == "java.io.Serializable") {
- serializableImpl = true;
- }
+ if (!(obj instanceof java.io.Serializable)) {
+ setWarning(new RowSetWarning("Warning, the object passed to the constructor does not implement Serializable"));
}
// can only determine public fields (obviously). If
@@ -93,21 +85,13 @@
boolean anyStaticFields = false;
fields = c.getFields();
- //fields = new Object[field.length];
for (int i = 0; i < fields.length; i++ ) {
if ( fields[i].getModifiers() == Modifier.STATIC ) {
anyStaticFields = true;
}
- //fields[i] = field[i].get(obj);
}
- try {
- if (!(serializableImpl)) {
- throw new RowSetWarning("Test");
- }
- } catch (RowSetWarning w) {
- setWarning(w);
- }
+
if (anyStaticFields) {
throw new SerialException("Located static fields in " +
@@ -139,11 +123,8 @@
*/
public Field[] getFields() throws SerialException {
if (fields != null) {
- Class c = this.obj.getClass();
- //the following has to be commented before mustang integration
- //return c.getFields();
- //the following has to be uncommented before mustang integration
- return sun.reflect.misc.FieldUtil.getFields(c);
+ Class<?> c = this.obj.getClass();
+ return c.getFields();
} else {
throw new SerialException("SerialJavaObject does not contain" +
" a serialized object instance");
--- a/jdk/src/share/classes/javax/swing/AbstractButton.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/AbstractButton.java Fri Feb 18 12:04:36 2011 -0800
@@ -1335,7 +1335,6 @@
*
* @param a the button's action
* @since 1.3
- * @see <a href="#actions">Actions</a>
* @see Action
* @see #setAction
*/
--- a/jdk/src/share/classes/javax/swing/JEditorPane.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/JEditorPane.java Fri Feb 18 12:04:36 2011 -0800
@@ -145,8 +145,8 @@
* <li>
* One way is to specify the character set as a parameter of the MIME
* type. This will be established by a call to the
- * <a href="#setContentType">setContentType</a> method. If the content
- * is loaded by the <a href="#setPage">setPage</a> method the content
+ * {@link #setContentType setContentType} method. If the content
+ * is loaded by the {@link #setPage setPage} method the content
* type will have been set according to the specification of the URL.
* It the file is loaded directly, the content type would be expected to
* have been set prior to loading.
--- a/jdk/src/share/classes/javax/swing/JFileChooser.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/JFileChooser.java Fri Feb 18 12:04:36 2011 -0800
@@ -256,10 +256,6 @@
private FileView fileView = null;
- // uiFileView is not serialized, as it is initialized
- // by updateUI() after deserialization
- private transient FileView uiFileView = null;
-
private boolean controlsShown = true;
private boolean useFileHiding = true;
@@ -1504,6 +1500,9 @@
if(getFileView() != null) {
filename = getFileView().getName(f);
}
+
+ FileView uiFileView = getUI().getFileView(this);
+
if(filename == null && uiFileView != null) {
filename = uiFileView.getName(f);
}
@@ -1524,6 +1523,9 @@
if(getFileView() != null) {
description = getFileView().getDescription(f);
}
+
+ FileView uiFileView = getUI().getFileView(this);
+
if(description == null && uiFileView != null) {
description = uiFileView.getDescription(f);
}
@@ -1544,6 +1546,9 @@
if(getFileView() != null) {
typeDescription = getFileView().getTypeDescription(f);
}
+
+ FileView uiFileView = getUI().getFileView(this);
+
if(typeDescription == null && uiFileView != null) {
typeDescription = uiFileView.getTypeDescription(f);
}
@@ -1564,6 +1569,9 @@
if(getFileView() != null) {
icon = getFileView().getIcon(f);
}
+
+ FileView uiFileView = getUI().getFileView(this);
+
if(icon == null && uiFileView != null) {
icon = uiFileView.getIcon(f);
}
@@ -1584,6 +1592,9 @@
if (getFileView() != null) {
traversable = getFileView().isTraversable(f);
}
+
+ FileView uiFileView = getUI().getFileView(this);
+
if (traversable == null && uiFileView != null) {
traversable = uiFileView.isTraversable(f);
}
@@ -1791,7 +1802,6 @@
}
setUI(ui);
- uiFileView = getUI().getFileView(this);
if(isAcceptAllFileFilterUsed()) {
addChoosableFileFilter(getAcceptAllFileFilter());
}
--- a/jdk/src/share/classes/javax/swing/SizeSequence.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/SizeSequence.java Fri Feb 18 12:04:36 2011 -0800
@@ -132,7 +132,7 @@
* can use <code>insertEntries</code> or <code>setSizes</code>.
*
* @see #insertEntries
- * @see #setSizes
+ * @see #setSizes(int[])
*/
public SizeSequence() {
a = emptyArray;
--- a/jdk/src/share/classes/javax/swing/TransferHandler.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/TransferHandler.java Fri Feb 18 12:04:36 2011 -0800
@@ -344,7 +344,7 @@
*
* @return the drop location
* @throws IllegalStateException if this is not a drop
- * @see #isDrop
+ * @see #isDrop()
*/
public DropLocation getDropLocation() {
assureIsDrop();
@@ -380,7 +380,7 @@
*
* @param showDropLocation whether or not to indicate the drop location
* @throws IllegalStateException if this is not a drop
- * @see #isDrop
+ * @see #isDrop()
*/
public void setShowDropLocation(boolean showDropLocation) {
assureIsDrop();
@@ -406,7 +406,7 @@
* @see #getDropAction
* @see #getUserDropAction
* @see #getSourceDropActions
- * @see #isDrop
+ * @see #isDrop()
*/
public void setDropAction(int dropAction) {
assureIsDrop();
@@ -440,7 +440,7 @@
* @throws IllegalStateException if this is not a drop
* @see #setDropAction
* @see #getUserDropAction
- * @see #isDrop
+ * @see #isDrop()
*/
public int getDropAction() {
return dropAction == -1 ? getUserDropAction() : dropAction;
@@ -468,7 +468,7 @@
* @throws IllegalStateException if this is not a drop
* @see #setDropAction
* @see #getDropAction
- * @see #isDrop
+ * @see #isDrop()
*/
public int getUserDropAction() {
assureIsDrop();
@@ -501,7 +501,7 @@
*
* @return the drag source's supported drop actions
* @throws IllegalStateException if this is not a drop
- * @see #isDrop
+ * @see #isDrop()
*/
public int getSourceDropActions() {
assureIsDrop();
--- a/jdk/src/share/classes/javax/swing/event/InternalFrameAdapter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/event/InternalFrameAdapter.java Fri Feb 18 12:04:36 2011 -0800
@@ -32,8 +32,7 @@
* equivalent to the WindowAdapter class in the AWT.
* <p>
* See <a href="http://java.sun.com/docs/books/tutorial/uiswing/events/internalframelistener.html">How to Write an Internal Frame Listener</a>
- * in <em>The Java Tutorial</em> and
- * <a href="http://www.awl.com/cp/javaseries/jcl1_2.html">The Java Class Libraries (update)</a>
+ * in <em>The Java Tutorial</em>
*
* @see InternalFrameEvent
* @see InternalFrameListener
--- a/jdk/src/share/classes/javax/swing/event/InternalFrameListener.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/event/InternalFrameListener.java Fri Feb 18 12:04:36 2011 -0800
@@ -33,9 +33,7 @@
* in the AWT.
* <p>
* See <a href="http://java.sun.com/docs/books/tutorial/uiswing/events/internalframelistener.html">How to Write an Internal Frame Listener</a>
- * in <em>The Java Tutorial</em> and
- * <a href="http://www.awl.com/cp/javaseries/jcl1_2.html">The Java Class Libraries (update)</a>
- * for further documentation.
+ * in <em>The Java Tutorial</em> for further documentation.
*
* @see java.awt.event.WindowListener
*
--- a/jdk/src/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/plaf/multi/doc-files/multi_tsc.html Fri Feb 18 12:04:36 2011 -0800
@@ -66,7 +66,7 @@
Before reading further, you should be familiar
with the concept of pluggable look and feels.
For basic information, see
-<a href="http://java.sun.com/docs/books/tutorial/uiswing/start/swingTour.html#plaf">Choosing the Look and Feel</a>,
+<a href="http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/plaf.html">How to Set the Look and Feel</a>,
a section in
<em>The Java Tutorial</em>.
For architectural details, you can read
--- a/jdk/src/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/doc-files/synthFileFormat.html Fri Feb 18 12:04:36 2011 -0800
@@ -91,7 +91,7 @@
<div class="dtd-fragment">
<pre class="dtd-fragment">
<!ELEMENT <a name="e.style">style</a> (<a href="#e.property">property</a> | <a href="#e.defaultsProperty">defaultsProperty</a> | <a href="#e.state">state</a> | <a href="#e.font">font</a> | <a href="#e.graphicsUtils">graphicsUtils</a> |
- <a href="#e.insets">insets</a> | <a href="#e.painter">painter</a> | <a href="#e.imagePainter">imagePainter</a> | <a href="#e.opaque">opaque</a> | (<a href="#beansPersistance">%beansPersistance;</a>) |
+ <a href="#e.insets">insets</a> | <a href="#e.painter">painter</a> | <a href="#e.imagePainter">imagePainter</a> | <a href="#e.opaque">opaque</a> | (<a href="#ee.beansPersistance">%beansPersistance;</a>) |
<a href="#e.imageIcon">imageIcon</a>)*>
<!ATTLIST style
<a href="#style.id">id</a> ID #IMPLIED
@@ -250,8 +250,8 @@
<p>
Defines the font for the current <a href="#e.state">state</a>,
or <a href="#e.style">style</a>. You must
- specify either an <a href="#state.idref">idref</a> or a
- <a href="#state.name">name</a> and <a href="#state.size">size</a>.
+ specify either an <a href="#font.idref">idref</a> or a
+ <a href="#font.name">name</a> and <a href="#font.size">size</a>.
</p>
<p>
The following example creates a style with a Font of
@@ -797,7 +797,7 @@
<a href="#imagePainter.path">path</a> CDATA #REQUIRED
<a href="#imagePainter.sourceInsets">sourceInsets</a> CDATA #IMPLIED
<a href="#imagePainter.destinationInsets">destinationInsets</a> CDATA #IMPLIED
- <a href="#imagePainter.paintCenter">paintCenter</a> (true|false) "true"
+ <a href="#imagePainter.painterCenter">paintCenter</a> (true|false) "true"
<a href="#imagePainter.stretch">stretch</a> (true|false) "true"
<a href="#imagePainter.center">center</a> (true|false) "false"
>
--- a/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/AsyncBoxView.java Fri Feb 18 12:04:36 2011 -0800
@@ -384,7 +384,7 @@
/**
* Loads all of the children to initialize the view.
- * This is called by the <a href="#setParent">setParent</a>
+ * This is called by the {@link #setParent setParent}
* method. Subclasses can reimplement this to initialize
* their child views in a different manner. The default
* implementation creates a child view for each
--- a/jdk/src/share/classes/javax/swing/text/DefaultCaret.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/DefaultCaret.java Fri Feb 18 12:04:36 2011 -0800
@@ -70,7 +70,7 @@
* will render a solid color as specified in the associated text component
* in the <code>SelectionColor</code> property. This can easily be changed
* by reimplementing the
- * <a href="#getSelectionHighlighter">getSelectionHighlighter</a>
+ * {@link #getSelectionPainter getSelectionPainter}
* method.
* <p>
* A customized caret appearance can be achieved by reimplementing
--- a/jdk/src/share/classes/javax/swing/text/TableView.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/TableView.java Fri Feb 18 12:04:36 2011 -0800
@@ -315,7 +315,7 @@
* updated along the minor axis.
* <p>
* This is implemented to call the
- * <a href="#layoutColumns">layoutColumns</a> method, and then
+ * {@link #layoutColumns layoutColumns} method, and then
* forward to the superclass to actually carry out the layout
* of the tables rows.
*
--- a/jdk/src/share/classes/javax/swing/text/View.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/View.java Fri Feb 18 12:04:36 2011 -0800
@@ -117,7 +117,7 @@
what it is prepared to deal with.
<li>The coordinate system is the same as the hosting <code>Component</code>
(i.e. the <code>Component</code> returned by the
- <a href="#getContainer">getContainer</a> method).
+ {@link #getContainer getContainer} method).
This means a child view lives in the same coordinate system as the parent
view unless the parent has explicitly changed the coordinate system.
To schedule itself to be repainted a view can call repaint on the hosting
@@ -180,9 +180,9 @@
starting from the root of the view hierarchy.
The methods for doing this are:
<ul>
- <li><a href="#insertUpdate">insertUpdate</a>
- <li><a href="#removeUpdate">removeUpdate</a>
- <li><a href="#changedUpdate">changedUpdate</a>
+ <li>{@link #insertUpdate insertUpdate}
+ <li>{@link #removeUpdate removeUpdate}
+ <li>{@link #changedUpdate changedUpdate}
</ul>
<p>
</dl>
@@ -497,6 +497,10 @@
public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a,
int direction, Position.Bias[] biasRet)
throws BadLocationException {
+ if (pos < -1) {
+ // -1 is a reserved value, see the code below
+ throw new BadLocationException("Invalid position", pos);
+ }
biasRet[0] = Position.Bias.Forward;
switch (direction) {
@@ -670,15 +674,15 @@
* spread out into the following calls that subclasses can
* reimplement:
* <ol>
- * <li><a href="#updateChildren">updateChildren</a> is called
+ * <li>{@link #updateChildren updateChildren} is called
* if there were any changes to the element this view is
* responsible for. If this view has child views that are
* represent the child elements, then this method should do
* whatever is necessary to make sure the child views correctly
* represent the model.
- * <li><a href="#forwardUpdate">forwardUpdate</a> is called
+ * <li>{@link #forwardUpdate forwardUpdate} is called
* to forward the DocumentEvent to the appropriate child views.
- * <li><a href="#updateLayout">updateLayout</a> is called to
+ * <li>{@link #updateLayout updateLayout} is called to
* give the view a chance to either repair its layout, to reschedule
* layout, or do nothing.
* </ol>
@@ -711,15 +715,15 @@
* spread out into the following calls that subclasses can
* reimplement:
* <ol>
- * <li><a href="#updateChildren">updateChildren</a> is called
+ * <li>{@link #updateChildren updateChildren} is called
* if there were any changes to the element this view is
* responsible for. If this view has child views that are
* represent the child elements, then this method should do
* whatever is necessary to make sure the child views correctly
* represent the model.
- * <li><a href="#forwardUpdate">forwardUpdate</a> is called
+ * <li>{@link #forwardUpdate forwardUpdate} is called
* to forward the DocumentEvent to the appropriate child views.
- * <li><a href="#updateLayout">updateLayout</a> is called to
+ * <li>{@link #updateLayout updateLayout} is called to
* give the view a chance to either repair its layout, to reschedule
* layout, or do nothing.
* </ol>
@@ -752,15 +756,15 @@
* spread out into the following calls that subclasses can
* reimplement:
* <ol>
- * <li><a href="#updateChildren">updateChildren</a> is called
+ * <li>{@link #updateChildren updateChildren} is called
* if there were any changes to the element this view is
* responsible for. If this view has child views that are
* represent the child elements, then this method should do
* whatever is necessary to make sure the child views correctly
* represent the model.
- * <li><a href="#forwardUpdate">forwardUpdate</a> is called
+ * <li>{@link #forwardUpdate forwardUpdate} is called
* to forward the DocumentEvent to the appropriate child views.
- * <li><a href="#updateLayout">updateLayout</a> is called to
+ * <li>{@link #updateLayout updateLayout} is called to
* give the view a chance to either repair its layout, to reschedule
* layout, or do nothing.
* </ol>
@@ -1186,7 +1190,7 @@
* simply messages the view with a call to <code>insertUpdate</code>,
* <code>removeUpdate</code>, or <code>changedUpdate</code> depending
* upon the type of the event. This is called by
- * <a href="#forwardUpdate">forwardUpdate</a> to forward
+ * {@link #forwardUpdate forwardUpdate} to forward
* the event to children that need it.
*
* @param v the child view to forward the event to
--- a/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/HTMLEditorKit.java Fri Feb 18 12:04:36 2011 -0800
@@ -123,7 +123,7 @@
* to load. By default, this kit produces documents that will be
* loaded asynchronously if loaded using <code>JEditorPane.setPage</code>.
* This is controlled by a property on the document. The method
- * <a href="#createDefaultDocument">createDefaultDocument</a> can
+ * {@link #createDefaultDocument createDefaultDocument} can
* be overriden to change this. The batching of work is done
* by the <code>HTMLDocument.HTMLReader</code> class. The actual
* work is done by the <code>DefaultStyledDocument</code> and
@@ -558,7 +558,7 @@
* automatically or only <code>FormSubmitEvent</code> is fired.
* By default it is set to true.
*
- * @see #isAutoFormSubmission
+ * @see #isAutoFormSubmission()
* @see FormSubmitEvent
* @since 1.5
*/
--- a/jdk/src/share/classes/javax/swing/text/html/ParagraphView.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/ParagraphView.java Fri Feb 18 12:04:36 2011 -0800
@@ -61,7 +61,7 @@
* <p>
* This is implemented
* to forward to the superclass as well as call the
- * <a href="#setPropertiesFromAttributes">setPropertiesFromAttributes</a>
+ * {@link #setPropertiesFromAttributes setPropertiesFromAttributes}
* method to set the paragraph properties from the css
* attributes. The call is made at this time to ensure
* the ability to resolve upward through the parents
--- a/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/StyleSheet.java Fri Feb 18 12:04:36 2011 -0800
@@ -51,7 +51,7 @@
* <p>
* The primary entry point for HTML View implementations
* to get their attributes is the
- * <a href="#getViewAttributes">getViewAttributes</a>
+ * {@link #getViewAttributes getViewAttributes}
* method. This should be implemented to establish the
* desired policy used to associate attributes with the view.
* Each HTMLEditorKit (i.e. and therefore each associated
--- a/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/javax/swing/text/html/parser/ParserDelegator.java Fri Feb 18 12:04:36 2011 -0800
@@ -48,7 +48,11 @@
private static final Object DTD_KEY = new Object();
- protected static synchronized void setDefaultDTD() {
+ protected static void setDefaultDTD() {
+ getDefaultDTD();
+ }
+
+ private static synchronized DTD getDefaultDTD() {
AppContext appContext = AppContext.getAppContext();
DTD dtd = (DTD) appContext.get(DTD_KEY);
@@ -67,6 +71,8 @@
appContext.put(DTD_KEY, dtd);
}
+
+ return dtd;
}
protected static DTD createDTD(DTD dtd, String name) {
@@ -92,7 +98,7 @@
}
public void parse(Reader r, HTMLEditorKit.ParserCallback cb, boolean ignoreCharSet) throws IOException {
- new DocumentParser((DTD) AppContext.getAppContext().get(DTD_KEY)).parse(r, cb, ignoreCharSet);
+ new DocumentParser(getDefaultDTD()).parse(r, cb, ignoreCharSet);
}
/**
--- a/jdk/src/share/classes/sun/applet/AppletClassLoader.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/applet/AppletClassLoader.java Fri Feb 18 12:04:36 2011 -0800
@@ -663,13 +663,15 @@
// set the context class loader to the AppletClassLoader.
creatorThread.setContextClassLoader(AppletClassLoader.this);
- synchronized(creatorThread.syncObject) {
- creatorThread.start();
- try {
- creatorThread.syncObject.wait();
- } catch (InterruptedException e) { }
- appContext = creatorThread.appContext;
- }
+ creatorThread.start();
+ try {
+ synchronized(creatorThread.syncObject) {
+ while (!creatorThread.created) {
+ creatorThread.syncObject.wait();
+ }
+ }
+ } catch (InterruptedException e) { }
+ appContext = creatorThread.appContext;
return null;
}
});
@@ -854,14 +856,16 @@
class AppContextCreator extends Thread {
Object syncObject = new Object();
AppContext appContext = null;
+ volatile boolean created = false;
AppContextCreator(ThreadGroup group) {
super(group, "AppContextCreator");
}
public void run() {
- synchronized(syncObject) {
- appContext = SunToolkit.createNewAppContext();
+ appContext = SunToolkit.createNewAppContext();
+ created = true;
+ synchronized(syncObject) {
syncObject.notifyAll();
}
} // run()
--- a/jdk/src/share/classes/sun/awt/SunToolkit.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/awt/SunToolkit.java Fri Feb 18 12:04:36 2011 -0800
@@ -696,7 +696,9 @@
synchronized (lock) {
executeOnEventHandlerThread(event);
- lock.wait();
+ while(!event.isDispatched()) {
+ lock.wait();
+ }
}
Throwable eventThrowable = event.getThrowable();
--- a/jdk/src/share/classes/sun/awt/image/ImageFetcher.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/awt/image/ImageFetcher.java Fri Feb 18 12:04:36 2011 -0800
@@ -61,8 +61,10 @@
/**
* Adds an ImageFetchable to the queue of items to fetch. Instantiates
* a new ImageFetcher if it's reasonable to do so.
+ * If there is no available fetcher to process an ImageFetchable, then
+ * reports failure to caller.
*/
- public static void add(ImageFetchable src) {
+ public static boolean add(ImageFetchable src) {
final FetcherInfo info = FetcherInfo.getFetcherInfo();
synchronized(info.waitList) {
if (!info.waitList.contains(src)) {
@@ -71,9 +73,23 @@
info.numFetchers < info.fetchers.length) {
createFetchers(info);
}
- info.waitList.notify();
+ /* Creation of new fetcher may fail due to high vm load
+ * or some other reason.
+ * If there is already exist, but busy, fetcher, we leave
+ * the src in queue (it will be handled by existing
+ * fetcher later).
+ * Otherwise, we report failure: there is no fetcher
+ * to handle the src.
+ */
+ if (info.numFetchers > 0) {
+ info.waitList.notify();
+ } else {
+ info.waitList.removeElement(src);
+ return false;
+ }
}
}
+ return true;
}
/**
@@ -291,11 +307,15 @@
public Object run() {
for (int i = 0; i < info.fetchers.length; i++) {
if (info.fetchers[i] == null) {
- info.fetchers[i] = new ImageFetcher(
+ ImageFetcher f = new ImageFetcher(
fetcherGroup, i);
- info.fetchers[i].start();
- info.numFetchers++;
- break;
+ try {
+ f.start();
+ info.fetchers[i] = f;
+ info.numFetchers++;
+ break;
+ } catch (Error e) {
+ }
}
}
return null;
--- a/jdk/src/share/classes/sun/awt/image/InputStreamImageSource.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/awt/image/InputStreamImageSource.java Fri Feb 18 12:04:36 2011 -0800
@@ -164,8 +164,13 @@
private synchronized void startProduction() {
if (!awaitingFetch) {
- ImageFetcher.add(this);
- awaitingFetch = true;
+ if (ImageFetcher.add(this)) {
+ awaitingFetch = true;
+ } else {
+ ImageConsumerQueue cq = consumers;
+ consumers = null;
+ errorAllConsumers(cq, false);
+ }
}
}
--- a/jdk/src/share/classes/sun/font/FontUtilities.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/font/FontUtilities.java Fri Feb 18 12:04:36 2011 -0800
@@ -30,6 +30,8 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
+import java.lang.ref.SoftReference;
+import java.util.concurrent.ConcurrentHashMap;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -383,6 +385,10 @@
* }
* return fuir;
*/
+ private static volatile
+ SoftReference<ConcurrentHashMap<PhysicalFont, CompositeFont>>
+ compMapRef = new SoftReference(null);
+
public static FontUIResource getCompositeFontUIResource(Font font) {
FontUIResource fuir = new FontUIResource(font);
@@ -402,12 +408,22 @@
FontManager fm = FontManagerFactory.getInstance();
CompositeFont dialog2D =
- (CompositeFont) fm.findFont2D("dialog", font.getStyle(), FontManager.NO_FALLBACK);
+ (CompositeFont) fm.findFont2D("dialog", font.getStyle(),
+ FontManager.NO_FALLBACK);
if (dialog2D == null) { /* shouldn't happen */
return fuir;
}
PhysicalFont physicalFont = (PhysicalFont)font2D;
- CompositeFont compFont = new CompositeFont(physicalFont, dialog2D);
+ ConcurrentHashMap<PhysicalFont, CompositeFont> compMap = compMapRef.get();
+ if (compMap == null) { // Its been collected.
+ compMap = new ConcurrentHashMap<PhysicalFont, CompositeFont>();
+ compMapRef = new SoftReference(compMap);
+ }
+ CompositeFont compFont = compMap.get(physicalFont);
+ if (compFont == null) {
+ compFont = new CompositeFont(physicalFont, dialog2D);
+ compMap.put(physicalFont, compFont);
+ }
FontAccess.getFontAccess().setFont2D(fuir, compFont.handle);
/* marking this as a created font is needed as only created fonts
* copy their creator's handles.
--- a/jdk/src/share/classes/sun/java2d/pisces/Curve.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Curve.java Fri Feb 18 12:04:36 2011 -0800
@@ -27,7 +27,7 @@
import java.util.Iterator;
-class Curve {
+final class Curve {
float ax, ay, bx, by, cx, cy, dx, dy;
float dax, day, dbx, dby;
@@ -101,14 +101,6 @@
return t * (t * day + dby) + cy;
}
- private float ddxat(float t) {
- return 2 * dax * t + dbx;
- }
-
- private float ddyat(float t) {
- return 2 * day * t + dby;
- }
-
int dxRoots(float[] roots, int off) {
return Helpers.quadraticRoots(dax, dbx, cx, roots, off);
}
@@ -131,17 +123,17 @@
// finds points where the first and second derivative are
// perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
// * is a dot product). Unfortunately, we have to solve a cubic.
- private int perpendiculardfddf(float[] pts, int off, final float err) {
+ private int perpendiculardfddf(float[] pts, int off) {
assert pts.length >= off + 4;
- // these are the coefficients of g(t):
+ // these are the coefficients of some multiple of g(t) (not g(t),
+ // because the roots of a polynomial are not changed after multiplication
+ // by a constant, and this way we save a few multiplications).
final float a = 2*(dax*dax + day*day);
final float b = 3*(dax*dbx + day*dby);
final float c = 2*(dax*cx + day*cy) + dbx*dbx + dby*dby;
final float d = dbx*cx + dby*cy;
- // TODO: We might want to divide the polynomial by a to make the
- // coefficients smaller. This won't change the roots.
- return Helpers.cubicRootsInAB(a, b, c, d, pts, off, err, 0f, 1f);
+ return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0f, 1f);
}
// Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
@@ -161,7 +153,7 @@
// no OOB exception, because by now off<=6, and roots.length >= 10
assert off <= 6 && roots.length >= 10;
int ret = off;
- int numPerpdfddf = perpendiculardfddf(roots, off, err);
+ int numPerpdfddf = perpendiculardfddf(roots, off);
float t0 = 0, ft0 = ROCsq(t0) - w*w;
roots[off + numPerpdfddf] = 1f; // always check interval end points
numPerpdfddf++;
@@ -189,8 +181,9 @@
// A slight modification of the false position algorithm on wikipedia.
// This only works for the ROCsq-x functions. It might be nice to have
// the function as an argument, but that would be awkward in java6.
- // It is something to consider for java7, depending on how closures
- // and function objects turn out. Same goes for the newton's method
+ // TODO: It is something to consider for java8 (or whenever lambda
+ // expressions make it into the language), depending on how closures
+ // and turn out. Same goes for the newton's method
// algorithm in Helpers.java
private float falsePositionROCsqMinusX(float x0, float x1,
final float x, final float err)
@@ -203,7 +196,7 @@
for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
r = (fs * t - ft * s) / (fs - ft);
fr = ROCsq(r) - x;
- if (fr * ft > 0) {// have the same sign
+ if (sameSign(fr, ft)) {
ft = fr; t = r;
if (side < 0) {
fs /= (1 << (-side));
@@ -226,55 +219,65 @@
return r;
}
+ private static boolean sameSign(double x, double y) {
+ // another way is to test if x*y > 0. This is bad for small x, y.
+ return (x < 0 && y < 0) || (x > 0 && y > 0);
+ }
+
// returns the radius of curvature squared at t of this curve
// see http://en.wikipedia.org/wiki/Radius_of_curvature_(applications)
private float ROCsq(final float t) {
- final float dx = dxat(t);
- final float dy = dyat(t);
- final float ddx = ddxat(t);
- final float ddy = ddyat(t);
+ // dx=xat(t) and dy=yat(t). These calls have been inlined for efficiency
+ final float dx = t * (t * dax + dbx) + cx;
+ final float dy = t * (t * day + dby) + cy;
+ final float ddx = 2 * dax * t + dbx;
+ final float ddy = 2 * day * t + dby;
final float dx2dy2 = dx*dx + dy*dy;
final float ddx2ddy2 = ddx*ddx + ddy*ddy;
final float ddxdxddydy = ddx*dx + ddy*dy;
- float ret = ((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy))*dx2dy2;
- return ret;
+ return dx2dy2*((dx2dy2*dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy*ddxdxddydy));
}
- // curve to be broken should be in pts[0]
- // this will change the contents of both pts and Ts
+ // curve to be broken should be in pts
+ // this will change the contents of pts but not Ts
// TODO: There's no reason for Ts to be an array. All we need is a sequence
// of t values at which to subdivide. An array statisfies this condition,
// but is unnecessarily restrictive. Ts should be an Iterator<Float> instead.
// Doing this will also make dashing easier, since we could easily make
// LengthIterator an Iterator<Float> and feed it to this function to simplify
// the loop in Dasher.somethingTo.
- static Iterator<float[]> breakPtsAtTs(final float[][] pts, final int type,
+ static Iterator<Integer> breakPtsAtTs(final float[] pts, final int type,
final float[] Ts, final int numTs)
{
- assert pts.length >= 2 && pts[0].length >= 8 && numTs <= Ts.length;
- return new Iterator<float[]>() {
- int nextIdx = 0;
+ assert pts.length >= 2*type && numTs <= Ts.length;
+ return new Iterator<Integer>() {
+ // these prevent object creation and destruction during autoboxing.
+ // Because of this, the compiler should be able to completely
+ // eliminate the boxing costs.
+ final Integer i0 = 0;
+ final Integer itype = type;
int nextCurveIdx = 0;
+ Integer curCurveOff = i0;
float prevT = 0;
@Override public boolean hasNext() {
return nextCurveIdx < numTs + 1;
}
- @Override public float[] next() {
- float[] ret;
+ @Override public Integer next() {
+ Integer ret;
if (nextCurveIdx < numTs) {
float curT = Ts[nextCurveIdx];
float splitT = (curT - prevT) / (1 - prevT);
Helpers.subdivideAt(splitT,
- pts[nextIdx], 0,
- pts[nextIdx], 0,
- pts[1-nextIdx], 0, type);
- updateTs(Ts, Ts[nextCurveIdx], nextCurveIdx + 1, numTs - nextCurveIdx - 1);
- ret = pts[nextIdx];
- nextIdx = 1 - nextIdx;
+ pts, curCurveOff,
+ pts, 0,
+ pts, type, type);
+ prevT = curT;
+ ret = i0;
+ curCurveOff = itype;
} else {
- ret = pts[nextIdx];
+ ret = curCurveOff;
}
nextCurveIdx++;
return ret;
@@ -283,12 +286,5 @@
@Override public void remove() {}
};
}
-
- // precondition: ts[off]...ts[off+len-1] must all be greater than t.
- private static void updateTs(float[] ts, final float t, final int off, final int len) {
- for (int i = off; i < off + len; i++) {
- ts[i] = (ts[i] - t) / (1 - t);
- }
- }
}
--- a/jdk/src/share/classes/sun/java2d/pisces/Dasher.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Dasher.java Fri Feb 18 12:04:36 2011 -0800
@@ -38,7 +38,7 @@
* semantics are unclear.
*
*/
-public class Dasher implements sun.awt.geom.PathConsumer2D {
+final class Dasher implements sun.awt.geom.PathConsumer2D {
private final PathConsumer2D out;
private final float[] dash;
@@ -169,7 +169,7 @@
float dx = x1 - x0;
float dy = y1 - y0;
- float len = (float) Math.hypot(dx, dy);
+ float len = (float) Math.sqrt(dx*dx + dy*dy);
if (len == 0) {
return;
@@ -226,7 +226,7 @@
return;
}
if (li == null) {
- li = new LengthIterator(4, 0.0001f);
+ li = new LengthIterator(4, 0.01f);
}
li.initializeIterationOnCurve(curCurvepts, type);
@@ -237,9 +237,9 @@
while ((t = li.next(leftInThisDashSegment)) < 1) {
if (t != 0) {
Helpers.subdivideAt((t - lastSplitT) / (1 - lastSplitT),
- curCurvepts, curCurveoff,
- curCurvepts, 0,
- curCurvepts, type, type);
+ curCurvepts, curCurveoff,
+ curCurvepts, 0,
+ curCurvepts, type, type);
lastSplitT = t;
goTo(curCurvepts, 2, type);
curCurveoff = type;
@@ -307,6 +307,11 @@
private int recLevel;
private boolean done;
+ // the lengths of the lines of the control polygon. Only its first
+ // curveType/2 - 1 elements are valid. This is an optimization. See
+ // next(float) for more detail.
+ private float[] curLeafCtrlPolyLengths = new float[3];
+
public LengthIterator(int reclimit, float err) {
this.limit = reclimit;
this.minTincrement = 1f / (1 << limit);
@@ -344,11 +349,52 @@
this.lastSegLen = 0;
}
+ // 0 == false, 1 == true, -1 == invalid cached value.
+ private int cachedHaveLowAcceleration = -1;
+
+ private boolean haveLowAcceleration(float err) {
+ if (cachedHaveLowAcceleration == -1) {
+ final float len1 = curLeafCtrlPolyLengths[0];
+ final float len2 = curLeafCtrlPolyLengths[1];
+ // the test below is equivalent to !within(len1/len2, 1, err).
+ // It is using a multiplication instead of a division, so it
+ // should be a bit faster.
+ if (!Helpers.within(len1, len2, err*len2)) {
+ cachedHaveLowAcceleration = 0;
+ return false;
+ }
+ if (curveType == 8) {
+ final float len3 = curLeafCtrlPolyLengths[2];
+ // if len1 is close to 2 and 2 is close to 3, that probably
+ // means 1 is close to 3 so the second part of this test might
+ // not be needed, but it doesn't hurt to include it.
+ if (!(Helpers.within(len2, len3, err*len3) &&
+ Helpers.within(len1, len3, err*len3))) {
+ cachedHaveLowAcceleration = 0;
+ return false;
+ }
+ }
+ cachedHaveLowAcceleration = 1;
+ return true;
+ }
+
+ return (cachedHaveLowAcceleration == 1);
+ }
+
+ // we want to avoid allocations/gc so we keep this array so we
+ // can put roots in it,
+ private float[] nextRoots = new float[4];
+
+ // caches the coefficients of the current leaf in its flattened
+ // form (see inside next() for what that means). The cache is
+ // invalid when it's third element is negative, since in any
+ // valid flattened curve, this would be >= 0.
+ private float[] flatLeafCoefCache = new float[] {0, 0, -1, 0};
// returns the t value where the remaining curve should be split in
// order for the left subdivided curve to have length len. If len
// is >= than the length of the uniterated curve, it returns 1.
- public float next(float len) {
- float targetLength = lenAtLastSplit + len;
+ public float next(final float len) {
+ final float targetLength = lenAtLastSplit + len;
while(lenAtNextT < targetLength) {
if (done) {
lastSegLen = lenAtNextT - lenAtLastSplit;
@@ -357,8 +403,46 @@
goToNextLeaf();
}
lenAtLastSplit = targetLength;
- float t = binSearchForLen(lenAtLastSplit - lenAtLastT,
- recCurveStack[recLevel], curveType, lenAtNextT - lenAtLastT, ERR);
+ final float leaflen = lenAtNextT - lenAtLastT;
+ float t = (targetLength - lenAtLastT) / leaflen;
+
+ // cubicRootsInAB is a fairly expensive call, so we just don't do it
+ // if the acceleration in this section of the curve is small enough.
+ if (!haveLowAcceleration(0.05f)) {
+ // We flatten the current leaf along the x axis, so that we're
+ // left with a, b, c which define a 1D Bezier curve. We then
+ // solve this to get the parameter of the original leaf that
+ // gives us the desired length.
+
+ if (flatLeafCoefCache[2] < 0) {
+ float x = 0+curLeafCtrlPolyLengths[0],
+ y = x+curLeafCtrlPolyLengths[1];
+ if (curveType == 8) {
+ float z = y + curLeafCtrlPolyLengths[2];
+ flatLeafCoefCache[0] = 3*(x - y) + z;
+ flatLeafCoefCache[1] = 3*(y - 2*x);
+ flatLeafCoefCache[2] = 3*x;
+ flatLeafCoefCache[3] = -z;
+ } else if (curveType == 6) {
+ flatLeafCoefCache[0] = 0f;
+ flatLeafCoefCache[1] = y - 2*x;
+ flatLeafCoefCache[2] = 2*x;
+ flatLeafCoefCache[3] = -y;
+ }
+ }
+ float a = flatLeafCoefCache[0];
+ float b = flatLeafCoefCache[1];
+ float c = flatLeafCoefCache[2];
+ float d = t*flatLeafCoefCache[3];
+
+ // we use cubicRootsInAB here, because we want only roots in 0, 1,
+ // and our quadratic root finder doesn't filter, so it's just a
+ // matter of convenience.
+ int n = Helpers.cubicRootsInAB(a, b, c, d, nextRoots, 0, 0, 1);
+ if (n == 1 && !Float.isNaN(nextRoots[0])) {
+ t = nextRoots[0];
+ }
+ }
// t is relative to the current leaf, so we must make it a valid parameter
// of the original curve.
t = t * (nextT - lastT) + lastT;
@@ -379,36 +463,6 @@
return lastSegLen;
}
- // Returns t such that if leaf is subdivided at t the left
- // curve will have length len. leafLen must be the length of leaf.
- private static Curve bsc = new Curve();
- private static float binSearchForLen(float len, float[] leaf, int type,
- float leafLen, float err)
- {
- assert len <= leafLen;
- bsc.set(leaf, type);
- float errBound = err*len;
- float left = 0, right = 1;
- while (left < right) {
- float m = (left + right) / 2;
- if (m == left || m == right) {
- return m;
- }
- float x = bsc.xat(m);
- float y = bsc.yat(m);
- float leftLen = Helpers.linelen(leaf[0], leaf[1], x, y);
- if (Math.abs(leftLen - len) < errBound) {
- return m;
- }
- if (leftLen < len) {
- left = m;
- } else {
- right = m;
- }
- }
- return left;
- }
-
// go to the next leaf (in an inorder traversal) in the recursion tree
// preconditions: must be on a leaf, and that leaf must not be the root.
private void goToNextLeaf() {
@@ -437,6 +491,9 @@
lenAtLastT = lenAtNextT;
nextT += (1 << (limit - recLevel)) * minTincrement;
lenAtNextT += len;
+ // invalidate caches
+ flatLeafCoefCache[2] = -1;
+ cachedHaveLowAcceleration = -1;
} else {
Helpers.subdivide(recCurveStack[recLevel], 0,
recCurveStack[recLevel+1], 0,
@@ -450,11 +507,24 @@
// this is a bit of a hack. It returns -1 if we're not on a leaf, and
// the length of the leaf if we are on a leaf.
private float onLeaf() {
- float polylen = Helpers.polyLineLength(recCurveStack[recLevel], 0, curveType);
- float linelen = Helpers.linelen(recCurveStack[recLevel][0], recCurveStack[recLevel][1],
- recCurveStack[recLevel][curveType - 2], recCurveStack[recLevel][curveType - 1]);
- return (polylen - linelen < ERR || recLevel == limit) ?
- (polylen + linelen)/2 : -1;
+ float[] curve = recCurveStack[recLevel];
+ float polyLen = 0;
+
+ float x0 = curve[0], y0 = curve[1];
+ for (int i = 2; i < curveType; i += 2) {
+ final float x1 = curve[i], y1 = curve[i+1];
+ final float len = Helpers.linelen(x0, y0, x1, y1);
+ polyLen += len;
+ curLeafCtrlPolyLengths[i/2 - 1] = len;
+ x0 = x1;
+ y0 = y1;
+ }
+
+ final float lineLen = Helpers.linelen(curve[0], curve[1], curve[curveType-2], curve[curveType-1]);
+ if (polyLen - lineLen < ERR || recLevel == limit) {
+ return (polyLen + lineLen)/2;
+ }
+ return -1;
}
}
--- a/jdk/src/share/classes/sun/java2d/pisces/Helpers.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Helpers.java Fri Feb 18 12:04:36 2011 -0800
@@ -26,6 +26,12 @@
package sun.java2d.pisces;
import java.util.Arrays;
+import static java.lang.Math.PI;
+import static java.lang.Math.cos;
+import static java.lang.Math.sqrt;
+import static java.lang.Math.cbrt;
+import static java.lang.Math.acos;
+
final class Helpers {
private Helpers() {
@@ -75,100 +81,74 @@
return ret - off;
}
- // find the roots of g(t) = a*t^3 + b*t^2 + c*t + d in [A,B)
- // We will not use Cardano's method, since it is complicated and
- // involves too many square and cubic roots. We will use Newton's method.
- // TODO: this should probably return ALL roots. Then the user can do
- // his own filtering of roots outside [A,B).
- static int cubicRootsInAB(final float a, final float b,
- final float c, final float d,
- float[] pts, final int off, final float E,
+ // find the roots of g(t) = d*t^3 + a*t^2 + b*t + c in [A,B)
+ static int cubicRootsInAB(float d, float a, float b, float c,
+ float[] pts, final int off,
final float A, final float B)
{
- if (a == 0) {
- return quadraticRoots(b, c, d, pts, off);
+ if (d == 0) {
+ int num = quadraticRoots(a, b, c, pts, off);
+ return filterOutNotInAB(pts, off, num, A, B) - off;
}
- // the coefficients of g'(t). no dc variable because dc=c
- // we use these to get the critical points of g(t), which
- // we then use to chose starting points for Newton's method. These
- // should be very close to the actual roots.
- final float da = 3 * a;
- final float db = 2 * b;
- int numCritPts = quadraticRoots(da, db, c, pts, off+1);
- numCritPts = filterOutNotInAB(pts, off+1, numCritPts, A, B) - off - 1;
- // need them sorted.
- if (numCritPts == 2 && pts[off+1] > pts[off+2]) {
- float tmp = pts[off+1];
- pts[off+1] = pts[off+2];
- pts[off+2] = tmp;
+ // From Graphics Gems:
+ // http://tog.acm.org/resources/GraphicsGems/gems/Roots3And4.c
+ // (also from awt.geom.CubicCurve2D. But here we don't need as
+ // much accuracy and we don't want to create arrays so we use
+ // our own customized version).
+
+ /* normal form: x^3 + ax^2 + bx + c = 0 */
+ a /= d;
+ b /= d;
+ c /= d;
+
+ // substitute x = y - A/3 to eliminate quadratic term:
+ // x^3 +Px + Q = 0
+ //
+ // Since we actually need P/3 and Q/2 for all of the
+ // calculations that follow, we will calculate
+ // p = P/3
+ // q = Q/2
+ // instead and use those values for simplicity of the code.
+ double sq_A = a * a;
+ double p = 1.0/3 * (-1.0/3 * sq_A + b);
+ double q = 1.0/2 * (2.0/27 * a * sq_A - 1.0/3 * a * b + c);
+
+ /* use Cardano's formula */
+
+ double cb_p = p * p * p;
+ double D = q * q + cb_p;
+
+ int num;
+ if (D < 0) {
+ // see: http://en.wikipedia.org/wiki/Cubic_function#Trigonometric_.28and_hyperbolic.29_method
+ final double phi = 1.0/3 * acos(-q / sqrt(-cb_p));
+ final double t = 2 * sqrt(-p);
+
+ pts[ off+0 ] = (float)( t * cos(phi));
+ pts[ off+1 ] = (float)(-t * cos(phi + PI / 3));
+ pts[ off+2 ] = (float)(-t * cos(phi - PI / 3));
+ num = 3;
+ } else {
+ final double sqrt_D = sqrt(D);
+ final double u = cbrt(sqrt_D - q);
+ final double v = - cbrt(sqrt_D + q);
+
+ pts[ off ] = (float)(u + v);
+ num = 1;
+
+ if (within(D, 0, 1e-8)) {
+ pts[off+1] = -(pts[off] / 2);
+ num = 2;
+ }
}
- int ret = off;
-
- // we don't actually care much about the extrema themselves. We
- // only use them to ensure that g(t) is monotonic in each
- // interval [pts[i],pts[i+1] (for i in off...off+numCritPts+1).
- // This will allow us to determine intervals containing exactly
- // one root.
- // The end points of the interval are always local extrema.
- pts[off] = A;
- pts[off + numCritPts + 1] = B;
- numCritPts += 2;
-
- float x0 = pts[off], fx0 = evalCubic(a, b, c, d, x0);
- for (int i = off; i < off + numCritPts - 1; i++) {
- float x1 = pts[i+1], fx1 = evalCubic(a, b, c, d, x1);
- if (fx0 == 0f) {
- pts[ret++] = x0;
- } else if (fx1 * fx0 < 0f) { // have opposite signs
- pts[ret++] = CubicNewton(a, b, c, d,
- x0 + fx0 * (x1 - x0) / (fx0 - fx1), E);
- }
- x0 = x1;
- fx0 = fx1;
- }
- return ret - off;
- }
+ final float sub = 1.0f/3 * a;
- // precondition: the polynomial to be evaluated must not be 0 at x0.
- static float CubicNewton(final float a, final float b,
- final float c, final float d,
- float x0, final float err)
- {
- // considering how this function is used, 10 should be more than enough
- final int itlimit = 10;
- float fx0 = evalCubic(a, b, c, d, x0);
- float x1;
- int count = 0;
- while(true) {
- x1 = x0 - (fx0 / evalCubic(0, 3 * a, 2 * b, c, x0));
- if (Math.abs(x1 - x0) < err * Math.abs(x1 + x0) || count == itlimit) {
- break;
- }
- x0 = x1;
- fx0 = evalCubic(a, b, c, d, x0);
- count++;
+ for (int i = 0; i < num; ++i) {
+ pts[ off+i ] -= sub;
}
- return x1;
- }
- // fills the input array with numbers 0, INC, 2*INC, ...
- static void fillWithIdxes(final float[] data, final int[] idxes) {
- if (idxes.length > 0) {
- idxes[0] = 0;
- for (int i = 1; i < idxes.length; i++) {
- idxes[i] = idxes[i-1] + (int)data[idxes[i-1]];
- }
- }
- }
-
- static void fillWithIdxes(final int[] idxes, final int inc) {
- if (idxes.length > 0) {
- idxes[0] = 0;
- for (int i = 1; i < idxes.length; i++) {
- idxes[i] = idxes[i-1] + inc;
- }
- }
+ return filterOutNotInAB(pts, off, num, A, B) - off;
}
// These use a hardcoded factor of 2 for increasing sizes. Perhaps this
@@ -182,6 +162,7 @@
}
return Arrays.copyOf(in, 2 * (cursize + numToAdd));
}
+
static int[] widenArray(int[] in, final int cursize, final int numToAdd) {
if (in.length >= cursize + numToAdd) {
return in;
@@ -208,7 +189,7 @@
{
int ret = off;
for (int i = off; i < off + len; i++) {
- if (nums[i] > a && nums[i] < b) {
+ if (nums[i] >= a && nums[i] < b) {
nums[ret++] = nums[i];
}
}
@@ -225,7 +206,9 @@
}
static float linelen(float x1, float y1, float x2, float y2) {
- return (float)Math.hypot(x2 - x1, y2 - y1);
+ final float dx = x2 - x1;
+ final float dy = y2 - y1;
+ return (float)Math.sqrt(dx*dx + dy*dy);
}
static void subdivide(float[] src, int srcoff, float[] left, int leftoff,
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesCache.java Fri Feb 18 12:04:36 2011 -0800
@@ -32,7 +32,7 @@
*
* @see PiscesRenderer#render
*/
-public final class PiscesCache {
+final class PiscesCache {
final int bboxX0, bboxY0, bboxX1, bboxY1;
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesRenderingEngine.java Fri Feb 18 12:04:36 2011 -0800
@@ -27,7 +27,6 @@
import java.awt.Shape;
import java.awt.BasicStroke;
-import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Path2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.PathIterator;
@@ -250,7 +249,7 @@
float dashphase,
PathConsumer2D pc2d)
{
- // We use inat and outat so that in Stroker and Dasher we can work only
+ // We use strokerat and outat so that in Stroker and Dasher we can work only
// with the pre-transformation coordinates. This will repeat a lot of
// computations done in the path iterator, but the alternative is to
// work with transformed paths and compute untransformed coordinates
@@ -265,7 +264,7 @@
// transformation after the path processing has been done.
// We can't do this if normalization is on, because it isn't a good
// idea to normalize before the transformation is applied.
- AffineTransform inat = null;
+ AffineTransform strokerat = null;
AffineTransform outat = null;
PathIterator pi = null;
@@ -284,9 +283,9 @@
// again so, nothing can be drawn.
// Every path needs an initial moveTo and a pathDone. If these
- // aren't there this causes a SIGSEV in libawt.so (at the time
+ // are not there this causes a SIGSEGV in libawt.so (at the time
// of writing of this comment (September 16, 2010)). Actually,
- // I'm not sure if the moveTo is necessary to avoid the SIGSEV
+ // I am not sure if the moveTo is necessary to avoid the SIGSEGV
// but the pathDone is definitely needed.
pc2d.moveTo(0, 0);
pc2d.pathDone();
@@ -313,25 +312,32 @@
if (normalize != NormMode.OFF) {
pi = new NormalizingPathIterator(pi, normalize);
}
- // leave inat and outat null.
+ // by now strokerat == null && outat == null. Input paths to
+ // stroker (and maybe dasher) will have the full transform at
+ // applied to them and nothing will happen to the output paths.
} else {
- // We only need the inverse if normalization is on. Otherwise
- // we just don't transform the input paths, do all the stroking
- // and then transform out output (instead of making PathIterator
- // apply the transformation, us applying the inverse, and then
- // us applying the transform again to our output).
- outat = at;
if (normalize != NormMode.OFF) {
- try {
- inat = outat.createInverse();
- } catch (NoninvertibleTransformException e) {
- // we made sure this can't happen
- e.printStackTrace();
- }
+ strokerat = at;
pi = src.getPathIterator(at);
pi = new NormalizingPathIterator(pi, normalize);
+ // by now strokerat == at && outat == null. Input paths to
+ // stroker (and maybe dasher) will have the full transform at
+ // applied to them, then they will be normalized, and then
+ // the inverse of *only the non translation part of at* will
+ // be applied to the normalized paths. This won't cause problems
+ // in stroker, because, suppose at = T*A, where T is just the
+ // translation part of at, and A is the rest. T*A has already
+ // been applied to Stroker/Dasher's input. Then Ainv will be
+ // applied. Ainv*T*A is not equal to T, but it is a translation,
+ // which means that none of stroker's assumptions about its
+ // input will be violated. After all this, A will be applied
+ // to stroker's output.
} else {
+ outat = at;
pi = src.getPathIterator(null);
+ // outat == at && strokerat == null. This is because if no
+ // normalization is done, we can just apply all our
+ // transformations to stroker's output.
}
}
} else {
@@ -343,13 +349,17 @@
}
}
+ // by now, at least one of outat and strokerat will be null. Unless at is not
+ // a constant multiple of an orthogonal transformation, they will both be
+ // null. In other cases, outat == at if normalization is off, and if
+ // normalization is on, strokerat == at.
pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, outat);
+ pc2d = TransformingPathConsumer2D.deltaTransformConsumer(pc2d, strokerat);
pc2d = new Stroker(pc2d, width, caps, join, miterlimit);
if (dashes != null) {
pc2d = new Dasher(pc2d, dashes, dashphase);
}
- pc2d = TransformingPathConsumer2D.transformConsumer(pc2d, inat);
-
+ pc2d = TransformingPathConsumer2D.inverseDeltaTransformConsumer(pc2d, strokerat);
pathTo(pi, pc2d);
}
@@ -588,9 +598,9 @@
}
Renderer r = new Renderer(3, 3,
- clip.getLoX(), clip.getLoY(),
- clip.getWidth(), clip.getHeight(),
- PathIterator.WIND_EVEN_ODD);
+ clip.getLoX(), clip.getLoY(),
+ clip.getWidth(), clip.getHeight(),
+ PathIterator.WIND_EVEN_ODD);
r.moveTo((float) x, (float) y);
r.lineTo((float) (x+dx1), (float) (y+dy1));
--- a/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/PiscesTileGenerator.java Fri Feb 18 12:04:36 2011 -0800
@@ -30,7 +30,7 @@
import sun.java2d.pipe.AATileGenerator;
-public final class PiscesTileGenerator implements AATileGenerator {
+final class PiscesTileGenerator implements AATileGenerator {
public static final int TILE_SIZE = PiscesCache.TILE_SIZE;
// perhaps we should be using weak references here, but right now
--- a/jdk/src/share/classes/sun/java2d/pisces/Renderer.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Renderer.java Fri Feb 18 12:04:36 2011 -0800
@@ -25,12 +25,9 @@
package sun.java2d.pisces;
-import java.util.Arrays;
-import java.util.Iterator;
-
import sun.awt.geom.PathConsumer2D;
-public class Renderer implements PathConsumer2D {
+final class Renderer implements PathConsumer2D {
private class ScanlineIterator {
@@ -39,115 +36,81 @@
// crossing bounds. The bounds are not necessarily tight (the scan line
// at minY, for example, might have no crossings). The x bounds will
// be accumulated as crossings are computed.
- private int minY, maxY;
+ private final int maxY;
private int nextY;
// indices into the segment pointer lists. They indicate the "active"
// sublist in the segment lists (the portion of the list that contains
// all the segments that cross the next scan line).
- private int elo, ehi;
- private final int[] edgePtrs;
- private int qlo, qhi;
- private final int[] quadPtrs;
- private int clo, chi;
- private final int[] curvePtrs;
+ private int edgeCount;
+ private int[] edgePtrs;
private static final int INIT_CROSSINGS_SIZE = 10;
private ScanlineIterator() {
crossings = new int[INIT_CROSSINGS_SIZE];
-
- edgePtrs = new int[numEdges];
- Helpers.fillWithIdxes(edgePtrs, SIZEOF_EDGE);
- qsort(edges, edgePtrs, YMIN, 0, numEdges - 1);
-
- quadPtrs = new int[numQuads];
- Helpers.fillWithIdxes(quadPtrs, SIZEOF_QUAD);
- qsort(quads, quadPtrs, YMIN, 0, numQuads - 1);
-
- curvePtrs = new int[numCurves];
- Helpers.fillWithIdxes(curvePtrs, SIZEOF_CURVE);
- qsort(curves, curvePtrs, YMIN, 0, numCurves - 1);
+ edgePtrs = new int[INIT_CROSSINGS_SIZE];
// We don't care if we clip some of the line off with ceil, since
// no scan line crossings will be eliminated (in fact, the ceil is
// the y of the first scan line crossing).
- nextY = minY = Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
- maxY = Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
-
- for (elo = 0; elo < numEdges && edges[edgePtrs[elo]+YMAX] <= minY; elo++)
- ;
- // the active list is *edgePtrs[lo] (inclusive) *edgePtrs[hi] (exclusive)
- for (ehi = elo; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= minY; ehi++)
- edgeSetCurY(edgePtrs[ehi], minY);// TODO: make minY a float to avoid casts
-
- for (qlo = 0; qlo < numQuads && quads[quadPtrs[qlo]+YMAX] <= minY; qlo++)
- ;
- for (qhi = qlo; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= minY; qhi++)
- quadSetCurY(quadPtrs[qhi], minY);
-
- for (clo = 0; clo < numCurves && curves[curvePtrs[clo]+YMAX] <= minY; clo++)
- ;
- for (chi = clo; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= minY; chi++)
- curveSetCurY(curvePtrs[chi], minY);
+ final int minY = getFirstScanLineCrossing();
+ nextY = minY;
+ maxY = getScanLineCrossingEnd()-1;
+ edgeCount = 0;
}
private int next() {
- // we go through the active lists and remove segments that don't cross
- // the nextY scanline.
- int crossingIdx = 0;
- for (int i = elo; i < ehi; i++) {
- if (edges[edgePtrs[i]+YMAX] <= nextY) {
- edgePtrs[i] = edgePtrs[elo++];
+ int cury = nextY++;
+ int bucket = cury - boundsMinY;
+ int count = this.edgeCount;
+ int ptrs[] = this.edgePtrs;
+ int bucketcount = edgeBucketCounts[bucket];
+ if ((bucketcount & 0x1) != 0) {
+ int newCount = 0;
+ for (int i = 0; i < count; i++) {
+ int ecur = ptrs[i];
+ if (edges[ecur+YMAX] > cury) {
+ ptrs[newCount++] = ecur;
+ }
}
+ count = newCount;
}
- for (int i = qlo; i < qhi; i++) {
- if (quads[quadPtrs[i]+YMAX] <= nextY) {
- quadPtrs[i] = quadPtrs[qlo++];
- }
- }
- for (int i = clo; i < chi; i++) {
- if (curves[curvePtrs[i]+YMAX] <= nextY) {
- curvePtrs[i] = curvePtrs[clo++];
- }
+ ptrs = Helpers.widenArray(ptrs, count, bucketcount >> 1);
+ for (int ecur = edgeBuckets[bucket]; ecur != NULL; ecur = (int)edges[ecur+NEXT]) {
+ ptrs[count++] = ecur;
+ // REMIND: Adjust start Y if necessary
}
-
- crossings = Helpers.widenArray(crossings, 0, ehi-elo+qhi-qlo+chi-clo);
-
- // Now every edge between lo and hi crosses nextY. Compute it's
- // crossing and put it in the crossings array.
- for (int i = elo; i < ehi; i++) {
- int ptr = edgePtrs[i];
- addCrossing(nextY, (int)edges[ptr+CURX], edges[ptr+OR], crossingIdx);
- edgeGoToNextY(ptr);
- crossingIdx++;
- }
- for (int i = qlo; i < qhi; i++) {
- int ptr = quadPtrs[i];
- addCrossing(nextY, (int)quads[ptr+CURX], quads[ptr+OR], crossingIdx);
- quadGoToNextY(ptr);
- crossingIdx++;
+ this.edgePtrs = ptrs;
+ this.edgeCount = count;
+// if ((count & 0x1) != 0) {
+// System.out.println("ODD NUMBER OF EDGES!!!!");
+// }
+ int xings[] = this.crossings;
+ if (xings.length < count) {
+ this.crossings = xings = new int[ptrs.length];
}
- for (int i = clo; i < chi; i++) {
- int ptr = curvePtrs[i];
- addCrossing(nextY, (int)curves[ptr+CURX], curves[ptr+OR], crossingIdx);
- curveGoToNextY(ptr);
- crossingIdx++;
+ for (int i = 0; i < count; i++) {
+ int ecur = ptrs[i];
+ float curx = edges[ecur+CURX];
+ int cross = ((int) curx) << 1;
+ edges[ecur+CURX] = curx + edges[ecur+SLOPE];
+ if (edges[ecur+OR] > 0) {
+ cross |= 1;
+ }
+ int j = i;
+ while (--j >= 0) {
+ int jcross = xings[j];
+ if (jcross <= cross) {
+ break;
+ }
+ xings[j+1] = jcross;
+ ptrs[j+1] = ptrs[j];
+ }
+ xings[j+1] = cross;
+ ptrs[j+1] = ecur;
}
-
- nextY++;
- // Expand active lists to include new edges.
- for (; ehi < numEdges && edges[edgePtrs[ehi]+YMIN] <= nextY; ehi++) {
- edgeSetCurY(edgePtrs[ehi], nextY);
- }
- for (; qhi < numQuads && quads[quadPtrs[qhi]+YMIN] <= nextY; qhi++) {
- quadSetCurY(quadPtrs[qhi], nextY);
- }
- for (; chi < numCurves && curves[curvePtrs[chi]+YMIN] <= nextY; chi++) {
- curveSetCurY(curvePtrs[chi], nextY);
- }
- Arrays.sort(crossings, 0, crossingIdx);
- return crossingIdx;
+ return count;
}
private boolean hasNext() {
@@ -157,51 +120,7 @@
private int curY() {
return nextY - 1;
}
-
- private void addCrossing(int y, int x, float or, int idx) {
- x <<= 1;
- crossings[idx] = ((or > 0) ? (x | 0x1) : x);
- }
}
- // quicksort implementation for sorting the edge indices ("pointers")
- // by increasing y0. first, last are indices into the "pointer" array
- // It sorts the pointer array from first (inclusive) to last (inclusive)
- private static void qsort(final float[] data, final int[] ptrs,
- final int fieldForCmp, int first, int last)
- {
- if (last > first) {
- int p = partition(data, ptrs, fieldForCmp, first, last);
- if (first < p - 1) {
- qsort(data, ptrs, fieldForCmp, first, p - 1);
- }
- if (p < last) {
- qsort(data, ptrs, fieldForCmp, p, last);
- }
- }
- }
-
- // i, j are indices into edgePtrs.
- private static int partition(final float[] data, final int[] ptrs,
- final int fieldForCmp, int i, int j)
- {
- int pivotValFieldForCmp = ptrs[i]+fieldForCmp;
- while (i <= j) {
- // edges[edgePtrs[i]+1] is equivalent to (*(edgePtrs[i])).y0 in C
- while (data[ptrs[i]+fieldForCmp] < data[pivotValFieldForCmp])
- i++;
- while (data[ptrs[j]+fieldForCmp] > data[pivotValFieldForCmp])
- j--;
- if (i <= j) {
- int tmp = ptrs[i];
- ptrs[i] = ptrs[j];
- ptrs[j] = tmp;
- i++;
- j--;
- }
- }
- return i;
- }
-//============================================================================
//////////////////////////////////////////////////////////////////////////////
@@ -209,269 +128,89 @@
//////////////////////////////////////////////////////////////////////////////
// TODO(maybe): very tempting to use fixed point here. A lot of opportunities
// for shifts and just removing certain operations altogether.
-// TODO: it might be worth it to make an EdgeList class. It would probably
-// clean things up a bit and not impact performance much.
// common to all types of input path segments.
- private static final int YMIN = 0;
- private static final int YMAX = 1;
- private static final int CURX = 2;
- // this and OR are meant to be indeces into "int" fields, but arrays must
+ private static final int YMAX = 0;
+ private static final int CURX = 1;
+ // NEXT and OR are meant to be indices into "int" fields, but arrays must
// be homogenous, so every field is a float. However floats can represent
// exactly up to 26 bit ints, so we're ok.
- private static final int CURY = 3;
- private static final int OR = 4;
-
- // for straight lines only:
- private static final int SLOPE = 5;
-
- // for quads and cubics:
- private static final int X0 = 5;
- private static final int Y0 = 6;
- private static final int XL = 7;
- private static final int COUNT = 8;
- private static final int CURSLOPE = 9;
- private static final int DX = 10;
- private static final int DY = 11;
- private static final int DDX = 12;
- private static final int DDY = 13;
-
- // for cubics only
- private static final int DDDX = 14;
- private static final int DDDY = 15;
+ private static final int OR = 2;
+ private static final int SLOPE = 3;
+ private static final int NEXT = 4;
private float edgeMinY = Float.POSITIVE_INFINITY;
private float edgeMaxY = Float.NEGATIVE_INFINITY;
private float edgeMinX = Float.POSITIVE_INFINITY;
private float edgeMaxX = Float.NEGATIVE_INFINITY;
- private static final int SIZEOF_EDGE = 6;
+ private static final int SIZEOF_EDGE = 5;
+ // don't just set NULL to -1, because we want NULL+NEXT to be negative.
+ private static final int NULL = -SIZEOF_EDGE;
private float[] edges = null;
+ private int[] edgeBuckets = null;
+ private int[] edgeBucketCounts = null; // 2*newedges + (1 if pruning needed)
private int numEdges;
- // these are static because we need them to be usable from ScanlineIterator
- private void edgeSetCurY(final int idx, int y) {
- edges[idx+CURX] += (y - edges[idx+CURY]) * edges[idx+SLOPE];
- edges[idx+CURY] = y;
- }
- private void edgeGoToNextY(final int idx) {
- edges[idx+CURY] += 1;
- edges[idx+CURX] += edges[idx+SLOPE];
- }
-
-
- private static final int SIZEOF_QUAD = 14;
- private float[] quads = null;
- private int numQuads;
- // This function should be called exactly once, to set the first scanline
- // of the curve. Before it is called, the curve should think its first
- // scanline is CEIL(YMIN).
- private void quadSetCurY(final int idx, final int y) {
- assert y < quads[idx+YMAX];
- assert (quads[idx+CURY] > y);
- assert (quads[idx+CURY] == Math.ceil(quads[idx+CURY]));
-
- while (quads[idx+CURY] < ((float)y)) {
- quadGoToNextY(idx);
- }
- }
- private void quadGoToNextY(final int idx) {
- quads[idx+CURY] += 1;
- // this will get overriden if the while executes.
- quads[idx+CURX] += quads[idx+CURSLOPE];
- int count = (int)quads[idx+COUNT];
- // this loop should never execute more than once because our
- // curve is monotonic in Y. Still we put it in because you can
- // never be too sure when dealing with floating point.
- while(quads[idx+CURY] >= quads[idx+Y0] && count > 0) {
- float x0 = quads[idx+X0], y0 = quads[idx+Y0];
- count = executeQuadAFDIteration(idx);
- float x1 = quads[idx+X0], y1 = quads[idx+Y0];
- // our quads are monotonic, so this shouldn't happen, but
- // it is conceivable that for very flat quads with different
- // y values at their endpoints AFD might give us a horizontal
- // segment.
- if (y1 == y0) {
- continue;
- }
- quads[idx+CURSLOPE] = (x1 - x0) / (y1 - y0);
- quads[idx+CURX] = x0 + (quads[idx+CURY] - y0) * quads[idx+CURSLOPE];
- }
- }
-
-
- private static final int SIZEOF_CURVE = 16;
- private float[] curves = null;
- private int numCurves;
- private void curveSetCurY(final int idx, final int y) {
- assert y < curves[idx+YMAX];
- assert (curves[idx+CURY] > y);
- assert (curves[idx+CURY] == Math.ceil(curves[idx+CURY]));
-
- while (curves[idx+CURY] < ((float)y)) {
- curveGoToNextY(idx);
- }
- }
- private void curveGoToNextY(final int idx) {
- curves[idx+CURY] += 1;
- // this will get overriden if the while executes.
- curves[idx+CURX] += curves[idx+CURSLOPE];
- int count = (int)curves[idx+COUNT];
- // this loop should never execute more than once because our
- // curve is monotonic in Y. Still we put it in because you can
- // never be too sure when dealing with floating point.
- while(curves[idx+CURY] >= curves[idx+Y0] && count > 0) {
- float x0 = curves[idx+X0], y0 = curves[idx+Y0];
- count = executeCurveAFDIteration(idx);
- float x1 = curves[idx+X0], y1 = curves[idx+Y0];
- // our curves are monotonic, so this shouldn't happen, but
- // it is conceivable that for very flat curves with different
- // y values at their endpoints AFD might give us a horizontal
- // segment.
- if (y1 == y0) {
- continue;
- }
- curves[idx+CURSLOPE] = (x1 - x0) / (y1 - y0);
- curves[idx+CURX] = x0 + (curves[idx+CURY] - y0) * curves[idx+CURSLOPE];
- }
- }
-
private static final float DEC_BND = 20f;
private static final float INC_BND = 8f;
+
+ // each bucket is a linked list. this method adds eptr to the
+ // start "bucket"th linked list.
+ private void addEdgeToBucket(final int eptr, final int bucket) {
+ edges[eptr+NEXT] = edgeBuckets[bucket];
+ edgeBuckets[bucket] = eptr;
+ edgeBucketCounts[bucket] += 2;
+ }
+
// Flattens using adaptive forward differencing. This only carries out
// one iteration of the AFD loop. All it does is update AFD variables (i.e.
// X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
- private int executeQuadAFDIteration(int idx) {
- int count = (int)quads[idx+COUNT];
- float ddx = quads[idx+DDX];
- float ddy = quads[idx+DDY];
- float dx = quads[idx+DX];
- float dy = quads[idx+DY];
-
- while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
- ddx = ddx / 4;
- ddy = ddy / 4;
- dx = (dx - ddx) / 2;
- dy = (dy - ddy) / 2;
+ private void quadBreakIntoLinesAndAdd(float x0, float y0,
+ final Curve c,
+ final float x2, final float y2) {
+ final float QUAD_DEC_BND = 32;
+ final int countlg = 4;
+ int count = 1 << countlg;
+ int countsq = count * count;
+ float maxDD = Math.max(c.dbx / countsq, c.dby / countsq);
+ while (maxDD > QUAD_DEC_BND) {
+ maxDD /= 4;
count <<= 1;
}
- // can only do this on even "count" values, because we must divide count by 2
- while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
- dx = 2 * dx + ddx;
- dy = 2 * dy + ddy;
- ddx = 4 * ddx;
- ddy = 4 * ddy;
- count >>= 1;
- }
- count--;
- if (count > 0) {
- quads[idx+X0] += dx;
- dx += ddx;
- quads[idx+Y0] += dy;
- dy += ddy;
- } else {
- quads[idx+X0] = quads[idx+XL];
- quads[idx+Y0] = quads[idx+YMAX];
- }
- quads[idx+COUNT] = count;
- quads[idx+DDX] = ddx;
- quads[idx+DDY] = ddy;
- quads[idx+DX] = dx;
- quads[idx+DY] = dy;
- return count;
- }
- private int executeCurveAFDIteration(int idx) {
- int count = (int)curves[idx+COUNT];
- float ddx = curves[idx+DDX];
- float ddy = curves[idx+DDY];
- float dx = curves[idx+DX];
- float dy = curves[idx+DY];
- float dddx = curves[idx+DDDX];
- float dddy = curves[idx+DDDY];
+
+ countsq = count * count;
+ final float ddx = c.dbx / countsq;
+ final float ddy = c.dby / countsq;
+ float dx = c.bx / countsq + c.cx / count;
+ float dy = c.by / countsq + c.cy / count;
- while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
- dddx /= 8;
- dddy /= 8;
- ddx = ddx/4 - dddx;
- ddy = ddy/4 - dddy;
- dx = (dx - ddx) / 2;
- dy = (dy - ddy) / 2;
- count <<= 1;
- }
- // can only do this on even "count" values, because we must divide count by 2
- while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
- dx = 2 * dx + ddx;
- dy = 2 * dy + ddy;
- ddx = 4 * (ddx + dddx);
- ddy = 4 * (ddy + dddy);
- dddx = 8 * dddx;
- dddy = 8 * dddy;
- count >>= 1;
+ while (count-- > 1) {
+ float x1 = x0 + dx;
+ dx += ddx;
+ float y1 = y0 + dy;
+ dy += ddy;
+ addLine(x0, y0, x1, y1);
+ x0 = x1;
+ y0 = y1;
}
- count--;
- if (count > 0) {
- curves[idx+X0] += dx;
- dx += ddx;
- ddx += dddx;
- curves[idx+Y0] += dy;
- dy += ddy;
- ddy += dddy;
- } else {
- curves[idx+X0] = curves[idx+XL];
- curves[idx+Y0] = curves[idx+YMAX];
- }
- curves[idx+COUNT] = count;
- curves[idx+DDDX] = dddx;
- curves[idx+DDDY] = dddy;
- curves[idx+DDX] = ddx;
- curves[idx+DDY] = ddy;
- curves[idx+DX] = dx;
- curves[idx+DY] = dy;
- return count;
+ addLine(x0, y0, x2, y2);
}
-
- private void initLine(final int idx, float[] pts, int or) {
- edges[idx+SLOPE] = (pts[2] - pts[0]) / (pts[3] - pts[1]);
- edges[idx+CURX] = pts[0] + (edges[idx+CURY] - pts[1]) * edges[idx+SLOPE];
- }
-
- private void initQuad(final int idx, float[] points, int or) {
+ // x0, y0 and x3,y3 are the endpoints of the curve. We could compute these
+ // using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce
+ // numerical errors, and our callers already have the exact values.
+ // Another alternative would be to pass all the control points, and call c.set
+ // here, but then too many numbers are passed around.
+ private void curveBreakIntoLinesAndAdd(float x0, float y0,
+ final Curve c,
+ final float x3, final float y3) {
final int countlg = 3;
- final int count = 1 << countlg;
+ int count = 1 << countlg;
// the dx and dy refer to forward differencing variables, not the last
// coefficients of the "points" polynomial
- final float ddx, ddy, dx, dy;
- c.set(points, 6);
-
- ddx = c.dbx / (1 << (2 * countlg));
- ddy = c.dby / (1 << (2 * countlg));
- dx = c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
- dy = c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
-
- quads[idx+DDX] = ddx;
- quads[idx+DDY] = ddy;
- quads[idx+DX] = dx;
- quads[idx+DY] = dy;
- quads[idx+COUNT] = count;
- quads[idx+XL] = points[4];
- quads[idx+X0] = points[0];
- quads[idx+Y0] = points[1];
- executeQuadAFDIteration(idx);
- float x1 = quads[idx+X0], y1 = quads[idx+Y0];
- quads[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]);
- quads[idx+CURX] = points[0] + (quads[idx+CURY] - points[1])*quads[idx+CURSLOPE];
- }
-
- private void initCurve(final int idx, float[] points, int or) {
- final int countlg = 3;
- final int count = 1 << countlg;
-
- // the dx and dy refer to forward differencing variables, not the last
- // coefficients of the "points" polynomial
- final float dddx, dddy, ddx, ddy, dx, dy;
- c.set(points, 8);
+ float dddx, dddy, ddx, ddy, dx, dy;
dddx = 2f * c.dax / (1 << (3 * countlg));
dddy = 2f * c.day / (1 << (3 * countlg));
@@ -480,93 +219,100 @@
dx = c.ax / (1 << (3 * countlg)) + c.bx / (1 << (2 * countlg)) + c.cx / (1 << countlg);
dy = c.ay / (1 << (3 * countlg)) + c.by / (1 << (2 * countlg)) + c.cy / (1 << countlg);
- curves[idx+DDDX] = dddx;
- curves[idx+DDDY] = dddy;
- curves[idx+DDX] = ddx;
- curves[idx+DDY] = ddy;
- curves[idx+DX] = dx;
- curves[idx+DY] = dy;
- curves[idx+COUNT] = count;
- curves[idx+XL] = points[6];
- curves[idx+X0] = points[0];
- curves[idx+Y0] = points[1];
- executeCurveAFDIteration(idx);
- float x1 = curves[idx+X0], y1 = curves[idx+Y0];
- curves[idx+CURSLOPE] = (x1 - points[0]) / (y1 - points[1]);
- curves[idx+CURX] = points[0] + (curves[idx+CURY] - points[1])*curves[idx+CURSLOPE];
- }
-
- private void addPathSegment(float[] pts, final int type, final int or) {
- int idx;
- float[] addTo;
- switch (type) {
- case 4:
- idx = numEdges * SIZEOF_EDGE;
- addTo = edges = Helpers.widenArray(edges, numEdges*SIZEOF_EDGE, SIZEOF_EDGE);
- numEdges++;
- break;
- case 6:
- idx = numQuads * SIZEOF_QUAD;
- addTo = quads = Helpers.widenArray(quads, numQuads*SIZEOF_QUAD, SIZEOF_QUAD);
- numQuads++;
- break;
- case 8:
- idx = numCurves * SIZEOF_CURVE;
- addTo = curves = Helpers.widenArray(curves, numCurves*SIZEOF_CURVE, SIZEOF_CURVE);
- numCurves++;
- break;
- default:
- throw new InternalError();
- }
- // set the common fields, except CURX, for which we must know the kind
- // of curve. NOTE: this must be done before the type specific fields
- // are initialized, because those depend on the common ones.
- addTo[idx+YMIN] = pts[1];
- addTo[idx+YMAX] = pts[type-1];
- addTo[idx+OR] = or;
- addTo[idx+CURY] = (float)Math.ceil(pts[1]);
- switch (type) {
- case 4:
- initLine(idx, pts, or);
- break;
- case 6:
- initQuad(idx, pts, or);
- break;
- case 8:
- initCurve(idx, pts, or);
- break;
- default:
- throw new InternalError();
+ // we use x0, y0 to walk the line
+ float x1 = x0, y1 = y0;
+ while (count > 0) {
+ while (Math.abs(ddx) > DEC_BND || Math.abs(ddy) > DEC_BND) {
+ dddx /= 8;
+ dddy /= 8;
+ ddx = ddx/4 - dddx;
+ ddy = ddy/4 - dddy;
+ dx = (dx - ddx) / 2;
+ dy = (dy - ddy) / 2;
+ count <<= 1;
+ }
+ // can only do this on even "count" values, because we must divide count by 2
+ while (count % 2 == 0 && Math.abs(dx) <= INC_BND && Math.abs(dy) <= INC_BND) {
+ dx = 2 * dx + ddx;
+ dy = 2 * dy + ddy;
+ ddx = 4 * (ddx + dddx);
+ ddy = 4 * (ddy + dddy);
+ dddx = 8 * dddx;
+ dddy = 8 * dddy;
+ count >>= 1;
+ }
+ count--;
+ if (count > 0) {
+ x1 += dx;
+ dx += ddx;
+ ddx += dddx;
+ y1 += dy;
+ dy += ddy;
+ ddy += dddy;
+ } else {
+ x1 = x3;
+ y1 = y3;
+ }
+ addLine(x0, y0, x1, y1);
+ x0 = x1;
+ y0 = y1;
}
}
- // precondition: the curve in pts must be monotonic and increasing in y.
- private void somethingTo(float[] pts, final int type, final int or) {
- // NOTE: it's very important that we check for or >= 0 below (as
- // opposed to or == 1, or or > 0, or anything else). That's
- // because if we check for or==1, when the curve being added
- // is a horizontal line, or will be 0 so or==1 will be false and
- // x0 and y0 will be updated to pts[0] and pts[1] instead of pts[type-2]
- // and pts[type-1], which is the correct thing to do.
- this.x0 = or >= 0 ? pts[type - 2] : pts[0];
- this.y0 = or >= 0 ? pts[type - 1] : pts[1];
-
- float minY = pts[1], maxY = pts[type - 1];
- if (Math.ceil(minY) >= Math.ceil(maxY) ||
- Math.ceil(minY) >= boundsMaxY || maxY < boundsMinY)
- {
+ // Preconditions: y2 > y1 and the curve must cross some scanline
+ // i.e.: y1 <= y < y2 for some y such that boundsMinY <= y < boundsMaxY
+ private void addLine(float x1, float y1, float x2, float y2) {
+ float or = 1; // orientation of the line. 1 if y increases, 0 otherwise.
+ if (y2 < y1) {
+ or = y2; // no need to declare a temp variable. We have or.
+ y2 = y1;
+ y1 = or;
+ or = x2;
+ x2 = x1;
+ x1 = or;
+ or = 0;
+ }
+ final int firstCrossing = Math.max((int) Math.ceil(y1), boundsMinY);
+ final int lastCrossing = Math.min((int)Math.ceil(y2), boundsMaxY);
+ if (firstCrossing >= lastCrossing) {
return;
}
- if (minY < edgeMinY) { edgeMinY = minY; }
- if (maxY > edgeMaxY) { edgeMaxY = maxY; }
+ if (y1 < edgeMinY) { edgeMinY = y1; }
+ if (y2 > edgeMaxY) { edgeMaxY = y2; }
+
+ final float slope = (x2 - x1) / (y2 - y1);
+
+ if (slope > 0) { // <==> x1 < x2
+ if (x1 < edgeMinX) { edgeMinX = x1; }
+ if (x2 > edgeMaxX) { edgeMaxX = x2; }
+ } else {
+ if (x2 < edgeMinX) { edgeMinX = x2; }
+ if (x1 > edgeMaxX) { edgeMaxX = x1; }
+ }
- int minXidx = (pts[0] < pts[type-2] ? 0 : type - 2);
- float minX = pts[minXidx];
- float maxX = pts[type - 2 - minXidx];
- if (minX < edgeMinX) { edgeMinX = minX; }
- if (maxX > edgeMaxX) { edgeMaxX = maxX; }
- addPathSegment(pts, type, or);
+ final int ptr = numEdges * SIZEOF_EDGE;
+ edges = Helpers.widenArray(edges, ptr, SIZEOF_EDGE);
+ numEdges++;
+ edges[ptr+OR] = or;
+ edges[ptr+CURX] = x1 + (firstCrossing - y1) * slope;
+ edges[ptr+SLOPE] = slope;
+ edges[ptr+YMAX] = y2;
+ final int bucketIdx = firstCrossing - boundsMinY;
+ addEdgeToBucket(ptr, bucketIdx);
+ if (lastCrossing < boundsMaxY) {
+ edgeBucketCounts[lastCrossing - boundsMinY] |= 1;
+ }
+ }
+
+ // preconditions: should not be called before the last line has been added
+ // to the edge list (even though it will return a correct answer at that
+ // point in time, it's not meant to be used that way).
+ private int getFirstScanLineCrossing() {
+ return Math.max(boundsMinY, (int)Math.ceil(edgeMinY));
+ }
+ private int getScanLineCrossingEnd() {
+ return Math.min(boundsMaxY, (int)Math.ceil(edgeMaxY));
}
// END EDGE LIST
@@ -619,6 +365,10 @@
this.boundsMinY = pix_boundsY * SUBPIXEL_POSITIONS_Y;
this.boundsMaxX = (pix_boundsX + pix_boundsWidth) * SUBPIXEL_POSITIONS_X;
this.boundsMaxY = (pix_boundsY + pix_boundsHeight) * SUBPIXEL_POSITIONS_Y;
+
+ edgeBuckets = new int[boundsMaxY - boundsMinY];
+ java.util.Arrays.fill(edgeBuckets, NULL);
+ edgeBucketCounts = new int[edgeBuckets.length];
}
private float tosubpixx(float pix_x) {
@@ -636,74 +386,34 @@
this.x0 = tosubpixx(pix_x0);
}
- public void lineJoin() { /* do nothing */ }
-
- private final float[][] pts = new float[2][8];
- private final float[] ts = new float[4];
-
- private static void invertPolyPoints(float[] pts, int off, int type) {
- for (int i = off, j = off + type - 2; i < j; i += 2, j -= 2) {
- float tmp = pts[i];
- pts[i] = pts[j];
- pts[j] = tmp;
- tmp = pts[i+1];
- pts[i+1] = pts[j+1];
- pts[j+1] = tmp;
- }
- }
-
- // return orientation before making the curve upright.
- private static int makeMonotonicCurveUpright(float[] pts, int off, int type) {
- float y0 = pts[off + 1];
- float y1 = pts[off + type - 1];
- if (y0 > y1) {
- invertPolyPoints(pts, off, type);
- return -1;
- } else if (y0 < y1) {
- return 1;
- }
- return 0;
- }
-
public void lineTo(float pix_x1, float pix_y1) {
- pts[0][0] = x0; pts[0][1] = y0;
- pts[0][2] = tosubpixx(pix_x1); pts[0][3] = tosubpixy(pix_y1);
- int or = makeMonotonicCurveUpright(pts[0], 0, 4);
- somethingTo(pts[0], 4, or);
+ float x1 = tosubpixx(pix_x1);
+ float y1 = tosubpixy(pix_y1);
+ addLine(x0, y0, x1, y1);
+ x0 = x1;
+ y0 = y1;
}
Curve c = new Curve();
- private void curveOrQuadTo(int type) {
- c.set(pts[0], type);
- int numTs = c.dxRoots(ts, 0);
- numTs += c.dyRoots(ts, numTs);
- numTs = Helpers.filterOutNotInAB(ts, 0, numTs, 0, 1);
- Helpers.isort(ts, 0, numTs);
-
- Iterator<float[]> it = Curve.breakPtsAtTs(pts, type, ts, numTs);
- while(it.hasNext()) {
- float[] curCurve = it.next();
- int or = makeMonotonicCurveUpright(curCurve, 0, type);
- somethingTo(curCurve, type, or);
- }
- }
-
@Override public void curveTo(float x1, float y1,
float x2, float y2,
float x3, float y3)
{
- pts[0][0] = x0; pts[0][1] = y0;
- pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1);
- pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2);
- pts[0][6] = tosubpixx(x3); pts[0][7] = tosubpixy(y3);
- curveOrQuadTo(8);
+ final float xe = tosubpixx(x3);
+ final float ye = tosubpixy(y3);
+ c.set(x0, y0, tosubpixx(x1), tosubpixy(y1), tosubpixx(x2), tosubpixy(y2), xe, ye);
+ curveBreakIntoLinesAndAdd(x0, y0, c, xe, ye);
+ x0 = xe;
+ y0 = ye;
}
@Override public void quadTo(float x1, float y1, float x2, float y2) {
- pts[0][0] = x0; pts[0][1] = y0;
- pts[0][2] = tosubpixx(x1); pts[0][3] = tosubpixy(y1);
- pts[0][4] = tosubpixx(x2); pts[0][5] = tosubpixy(y2);
- curveOrQuadTo(6);
+ final float xe = tosubpixx(x2);
+ final float ye = tosubpixy(y2);
+ c.set(x0, y0, tosubpixx(x1), tosubpixy(y1), xe, ye);
+ quadBreakIntoLinesAndAdd(x0, y0, c, xe, ye);
+ x0 = xe;
+ y0 = ye;
}
public void closePath() {
@@ -728,9 +438,9 @@
// 0x1 if EVEN_ODD, all bits if NON_ZERO
int mask = (windingRule == WIND_EVEN_ODD) ? 0x1 : ~0x0;
- // add 1 to better deal with the last pixel in a pixel row.
- int width = pix_bboxx1 - pix_bboxx0 + 1;
- int[] alpha = new int[width+1];
+ // add 2 to better deal with the last pixel in a pixel row.
+ int width = pix_bboxx1 - pix_bboxx0;
+ int[] alpha = new int[width+2];
int bboxx0 = pix_bboxx0 << SUBPIXEL_LG_POSITIONS_X;
int bboxx1 = pix_bboxx1 << SUBPIXEL_LG_POSITIONS_X;
@@ -766,7 +476,8 @@
for (int i = 0; i < numCrossings; i++) {
int curxo = crossings[i];
int curx = curxo >> 1;
- int crorientation = ((curxo & 0x1) == 0x1) ? 1 : -1;
+ // to turn {0, 1} into {-1, 1}, multiply by 2 and subtract 1.
+ int crorientation = ((curxo & 0x1) << 1) -1;
if ((sum & mask) != 0) {
int x0 = Math.max(prev, bboxx0);
int x1 = Math.min(curx, bboxx1);
@@ -811,26 +522,26 @@
}
public void endRendering() {
- final int bminx = boundsMinX >> SUBPIXEL_LG_POSITIONS_X;
- final int bmaxx = boundsMaxX >> SUBPIXEL_LG_POSITIONS_X;
- final int bminy = boundsMinY >> SUBPIXEL_LG_POSITIONS_Y;
- final int bmaxy = boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y;
- final int eminx = ((int)Math.floor(edgeMinX)) >> SUBPIXEL_LG_POSITIONS_X;
- final int emaxx = ((int)Math.ceil(edgeMaxX)) >> SUBPIXEL_LG_POSITIONS_X;
- final int eminy = ((int)Math.floor(edgeMinY)) >> SUBPIXEL_LG_POSITIONS_Y;
- final int emaxy = ((int)Math.ceil(edgeMaxY)) >> SUBPIXEL_LG_POSITIONS_Y;
+ int spminX = Math.max((int)Math.ceil(edgeMinX), boundsMinX);
+ int spmaxX = Math.min((int)Math.ceil(edgeMaxX), boundsMaxX);
+ int spminY = Math.max((int)Math.ceil(edgeMinY), boundsMinY);
+ int spmaxY = Math.min((int)Math.ceil(edgeMaxY), boundsMaxY);
- final int minX = Math.max(bminx, eminx);
- final int maxX = Math.min(bmaxx, emaxx);
- final int minY = Math.max(bminy, eminy);
- final int maxY = Math.min(bmaxy, emaxy);
- if (minX > maxX || minY > maxY) {
- this.cache = new PiscesCache(bminx, bminy, bmaxx, bmaxy);
+ int pminX = spminX >> SUBPIXEL_LG_POSITIONS_X;
+ int pmaxX = (spmaxX + SUBPIXEL_MASK_X) >> SUBPIXEL_LG_POSITIONS_X;
+ int pminY = spminY >> SUBPIXEL_LG_POSITIONS_Y;
+ int pmaxY = (spmaxY + SUBPIXEL_MASK_Y) >> SUBPIXEL_LG_POSITIONS_Y;
+
+ if (pminX > pmaxX || pminY > pmaxY) {
+ this.cache = new PiscesCache(boundsMinX >> SUBPIXEL_LG_POSITIONS_X,
+ boundsMinY >> SUBPIXEL_LG_POSITIONS_Y,
+ boundsMaxX >> SUBPIXEL_LG_POSITIONS_X,
+ boundsMaxY >> SUBPIXEL_LG_POSITIONS_Y);
return;
}
- this.cache = new PiscesCache(minX, minY, maxX, maxY);
- _endRendering(minX, minY, maxX, maxY);
+ this.cache = new PiscesCache(pminX, pminY, pmaxX, pmaxY);
+ _endRendering(pminX, pminY, pmaxX, pmaxY);
}
public PiscesCache getCache() {
--- a/jdk/src/share/classes/sun/java2d/pisces/Stroker.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/Stroker.java Fri Feb 18 12:04:36 2011 -0800
@@ -33,7 +33,7 @@
// TODO: some of the arithmetic here is too verbose and prone to hard to
// debug typos. We should consider making a small Point/Vector class that
// has methods like plus(Point), minus(Point), dot(Point), cross(Point)and such
-public class Stroker implements PathConsumer2D {
+final class Stroker implements PathConsumer2D {
private static final int MOVE_TO = 0;
private static final int DRAWING_OP_TO = 1; // ie. curve, line, or quad
@@ -130,7 +130,7 @@
private static void computeOffset(final float lx, final float ly,
final float w, final float[] m)
{
- final float len = (float)Math.hypot(lx, ly);
+ final float len = (float)Math.sqrt(lx*lx + ly*ly);
if (len == 0) {
m[0] = m[1] = 0;
} else {
@@ -758,7 +758,7 @@
// This is where the curve to be processed is put. We give it
// enough room to store 2 curves: one for the current subdivision, the
// other for the rest of the curve.
- private float[][] middle = new float[2][8];
+ private float[] middle = new float[2*8];
private float[] lp = new float[8];
private float[] rp = new float[8];
private static final int MAX_N_CURVES = 11;
@@ -766,55 +766,55 @@
private void somethingTo(final int type) {
// need these so we can update the state at the end of this method
- final float xf = middle[0][type-2], yf = middle[0][type-1];
- float dxs = middle[0][2] - middle[0][0];
- float dys = middle[0][3] - middle[0][1];
- float dxf = middle[0][type - 2] - middle[0][type - 4];
- float dyf = middle[0][type - 1] - middle[0][type - 3];
+ final float xf = middle[type-2], yf = middle[type-1];
+ float dxs = middle[2] - middle[0];
+ float dys = middle[3] - middle[1];
+ float dxf = middle[type - 2] - middle[type - 4];
+ float dyf = middle[type - 1] - middle[type - 3];
switch(type) {
case 6:
if ((dxs == 0f && dys == 0f) ||
(dxf == 0f && dyf == 0f)) {
- dxs = dxf = middle[0][4] - middle[0][0];
- dys = dyf = middle[0][5] - middle[0][1];
+ dxs = dxf = middle[4] - middle[0];
+ dys = dyf = middle[5] - middle[1];
}
break;
case 8:
boolean p1eqp2 = (dxs == 0f && dys == 0f);
boolean p3eqp4 = (dxf == 0f && dyf == 0f);
if (p1eqp2) {
- dxs = middle[0][4] - middle[0][0];
- dys = middle[0][5] - middle[0][1];
+ dxs = middle[4] - middle[0];
+ dys = middle[5] - middle[1];
if (dxs == 0f && dys == 0f) {
- dxs = middle[0][6] - middle[0][0];
- dys = middle[0][7] - middle[0][1];
+ dxs = middle[6] - middle[0];
+ dys = middle[7] - middle[1];
}
}
if (p3eqp4) {
- dxf = middle[0][6] - middle[0][2];
- dyf = middle[0][7] - middle[0][3];
+ dxf = middle[6] - middle[2];
+ dyf = middle[7] - middle[3];
if (dxf == 0f && dyf == 0f) {
- dxf = middle[0][6] - middle[0][0];
- dyf = middle[0][7] - middle[0][1];
+ dxf = middle[6] - middle[0];
+ dyf = middle[7] - middle[1];
}
}
}
if (dxs == 0f && dys == 0f) {
// this happens iff the "curve" is just a point
- lineTo(middle[0][0], middle[0][1]);
+ lineTo(middle[0], middle[1]);
return;
}
// if these vectors are too small, normalize them, to avoid future
// precision problems.
if (Math.abs(dxs) < 0.1f && Math.abs(dys) < 0.1f) {
- double len = Math.hypot(dxs, dys);
- dxs = (float)(dxs / len);
- dys = (float)(dys / len);
+ float len = (float)Math.sqrt(dxs*dxs + dys*dys);
+ dxs /= len;
+ dys /= len;
}
if (Math.abs(dxf) < 0.1f && Math.abs(dyf) < 0.1f) {
- double len = Math.hypot(dxf, dyf);
- dxf = (float)(dxf / len);
- dyf = (float)(dyf / len);
+ float len = (float)Math.sqrt(dxf*dxf + dyf*dyf);
+ dxf /= len;
+ dyf /= len;
}
computeOffset(dxs, dys, lineWidth2, offset[0]);
@@ -822,20 +822,20 @@
final float my = offset[0][1];
drawJoin(cdx, cdy, cx0, cy0, dxs, dys, cmx, cmy, mx, my);
- int nSplits = findSubdivPoints(middle[0], subdivTs, type,lineWidth2);
+ int nSplits = findSubdivPoints(middle, subdivTs, type, lineWidth2);
int kind = 0;
- Iterator<float[]> it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
+ Iterator<Integer> it = Curve.breakPtsAtTs(middle, type, subdivTs, nSplits);
while(it.hasNext()) {
- float[] curCurve = it.next();
+ int curCurveOff = it.next();
kind = 0;
switch (type) {
case 8:
- kind = computeOffsetCubic(curCurve, 0, lp, rp);
+ kind = computeOffsetCubic(middle, curCurveOff, lp, rp);
break;
case 6:
- kind = computeOffsetQuad(curCurve, 0, lp, rp);
+ kind = computeOffsetQuad(middle, curCurveOff, lp, rp);
break;
}
if (kind != 0) {
@@ -871,8 +871,7 @@
// to get good offset curves a distance of w away from the middle curve.
// Stores the points in ts, and returns how many of them there were.
private static Curve c = new Curve();
- private static int findSubdivPoints(float[] pts, float[] ts,
- final int type, final float w)
+ private static int findSubdivPoints(float[] pts, float[] ts, final int type, final float w)
{
final float x12 = pts[2] - pts[0];
final float y12 = pts[3] - pts[1];
@@ -919,6 +918,7 @@
// now we must subdivide at points where one of the offset curves will have
// a cusp. This happens at ts where the radius of curvature is equal to w.
ret += c.rootsOfROCMinusW(ts, ret, w, 0.0001f);
+
ret = Helpers.filterOutNotInAB(ts, 0, ret, 0.0001f, 0.9999f);
Helpers.isort(ts, 0, ret);
return ret;
@@ -928,10 +928,10 @@
float x2, float y2,
float x3, float y3)
{
- middle[0][0] = cx0; middle[0][1] = cy0;
- middle[0][2] = x1; middle[0][3] = y1;
- middle[0][4] = x2; middle[0][5] = y2;
- middle[0][6] = x3; middle[0][7] = y3;
+ middle[0] = cx0; middle[1] = cy0;
+ middle[2] = x1; middle[3] = y1;
+ middle[4] = x2; middle[5] = y2;
+ middle[6] = x3; middle[7] = y3;
somethingTo(8);
}
@@ -940,9 +940,9 @@
}
@Override public void quadTo(float x1, float y1, float x2, float y2) {
- middle[0][0] = cx0; middle[0][1] = cy0;
- middle[0][2] = x1; middle[0][3] = y1;
- middle[0][4] = x2; middle[0][5] = y2;
+ middle[0] = cx0; middle[1] = cy0;
+ middle[2] = x1; middle[3] = y1;
+ middle[4] = x2; middle[5] = y2;
somethingTo(6);
}
--- a/jdk/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/java2d/pisces/TransformingPathConsumer2D.java Fri Feb 18 12:04:36 2011 -0800
@@ -28,7 +28,7 @@
import sun.awt.geom.PathConsumer2D;
import java.awt.geom.AffineTransform;
-public class TransformingPathConsumer2D {
+final class TransformingPathConsumer2D {
public static PathConsumer2D
transformConsumer(PathConsumer2D out,
AffineTransform at)
@@ -50,17 +50,72 @@
return new TranslateFilter(out, Mxt, Myt);
}
} else {
- return new ScaleFilter(out, Mxx, Myy, Mxt, Myt);
+ if (Mxt == 0f && Myt == 0f) {
+ return new DeltaScaleFilter(out, Mxx, Myy);
+ } else {
+ return new ScaleFilter(out, Mxx, Myy, Mxt, Myt);
+ }
}
+ } else if (Mxt == 0f && Myt == 0f) {
+ return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy);
} else {
return new TransformFilter(out, Mxx, Mxy, Mxt, Myx, Myy, Myt);
}
}
- static class TranslateFilter implements PathConsumer2D {
- PathConsumer2D out;
- float tx;
- float ty;
+ public static PathConsumer2D
+ deltaTransformConsumer(PathConsumer2D out,
+ AffineTransform at)
+ {
+ if (at == null) {
+ return out;
+ }
+ float Mxx = (float) at.getScaleX();
+ float Mxy = (float) at.getShearX();
+ float Myx = (float) at.getShearY();
+ float Myy = (float) at.getScaleY();
+ if (Mxy == 0f && Myx == 0f) {
+ if (Mxx == 1f && Myy == 1f) {
+ return out;
+ } else {
+ return new DeltaScaleFilter(out, Mxx, Myy);
+ }
+ } else {
+ return new DeltaTransformFilter(out, Mxx, Mxy, Myx, Myy);
+ }
+ }
+
+ public static PathConsumer2D
+ inverseDeltaTransformConsumer(PathConsumer2D out,
+ AffineTransform at)
+ {
+ if (at == null) {
+ return out;
+ }
+ float Mxx = (float) at.getScaleX();
+ float Mxy = (float) at.getShearX();
+ float Myx = (float) at.getShearY();
+ float Myy = (float) at.getScaleY();
+ if (Mxy == 0f && Myx == 0f) {
+ if (Mxx == 1f && Myy == 1f) {
+ return out;
+ } else {
+ return new DeltaScaleFilter(out, 1.0f/Mxx, 1.0f/Myy);
+ }
+ } else {
+ float det = Mxx * Myy - Mxy * Myx;
+ return new DeltaTransformFilter(out,
+ Myy / det,
+ -Mxy / det,
+ -Myx / det,
+ Mxx / det);
+ }
+ }
+
+ static final class TranslateFilter implements PathConsumer2D {
+ private final PathConsumer2D out;
+ private final float tx;
+ private final float ty;
TranslateFilter(PathConsumer2D out,
float tx, float ty)
@@ -107,12 +162,12 @@
}
}
- static class ScaleFilter implements PathConsumer2D {
- PathConsumer2D out;
- float sx;
- float sy;
- float tx;
- float ty;
+ static final class ScaleFilter implements PathConsumer2D {
+ private final PathConsumer2D out;
+ private final float sx;
+ private final float sy;
+ private final float tx;
+ private final float ty;
ScaleFilter(PathConsumer2D out,
float sx, float sy, float tx, float ty)
@@ -161,14 +216,14 @@
}
}
- static class TransformFilter implements PathConsumer2D {
- PathConsumer2D out;
- float Mxx;
- float Mxy;
- float Mxt;
- float Myx;
- float Myy;
- float Myt;
+ static final class TransformFilter implements PathConsumer2D {
+ private final PathConsumer2D out;
+ private final float Mxx;
+ private final float Mxy;
+ private final float Mxt;
+ private final float Myx;
+ private final float Myy;
+ private final float Myt;
TransformFilter(PathConsumer2D out,
float Mxx, float Mxy, float Mxt,
@@ -226,4 +281,113 @@
return 0;
}
}
+
+ static final class DeltaScaleFilter implements PathConsumer2D {
+ private final float sx, sy;
+ private final PathConsumer2D out;
+
+ public DeltaScaleFilter(PathConsumer2D out, float Mxx, float Myy) {
+ sx = Mxx;
+ sy = Myy;
+ this.out = out;
+ }
+
+ public void moveTo(float x0, float y0) {
+ out.moveTo(x0 * sx, y0 * sy);
+ }
+
+ public void lineTo(float x1, float y1) {
+ out.lineTo(x1 * sx, y1 * sy);
+ }
+
+ public void quadTo(float x1, float y1,
+ float x2, float y2)
+ {
+ out.quadTo(x1 * sx, y1 * sy,
+ x2 * sx, y2 * sy);
+ }
+
+ public void curveTo(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3)
+ {
+ out.curveTo(x1 * sx, y1 * sy,
+ x2 * sx, y2 * sy,
+ x3 * sx, y3 * sy);
+ }
+
+ public void closePath() {
+ out.closePath();
+ }
+
+ public void pathDone() {
+ out.pathDone();
+ }
+
+ public long getNativeConsumer() {
+ return 0;
+ }
+ }
+
+ static final class DeltaTransformFilter implements PathConsumer2D {
+ private PathConsumer2D out;
+ private final float Mxx;
+ private final float Mxy;
+ private final float Myx;
+ private final float Myy;
+
+ DeltaTransformFilter(PathConsumer2D out,
+ float Mxx, float Mxy,
+ float Myx, float Myy)
+ {
+ this.out = out;
+ this.Mxx = Mxx;
+ this.Mxy = Mxy;
+ this.Myx = Myx;
+ this.Myy = Myy;
+ }
+
+ public void moveTo(float x0, float y0) {
+ out.moveTo(x0 * Mxx + y0 * Mxy,
+ x0 * Myx + y0 * Myy);
+ }
+
+ public void lineTo(float x1, float y1) {
+ out.lineTo(x1 * Mxx + y1 * Mxy,
+ x1 * Myx + y1 * Myy);
+ }
+
+ public void quadTo(float x1, float y1,
+ float x2, float y2)
+ {
+ out.quadTo(x1 * Mxx + y1 * Mxy,
+ x1 * Myx + y1 * Myy,
+ x2 * Mxx + y2 * Mxy,
+ x2 * Myx + y2 * Myy);
+ }
+
+ public void curveTo(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3)
+ {
+ out.curveTo(x1 * Mxx + y1 * Mxy,
+ x1 * Myx + y1 * Myy,
+ x2 * Mxx + y2 * Mxy,
+ x2 * Myx + y2 * Myy,
+ x3 * Mxx + y3 * Mxy,
+ x3 * Myx + y3 * Myy);
+ }
+
+ public void closePath() {
+ out.closePath();
+ }
+
+ public void pathDone() {
+ out.pathDone();
+ }
+
+ public long getNativeConsumer() {
+ return 0;
+ }
+ }
}
--- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java Fri Feb 18 12:04:36 2011 -0800
@@ -401,6 +401,14 @@
}
}
+
+ // From src/share/bin/java.c:
+ // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR };
+
+ private static final int LM_UNKNOWN = 0;
+ private static final int LM_CLASS = 1;
+ private static final int LM_JAR = 2;
+
/**
* This method does the following:
* 1. gets the classname from a Jar's manifest, if necessary
@@ -420,24 +428,40 @@
* @return
* @throws java.io.IOException
*/
- public static Object checkAndLoadMain(boolean printToStderr,
- boolean isJar, String name) throws IOException {
+ public static Class<?> checkAndLoadMain(boolean printToStderr,
+ int mode,
+ String what) throws IOException
+ {
+
+ ClassLoader ld = ClassLoader.getSystemClassLoader();
+
// get the class name
- String classname = (isJar) ? getMainClassFromJar(name) : name;
- classname = classname.replace('/', '.');
- ClassLoader loader = ClassLoader.getSystemClassLoader();
- Class<?> clazz = null;
+ String cn = null;
+ switch (mode) {
+ case LM_CLASS:
+ cn = what;
+ break;
+ case LM_JAR:
+ cn = getMainClassFromJar(what);
+ break;
+ default:
+ throw new InternalError("" + mode + ": Unknown launch mode");
+ }
+ cn = cn.replace('/', '.');
+
PrintStream ostream = (printToStderr) ? System.err : System.out;
+ Class<?> c = null;
try {
- clazz = loader.loadClass(classname);
+ c = ld.loadClass(cn);
} catch (ClassNotFoundException cnfe) {
- ostream.println(getLocalizedMessage("java.launcher.cls.error1", classname));
- NoClassDefFoundError ncdfe = new NoClassDefFoundError(classname);
+ ostream.println(getLocalizedMessage("java.launcher.cls.error1",
+ cn));
+ NoClassDefFoundError ncdfe = new NoClassDefFoundError(cn);
ncdfe.initCause(cnfe);
throw ncdfe;
}
- signatureDiagnostic(ostream, clazz);
- return clazz;
+ signatureDiagnostic(ostream, c);
+ return c;
}
static void signatureDiagnostic(PrintStream ostream, Class<?> clazz) {
--- a/jdk/src/share/classes/sun/management/ThreadImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/management/ThreadImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -25,7 +25,6 @@
package sun.management;
-import java.lang.management.ThreadMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
@@ -39,13 +38,14 @@
* ManagementFactory.getThreadMXBean() returns an instance
* of this class.
*/
-class ThreadImpl implements ThreadMXBean {
+class ThreadImpl implements com.sun.management.ThreadMXBean {
private final VMManagement jvm;
// default for thread contention monitoring is disabled.
private boolean contentionMonitoringEnabled = false;
private boolean cpuTimeEnabled;
+ private boolean allocatedMemoryEnabled;
/**
* Constructor of ThreadImpl class.
@@ -53,6 +53,7 @@
ThreadImpl(VMManagement vm) {
this.jvm = vm;
this.cpuTimeEnabled = jvm.isThreadCpuTimeEnabled();
+ this.allocatedMemoryEnabled = jvm.isThreadAllocatedMemoryEnabled();
}
public int getThreadCount() {
@@ -91,6 +92,10 @@
return jvm.isCurrentThreadCpuTimeSupported();
}
+ public boolean isThreadAllocatedMemorySupported() {
+ return jvm.isThreadAllocatedMemorySupported();
+ }
+
public boolean isThreadCpuTimeEnabled() {
if (!isThreadCpuTimeSupported() &&
!isCurrentThreadCpuTimeSupported()) {
@@ -100,6 +105,14 @@
return cpuTimeEnabled;
}
+ public boolean isThreadAllocatedMemoryEnabled() {
+ if (!isThreadAllocatedMemorySupported()) {
+ throw new UnsupportedOperationException(
+ "Thread allocated memory measurement is not supported");
+ }
+ return allocatedMemoryEnabled;
+ }
+
public long[] getAllThreadIds() {
Util.checkMonitorAccess();
@@ -114,11 +127,6 @@
}
public ThreadInfo getThreadInfo(long id) {
- if (id <= 0) {
- throw new IllegalArgumentException(
- "Invalid thread ID parameter: " + id);
- }
-
long[] ids = new long[1];
ids[0] = id;
final ThreadInfo[] infos = getThreadInfo(ids, 0);
@@ -126,15 +134,6 @@
}
public ThreadInfo getThreadInfo(long id, int maxDepth) {
- if (id <= 0) {
- throw new IllegalArgumentException(
- "Invalid thread ID parameter: " + id);
- }
- if (maxDepth < 0) {
- throw new IllegalArgumentException(
- "Invalid maxDepth parameter: " + maxDepth);
- }
-
long[] ids = new long[1];
ids[0] = id;
final ThreadInfo[] infos = getThreadInfo(ids, maxDepth);
@@ -145,11 +144,22 @@
return getThreadInfo(ids, 0);
}
- public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
+ private void verifyThreadIds(long[] ids) {
if (ids == null) {
throw new NullPointerException("Null ids parameter.");
}
+ for (int i = 0; i < ids.length; i++) {
+ if (ids[i] <= 0) {
+ throw new IllegalArgumentException(
+ "Invalid thread ID parameter: " + ids[i]);
+ }
+ }
+ }
+
+ public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
+ verifyThreadIds(ids);
+
if (maxDepth < 0) {
throw new IllegalArgumentException(
"Invalid maxDepth parameter: " + maxDepth);
@@ -157,17 +167,15 @@
Util.checkMonitorAccess();
- ThreadInfo[] infos = new ThreadInfo[ids.length];
+ ThreadInfo[] infos = new ThreadInfo[ids.length]; // nulls
if (maxDepth == Integer.MAX_VALUE) {
- getThreadInfo0(ids, -1, infos);
+ getThreadInfo1(ids, -1, infos);
} else {
- getThreadInfo0(ids, maxDepth, infos);
+ getThreadInfo1(ids, maxDepth, infos);
}
return infos;
}
-
-
public void setThreadContentionMonitoringEnabled(boolean enable) {
if (!isThreadContentionMonitoringSupported()) {
throw new UnsupportedOperationException(
@@ -192,69 +200,32 @@
}
}
- public long getCurrentThreadCpuTime() {
+ private boolean verifyCurrentThreadCpuTime() {
// check if Thread CPU time measurement is supported.
if (!isCurrentThreadCpuTimeSupported()) {
throw new UnsupportedOperationException(
"Current thread CPU time measurement is not supported.");
}
+ return isThreadCpuTimeEnabled();
+ }
- if (!isThreadCpuTimeEnabled()) {
- return -1;
+ public long getCurrentThreadCpuTime() {
+ if (verifyCurrentThreadCpuTime()) {
+ return getThreadTotalCpuTime0(0);
}
-
- return getThreadTotalCpuTime0(0);
+ return -1;
}
public long getThreadCpuTime(long id) {
- // check if Thread CPU time measurement is supported.
- if (!isThreadCpuTimeSupported() &&
- !isCurrentThreadCpuTimeSupported()) {
- throw new UnsupportedOperationException(
- "Thread CPU Time Measurement is not supported.");
- }
-
- if (!isThreadCpuTimeSupported()) {
- // support current thread only
- if (id != Thread.currentThread().getId()) {
- throw new UnsupportedOperationException(
- "Thread CPU Time Measurement is only supported" +
- " for the current thread.");
- }
- }
-
- if (id <= 0) {
- throw new IllegalArgumentException(
- "Invalid thread ID parameter: " + id);
- }
-
- if (!isThreadCpuTimeEnabled()) {
- return -1;
- }
-
- if (id == Thread.currentThread().getId()) {
- // current thread
- return getThreadTotalCpuTime0(0);
- } else {
- return getThreadTotalCpuTime0(id);
- }
+ long[] ids = new long[1];
+ ids[0] = id;
+ final long[] times = getThreadCpuTime(ids);
+ return times[0];
}
- public long getCurrentThreadUserTime() {
- // check if Thread CPU time measurement is supported.
- if (!isCurrentThreadCpuTimeSupported()) {
- throw new UnsupportedOperationException(
- "Current thread CPU time measurement is not supported.");
- }
+ private boolean verifyThreadCpuTime(long[] ids) {
+ verifyThreadIds(ids);
- if (!isThreadCpuTimeEnabled()) {
- return -1;
- }
-
- return getThreadUserCpuTime0(0);
- }
-
- public long getThreadUserTime(long id) {
// check if Thread CPU time measurement is supported.
if (!isThreadCpuTimeSupported() &&
!isCurrentThreadCpuTimeSupported()) {
@@ -264,30 +235,73 @@
if (!isThreadCpuTimeSupported()) {
// support current thread only
- if (id != Thread.currentThread().getId()) {
- throw new UnsupportedOperationException(
- "Thread CPU time measurement is only supported" +
- " for the current thread.");
+ for (int i = 0; i < ids.length; i++) {
+ if (ids[i] != Thread.currentThread().getId()) {
+ throw new UnsupportedOperationException(
+ "Thread CPU time measurement is only supported" +
+ " for the current thread.");
+ }
}
}
- if (id <= 0) {
- throw new IllegalArgumentException(
- "Invalid thread ID parameter: " + id);
- }
+ return isThreadCpuTimeEnabled();
+ }
+
+ public long[] getThreadCpuTime(long[] ids) {
+ boolean verified = verifyThreadCpuTime(ids);
+
+ int length = ids.length;
+ long[] times = new long[length];
+ java.util.Arrays.fill(times, -1);
- if (!isThreadCpuTimeEnabled()) {
- return -1;
+ if (verified) {
+ if (length == 1) {
+ long id = ids[0];
+ if (id == Thread.currentThread().getId()) {
+ id = 0;
+ }
+ times[0] = getThreadTotalCpuTime0(id);
+ } else {
+ getThreadTotalCpuTime1(ids, times);
+ }
}
-
- if (id == Thread.currentThread().getId()) {
- // current thread
- return getThreadUserCpuTime0(0);
- } else {
- return getThreadUserCpuTime0(id);
- }
+ return times;
}
+ public long getCurrentThreadUserTime() {
+ if (verifyCurrentThreadCpuTime()) {
+ return getThreadUserCpuTime0(0);
+ }
+ return -1;
+ }
+
+ public long getThreadUserTime(long id) {
+ long[] ids = new long[1];
+ ids[0] = id;
+ final long[] times = getThreadUserTime(ids);
+ return times[0];
+ }
+
+ public long[] getThreadUserTime(long[] ids) {
+ boolean verified = verifyThreadCpuTime(ids);
+
+ int length = ids.length;
+ long[] times = new long[length];
+ java.util.Arrays.fill(times, -1);
+
+ if (verified) {
+ if (length == 1) {
+ long id = ids[0];
+ if (id == Thread.currentThread().getId()) {
+ id = 0;
+ }
+ times[0] = getThreadUserCpuTime0(id);
+ } else {
+ getThreadUserCpuTime1(ids, times);
+ }
+ }
+ return times;
+ }
public void setThreadCpuTimeEnabled(boolean enable) {
if (!isThreadCpuTimeSupported() &&
@@ -299,13 +313,60 @@
Util.checkControlAccess();
synchronized (this) {
if (cpuTimeEnabled != enable) {
- // update VM of the state change
+ // notify VM of the state change
setThreadCpuTimeEnabled0(enable);
cpuTimeEnabled = enable;
}
}
}
+ public long getThreadAllocatedBytes(long id) {
+ long[] ids = new long[1];
+ ids[0] = id;
+ final long[] sizes = getThreadAllocatedBytes(ids);
+ return sizes[0];
+ }
+
+ private boolean verifyThreadAllocatedMemory(long[] ids) {
+ verifyThreadIds(ids);
+
+ // check if Thread allocated memory measurement is supported.
+ if (!isThreadAllocatedMemorySupported()) {
+ throw new UnsupportedOperationException(
+ "Thread allocated memory measurement is not supported.");
+ }
+
+ return isThreadAllocatedMemoryEnabled();
+ }
+
+ public long[] getThreadAllocatedBytes(long[] ids) {
+ boolean verified = verifyThreadAllocatedMemory(ids);
+
+ long[] sizes = new long[ids.length];
+ java.util.Arrays.fill(sizes, -1);
+
+ if (verified) {
+ getThreadAllocatedMemory1(ids, sizes);
+ }
+ return sizes;
+ }
+
+ public void setThreadAllocatedMemoryEnabled(boolean enable) {
+ if (!isThreadAllocatedMemorySupported()) {
+ throw new UnsupportedOperationException(
+ "Thread allocated memory measurement is not supported.");
+ }
+
+ Util.checkControlAccess();
+ synchronized (this) {
+ if (allocatedMemoryEnabled != enable) {
+ // notify VM of the state change
+ setThreadAllocatedMemoryEnabled0(enable);
+ allocatedMemoryEnabled = enable;
+ }
+ }
+ }
+
public long[] findMonitorDeadlockedThreads() {
Util.checkMonitorAccess();
@@ -356,49 +417,47 @@
return jvm.isSynchronizerUsageSupported();
}
- public ThreadInfo[] getThreadInfo(long[] ids,
- boolean lockedMonitors,
- boolean lockedSynchronizers) {
- if (ids == null) {
- throw new NullPointerException("Null ids parameter.");
- }
-
+ private void verifyDumpThreads(boolean lockedMonitors,
+ boolean lockedSynchronizers) {
if (lockedMonitors && !isObjectMonitorUsageSupported()) {
throw new UnsupportedOperationException(
"Monitoring of Object Monitor Usage is not supported.");
}
+
if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
throw new UnsupportedOperationException(
"Monitoring of Synchronizer Usage is not supported.");
}
Util.checkMonitorAccess();
+ }
+
+ public ThreadInfo[] getThreadInfo(long[] ids,
+ boolean lockedMonitors,
+ boolean lockedSynchronizers) {
+ verifyThreadIds(ids);
+ verifyDumpThreads(lockedMonitors, lockedSynchronizers);
return dumpThreads0(ids, lockedMonitors, lockedSynchronizers);
}
-
- public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
- if (lockedMonitors && !isObjectMonitorUsageSupported()) {
- throw new UnsupportedOperationException(
- "Monitoring of Object Monitor Usage is not supported.");
- }
- if (lockedSynchronizers && !isSynchronizerUsageSupported()) {
- throw new UnsupportedOperationException(
- "Monitoring of Synchronizer Usage is not supported.");
- }
-
- Util.checkMonitorAccess();
+ public ThreadInfo[] dumpAllThreads(boolean lockedMonitors,
+ boolean lockedSynchronizers) {
+ verifyDumpThreads(lockedMonitors, lockedSynchronizers);
return dumpThreads0(null, lockedMonitors, lockedSynchronizers);
}
// VM support where maxDepth == -1 to request entire stack dump
private static native Thread[] getThreads();
- private static native void getThreadInfo0(long[] ids,
+ private static native void getThreadInfo1(long[] ids,
int maxDepth,
ThreadInfo[] result);
private static native long getThreadTotalCpuTime0(long id);
+ private static native void getThreadTotalCpuTime1(long[] ids, long[] result);
private static native long getThreadUserCpuTime0(long id);
+ private static native void getThreadUserCpuTime1(long[] ids, long[] result);
+ private static native void getThreadAllocatedMemory1(long[] ids, long[] result);
private static native void setThreadCpuTimeEnabled0(boolean enable);
+ private static native void setThreadAllocatedMemoryEnabled0(boolean enable);
private static native void setThreadContentionMonitoringEnabled0(boolean enable);
private static native Thread[] findMonitorDeadlockedThreads0();
private static native Thread[] findDeadlockedThreads0();
--- a/jdk/src/share/classes/sun/management/VMManagement.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/management/VMManagement.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -43,6 +43,8 @@
public boolean isBootClassPathSupported();
public boolean isObjectMonitorUsageSupported();
public boolean isSynchronizerUsageSupported();
+ public boolean isThreadAllocatedMemorySupported();
+ public boolean isThreadAllocatedMemoryEnabled();
// Class Loading Subsystem
public long getTotalClassCount();
--- a/jdk/src/share/classes/sun/management/VMManagementImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/management/VMManagementImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -55,6 +55,7 @@
private static boolean bootClassPathSupport;
private static boolean objectMonitorUsageSupport;
private static boolean synchronizerUsageSupport;
+ private static boolean threadAllocatedMemorySupport;
static {
version = getVersion0();
@@ -95,9 +96,13 @@
return synchronizerUsageSupport;
}
+ public boolean isThreadAllocatedMemorySupported() {
+ return threadAllocatedMemorySupport;
+ }
+
public native boolean isThreadContentionMonitoringEnabled();
public native boolean isThreadCpuTimeEnabled();
-
+ public native boolean isThreadAllocatedMemoryEnabled();
// Class Loading Subsystem
public int getLoadedClassCount() {
--- a/jdk/src/share/classes/sun/misc/URLClassPath.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/misc/URLClassPath.java Fri Feb 18 12:04:36 2011 -0800
@@ -466,6 +466,7 @@
*/
private static class Loader implements Closeable {
private final URL base;
+ private JarFile jarfile; // if this points to a jar file
/*
* Creates a new Loader for the specified URL.
@@ -530,6 +531,17 @@
}
uc = url.openConnection();
InputStream in = uc.getInputStream();
+ if (uc instanceof JarURLConnection) {
+ /* JarURLConnection.getInputStream() returns a separate
+ * instance on each call. So we have to close this here.
+ * The jar file cache will keep the file open.
+ * Also, need to remember the jar file so it can be closed
+ * in a hurry.
+ */
+ JarURLConnection juc = (JarURLConnection)uc;
+ jarfile = juc.getJarFile();
+ in.close();
+ }
} catch (Exception e) {
return null;
}
@@ -559,7 +571,11 @@
* close this loader and release all resources
* method overridden in sub-classes
*/
- public void close () throws IOException {}
+ public void close () throws IOException {
+ if (jarfile != null) {
+ jarfile.close();
+ }
+ }
/*
* Returns the local class path for this loader, or null if none.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/SocksProxy.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,49 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package sun.net;
+
+import java.net.Proxy;
+import java.net.SocketAddress;
+
+/**
+ * Proxy wrapper class so we can determine the socks protocol version.
+ */
+public final class SocksProxy extends Proxy {
+ private final int version;
+
+ private SocksProxy(SocketAddress addr, int version) {
+ super(Proxy.Type.SOCKS, addr);
+ this.version = version;
+ }
+
+ public static SocksProxy create(SocketAddress addr, int version) {
+ return new SocksProxy(addr, version);
+ }
+
+ public int protocolVersion() {
+ return version;
+ }
+}
--- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java Fri Feb 18 12:04:36 2011 -0800
@@ -25,13 +25,20 @@
package sun.net.spi;
-import sun.net.NetProperties;
-import java.net.*;
-import java.util.*;
-import java.io.*;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.io.IOException;
import sun.misc.RegexpPool;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import sun.net.NetProperties;
+import sun.net.SocksProxy;
/**
* Supports proxy settings using system properties This proxy selector
@@ -75,6 +82,8 @@
{"socket", "socksProxy"}
};
+ private static final String SOCKS_PROXY_VERSION = "socksProxyVersion";
+
private static boolean hasSystemProxies = false;
static {
@@ -287,7 +296,8 @@
saddr = InetSocketAddress.createUnresolved(phost, pport);
// Socks is *always* the last on the list.
if (j == (props[i].length - 1)) {
- return new Proxy(Proxy.Type.SOCKS, saddr);
+ int version = NetProperties.getInteger(SOCKS_PROXY_VERSION, 5).intValue();
+ return SocksProxy.create(saddr, version);
} else {
return new Proxy(Proxy.Type.HTTP, saddr);
}
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java Fri Feb 18 12:04:36 2011 -0800
@@ -267,7 +267,7 @@
/* return a still valid, unused HttpClient */
synchronized void put(HttpClient h) {
- if (size() > KeepAliveCache.getMaxConnections()) {
+ if (size() >= KeepAliveCache.getMaxConnections()) {
h.closeServer(); // otherwise the connection remains in limbo
} else {
push(new KeepAliveEntry(h, System.currentTimeMillis()));
--- a/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/acl/AclEntryImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -37,7 +37,7 @@
*/
public class AclEntryImpl implements AclEntry {
private Principal user = null;
- private Vector<Permission> permissionSet = new Vector<Permission>(10, 10);
+ private Vector<Permission> permissionSet = new Vector<>(10, 10);
private boolean negative = false;
/**
--- a/jdk/src/share/classes/sun/security/acl/AclImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/acl/AclImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -41,15 +41,15 @@
// or principal.
//
private Hashtable<Principal, AclEntry> allowedUsersTable =
- new Hashtable<Principal, AclEntry>(23);
+ new Hashtable<>(23);
private Hashtable<Principal, AclEntry> allowedGroupsTable =
- new Hashtable<Principal, AclEntry>(23);
+ new Hashtable<>(23);
private Hashtable<Principal, AclEntry> deniedUsersTable =
- new Hashtable<Principal, AclEntry>(23);
+ new Hashtable<>(23);
private Hashtable<Principal, AclEntry> deniedGroupsTable =
- new Hashtable<Principal, AclEntry>(23);
+ new Hashtable<>(23);
private String aclName = null;
- private Vector<Permission> zeroSet = new Vector<Permission>(1,1);
+ private Vector<Permission> zeroSet = new Vector<>(1,1);
/**
@@ -294,7 +294,7 @@
//
private static Enumeration<Permission> union(Enumeration<Permission> e1,
Enumeration<Permission> e2) {
- Vector<Permission> v = new Vector<Permission>(20, 20);
+ Vector<Permission> v = new Vector<>(20, 20);
while (e1.hasMoreElements())
v.addElement(e1.nextElement());
@@ -313,7 +313,7 @@
//
private Enumeration<Permission> subtract(Enumeration<Permission> e1,
Enumeration<Permission> e2) {
- Vector<Permission> v = new Vector<Permission>(20, 20);
+ Vector<Permission> v = new Vector<>(20, 20);
while (e1.hasMoreElements())
v.addElement(e1.nextElement());
--- a/jdk/src/share/classes/sun/security/acl/GroupImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/acl/GroupImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -34,7 +34,7 @@
* @author Satish Dharmaraj
*/
public class GroupImpl implements Group {
- private Vector<Principal> groupMembers = new Vector<Principal>(50, 100);
+ private Vector<Principal> groupMembers = new Vector<>(50, 100);
private String group;
/**
@@ -131,7 +131,7 @@
if (groupMembers.contains(member)) {
return true;
} else {
- Vector<Group> alreadySeen = new Vector<Group>(10);
+ Vector<Group> alreadySeen = new Vector<>(10);
return isMemberRecurse(member, alreadySeen);
}
}
--- a/jdk/src/share/classes/sun/security/jca/ProviderList.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/jca/ProviderList.java Fri Feb 18 12:04:36 2011 -0800
@@ -96,7 +96,7 @@
if (providerList.getProvider(p.getName()) != null) {
return providerList;
}
- List<ProviderConfig> list = new ArrayList<ProviderConfig>
+ List<ProviderConfig> list = new ArrayList<>
(Arrays.asList(providerList.configs));
int n = list.size();
if ((position < 0) || (position > n)) {
@@ -160,7 +160,7 @@
* Return a new ProviderList parsed from the java.security Properties.
*/
private ProviderList() {
- List<ProviderConfig> configList = new ArrayList<ProviderConfig>();
+ List<ProviderConfig> configList = new ArrayList<>();
for (int i = 1; true; i++) {
String entry = Security.getProperty("security.provider." + i);
if (entry == null) {
@@ -200,7 +200,7 @@
* possible recursion and deadlock during verification.
*/
ProviderList getJarList(String[] jarClassNames) {
- List<ProviderConfig> newConfigs = new ArrayList<ProviderConfig>();
+ List<ProviderConfig> newConfigs = new ArrayList<>();
for (String className : jarClassNames) {
ProviderConfig newConfig = new ProviderConfig(className);
for (ProviderConfig config : configs) {
@@ -356,7 +356,7 @@
*/
@Deprecated
public List<Service> getServices(String type, List<String> algorithms) {
- List<ServiceId> ids = new ArrayList<ServiceId>();
+ List<ServiceId> ids = new ArrayList<>();
for (String alg : algorithms) {
ids.add(new ServiceId(type, alg));
}
--- a/jdk/src/share/classes/sun/security/jca/Providers.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/jca/Providers.java Fri Feb 18 12:04:36 2011 -0800
@@ -40,7 +40,7 @@
public class Providers {
private static final ThreadLocal<ProviderList> threadLists =
- new InheritableThreadLocal<ProviderList>();
+ new InheritableThreadLocal<>();
// number of threads currently using thread-local provider lists
// tracked to allow an optimization if == 0
--- a/jdk/src/share/classes/sun/security/krb5/Config.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/Config.java Fri Feb 18 12:04:36 2011 -0800
@@ -528,7 +528,7 @@
}
})));
String Line;
- Vector<String> v = new Vector<String> ();
+ Vector<String> v = new Vector<>();
String previous = null;
while ((Line = br.readLine()) != null) {
// ignore comments and blank line in the configuration file.
@@ -589,7 +589,7 @@
throw new KrbException("I/O error while reading" +
" configuration file.");
}
- Hashtable<String,Object> table = new Hashtable<String,Object> ();
+ Hashtable<String,Object> table = new Hashtable<>();
for (int i = 0; i < v.size(); i++) {
String line = v.elementAt(i).trim();
if (line.equalsIgnoreCase("[realms]")) {
@@ -598,7 +598,7 @@
if ((count == v.size()) ||
(v.elementAt(count).startsWith("["))) {
Hashtable<String,Hashtable<String,Vector<String>>> temp =
- new Hashtable<String,Hashtable<String,Vector<String>>>();
+ new Hashtable<>();
temp = parseRealmField(v, i + 1, count);
table.put("realms", temp);
i = count - 1;
@@ -611,7 +611,7 @@
if ((count == v.size()) ||
(v.elementAt(count).startsWith("["))) {
Hashtable<String,Hashtable<String,Vector<String>>> temp =
- new Hashtable<String,Hashtable<String,Vector<String>>>();
+ new Hashtable<>();
temp = parseRealmField(v, i + 1, count);
table.put("capaths", temp);
i = count - 1;
@@ -729,7 +729,7 @@
* Parses key-value pairs under a stanza name.
*/
private Hashtable<String,String> parseField(Vector<String> v, int start, int end) {
- Hashtable<String,String> table = new Hashtable<String,String> ();
+ Hashtable<String,String> table = new Hashtable<>();
String line;
for (int i = start; i < end; i++) {
line = v.elementAt(i);
@@ -751,7 +751,7 @@
* information for the realm given within a pair of braces.
*/
private Hashtable<String,Hashtable<String,Vector<String>>> parseRealmField(Vector<String> v, int start, int end) {
- Hashtable<String,Hashtable<String,Vector<String>>> table = new Hashtable<String,Hashtable<String,Vector<String>>> ();
+ Hashtable<String,Hashtable<String,Vector<String>>> table = new Hashtable<>();
String line;
for (int i = start; i < end; i++) {
line = v.elementAt(i).trim();
@@ -791,10 +791,9 @@
* Parses key-value pairs within each braces under [realms].
*/
private Hashtable<String,Vector<String>> parseRealmFieldEx(Vector<String> v, int start, int end) {
- Hashtable<String,Vector<String>> table =
- new Hashtable<String,Vector<String>> ();
- Vector<String> keyVector = new Vector<String> ();
- Vector<String> nameVector = new Vector<String> ();
+ Hashtable<String,Vector<String>> table = new Hashtable<>();
+ Vector<String> keyVector = new Vector<>();
+ Vector<String> nameVector = new Vector<>();
String line = "";
String key;
for (int i = start; i < end; i++) {
@@ -899,7 +898,7 @@
}
st = new StringTokenizer(default_enctypes, delim);
int len = st.countTokens();
- ArrayList<Integer> ls = new ArrayList<Integer> (len);
+ ArrayList<Integer> ls = new ArrayList<>(len);
int type;
for (int i = 0; i < len; i++) {
type = getType(st.nextToken());
--- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java Fri Feb 18 12:04:36 2011 -0800
@@ -462,7 +462,7 @@
*/
static class KdcAccessibility {
// Known bad KDCs
- private static Set<String> bads = new HashSet<String>();
+ private static Set<String> bads = new HashSet<>();
private static synchronized void addBad(String kdc) {
if (DEBUG) {
@@ -492,9 +492,9 @@
// Returns a preferred KDC list by putting the bad ones at the end
private static synchronized String[] list(String kdcList) {
StringTokenizer st = new StringTokenizer(kdcList);
- List<String> list = new ArrayList<String>();
+ List<String> list = new ArrayList<>();
if (badPolicy == BpType.TRY_LAST) {
- List<String> badkdcs = new ArrayList<String>();
+ List<String> badkdcs = new ArrayList<>();
while (st.hasMoreTokens()) {
String t = st.nextToken();
if (bads.contains(t)) badkdcs.add(t);
--- a/jdk/src/share/classes/sun/security/krb5/PrincipalName.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/PrincipalName.java Fri Feb 18 12:04:36 2011 -0800
@@ -244,7 +244,7 @@
if (subDer.getTag() != DerValue.tag_SequenceOf) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
- Vector<String> v = new Vector<String> ();
+ Vector<String> v = new Vector<>();
DerValue subSubDer;
while(subDer.getData().available() > 0) {
subSubDer = subDer.getData().getDerValue();
@@ -299,7 +299,7 @@
// Code repetition, realm parsed again by class Realm
protected static String[] parseName(String name) {
- Vector<String> tempStrings = new Vector<String> ();
+ Vector<String> tempStrings = new Vector<>();
String temp = name;
int i = 0;
int componentStart = 0;
--- a/jdk/src/share/classes/sun/security/krb5/Realm.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/Realm.java Fri Feb 18 12:04:36 2011 -0800
@@ -359,12 +359,12 @@
}
String tempTarget = null, tempRealm = null;
- Stack<String> iStack = new Stack<String> ();
+ Stack<String> iStack = new Stack<>();
/*
* I don't expect any more than a handful of intermediaries.
*/
- Vector<String> tempList = new Vector<String> (8, 8);
+ Vector<String> tempList = new Vector<>(8, 8);
/*
* The initiator at first location.
--- a/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/Authenticator.java Fri Feb 18 12:04:36 2011 -0800
@@ -176,7 +176,7 @@
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
- Vector<DerValue> v = new Vector<DerValue>();
+ Vector<DerValue> v = new Vector<>();
DerOutputStream temp = new DerOutputStream();
temp.putInteger(BigInteger.valueOf(authenticator_vno));
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x00), temp.toByteArray()));
--- a/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java Fri Feb 18 12:04:36 2011 -0800
@@ -99,8 +99,7 @@
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public AuthorizationData(DerValue der) throws Asn1Exception, IOException {
- Vector<AuthorizationDataEntry> v =
- new Vector<AuthorizationDataEntry>();
+ Vector<AuthorizationDataEntry> v = new Vector<>();
if (der.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/EncAPRepPart.java Fri Feb 18 12:04:36 2011 -0800
@@ -133,7 +133,7 @@
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
- Vector<DerValue> v = new Vector<DerValue>();
+ Vector<DerValue> v = new Vector<>();
DerOutputStream temp = new DerOutputStream();
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0x00), ctime.asn1Encode()));
--- a/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/HostAddresses.java Fri Feb 18 12:04:36 2011 -0800
@@ -179,7 +179,7 @@
*/
public HostAddresses(DerValue encoding)
throws Asn1Exception, IOException {
- Vector<HostAddress> tempAddresses = new Vector<HostAddress> ();
+ Vector<HostAddress> tempAddresses = new Vector<>();
DerValue der = null;
while (encoding.getData().available() > 0) {
der = encoding.getData().getDerValue();
@@ -265,8 +265,7 @@
if (addresses == null || addresses.length == 0)
return null;
- ArrayList<InetAddress> ipAddrs =
- new ArrayList<InetAddress> (addresses.length);
+ ArrayList<InetAddress> ipAddrs = new ArrayList<>(addresses.length);
for (int i = 0; i < addresses.length; i++) {
try {
--- a/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KDCReq.java Fri Feb 18 12:04:36 2011 -0800
@@ -150,7 +150,7 @@
if (subsubDer.getTag() != DerValue.tag_SequenceOf) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
- Vector<PAData> v = new Vector<PAData>();
+ Vector<PAData> v = new Vector<>();
while (subsubDer.getData().available() > 0) {
v.addElement(new PAData(subsubDer.getData().getDerValue()));
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KDCReqBody.java Fri Feb 18 12:04:36 2011 -0800
@@ -158,7 +158,7 @@
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
der = encoding.getData().getDerValue();
- Vector<Integer> v = new Vector<Integer> ();
+ Vector<Integer> v = new Vector<>();
if ((der.getTag() & (byte)0x1F) == (byte)0x08) {
subDer = der.getData().getDerValue();
@@ -183,7 +183,7 @@
encAuthorizationData = EncryptedData.parse(encoding.getData(), (byte)0x0A, true);
}
if (encoding.getData().available() > 0) {
- Vector<Ticket> tempTickets = new Vector<Ticket> ();
+ Vector<Ticket> tempTickets = new Vector<>();
der = encoding.getData().getDerValue();
if ((der.getTag() & (byte)0x1F) == (byte)0x0B) {
subDer = der.getData().getDerValue();
@@ -216,7 +216,7 @@
*
*/
public byte[] asn1Encode(int msgType) throws Asn1Exception, IOException {
- Vector<DerValue> v = new Vector<DerValue> ();
+ Vector<DerValue> v = new Vector<>();
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), kdcOptions.asn1Encode()));
if (msgType == Krb5.KRB_AS_REQ) {
if (cname != null) {
--- a/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KRBCred.java Fri Feb 18 12:04:36 2011 -0800
@@ -134,7 +134,7 @@
if (subsubDer.getTag() != DerValue.tag_SequenceOf) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
- Vector<Ticket> v = new Vector<Ticket>();
+ Vector<Ticket> v = new Vector<>();
while (subsubDer.getData().available() > 0) {
v.addElement(new Ticket(subsubDer.getData().getDerValue()));
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KRBError.java Fri Feb 18 12:04:36 2011 -0800
@@ -260,7 +260,7 @@
private void parsePAData(byte[] data)
throws IOException, Asn1Exception {
DerValue derPA = new DerValue(data);
- List<PAData> paList = new ArrayList<PAData>();
+ List<PAData> paList = new ArrayList<>();
while (derPA.data.available() > 0) {
// read the PA-DATA
DerValue tmp = derPA.data.getDerValue();
--- a/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java Fri Feb 18 12:04:36 2011 -0800
@@ -157,7 +157,7 @@
* @exception IOException if an I/O error occurs while reading encoded data.
*/
public byte[] asn1Encode() throws Asn1Exception, IOException {
- Vector<DerValue> v = new Vector<DerValue> ();
+ Vector<DerValue> v = new Vector<>();
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x00), key.asn1Encode()));
if (prealm != null)
v.addElement(new DerValue(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte)0x01), prealm.asn1Encode()));
--- a/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/LastReq.java Fri Feb 18 12:04:36 2011 -0800
@@ -77,7 +77,7 @@
*/
public LastReq(DerValue encoding) throws Asn1Exception, IOException {
- Vector<LastReqEntry> v= new Vector<LastReqEntry> ();
+ Vector<LastReqEntry> v= new Vector<>();
if (encoding.getTag() != DerValue.tag_Sequence) {
throw new Asn1Exception(Krb5.ASN1_BAD_ID);
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Fri Feb 18 12:04:36 2011 -0800
@@ -490,7 +490,7 @@
private static String exec(String c) {
StringTokenizer st = new StringTokenizer(c);
- Vector<String> v = new Vector<String> ();
+ Vector<String> v = new Vector<>();
while (st.hasMoreTokens()) {
v.addElement(st.nextToken());
}
--- a/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Fri Feb 18 12:04:36 2011 -0800
@@ -257,7 +257,7 @@
+ configName);
}
- List<Integer> list = new ArrayList<Integer> (answer.length);
+ List<Integer> list = new ArrayList<>(answer.length);
for (int i = 0; i < answer.length; i++) {
if (EncryptionKey.findKey(answer[i], keys) != null) {
list.add(answer[i]);
--- a/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Fri Feb 18 12:04:36 2011 -0800
@@ -57,7 +57,7 @@
private static KeyTab singleton = null;
private static final boolean DEBUG = Krb5.DEBUG;
private static String name;
- private Vector<KeyTabEntry> entries = new Vector<KeyTabEntry> ();
+ private Vector<KeyTabEntry> entries = new Vector<>();
private KeyTab(String filename) throws IOException, RealmException {
init(filename);
@@ -240,7 +240,7 @@
KeyTabEntry entry;
EncryptionKey key;
int size = entries.size();
- ArrayList<EncryptionKey> keys = new ArrayList<EncryptionKey> (size);
+ ArrayList<EncryptionKey> keys = new ArrayList<>(size);
for (int i = size-1; i >= 0; i--) {
entry = entries.elementAt(i);
--- a/jdk/src/share/classes/sun/security/provider/PolicyFile.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/provider/PolicyFile.java Fri Feb 18 12:04:36 2011 -0800
@@ -299,8 +299,7 @@
private static final int DEFAULT_CACHE_SIZE = 1;
// contains the policy grant entries, PD cache, and alias mapping
- private AtomicReference<PolicyInfo> policyInfo =
- new AtomicReference<PolicyInfo>();
+ private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
private boolean constructed = false;
private boolean expandProperties = true;
@@ -1334,8 +1333,7 @@
List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
if (debug != null) {
- ArrayList<PolicyParser.PrincipalEntry> accPs =
- new ArrayList<PolicyParser.PrincipalEntry>();
+ ArrayList<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
if (principals != null) {
for (int i = 0; i < principals.length; i++) {
accPs.add(new PolicyParser.PrincipalEntry
@@ -1416,8 +1414,7 @@
// check if the PrincipalComparator
// implies the current thread's principals
- Set<Principal> pSet =
- new HashSet<Principal>(principals.length);
+ Set<Principal> pSet = new HashSet<>(principals.length);
for (int j = 0; j < principals.length; j++) {
pSet.add(principals[j]);
}
@@ -1700,7 +1697,7 @@
// build an info array for every principal
// in the current domain which has a principal class
// that is equal to policy entry principal class name
- List<Principal> plist = new ArrayList<Principal>();
+ List<Principal> plist = new ArrayList<>();
for (int i = 0; i < pdp.length; i++) {
if(pe.principalClass.equals(pdp[i].getClass().getName()))
plist.add(pdp[i]);
@@ -1770,7 +1767,7 @@
// Done
return certs;
- ArrayList<Certificate> userCertList = new ArrayList<Certificate>();
+ ArrayList<Certificate> userCertList = new ArrayList<>();
i = 0;
while (i < certs.length) {
userCertList.add(certs[i]);
@@ -2234,7 +2231,7 @@
if (this.certs == null) {
// extract the signer certs
ArrayList<Certificate> signerCerts =
- new ArrayList<Certificate>();
+ new ArrayList<>();
i = 0;
while (i < certs.length) {
signerCerts.add(certs[i]);
--- a/jdk/src/share/classes/sun/security/provider/Sun.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/provider/Sun.java Fri Feb 18 12:04:36 2011 -0800
@@ -55,7 +55,7 @@
SunEntries.putEntries(this);
} else {
// use LinkedHashMap to preserve the order of the PRNGs
- Map<Object, Object> map = new LinkedHashMap<Object, Object>();
+ Map<Object, Object> map = new LinkedHashMap<>();
SunEntries.putEntries(map);
AccessController.doPrivileged(new PutAllAction(this, map));
}
--- a/jdk/src/share/classes/sun/security/provider/VerificationProvider.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/provider/VerificationProvider.java Fri Feb 18 12:04:36 2011 -0800
@@ -76,7 +76,7 @@
SunRsaSignEntries.putEntries(this);
} else {
// use LinkedHashMap to preserve the order of the PRNGs
- Map<Object, Object> map = new LinkedHashMap<Object, Object>();
+ Map<Object, Object> map = new LinkedHashMap<>();
SunEntries.putEntries(map);
SunRsaSignEntries.putEntries(map);
AccessController.doPrivileged(new PutAllAction(this, map));
--- a/jdk/src/share/classes/sun/security/provider/X509Factory.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java Fri Feb 18 12:04:36 2011 -0800
@@ -409,10 +409,10 @@
parseX509orPKCS7Cert(InputStream is)
throws CertificateException, IOException
{
- Collection<X509CertImpl> coll = new ArrayList<X509CertImpl>();
+ Collection<X509CertImpl> coll = new ArrayList<>();
byte[] data = readOneBlock(is);
if (data == null) {
- return new ArrayList<X509CertImpl>(0);
+ return new ArrayList<>(0);
}
try {
PKCS7 pkcs7 = new PKCS7(data);
@@ -422,7 +422,7 @@
return Arrays.asList(certs);
} else {
// no crls provided
- return new ArrayList<X509Certificate>(0);
+ return new ArrayList<>(0);
}
} catch (ParsingException e) {
while (data != null) {
@@ -442,10 +442,10 @@
parseX509orPKCS7CRL(InputStream is)
throws CRLException, IOException
{
- Collection<X509CRLImpl> coll = new ArrayList<X509CRLImpl>();
+ Collection<X509CRLImpl> coll = new ArrayList<>();
byte[] data = readOneBlock(is);
if (data == null) {
- return new ArrayList<X509CRL>(0);
+ return new ArrayList<>(0);
}
try {
PKCS7 pkcs7 = new PKCS7(data);
@@ -455,7 +455,7 @@
return Arrays.asList(crls);
} else {
// no crls provided
- return new ArrayList<X509CRL>(0);
+ return new ArrayList<>(0);
}
} catch (ParsingException e) {
while (data != null) {
--- a/jdk/src/share/classes/sun/security/rsa/RSACore.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/rsa/RSACore.java Fri Feb 18 12:04:36 2011 -0800
@@ -215,11 +215,11 @@
// value suggested by Paul Kocher (quoted by NSS)
private final static int BLINDING_MAX_REUSE = 50;
- // cache for blinding parameters. Map<BigInteger,BlindingParameters>
+ // cache for blinding parameters. Map<BigInteger, BlindingParameters>
// use a weak hashmap so that cached values are automatically cleared
// when the modulus is GC'ed
- private final static Map<BigInteger,BlindingParameters> blindingCache =
- new WeakHashMap<BigInteger,BlindingParameters>();
+ private final static Map<BigInteger, BlindingParameters> blindingCache =
+ new WeakHashMap<>();
/**
* Set of blinding parameters for a given RSA key.
--- a/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/rsa/SunRsaSign.java Fri Feb 18 12:04:36 2011 -0800
@@ -52,7 +52,7 @@
SunRsaSignEntries.putEntries(this);
} else {
// use LinkedHashMap to preserve the order of the PRNGs
- Map<Object, Object> map = new HashMap<Object, Object>();
+ Map<Object, Object> map = new HashMap<>();
SunRsaSignEntries.putEntries(map);
AccessController.doPrivileged(new PutAllAction(this, map));
}
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuite.java Fri Feb 18 12:04:36 2011 -0800
@@ -393,7 +393,7 @@
// Map BulkCipher -> Boolean(available)
private final static Map<BulkCipher,Boolean> availableCache =
- new HashMap<BulkCipher,Boolean>(8);
+ new HashMap<>(8);
// descriptive name including key size, e.g. AES/128
final String description;
--- a/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/CipherSuiteList.java Fri Feb 18 12:04:36 2011 -0800
@@ -221,7 +221,7 @@
private static CipherSuiteList buildAvailableCache(int minPriority) {
// SortedSet automatically arranges ciphersuites in default
// preference order
- Set<CipherSuite> cipherSuites = new TreeSet<CipherSuite>();
+ Set<CipherSuite> cipherSuites = new TreeSet<>();
Collection<CipherSuite> allowedCipherSuites =
CipherSuite.allowedCipherSuites();
for (CipherSuite c : allowedCipherSuites) {
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Feb 18 12:04:36 2011 -0800
@@ -655,7 +655,7 @@
if (certRequest != null) {
X509ExtendedKeyManager km = sslContext.getX509KeyManager();
- ArrayList<String> keytypesTmp = new ArrayList<String>(4);
+ ArrayList<String> keytypesTmp = new ArrayList<>(4);
for (int i = 0; i < certRequest.types.length; i++) {
String typeName;
@@ -1174,8 +1174,7 @@
"Can't reuse existing SSL client session");
}
- Collection<CipherSuite> cipherList =
- new ArrayList<CipherSuite>(2);
+ Collection<CipherSuite> cipherList = new ArrayList<>(2);
cipherList.add(sessionSuite);
if (!secureRenegotiation &&
cipherSuites.contains(CipherSuite.C_SCSV)) {
@@ -1193,7 +1192,7 @@
// exclude SCSV for secure renegotiation
if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
Collection<CipherSuite> cipherList =
- new ArrayList<CipherSuite>(cipherSuites.size() - 1);
+ new ArrayList<>(cipherSuites.size() - 1);
for (CipherSuite suite : cipherSuites.collection()) {
if (suite != CipherSuite.C_SCSV) {
cipherList.add(suite);
--- a/jdk/src/share/classes/sun/security/ssl/DefaultSSLContextImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/DefaultSSLContextImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -98,7 +98,7 @@
return defaultKeyManagers;
}
- final Map<String,String> props = new HashMap<String,String>();
+ final Map<String,String> props = new HashMap<>();
AccessController.doPrivileged(
new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
--- a/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/HandshakeMessage.java Fri Feb 18 12:04:36 2011 -0800
@@ -258,7 +258,7 @@
// add server_name extension
void addServerNameIndicationExtension(String hostname) {
// We would have checked that the hostname ia a FQDN.
- ArrayList<String> hostnames = new ArrayList<String>(1);
+ ArrayList<String> hostnames = new ArrayList<>(1);
hostnames.add(hostname);
try {
@@ -434,7 +434,7 @@
CertificateMsg(HandshakeInStream input) throws IOException {
int chainLen = input.getInt24();
- List<Certificate> v = new ArrayList<Certificate>(4);
+ List<Certificate> v = new ArrayList<>(4);
CertificateFactory cf = null;
while (chainLen > 0) {
@@ -1328,7 +1328,7 @@
// read the certificate_authorities
int len = input.getInt16();
- ArrayList<DistinguishedName> v = new ArrayList<DistinguishedName>();
+ ArrayList<DistinguishedName> v = new ArrayList<>();
while (len >= 3) {
DistinguishedName dn = new DistinguishedName(input);
v.add(dn);
@@ -1719,7 +1719,7 @@
// Note that this will prevent the Spi classes from being GC'd. We assume
// that is not a problem.
private final static Map<Class,Object> methodCache =
- new ConcurrentHashMap<Class,Object>();
+ new ConcurrentHashMap<>();
private static void digestKey(MessageDigest md, SecretKey key) {
try {
--- a/jdk/src/share/classes/sun/security/ssl/Handshaker.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/Handshaker.java Fri Feb 18 12:04:36 2011 -0800
@@ -569,7 +569,7 @@
activeProtocols = getActiveProtocols();
}
- ArrayList<CipherSuite> suites = new ArrayList<CipherSuite>();
+ ArrayList<CipherSuite> suites = new ArrayList<>();
if (!(activeProtocols.collection().isEmpty()) &&
activeProtocols.min.v != ProtocolVersion.NONE.v) {
for (CipherSuite suite : enabledCipherSuites.collection()) {
@@ -614,8 +614,7 @@
*/
ProtocolList getActiveProtocols() {
if (activeProtocols == null) {
- ArrayList<ProtocolVersion> protocols =
- new ArrayList<ProtocolVersion>(4);
+ ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
for (ProtocolVersion protocol : enabledProtocols.collection()) {
boolean found = false;
for (CipherSuite suite : enabledCipherSuites.collection()) {
--- a/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/HelloExtensions.java Fri Feb 18 12:04:36 2011 -0800
@@ -169,8 +169,7 @@
return name;
}
- static List<ExtensionType> knownExtensions =
- new ArrayList<ExtensionType>(9);
+ static List<ExtensionType> knownExtensions = new ArrayList<>(9);
static ExtensionType get(int id) {
for (ExtensionType ext : knownExtensions) {
@@ -674,7 +673,7 @@
}
public String toString() {
- List<String> list = new ArrayList<String>();
+ List<String> list = new ArrayList<>();
for (byte format : formats) {
list.add(toString(format));
}
--- a/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/ProtocolList.java Fri Feb 18 12:04:36 2011 -0800
@@ -83,7 +83,7 @@
throw new IllegalArgumentException("Protocols may not be null");
}
- ArrayList<ProtocolVersion> versions = new ArrayList<ProtocolVersion>(3);
+ ArrayList<ProtocolVersion> versions = new ArrayList<>(3);
for (int i = 0; i < names.length; i++ ) {
ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
if (versions.contains(version) == false) {
--- a/jdk/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLAlgorithmConstraints.java Fri Feb 18 12:04:36 2011 -0800
@@ -261,7 +261,7 @@
protected Set<String> decomposes(KeyExchange keyExchange,
boolean forCertPathOnly) {
- Set<String> components = new HashSet<String>();
+ Set<String> components = new HashSet<>();
switch (keyExchange) {
case K_NULL:
if (!forCertPathOnly) {
@@ -356,7 +356,7 @@
}
protected Set<String> decomposes(BulkCipher bulkCipher) {
- Set<String> components = new HashSet<String>();
+ Set<String> components = new HashSet<>();
if (bulkCipher.transformation != null) {
components.addAll(super.decomposes(bulkCipher.transformation));
@@ -366,7 +366,7 @@
}
protected Set<String> decomposes(MacAlg macAlg) {
- Set<String> components = new HashSet<String>();
+ Set<String> components = new HashSet<>();
if (macAlg == CipherSuite.M_MD5) {
components.add("MD5");
@@ -407,7 +407,7 @@
}
if (cipherSuite != null) {
- Set<String> components = new HashSet<String>();
+ Set<String> components = new HashSet<>();
if(cipherSuite.keyExchange != null) {
components.addAll(
@@ -448,7 +448,7 @@
}
if (cipherSuite != null) {
- Set<String> components = new HashSet<String>();
+ Set<String> components = new HashSet<>();
if(cipherSuite.keyExchange != null) {
components.addAll(
--- a/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -618,8 +618,7 @@
* key and the calling security context. This is important since
* sessions can be shared across different protection domains.
*/
- private Hashtable<SecureKey, Object> table =
- new Hashtable<SecureKey, Object>();
+ private Hashtable<SecureKey, Object> table = new Hashtable<>();
/**
* Assigns a session value. Session change events are given if
@@ -687,7 +686,7 @@
*/
public String[] getValueNames() {
Enumeration<SecureKey> e;
- Vector<Object> v = new Vector<Object>();
+ Vector<Object> v = new Vector<>();
SecureKey key;
Object securityCtx = SecureKey.getCurrentSecurityContext();
--- a/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Fri Feb 18 12:04:36 2011 -0800
@@ -153,8 +153,7 @@
static Collection<SignatureAndHashAlgorithm>
getSupportedAlgorithms(AlgorithmConstraints constraints) {
- Collection<SignatureAndHashAlgorithm> supported =
- new ArrayList<SignatureAndHashAlgorithm>();
+ Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
synchronized (priorityMap) {
for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) {
if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
@@ -171,8 +170,7 @@
// Get supported algorithm collection from an untrusted collection
static Collection<SignatureAndHashAlgorithm> getSupportedAlgorithms(
Collection<SignatureAndHashAlgorithm> algorithms ) {
- Collection<SignatureAndHashAlgorithm> supported =
- new ArrayList<SignatureAndHashAlgorithm>();
+ Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
for (SignatureAndHashAlgorithm sigAlg : algorithms) {
if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
supported.add(sigAlg);
@@ -184,7 +182,7 @@
static String[] getAlgorithmNames(
Collection<SignatureAndHashAlgorithm> algorithms) {
- ArrayList<String> algorithmNames = new ArrayList<String>();
+ ArrayList<String> algorithmNames = new ArrayList<>();
if (algorithms != null) {
for (SignatureAndHashAlgorithm sigAlg : algorithms) {
algorithmNames.add(sigAlg.algorithm);
@@ -197,7 +195,7 @@
static Set<String> getHashAlgorithmNames(
Collection<SignatureAndHashAlgorithm> algorithms) {
- Set<String> algorithmNames = new HashSet<String>();
+ Set<String> algorithmNames = new HashSet<>();
if (algorithms != null) {
for (SignatureAndHashAlgorithm sigAlg : algorithms) {
if (sigAlg.hash.value > 0) {
--- a/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/SunX509KeyManagerImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -337,7 +337,7 @@
X500Principal[] x500Issuers = (X500Principal[])issuers;
// the algorithm below does not produce duplicates, so avoid Set
- List<String> aliases = new ArrayList<String>();
+ List<String> aliases = new ArrayList<>();
for (Map.Entry<String,X509Credentials> entry :
credentialsMap.entrySet()) {
@@ -397,7 +397,7 @@
* possible. Principals that cannot be converted are ignored.
*/
private static X500Principal[] convertPrincipals(Principal[] principals) {
- List<X500Principal> list = new ArrayList<X500Principal>(principals.length);
+ List<X500Principal> list = new ArrayList<>(principals.length);
for (int i = 0; i < principals.length; i++) {
Principal p = principals[i];
if (p instanceof X500Principal) {
--- a/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -134,7 +134,7 @@
FileInputStream fis = null;
String defaultTrustStoreType;
String defaultTrustStoreProvider;
- final HashMap<String,String> props = new HashMap<String,String>();
+ final HashMap<String,String> props = new HashMap<>();
final String sep = File.separator;
KeyStore ks = null;
--- a/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/ssl/X509KeyManagerImpl.java Fri Feb 18 12:04:36 2011 -0800
@@ -307,7 +307,7 @@
(keyTypes.length == 0) || (keyTypes[0] == null)) {
return null;
}
- List<KeyType> list = new ArrayList<KeyType>(keyTypes.length);
+ List<KeyType> list = new ArrayList<>(keyTypes.length);
for (String keyType : keyTypes) {
list.add(new KeyType(keyType));
}
@@ -429,7 +429,7 @@
// make a Set out of the array
private Set<Principal> getIssuerSet(Principal[] issuers) {
if ((issuers != null) && (issuers.length != 0)) {
- return new HashSet<Principal>(Arrays.asList(issuers));
+ return new HashSet<>(Arrays.asList(issuers));
} else {
return null;
}
--- a/jdk/src/share/classes/sun/security/tools/JarSigner.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java Fri Feb 18 12:04:36 2011 -0800
@@ -123,19 +123,19 @@
// or the default keystore, never null
String keystore; // key store file
- List<String> crlfiles = new ArrayList<String>(); // CRL files to add
+ List<String> crlfiles = new ArrayList<>(); // CRL files to add
boolean nullStream = false; // null keystore input stream (NONE)
boolean token = false; // token-based keystore
String jarfile; // jar files to sign or verify
String alias; // alias to sign jar with
- List<String> ckaliases = new ArrayList<String>(); // aliases in -verify
+ List<String> ckaliases = new ArrayList<>(); // aliases in -verify
char[] storepass; // keystore password
boolean protectedPath; // protected authentication path
String storetype; // keystore type
String providerName; // provider name
Vector<String> providers = null; // list of providers
// arguments for provider constructors
- HashMap<String,String> providerArgs = new HashMap<String, String>();
+ HashMap<String,String> providerArgs = new HashMap<>();
char[] keypass; // private key password
String sigfile; // name of .SF file
String sigalg; // name of signature algorithm
@@ -236,7 +236,7 @@
if (crlfiles.size() > 0 || autoCRL) {
CertificateFactory fac =
CertificateFactory.getInstance("X509");
- List<CRL> list = new ArrayList<CRL>();
+ List<CRL> list = new ArrayList<>();
for (String file: crlfiles) {
Collection<? extends CRL> tmp = KeyTool.loadCRLs(file);
for (CRL crl: tmp) {
@@ -606,7 +606,7 @@
try {
jf = new JarFile(jarName, true);
- Vector<JarEntry> entriesVec = new Vector<JarEntry>();
+ Vector<JarEntry> entriesVec = new Vector<>();
byte[] buffer = new byte[8192];
Enumeration<JarEntry> entries = jf.entries();
@@ -633,8 +633,7 @@
// The map to record display info, only used when -verbose provided
// key: signer info string
// value: the list of files with common key
- Map<String,List<String>> output =
- new LinkedHashMap<String,List<String>>();
+ Map<String,List<String>> output = new LinkedHashMap<>();
if (man != null) {
if (verbose != null) System.out.println();
@@ -1000,8 +999,7 @@
.append(signTimeForm.format(source)).append("]").toString();
}
- private Map<CodeSigner,Integer> cacheForInKS =
- new IdentityHashMap<CodeSigner,Integer>();
+ private Map<CodeSigner,Integer> cacheForInKS = new IdentityHashMap<>();
private int inKeyStoreForOneSigner(CodeSigner signer) {
if (cacheForInKS.containsKey(signer)) {
@@ -1044,8 +1042,7 @@
return result;
}
- Hashtable<Certificate, String> storeHash =
- new Hashtable<Certificate, String>();
+ Hashtable<Certificate, String> storeHash = new Hashtable<>();
int inKeyStore(CodeSigner[] signers) {
@@ -1175,7 +1172,7 @@
* generated one. (This may invalidate existing signatures!)
*/
BASE64Encoder encoder = new JarBASE64Encoder();
- Vector<ZipEntry> mfFiles = new Vector<ZipEntry>();
+ Vector<ZipEntry> mfFiles = new Vector<>();
boolean wasSigned = false;
@@ -1531,7 +1528,7 @@
return false;
}
- Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<CodeSigner,String>();
+ Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
/**
* Returns a string of singer info, with a newline at the end
@@ -1655,7 +1652,7 @@
}
}
}
- Set<TrustAnchor> tas = new HashSet<TrustAnchor>();
+ Set<TrustAnchor> tas = new HashSet<>();
try {
KeyStore caks = KeyTool.getCacertsKeyStore();
if (caks != null) {
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java Fri Feb 18 12:04:36 2011 -0800
@@ -153,11 +153,11 @@
private KeyStore caks = null; // "cacerts" keystore
private char[] srcstorePass = null;
private String srcstoretype = null;
- private Set<char[]> passwords = new HashSet<char[]> ();
+ private Set<char[]> passwords = new HashSet<>();
private String startDate = null;
- private List <String> ids = new ArrayList <String> (); // used in GENCRL
- private List <String> v3ext = new ArrayList <String> ();
+ private List<String> ids = new ArrayList<>(); // used in GENCRL
+ private List<String> v3ext = new ArrayList<>();
enum Command {
CERTREQ("Generates.a.certificate.request",
@@ -2091,7 +2091,7 @@
*/
public static List<CRL> readCRLsFromCert(X509Certificate cert)
throws Exception {
- List<CRL> crls = new ArrayList<CRL>();
+ List<CRL> crls = new ArrayList<>();
CRLDistributionPointsExtension ext =
X509CertImpl.toImpl(cert).getCRLDistributionPointsExtension();
if (ext == null) return crls;
@@ -2258,7 +2258,7 @@
if (jarfile != null) {
JarFile jf = new JarFile(jarfile, true);
Enumeration<JarEntry> entries = jf.entries();
- Set<CodeSigner> ss = new HashSet<CodeSigner>();
+ Set<CodeSigner> ss = new HashSet<>();
byte[] buffer = new byte[8192];
int pos = 0;
while (entries.hasMoreElements()) {
@@ -3347,7 +3347,7 @@
}
// start building chain
- Vector<Certificate> chain = new Vector<Certificate>(2);
+ Vector<Certificate> chain = new Vector<>(2);
if (buildChain((X509Certificate)certToVerify, chain, certs)) {
Certificate[] newChain = new Certificate[chain.size()];
// buildChain() returns chain with self-signed root-cert first and
@@ -3873,8 +3873,7 @@
break;
case 2: // EKU
if(value != null) {
- Vector <ObjectIdentifier> v =
- new Vector <ObjectIdentifier>();
+ Vector<ObjectIdentifier> v = new Vector<>();
for (String s: value.split(",")) {
int p = oneOf(s,
"anyExtendedKeyUsage",
@@ -3944,7 +3943,7 @@
}
if(value != null) {
List<AccessDescription> accessDescriptions =
- new ArrayList<AccessDescription>();
+ new ArrayList<>();
String[] ps = value.split(",");
for(String item: ps) {
colonpos = item.indexOf(':');
@@ -4228,7 +4227,7 @@
}
public static <A,B> Pair<A,B> of(A a, B b) {
- return new Pair<A,B>(a,b);
+ return new Pair<>(a,b);
}
}
--- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Fri Feb 18 12:04:36 2011 -0800
@@ -643,7 +643,7 @@
Class<?> pc = Class.forName(type, true,
Thread.currentThread().getContextClassLoader());
Constructor<?> c = null;
- Vector<String> objects = new Vector<String>(2);
+ Vector<String> objects = new Vector<>(2);
if (name != null) objects.add(name);
if (actions != null) objects.add(actions);
switch (objects.size()) {
@@ -1722,8 +1722,7 @@
new PolicyParser.GrantEntry(signedby, codebase);
// get the new Principals
- LinkedList<PolicyParser.PrincipalEntry> prins =
- new LinkedList<PolicyParser.PrincipalEntry>();
+ LinkedList<PolicyParser.PrincipalEntry> prins = new LinkedList<>();
TaggedList prinList = (TaggedList)getComponent(PE_PRIN_LIST);
for (int i = 0; i < prinList.getItemCount(); i++) {
prins.add((PolicyParser.PrincipalEntry)prinList.getObject(i));
@@ -1731,8 +1730,7 @@
ge.principals = prins;
// get the new Permissions
- Vector<PolicyParser.PermissionEntry> perms =
- new Vector<PolicyParser.PermissionEntry>();
+ Vector<PolicyParser.PermissionEntry> perms = new Vector<>();
TaggedList permList = (TaggedList)getComponent(PE_PERM_LIST);
for (int i = 0; i < permList.getItemCount(); i++) {
perms.addElement((PolicyParser.PermissionEntry)permList.getObject(i));
@@ -3649,7 +3647,7 @@
* This is a java.awt.List that bind an Object to each String it holds.
*/
class TaggedList extends List {
- private java.util.List<Object> data = new LinkedList<Object>();
+ private java.util.List<Object> data = new LinkedList<>();
public TaggedList(int i, boolean b) {
super(i, b);
}
--- a/jdk/src/share/demo/jvmti/index.html Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/demo/jvmti/index.html Fri Feb 18 12:04:36 2011 -0800
@@ -389,10 +389,9 @@
<li>
MS DLL Runtime: Use the <code>/MD /D _STATIC_CPPLIB</code> option.
<br>
-This causes your dll to become dependent on MSVCRT.DLL and/or
-the newer C++ runtime MSVCR71.DLL.
+This causes your dll to become dependent on just MSVCR*.DLL.
The option /D _STATIC_CPPLIB prevents you from becoming dependent on the
-C++ library MSVCP71.DLL.
+C++ library MSVCP*.DLL.
This is what we use in the JDK, but there are probably many combinations
that you could safely use, unfortunately there are many combinations
of runtimes that will not work.
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipFileSystem.java Fri Feb 18 12:04:36 2011 -0800
@@ -78,7 +78,6 @@
// configurable by env map
private final String defaultDir; // default dir for the file system
private final String nameEncoding; // default encoding for name/comment
- private final boolean buildDirTree; // build a dir tree for directoryStream ops
private final boolean useTempFile; // use a temp file for newOS, default
// is to use BAOS for better performance
private final boolean createNew; // create a new zip if not exists
@@ -94,7 +93,6 @@
this.createNew = "true".equals(env.get("create"));
this.nameEncoding = env.containsKey("encoding") ?
(String)env.get("encoding") : "UTF-8";
- this.buildDirTree = TRUE.equals(env.get("buildDirTreea"));
this.useTempFile = TRUE.equals(env.get("useTempFile"));
this.defaultDir = env.containsKey("default.dir") ?
(String)env.get("default.dir") : "/";
@@ -290,28 +288,16 @@
try {
ensureOpen();
e = getEntry0(path);
- } finally {
- endRead();
- }
- if (e == null) {
- if (path.length == 0) {
- e = new Entry(new byte[0]); // root
- } else if (buildDirTree) {
- IndexNode inode = getDirs().get(IndexNode.keyOf(path));
+ if (e == null) {
+ IndexNode inode = getInode(path);
if (inode == null)
return null;
- e = new Entry(inode.name);
- } else {
- return null;
+ e = new Entry(inode.name); // pseudo directory
+ e.method = METHOD_STORED; // STORED for dir
+ e.mtime = e.atime = e.ctime = -1;// -1 for all times
}
- e.method = METHOD_STORED; // STORED for dir
- BasicFileAttributes bfas = Attributes.readBasicFileAttributes(zfpath);
- if (bfas.lastModifiedTime() != null)
- e.mtime = bfas.lastModifiedTime().toMillis();
- if (bfas.lastAccessTime() != null)
- e.atime = bfas.lastAccessTime().toMillis();
- if (bfas.creationTime() != null)
- e.ctime = bfas.creationTime().toMillis();
+ } finally {
+ endRead();
}
return new ZipFileAttributes(e);
}
@@ -346,7 +332,7 @@
beginRead();
try {
ensureOpen();
- return getEntry0(path) != null;
+ return getInode(path) != null;
} finally {
endRead();
}
@@ -355,13 +341,10 @@
boolean isDirectory(byte[] path)
throws IOException
{
- if (buildDirTree)
- return getDirs().containsKey(IndexNode.keyOf(path));
-
beginRead();
try {
- Entry e = getEntry0(path);
- return (e != null && e.isDir()) || path.length == 0;
+ IndexNode n = getInode(path);
+ return n != null && n.isDir();
} finally {
endRead();
}
@@ -383,39 +366,16 @@
beginWrite(); // iteration of inodes needs exclusive lock
try {
ensureOpen();
- if (buildDirTree) {
- IndexNode inode = getDirs().get(IndexNode.keyOf(path));
- if (inode == null)
- throw new NotDirectoryException(getString(path));
- List<Path> list = new ArrayList<>();
- IndexNode child = inode.child;
- while (child != null) {
- ZipPath zp = toZipPath(child.name);
- if (filter == null || filter.accept(zp))
- list.add(zp);
- child = child.sibling;
- }
- return list.iterator();
- }
-
- if (!isDirectory(path))
+ IndexNode inode = getInode(path);
+ if (inode == null)
throw new NotDirectoryException(getString(path));
List<Path> list = new ArrayList<>();
- path = toDirectoryPath(path);
- for (IndexNode key : inodes.keySet()) {
- if (!isParentOf(path, key.name)) // is "path" the parent of "name"
- continue;
- int off = path.length;
- while (off < key.name.length) {
- if (key.name[off] == '/')
- break;
- off++;
- }
- if (off < (key.name.length - 1))
- continue;
- ZipPath zp = toZipPath(key.name);
+ IndexNode child = inode.child;
+ while (child != null) {
+ ZipPath zp = toZipPath(child.name);
if (filter == null || filter.accept(zp))
list.add(zp);
+ child = child.sibling;
}
return list.iterator();
} finally {
@@ -433,7 +393,6 @@
ensureOpen();
if (dir.length == 0 || exists(dir)) // root dir, or exiting dir
throw new FileAlreadyExistsException(getString(dir));
-
checkParents(dir);
Entry e = new Entry(dir, Entry.NEW);
e.method = METHOD_STORED; // STORED for dir
@@ -476,7 +435,7 @@
checkParents(dst);
}
Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry
- u.name = dst; // change name
+ u.name(dst); // change name
if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH)
{
u.type = eSrc.type; // make it the same type
@@ -518,7 +477,7 @@
if (opt == APPEND)
hasAppend = true;
}
- beginRead(); // only need a readlock, the "update()" will
+ beginRead(); // only need a readlock, the "update()" will
try { // try to obtain a writelock when the os is
ensureOpen(); // being closed.
Entry e = getEntry0(path);
@@ -869,43 +828,27 @@
private void checkParents(byte[] path) throws IOException {
beginRead();
try {
- while ((path = getParent(path)) != null) {
- if (!inodes.containsKey(IndexNode.keyOf(path)))
+ while ((path = getParent(path)) != null && path.length != 0) {
+ if (!inodes.containsKey(IndexNode.keyOf(path))) {
throw new NoSuchFileException(getString(path));
+ }
}
} finally {
endRead();
}
}
+ private static byte[] ROOTPATH = new byte[0];
private static byte[] getParent(byte[] path) {
int off = path.length - 1;
if (off > 0 && path[off] == '/') // isDirectory
off--;
while (off > 0 && path[off] != '/') { off--; }
- if (off == 0)
- return null; // top entry
+ if (off <= 0)
+ return ROOTPATH;
return Arrays.copyOf(path, off + 1);
}
- // If "starter" is the parent directory of "path"
- private static boolean isParentOf(byte[] p, byte[] c) {
- final int plen = p.length;
- if (plen == 0) // root dir
- return true;
- if (plen >= c.length)
- return false;
- int n = 0;
- while (n < plen) {
- if (p[n] != c[n])
- return false;
- n++;
- }
- if (p[n - 1] != '/' && (c[n] != '/' || n == c.length - 1))
- return false;
- return true;
- }
-
private final void beginWrite() {
rwlock.writeLock().lock();
}
@@ -926,7 +869,7 @@
private volatile boolean isOpen = true;
private final SeekableByteChannel ch; // channel to the zipfile
- final byte[] cen; // CEN & ENDHDR
+ final byte[] cen; // CEN & ENDHDR
private END end;
private long locpos; // position of first LOC header (usually 0)
@@ -1058,6 +1001,7 @@
if (end.endpos == 0) {
inodes = new LinkedHashMap<>(10);
locpos = 0;
+ buildNodeTree();
return null; // only END header present
}
if (end.cenlen > end.endpos)
@@ -1101,6 +1045,7 @@
if (pos + ENDHDR != cen.length) {
zerror("invalid CEN header (bad header size)");
}
+ buildNodeTree();
return cen;
}
@@ -1125,12 +1070,15 @@
private boolean hasUpdate = false;
+ // shared key. consumer guarantees the "writeLock" before use it.
+ private final IndexNode LOOKUPKEY = IndexNode.keyOf(null);
+
private void updateDelete(Entry e) {
beginWrite();
try {
- inodes.remove(IndexNode.keyOf(e.name)); //inodes.remove(e.name);
+ removeFromTree(e);
+ inodes.remove(e);
hasUpdate = true;
- dirs = null;
} finally {
endWrite();
}
@@ -1139,9 +1087,16 @@
private void update(Entry e) {
beginWrite();
try {
- inodes.put(IndexNode.keyOf(e.name), e); //inodes.put(e, e);
+ IndexNode old = inodes.put(e, e);
+ if (old != null) {
+ removeFromTree(old);
+ }
+ if (e.type == Entry.NEW || e.type == Entry.FILECH) {
+ IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(e.name)));
+ e.sibling = parent.child;
+ parent.child = e;
+ }
hasUpdate = true;
- dirs = null;
} finally {
endWrite();
}
@@ -1229,7 +1184,7 @@
// ext) without enflating/deflating from the old zip
// file LOC entry.
written += copyLOCEntry(e, true, os, written, buf);
- } else { // NEW or FILECH
+ } else { // NEW, FILECH or CEN
e.locoff = written;
written += e.writeLOC(os); // write loc header
if (e.bytes != null) { // in-memory, deflated
@@ -1265,7 +1220,10 @@
} catch (IOException x) {
x.printStackTrace(); // skip any in-accurate entry
}
- } else { // unchanged inode
+ } else { // unchanged inode
+ if (inode.pos == -1) {
+ continue; // pseudo directory node
+ }
e = Entry.readCEN(this, inode.pos);
try {
written += copyLOCEntry(e, false, os, written, buf);
@@ -1318,34 +1276,28 @@
//System.out.printf("->sync(%s) done!%n", toString());
}
- private Entry getEntry0(byte[] path) throws IOException {
+ private IndexNode getInode(byte[] path) {
if (path == null)
throw new NullPointerException("path");
- if (path.length == 0)
- return null;
- IndexNode inode = null;
IndexNode key = IndexNode.keyOf(path);
- if ((inode = inodes.get(key)) == null) {
- if (path[path.length -1] == '/') // already has a slash
- return null;
+ IndexNode inode = inodes.get(key);
+ if (inode == null &&
+ (path.length == 0 || path[path.length -1] != '/')) {
+ // if does not ends with a slash
path = Arrays.copyOf(path, path.length + 1);
path[path.length - 1] = '/';
- if ((inode = inodes.get(key.as(path))) == null)
- return null;
+ inode = inodes.get(key.as(path));
}
- if (inode instanceof Entry)
- return (Entry)inode;
- return Entry.readCEN(this, inode.pos);
+ return inode;
}
- // Test if the "name" a parent directory of any entry (dir empty)
- boolean isAncestor(byte[] name) {
- for (Map.Entry<IndexNode, IndexNode> entry : inodes.entrySet()) {
- byte[] ename = entry.getKey().name;
- if (isParentOf(name, ename))
- return true;
- }
- return false;
+ private Entry getEntry0(byte[] path) throws IOException {
+ IndexNode inode = getInode(path);
+ if (inode instanceof Entry)
+ return (Entry)inode;
+ if (inode == null || inode.pos == -1)
+ return null;
+ return Entry.readCEN(this, inode.pos);
}
public void deleteFile(byte[] path, boolean failIfNotExists)
@@ -1359,7 +1311,7 @@
if (failIfNotExists)
throw new NoSuchFileException(getString(path));
} else {
- if (e.isDir() && isAncestor(path))
+ if (e.isDir() && e.child != null)
throw new DirectoryNotEmptyException(getString(path));
updateDelete(e);
}
@@ -1539,7 +1491,6 @@
public int available() {
return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem;
}
-
public long size() {
return size;
}
@@ -1762,7 +1713,7 @@
int pos = -1; // postion in cen table, -1 menas the
// entry does not exists in zip file
IndexNode(byte[] name, int pos) {
- as(name);
+ name(name);
this.pos = pos;
}
@@ -1770,15 +1721,25 @@
return new IndexNode(name, -1);
}
- final IndexNode as(byte[] name) { // reuse the node, mostly
- this.name = name; // as a lookup "key"
+ final void name(byte[] name) {
+ this.name = name;
this.hashcode = Arrays.hashCode(name);
+ }
+
+ final IndexNode as(byte[] name) { // reuse the node, mostly
+ name(name); // as a lookup "key"
return this;
}
+ boolean isDir() {
+ return name != null &&
+ (name.length == 0 || name[name.length - 1] == '/');
+ }
+
public boolean equals(Object other) {
- if (!(other instanceof IndexNode))
+ if (!(other instanceof IndexNode)) {
return false;
+ }
return Arrays.equals(name, ((IndexNode)other).name);
}
@@ -1798,6 +1759,7 @@
static final int FILECH = 3; // fch update in "file"
static final int COPY = 4; // copy of a CEN entry
+
byte[] bytes; // updated content bytes
Path file; // use tmp file to store bytes;
int type = CEN; // default is the entry read from cen
@@ -1825,7 +1787,7 @@
Entry() {}
Entry(byte[] name) {
- this.name = name;
+ name(name);
this.mtime = System.currentTimeMillis();
this.crc = 0;
this.size = 0;
@@ -1839,8 +1801,8 @@
}
Entry (Entry e, int type) {
+ name(e.name);
this.version = e.version;
- this.name = e.name;
this.ctime = e.ctime;
this.atime = e.atime;
this.mtime = e.mtime;
@@ -1855,7 +1817,6 @@
this.attrsEx = e.attrsEx;
this.locoff = e.locoff;
this.comment = e.comment;
-
this.type = type;
}
@@ -1865,12 +1826,6 @@
this.method = METHOD_STORED;
}
- boolean isDir() {
- return name != null &&
- (name.length == 0 ||
- name[name.length - 1] == '/');
- }
-
int version() throws ZipException {
if (method == METHOD_DEFLATED)
return 20;
@@ -1909,7 +1864,7 @@
locoff = CENOFF(cen, pos);
pos += CENHDR;
- name = Arrays.copyOfRange(cen, pos, pos + nlen);
+ name(Arrays.copyOfRange(cen, pos, pos + nlen));
pos += nlen;
if (elen > 0) {
@@ -2132,7 +2087,8 @@
}
writeShort(os, flag); // general purpose bit flag
writeShort(os, method); // compression method
- writeInt(os, mtime); // last modification time
+ // last modification time
+ writeInt(os, (int)javaToDosTime(mtime));
writeInt(os, crc); // crc-32
if (elen64 != 0) {
writeInt(os, ZIP64_MINVAL);
@@ -2318,50 +2274,56 @@
// structure.
// A possible solution is to build the node tree ourself as
// implemented below.
- private HashMap<IndexNode, IndexNode> dirs;
private IndexNode root;
- private IndexNode addToDir(IndexNode child) {
- IndexNode cinode = dirs.get(child);
- if (cinode != null)
- return cinode;
-
- byte[] cname = child.name;
- byte[] pname = getParent(cname);
- IndexNode pinode;
- if (pname != null)
- pinode = addToDir(IndexNode.keyOf(pname));
- else
- pinode = root;
- cinode = inodes.get(child);
- if (cname[cname.length -1] != '/') { // not a dir
- cinode.sibling = pinode.child;
- pinode.child = cinode;
- return null;
+ private void addToTree(IndexNode inode, HashSet<IndexNode> dirs) {
+ if (dirs.contains(inode)) {
+ return;
}
- //cinode = dirs.get(child);
- if (cinode == null) // pseudo directry entry
- cinode = new IndexNode(cname, -1);
- cinode.sibling = pinode.child;
- pinode.child = cinode;
-
- dirs.put(child, cinode);
- return cinode;
+ IndexNode parent;
+ byte[] name = inode.name;
+ byte[] pname = getParent(name);
+ if (inodes.containsKey(LOOKUPKEY.as(pname))) {
+ parent = inodes.get(LOOKUPKEY);
+ } else { // pseudo directory entry
+ parent = new IndexNode(pname, -1);
+ inodes.put(parent, parent);
+ }
+ addToTree(parent, dirs);
+ inode.sibling = parent.child;
+ parent.child = inode;
+ if (name[name.length -1] == '/')
+ dirs.add(inode);
}
- private HashMap<IndexNode, IndexNode> getDirs()
- throws IOException
- {
+ private void removeFromTree(IndexNode inode) {
+ IndexNode parent = inodes.get(LOOKUPKEY.as(getParent(inode.name)));
+ IndexNode child = parent.child;
+ if (child == inode) {
+ parent.child = child.sibling;
+ } else {
+ IndexNode last = child;
+ while ((child = child.sibling) != null) {
+ if (child == inode) {
+ last.sibling = child.sibling;
+ break;
+ } else {
+ last = child;
+ }
+ }
+ }
+ }
+
+ private void buildNodeTree() throws IOException {
beginWrite();
try {
- if (dirs != null)
- return dirs;
- dirs = new HashMap<>();
- root = new IndexNode(new byte[0], -1);
- dirs.put(root, root);
- for (IndexNode node : inodes.keySet())
- addToDir(node);
- return dirs;
+ HashSet<IndexNode> dirs = new HashSet<>();
+ IndexNode root = new IndexNode(ROOTPATH, -1);
+ inodes.put(root, root);
+ dirs.add(root);
+ for (IndexNode node : inodes.keySet().toArray(new IndexNode[0])) {
+ addToTree(node, dirs);
+ }
} finally {
endWrite();
}
--- a/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/demo/nio/zipfs/src/com/sun/nio/zipfs/ZipPath.java Fri Feb 18 12:04:36 2011 -0800
@@ -157,7 +157,7 @@
@Override
public ZipPath toRealPath(boolean resolveLinks) throws IOException {
- ZipPath realPath = new ZipPath(zfs, getResolvedPath());
+ ZipPath realPath = new ZipPath(zfs, getResolvedPath()).toAbsolutePath();
realPath.checkAccess();
return realPath;
}
@@ -472,8 +472,11 @@
int n = offsets[i];
int len = (i == offsets.length - 1)?
(path.length - n):(offsets[i + 1] - n - 1);
- if (len == 1 && path[n] == (byte)'.')
+ if (len == 1 && path[n] == (byte)'.') {
+ if (m == 0 && path[0] == '/') // absolute path
+ to[m++] = '/';
continue;
+ }
if (len == 2 && path[n] == '.' && path[n + 1] == '.') {
if (lastMOff >= 0) {
m = lastM[lastMOff--]; // retreat
@@ -726,6 +729,8 @@
@Override
public boolean isSameFile(Path other) throws IOException {
+ if (this.equals(other))
+ return true;
if (other == null ||
this.getFileSystem() != other.getFileSystem())
return false;
--- a/jdk/src/share/hpi/export/bool.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_BOOL_H_
-#define _JAVASOFT_BOOL_H_
-
-#undef TRUE
-#undef FALSE
-
-typedef enum {
- FALSE = 0,
- TRUE = 1
-} bool_t;
-
-#endif /* !_JAVASOFT_BOOL_H_ */
--- a/jdk/src/share/hpi/export/dll.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_DLL_H_
-#define _JAVASOFT_DLL_H_
-
-#include <jni.h>
-
-/* DLL.H: A common interface for helper DLLs loaded by the VM.
- * Each library exports the main entry point "DLL_Initialize". Through
- * that function the programmer can obtain a function pointer which has
- * type "GetInterfaceFunc." Through the function pointer the programmer
- * can obtain other interfaces supported in the DLL.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef jint (JNICALL * GetInterfaceFunc)
- (void **intfP, const char *name, jint ver);
-
-jint JNICALL DLL_Initialize(GetInterfaceFunc *, void *args);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_JAVASOFT_DLL_H_ */
--- a/jdk/src/share/hpi/export/hpi.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Host Porting Interface. This defines the "porting layer" for
- * POSIX.1 compliant operating systems.
- */
-
-#ifndef _JAVASOFT_HPI_H_
-#define _JAVASOFT_HPI_H_
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#include "jni.h"
-#include "bool.h"
-#include "hpi_md.h"
-#include "dll.h"
-
-#ifdef __solaris__
-#define SSIZE_T ssize_t
-#else
-#ifdef _LP64
-#define SSIZE_T ssize_t
-#else
-#define SSIZE_T int
-#endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * memory allocations
- */
-typedef struct {
- /*
- * Malloc must return a unique pointer if size == 0.
- */
- void * (*Malloc)(size_t size);
- void * (*Realloc)(void *ptr, size_t new_size);
- /*
- * Free must allow ptr == NULL to be a no-op.
- */
- void (*Free)(void *ptr);
- /*
- * Calloc must return a unique pointer for if
- * n_item == 0 || item_size == 0.
- */
- void * (*Calloc)(size_t n_item, size_t item_size);
- char * (*Strdup)(const char *str);
-
- void * (*MapMem)(size_t req_size, size_t *maped_size);
- void * (*UnmapMem)(void *req_addr, size_t req_size, size_t *unmap_size);
- /*
- * CommitMem should round the ptr down to the nearest page and
- * round the size up to the nearest page so that the committed
- * region is at least as large as the requested region.
- */
- void * (*CommitMem)(void *ptr, size_t size, size_t *actual);
- /*
- * sysDecommitMem should round the ptr up to the nearest page and
- * round the size down to the nearest page so that the decommitted
- * region is no greater than the requested region.
- */
- void * (*DecommitMem)(void *ptr, size_t size, size_t *actual);
-
-#define HPI_PAGE_ALIGNMENT (64 * 1024)
-
- void * (*AllocBlock)(size_t size, void **headP);
- void (*FreeBlock)(void *head);
-} HPI_MemoryInterface;
-
-/*
- * dynamic linking libraries
- */
-typedef struct {
- void (*BuildLibName)(char *buf, int buf_len, char *path, char *name);
- int (*BuildFunName)(char *name, int name_len, int arg_size, int en_idx);
-
- void * (*LoadLibrary)(const char *name, char *err_buf, int err_buflen);
- void (*UnloadLibrary)(void *lib);
- void * (*FindLibraryEntry)(void *lib, const char *name);
-} HPI_LibraryInterface;
-
-typedef void (*signal_handler_t)(int sig, void *siginfo, void *context);
-
-#define HPI_SIG_DFL (signal_handler_t)0
-#define HPI_SIG_ERR (signal_handler_t)-1
-#define HPI_SIG_IGN (signal_handler_t)1
-
-typedef struct {
- char *name; /* name such as green/native threads. */
- int isMP;
-} HPI_SysInfo;
-
-typedef struct {
- HPI_SysInfo * (*GetSysInfo)(void);
- long (*GetMilliTicks)(void);
- jlong (*TimeMillis)(void);
-
- signal_handler_t (*Signal)(int sig, signal_handler_t handler);
- void (*Raise)(int sig);
- void (*SignalNotify)(int sig);
- int (*SignalWait)(void);
-
- int (*Shutdown)(void);
-
- int (*SetLoggingLevel)(int level);
- bool_t (*SetMonitoringOn)(bool_t on);
- int (*GetLastErrorString)(char *buf, int len);
-} HPI_SystemInterface;
-
-/*
- * threads and monitors
- */
-typedef struct sys_thread sys_thread_t;
-typedef struct sys_mon sys_mon_t;
-
-#define HPI_OK 0
-#define HPI_ERR -1
-#define HPI_INTRPT -2 /* Operation was interrupted */
-#define HPI_TIMEOUT -3 /* A timer ran out */
-#define HPI_NOMEM -5 /* Ran out of memory */
-#define HPI_NORESOURCE -6 /* Ran out of some system resource */
-
-/* There are three basic states: RUNNABLE, MONITOR_WAIT, and CONDVAR_WAIT.
- * When the thread is suspended in any of these states, the
- * HPI_THREAD_SUSPENDED bit will be set
- */
-enum {
- HPI_THREAD_RUNNABLE = 1,
- HPI_THREAD_MONITOR_WAIT,
- HPI_THREAD_CONDVAR_WAIT
-};
-
-#define HPI_MINIMUM_PRIORITY 1
-#define HPI_MAXIMUM_PRIORITY 10
-#define HPI_NORMAL_PRIORITY 5
-
-#define HPI_THREAD_SUSPENDED 0x8000
-#define HPI_THREAD_INTERRUPTED 0x4000
-
-typedef struct {
- sys_thread_t *owner;
- long entry_count;
- sys_thread_t **monitor_waiters;
- sys_thread_t **condvar_waiters;
- int sz_monitor_waiters;
- int sz_condvar_waiters;
- int n_monitor_waiters;
- int n_condvar_waiters;
-} sys_mon_info;
-
-typedef struct {
- int (*ThreadBootstrap)(sys_thread_t **tidP,
- sys_mon_t **qlockP,
- int nReservedBytes);
- int (*ThreadCreate)(sys_thread_t **tidP,
- long stk_size,
- void (*func)(void *),
- void *arg);
- sys_thread_t * (*ThreadSelf)(void);
- void (*ThreadYield)(void);
- int (*ThreadSuspend)(sys_thread_t *tid);
- int (*ThreadResume)(sys_thread_t *tid);
- int (*ThreadSetPriority)(sys_thread_t *tid, int prio);
- int (*ThreadGetPriority)(sys_thread_t *tid, int *prio);
- void * (*ThreadStackPointer)(sys_thread_t *tid);
- void * (*ThreadStackTop)(sys_thread_t *tid);
- long * (*ThreadRegs)(sys_thread_t *tid, int *regs);
- int (*ThreadSingle)(void);
- void (*ThreadMulti)(void);
- int (*ThreadEnumerateOver)(int (*func)(sys_thread_t *, void *),
- void *arg);
- int (*ThreadCheckStack)(void);
- void (*ThreadPostException)(sys_thread_t *tid, void *arg);
- void (*ThreadInterrupt)(sys_thread_t *tid);
- int (*ThreadIsInterrupted)(sys_thread_t *tid, int clear);
- int (*ThreadAlloc)(sys_thread_t **tidP);
- int (*ThreadFree)(void);
- jlong (*ThreadCPUTime)(void);
- int (*ThreadGetStatus)(sys_thread_t *tid, sys_mon_t **monitor);
- void * (*ThreadInterruptEvent)(void);
- void * (*ThreadNativeID)(sys_thread_t *tid);
-
- /* These three functions are used by the CPU time profiler.
- * sysThreadIsRunning determines whether the thread is running (not just
- * runnable). It is only safe to call this function after calling
- * sysThreadProfSuspend.
- */
- bool_t (*ThreadIsRunning)(sys_thread_t *tid);
- void (*ThreadProfSuspend)(sys_thread_t *tid);
- void (*ThreadProfResume)(sys_thread_t *tid);
-
- int (*AdjustTimeSlice)(int ms);
-
- size_t (*MonitorSizeof)(void);
- int (*MonitorInit)(sys_mon_t *mid);
- int (*MonitorDestroy)(sys_mon_t *mid);
- int (*MonitorEnter)(sys_thread_t *self, sys_mon_t *mid);
- bool_t (*MonitorEntered)(sys_thread_t *self, sys_mon_t *mid);
- int (*MonitorExit)(sys_thread_t *self, sys_mon_t *mid);
- int (*MonitorNotify)(sys_thread_t *self, sys_mon_t *mid);
- int (*MonitorNotifyAll)(sys_thread_t *self, sys_mon_t *mid);
- int (*MonitorWait)(sys_thread_t *self, sys_mon_t *mid, jlong ms);
- bool_t (*MonitorInUse)(sys_mon_t *mid);
- sys_thread_t * (*MonitorOwner)(sys_mon_t *mid);
- int (*MonitorGetInfo)(sys_mon_t *mid, sys_mon_info *info);
-
-} HPI_ThreadInterface;
-
-/*
- * files
- */
-
-#define HPI_FILETYPE_REGULAR (0)
-#define HPI_FILETYPE_DIRECTORY (1)
-#define HPI_FILETYPE_OTHER (2)
-
-typedef struct {
- char * (*NativePath)(char *path);
- int (*FileType)(const char *path);
- int (*Open)(const char *name, int openMode, int filePerm);
- int (*Close)(int fd);
- jlong (*Seek)(int fd, jlong offset, int whence);
- int (*SetLength)(int fd, jlong length);
- int (*Sync)(int fd);
- int (*Available)(int fd, jlong *bytes);
- size_t (*Read)(int fd, void *buf, unsigned int nBytes);
- size_t (*Write)(int fd, const void *buf, unsigned int nBytes);
- int (*FileSizeFD)(int fd, jlong *size);
-} HPI_FileInterface;
-
-/*
- * sockets
- */
-struct sockaddr;
-struct hostent;
-
-typedef struct {
- int (*Close)(int fd);
- long (*Available)(int fd, jint *pbytes);
- int (*Connect)(int fd, struct sockaddr *him, int len);
- int (*Accept)(int fd, struct sockaddr *him, int *len);
- SSIZE_T (*SendTo)(int fd, char *buf, int len, int flags,
- struct sockaddr *to, int tolen);
- SSIZE_T (*RecvFrom)(int fd, char *buf, int nbytes, int flags,
- struct sockaddr *from, int *fromlen);
- int (*Listen)(int fd, int count);
- SSIZE_T (*Recv)(int fd, char *buf, int nBytes, int flags);
- SSIZE_T (*Send)(int fd, char *buf, int nBytes, int flags);
- int (*Timeout)(int fd, long timeout);
- struct hostent * (*GetHostByName)(char *hostname);
- int (*Socket)(int domain, int type, int protocol);
- int (*SocketShutdown)(int fd, int howto);
- int (*Bind)(int fd, struct sockaddr *him, int len);
- int (*GetSocketName)(int fd, struct sockaddr *him, int *len);
- int (*GetHostName)(char *hostname, int namelen);
- struct hostent * (*GetHostByAddr)(const char *hostname, int len, int type);
- int (*SocketGetOption)(int fd, int level, int optname, char *optval, int *optlen);
- int (*SocketSetOption)(int fd, int level, int optname, const char *optval, int optlen);
- struct protoent * (*GetProtoByName)(char* name);
-} HPI_SocketInterface;
-
-/*
- * callbacks.
- */
-typedef struct vm_calls {
- int (*jio_fprintf)(FILE *fp, const char *fmt, ...);
- void (*panic)(const char *fmt, ...);
- void (*monitorRegister)(sys_mon_t *mid, char *info_str);
-
- void (*monitorContendedEnter)(sys_thread_t *self, sys_mon_t *mid);
- void (*monitorContendedEntered)(sys_thread_t *self, sys_mon_t *mid);
- void (*monitorContendedExit)(sys_thread_t *self, sys_mon_t *mid);
-} vm_calls_t;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_JAVASOFT_HPI_H_ */
--- a/jdk/src/share/hpi/include/hpi_impl.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 1998, 2005, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_HPI_IMPL_H_
-#define _JAVASOFT_HPI_IMPL_H_
-
-#include "hpi.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm_calls.h"
-
-extern int nReservedBytes;
-sys_thread_t *allocThreadBlock(void);
-void freeThreadBlock(sys_thread_t *tid);
-int threadBootstrapMD(sys_thread_t **tid, sys_mon_t **lockP, int nb);
-
-HPI_SysInfo *sysGetSysInfo(void);
-long sysGetMilliTicks(void);
-jlong sysTimeMillis(void);
-
-signal_handler_t sysSignal(int sig, signal_handler_t handler);
-void sysRaise(int sig);
-void sysSignalNotify(int sig);
-int sysSignalWait(void);
-int sysShutdown(void);
-int sysSetLoggingLevel(int level);
-bool_t sysSetMonitoringOn(bool_t on);
-int sysGetLastErrorString(char *buf, int len);
-
-void * sysMalloc(size_t);
-void * sysRealloc(void*, size_t);
-void sysFree(void*);
-void * sysCalloc(size_t, size_t);
-char * sysStrdup(const char * string);
-void * sysMapMem(size_t, size_t *);
-void * sysUnmapMem(void *, size_t, size_t *);
-void * sysCommitMem(void * ptr, size_t size, size_t * actual);
-void * sysDecommitMem(void * ptr, size_t size, size_t * actual);
-void * sysAllocBlock(size_t, void**);
-void sysFreeBlock(void *);
-
-void sysBuildLibName(char *, int, char *, char *);
-int sysBuildFunName(char *, int, int, int);
-void * sysLoadLibrary(const char *, char *err_buf, int err_buflen);
-void sysUnloadLibrary(void *);
-void * sysFindLibraryEntry(void *, const char *);
-
-int sysThreadBootstrap(sys_thread_t **, sys_mon_t **, int);
-int sysThreadCreate(sys_thread_t **,
- long,
- void (*)(void *),
- void *arg);
-void sysThreadExit(void);
-sys_thread_t * sysThreadSelf(void);
-void sysThreadYield(void);
-int sysThreadSuspend(sys_thread_t *);
-int sysThreadResume(sys_thread_t *);
-int sysThreadSetPriority(sys_thread_t *, int);
-int sysThreadGetPriority(sys_thread_t *, int *);
-void * sysThreadStackPointer(sys_thread_t *);
-void * sysThreadStackTop(sys_thread_t *);
-long * sysThreadRegs(sys_thread_t *, int *);
-int sysThreadSingle(void);
-void sysThreadMulti(void);
-int sysThreadEnumerateOver(int (*)(sys_thread_t *, void *), void *);
-int sysThreadCheckStack(void);
-void sysThreadPostException(sys_thread_t *, void *);
-void sysThreadInterrupt(sys_thread_t *);
-int sysThreadIsInterrupted(sys_thread_t *, int);
-int sysThreadAlloc(sys_thread_t **);
-int sysThreadFree(void);
-size_t sysThreadSizeof(void);
-jlong sysThreadCPUTime(void);
-int sysThreadGetStatus(sys_thread_t *, sys_mon_t **);
-int sysAdjustUserThreadCount(int delta);
-bool_t sysThreadIsRunning(sys_thread_t *);
-void sysThreadProfSuspend(sys_thread_t *);
-void sysThreadProfResume(sys_thread_t *);
-int sysAdjustTimeSlice(int);
-int sysThreadEnumerateOver(int (*f)(sys_thread_t *, void *), void *arg);
-void * sysThreadInterruptEvent(void);
-void * sysThreadNativeID(sys_thread_t *);
-
-size_t sysMonitorSizeof(void);
-int sysMonitorInit(sys_mon_t *);
-int sysMonitorDestroy(sys_mon_t *);
-int sysMonitorEnter(sys_thread_t *, sys_mon_t *);
-bool_t sysMonitorEntered(sys_thread_t *, sys_mon_t *);
-int sysMonitorExit(sys_thread_t *, sys_mon_t *);
-int sysMonitorNotify(sys_thread_t *, sys_mon_t *);
-int sysMonitorNotifyAll(sys_thread_t *, sys_mon_t *);
-int sysMonitorWait(sys_thread_t *, sys_mon_t *, jlong);
-bool_t sysMonitorInUse(sys_mon_t *);
-sys_thread_t * sysMonitorOwner(sys_mon_t *);
-int sysMonitorGetInfo(sys_mon_t *, sys_mon_info *);
-
-char *sysNativePath(char *path);
-int sysFileType(const char *path);
-int sysOpen(const char *name, int openMode, int filePerm);
-int sysClose(int fd);
-jlong sysSeek(int fd, jlong offset, int whence);
-int sysSetLength(int fd, jlong length);
-int sysSync(int fd);
-int sysAvailable(int fd, jlong *bytes);
-size_t sysRead(int fd, void *buf, unsigned int nBytes);
-size_t sysWrite(int fd, const void *buf, unsigned int nBytes);
-int sysFileSizeFD(int fd, jlong *size);
-
-int sysSocketClose(int fd);
-int sysSocketShutdown(int fd, int howto);
-long sysSocketAvailable(int fd, jint *pbytes);
-int sysConnect(int fd, struct sockaddr *him, int len);
-int sysBind(int fd, struct sockaddr *him, int len);
-int sysAccept(int fd, struct sockaddr *him, int *len);
-int sysGetSockName(int fd, struct sockaddr *him, int *len);
-#ifdef _LP64
-ssize_t sysSendTo(int fd, char *buf, int len, int flags, struct sockaddr *to,
- int tolen);
-ssize_t sysRecvFrom(int fd, char *buf, int nbytes, int flags,
- struct sockaddr *from, int *fromlen);
-ssize_t sysRecv(int fd, char *buf, int nBytes, int flags);
-ssize_t sysSend(int fd, char *buf, int nBytes, int flags);
-#else
-int sysSendTo(int fd, char *buf, int len, int flags, struct sockaddr *to,
- int tolen);
-int sysRecvFrom(int fd, char *buf, int nbytes, int flags,
- struct sockaddr *from, int *fromlen);
-int sysRecv(int fd, char *buf, int nBytes, int flags);
-int sysSend(int fd, char *buf, int nBytes, int flags);
-#endif
-int sysListen(int fd, int count);
-int sysTimeout(int fd, long timeout);
-int sysGetHostName(char* name, int namelen);
-struct hostent *sysGetHostByAddr(const char* name, int len, int type);
-struct hostent *sysGetHostByName(char *hostname);
-int sysSocket(int domain, int type, int protocol);
-int sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen);
-int sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen);
-struct protoent * sysGetProtoByName(char* name);
-
-#define SYS_SIG_DFL HPI_SIG_DFL
-#define SYS_SIG_ERR HPI_SIG_ERR
-#define SYS_SIG_IGN HPI_SIG_IGN
-
-#define SYS_OK HPI_OK
-#define SYS_ERR HPI_ERR
-#define SYS_INTRPT HPI_INTRPT
-#define SYS_TIMEOUT HPI_TIMEOUT
-#define SYS_NOMEM HPI_NOMEM
-#define SYS_NORESOURCE HPI_NORESOURCE
-
-#define SYS_THREAD_RUNNABLE HPI_THREAD_RUNNABLE
-#define SYS_THREAD_MONITOR_WAIT HPI_THREAD_MONITOR_WAIT
-#define SYS_THREAD_CONDVAR_WAIT HPI_THREAD_CONDVAR_WAIT
-
-#define MinimumPriority HPI_MINIMUM_PRIORITY
-#define MaximumPriority HPI_MAXIMUM_PRIORITY
-#define NormalPriority HPI_NORMAL_PRIORITY
-
-#define SYS_THREAD_SUSPENDED HPI_THREAD_SUSPENDED
-
-#define PAGE_ALIGNMENT HPI_PAGE_ALIGNMENT
-
-#define SYS_TIMEOUT_INFINITY HPI_TIMEOUT_INFINITY
-
-#define SYS_FILETYPE_REGULAR HPI_FILETYPE_REGULAR
-#define SYS_FILETYPE_DIRECTORY HPI_FILETYPE_DIRECTORY
-#define SYS_FILETYPE_OTHER HPI_FILETYPE_OTHER
-
-typedef void *stackp_t;
-
-/* global vars */
-
-extern int logging_level;
-extern bool_t profiler_on;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !_JAVASOFT_HPI_IMPL_H_ */
--- a/jdk/src/share/hpi/include/vm_calls.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_VM_CALLS_H_
-#define _JAVASOFT_VM_CALLS_H_
-
-/* This file defines the function table and macros exported from the VM
- * for the implementation of HPI.
- */
-
-extern vm_calls_t *vm_calls;
-
-#define VM_CALLS_READY() vm_calls
-#define VM_CALL(f) (vm_calls->f)
-
-#undef sysAssert
-
-#ifdef DEBUG
-#define sysAssert(expression) { \
- if (!(expression)) { \
- vm_calls->panic \
- ("\"%s\", line %d: assertion failure\n", __FILE__, __LINE__); \
- } \
-}
-#else
-#define sysAssert(expression) ((void) 0)
-#endif
-
-#ifdef LOGGING
-
-#define Log(level, message) { \
- if (vm_calls && level <= logging_level) \
- vm_calls->jio_fprintf(stderr, message); \
-}
-
-#define Log1(level, message, x1) { \
- if (vm_calls && level <= logging_level) \
- vm_calls->jio_fprintf(stderr, message, (x1)); \
-}
-
-#define Log2(level, message, x1, x2) { \
- if (vm_calls && level <= logging_level) \
- vm_calls->jio_fprintf(stderr, message, (x1), (x2)); \
-}
-
-#define Log3(level, message, x1, x2, x3) { \
- if (vm_calls && level <= logging_level) \
- vm_calls->jio_fprintf(stderr, message, (x1), (x2), (x3)); \
-}
-
-#define Log4(level, message, x1, x2, x3, x4) { \
- if (vm_calls && level <= logging_level) \
- vm_calls->jio_fprintf(stderr, message, (x1), (x2), (x3), (x4)); \
-}
-
-#else
-
-#define Log(level, message) ((void) 0)
-#define Log1(level, message, x1) ((void) 0)
-#define Log2(level, message, x1, x2) ((void) 0)
-#define Log3(level, message, x1, x2, x3) ((void) 0)
-#define Log4(level, message, x1, x2, x3, x4) ((void) 0)
-
-#endif /* LOGGING */
-
-#endif /* !_JAVASOFT_VM_CALLS_H_ */
--- a/jdk/src/share/hpi/src/hpi.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*
- * Copyright (c) 1998, 1999, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-#include <string.h>
-
-#include "hpi_impl.h"
-#include "threads_md.h"
-
-int logging_level = 0;
-bool_t profiler_on = FALSE;
-
-int sysSetLoggingLevel(int level)
-{
- int old = logging_level;
- logging_level = level;
- return old;
-}
-
-bool_t sysSetMonitoringOn(bool_t s)
-{
- bool_t old = profiler_on;
- profiler_on = s;
- return old;
-}
-
-int nReservedBytes;
-
-sys_thread_t *allocThreadBlock()
-{
- char *p = sysCalloc(nReservedBytes + sizeof(sys_thread_t), 1);
- if (p == NULL) {
- return NULL;
- }
- return (sys_thread_t *)(p + nReservedBytes);
-}
-
-void freeThreadBlock(sys_thread_t *tid)
-{
- sysFree((char *)tid - nReservedBytes);
-}
-
-vm_calls_t *vm_calls = NULL;
-
-static HPI_MemoryInterface hpi_memory_interface = {
- sysMalloc,
- sysRealloc,
- sysFree,
- sysCalloc,
- sysStrdup,
- sysMapMem,
- sysUnmapMem,
- sysCommitMem,
- sysDecommitMem,
- sysAllocBlock,
- sysFreeBlock,
-};
-
-static HPI_LibraryInterface hpi_library_interface = {
- sysBuildLibName,
- sysBuildFunName,
- sysLoadLibrary,
- sysUnloadLibrary,
- sysFindLibraryEntry,
-};
-
-static HPI_SystemInterface hpi_system_interface = {
- sysGetSysInfo,
- sysGetMilliTicks,
- sysTimeMillis,
- sysSignal,
- sysRaise,
- sysSignalNotify,
- sysSignalWait,
- sysShutdown,
- sysSetLoggingLevel,
- sysSetMonitoringOn,
- sysGetLastErrorString
-};
-
-static HPI_ThreadInterface hpi_thread_interface = {
- sysThreadBootstrap,
- sysThreadCreate,
- sysThreadSelf,
- sysThreadYield,
- sysThreadSuspend,
- sysThreadResume,
- sysThreadSetPriority,
- sysThreadGetPriority,
- sysThreadStackPointer,
- sysThreadStackTop,
- sysThreadRegs,
- sysThreadSingle,
- sysThreadMulti,
- sysThreadEnumerateOver,
- sysThreadCheckStack,
- sysThreadPostException,
- sysThreadInterrupt,
- sysThreadIsInterrupted,
- sysThreadAlloc,
- sysThreadFree,
- sysThreadCPUTime,
- sysThreadGetStatus,
- sysThreadInterruptEvent,
- sysThreadNativeID,
- sysThreadIsRunning,
- sysThreadProfSuspend,
- sysThreadProfResume,
- sysAdjustTimeSlice,
- sysMonitorSizeof,
- sysMonitorInit,
- sysMonitorDestroy,
- sysMonitorEnter,
- sysMonitorEntered,
- sysMonitorExit,
- sysMonitorNotify,
- sysMonitorNotifyAll,
- sysMonitorWait,
- sysMonitorInUse,
- sysMonitorOwner,
- sysMonitorGetInfo,
-};
-
-static HPI_FileInterface hpi_file_interface = {
- sysNativePath,
- sysFileType,
- sysOpen,
- sysClose,
- sysSeek,
- sysSetLength,
- sysSync,
- sysAvailable,
- sysRead,
- sysWrite,
- sysFileSizeFD
-};
-
-static HPI_SocketInterface hpi_socket_interface = {
- sysSocketClose,
- sysSocketAvailable,
- sysConnect,
- sysAccept,
- sysSendTo,
- sysRecvFrom,
- sysListen,
- sysRecv,
- sysSend,
- sysTimeout,
- sysGetHostByName,
- sysSocket,
- sysSocketShutdown,
- sysBind,
- sysGetSockName,
- sysGetHostName,
- sysGetHostByAddr,
- sysGetSockOpt,
- sysSetSockOpt,
- sysGetProtoByName,
-};
-
-static jint JNICALL
-GetInterface(void **intfP, const char *name, jint version)
-{
- *intfP = NULL;
- if (version != 1) {
- return -1;
- }
- if (strcmp(name, "Memory") == 0) {
- *intfP = &hpi_memory_interface;
- return 0;
- }
- if (strcmp(name, "Library") == 0) {
- *intfP = &hpi_library_interface;
- return 0;
- }
- if (strcmp(name, "System") == 0) {
- *intfP = &hpi_system_interface;
- return 0;
- }
- if (strcmp(name, "Thread") == 0) {
- *intfP = &hpi_thread_interface;
- return 0;
- }
- if (strcmp(name, "File") == 0) {
- *intfP = &hpi_file_interface;
- return 0;
- }
- if (strcmp(name, "Socket") == 0) {
- *intfP = &hpi_socket_interface;
- return 0;
- }
- return -2;
-}
-
-jint JNICALL
-DLL_Initialize(GetInterfaceFunc *gi, void *args)
-{
- vm_calls = args;
- *gi = GetInterface;
- return SYS_OK;
-}
--- a/jdk/src/share/instrument/JPLISAgent.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/instrument/JPLISAgent.c Fri Feb 18 12:04:36 2011 -0800
@@ -209,7 +209,7 @@
*agent_ptr = NULL;
jnierror = (*vm)->GetEnv( vm,
(void **) &jvmtienv,
- JVMTI_VERSION);
+ JVMTI_VERSION_1_1);
if ( jnierror != JNI_OK ) {
initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
} else {
@@ -990,7 +990,7 @@
}
jnierror = (*agent->mJVM)->GetEnv( agent->mJVM,
(void **) &retransformerEnv,
- JVMTI_VERSION);
+ JVMTI_VERSION_1_1);
if ( jnierror != JNI_OK ) {
return NULL;
}
--- a/jdk/src/share/javavm/export/jmm.h Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/javavm/export/jmm.h Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2006, 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
@@ -60,7 +60,8 @@
unsigned int isBootClassPathSupported : 1;
unsigned int isObjectMonitorUsageSupported : 1;
unsigned int isSynchronizerUsageSupported : 1;
- unsigned int : 24;
+ unsigned int isThreadAllocatedMemorySupported : 1;
+ unsigned int : 23;
} jmmOptionalSupport;
typedef enum {
@@ -105,7 +106,8 @@
JMM_VERBOSE_GC = 21,
JMM_VERBOSE_CLASS = 22,
JMM_THREAD_CONTENTION_MONITORING = 23,
- JMM_THREAD_CPU_TIME = 24
+ JMM_THREAD_CPU_TIME = 24,
+ JMM_THREAD_ALLOCATED_MEMORY = 25
} jmmBoolAttribute;
@@ -213,7 +215,10 @@
jobject (JNICALL *GetMemoryPoolUsage) (JNIEnv* env, jobject pool);
jobject (JNICALL *GetPeakMemoryPoolUsage) (JNIEnv* env, jobject pool);
- void* reserved4;
+ void (JNICALL *GetThreadAllocatedMemory)
+ (JNIEnv *env,
+ jlongArray ids,
+ jlongArray sizeArray);
jobject (JNICALL *GetMemoryUsage) (JNIEnv* env, jboolean heap);
@@ -228,6 +233,8 @@
jlong* result);
jobjectArray (JNICALL *FindCircularBlockedThreads) (JNIEnv *env);
+
+ // Not used in JDK 6 or JDK 7
jlong (JNICALL *GetThreadCpuTime) (JNIEnv *env, jlong thread_id);
jobjectArray (JNICALL *GetVMGlobalNames) (JNIEnv *env);
@@ -262,14 +269,22 @@
void (JNICALL *GetLastGCStat) (JNIEnv *env,
jobject mgr,
jmmGCStat *gc_stat);
- jlong (JNICALL *GetThreadCpuTimeWithKind) (JNIEnv *env,
- jlong thread_id,
- jboolean user_sys_cpu_time);
- void* reserved5;
+
+ jlong (JNICALL *GetThreadCpuTimeWithKind)
+ (JNIEnv *env,
+ jlong thread_id,
+ jboolean user_sys_cpu_time);
+ void (JNICALL *GetThreadCpuTimesWithKind)
+ (JNIEnv *env,
+ jlongArray ids,
+ jlongArray timeArray,
+ jboolean user_sys_cpu_time);
+
jint (JNICALL *DumpHeap0) (JNIEnv *env,
jstring outputfile,
jboolean live);
- jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env, jboolean object_monitors_only);
+ jobjectArray (JNICALL *FindDeadlocks) (JNIEnv *env,
+ jboolean object_monitors_only);
void (JNICALL *SetVMGlobal) (JNIEnv *env,
jstring flag_name,
jvalue new_value);
--- a/jdk/src/share/javavm/export/jvmti.h Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/javavm/export/jvmti.h Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -41,8 +41,9 @@
JVMTI_VERSION_1 = 0x30010000,
JVMTI_VERSION_1_0 = 0x30010000,
JVMTI_VERSION_1_1 = 0x30010100,
-
- JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (1 * 0x100) + 102 /* version: 1.1.102 */
+ JVMTI_VERSION_1_2 = 0x30010200,
+
+ JVMTI_VERSION = 0x30000000 + (1 * 0x10000) + (2 * 0x100) + 1 /* version: 1.2.1 */
};
JNIEXPORT jint JNICALL
@@ -1774,6 +1775,12 @@
jobject object,
jlong* size_ptr);
+ /* 155 : Get Local Instance */
+ jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
+ jthread thread,
+ jint depth,
+ jobject* value_ptr);
+
} jvmtiInterface_1;
struct _jvmtiEnv {
@@ -2031,6 +2038,12 @@
return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
}
+ jvmtiError GetLocalInstance(jthread thread,
+ jint depth,
+ jobject* value_ptr) {
+ return functions->GetLocalInstance(this, thread, depth, value_ptr);
+ }
+
jvmtiError GetLocalInt(jthread thread,
jint depth,
jint slot,
@@ -2518,3 +2531,4 @@
#endif /* __cplusplus */
#endif /* !_JAVA_JVMTI_H_ */
+
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Fri Feb 18 12:04:36 2011 -0800
@@ -109,8 +109,8 @@
jobject stream; // ImageInputStream or ImageOutputStream
jbyteArray hstreamBuffer; // Handle to a Java buffer for the stream
JOCTET *buf; // Pinned buffer pointer */
- int bufferOffset; // holds offset between unpin and the next pin
- int bufferLength; // Allocated, nut just used
+ size_t bufferOffset; // holds offset between unpin and the next pin
+ size_t bufferLength; // Allocated, nut just used
int suspendable; // Set to true to suspend input
long remaining_skip; // Used only on input
} streamBuffer, *streamBufferPtr;
@@ -129,7 +129,7 @@
* Used to signal that no data need be restored from an unpin to a pin.
* I.e. the buffer is empty.
*/
-#define NO_DATA -1
+#define NO_DATA ((size_t)-1)
// Forward reference
static void resetStreamBuffer(JNIEnv *env, streamBufferPtr sb);
@@ -389,7 +389,6 @@
static imageIODataPtr initImageioData (JNIEnv *env,
j_common_ptr cinfo,
jobject obj) {
- int i, j;
imageIODataPtr data = (imageIODataPtr) malloc (sizeof(imageIOData));
if (data == NULL) {
@@ -982,7 +981,7 @@
streamBufferPtr sb = &data->streamBuf;
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jint ret;
- int offset, buflen;
+ size_t offset, buflen;
/*
* The original (jpegdecoder.c) had code here that called
@@ -1520,7 +1519,7 @@
imageio_dispose((j_common_ptr)cinfo);
return 0;
}
- return (jlong) ret;
+ return ptr_to_jlong(ret);
}
/*
@@ -1535,7 +1534,7 @@
jlong ptr,
jobject source) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_common_ptr cinfo;
if (data == NULL) {
@@ -1574,7 +1573,7 @@
int h_samp0, h_samp1, h_samp2;
int v_samp0, v_samp1, v_samp2;
jboolean retval = JNI_FALSE;
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_decompress_ptr cinfo;
struct jpeg_source_mgr *src;
sun_jpeg_error_ptr jerr;
@@ -1772,7 +1771,7 @@
jlong ptr,
jint code) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_decompress_ptr cinfo;
if (data == NULL) {
@@ -1814,7 +1813,7 @@
struct jpeg_source_mgr *src;
JSAMPROW scanLinePtr = NULL;
jint bands[MAX_BANDS];
- int i, j;
+ int i;
jint *body;
int scanlineLimit;
int pixelStride;
@@ -1824,14 +1823,12 @@
pixelBufferPtr pb;
sun_jpeg_error_ptr jerr;
boolean done;
- jint *bandSize;
- int maxBandValue, halfMaxBandValue;
boolean mustScale = FALSE;
boolean progressive = FALSE;
boolean orderedBands = TRUE;
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_decompress_ptr cinfo;
- unsigned int numBytes;
+ size_t numBytes;
/* verify the inputs */
@@ -1849,7 +1846,7 @@
cinfo = (j_decompress_ptr) data->jpegObj;
- if ((numBands < 1) ||
+ if ((numBands < 1) || (numBands > MAX_BANDS) ||
(sourceXStart < 0) || (sourceXStart >= (jint)cinfo->image_width) ||
(sourceYStart < 0) || (sourceYStart >= (jint)cinfo->image_height) ||
(sourceWidth < 1) || (sourceWidth > (jint)cinfo->image_width) ||
@@ -1863,10 +1860,10 @@
return JNI_FALSE;
}
- if (stepX > cinfo->image_width) {
+ if (stepX > (jint)cinfo->image_width) {
stepX = cinfo->image_width;
}
- if (stepY > cinfo->image_height) {
+ if (stepY > (jint)cinfo->image_height) {
stepY = cinfo->image_height;
}
@@ -2119,7 +2116,7 @@
jobject this,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
if (data == NULL) {
JNU_ThrowByName(env,
@@ -2137,7 +2134,7 @@
(JNIEnv *env,
jobject this,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_decompress_ptr cinfo;
if (data == NULL) {
@@ -2159,7 +2156,7 @@
jobject this,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_decompress_ptr cinfo;
sun_jpeg_error_ptr jerr;
@@ -2232,7 +2229,7 @@
jclass reader,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_common_ptr info = destroyImageioData(env, data);
imageio_dispose(info);
@@ -2317,8 +2314,8 @@
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
/* find out how much needs to be written */
- jint datacount = sb->bufferLength - dest->free_in_buffer;
-
+ /* this conversion from size_t to jint is safe, because the lenght of the buffer is limited by jint */
+ jint datacount = (jint)(sb->bufferLength - dest->free_in_buffer);
if (datacount != 0) {
RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
@@ -2485,7 +2482,7 @@
imageio_dispose((j_common_ptr)cinfo);
return 0;
}
- return (jlong) ret;
+ return ptr_to_jlong(ret);
}
JNIEXPORT void JNICALL
@@ -2495,7 +2492,7 @@
jlong ptr,
jobject destination) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo;
if (data == NULL) {
@@ -2526,7 +2523,7 @@
struct jpeg_destination_mgr *dest;
sun_jpeg_error_ptr jerr;
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo;
if (data == NULL) {
@@ -2625,10 +2622,11 @@
jint *scanData;
jint *bandSize;
int maxBandValue, halfMaxBandValue;
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo;
UINT8** scale = NULL;
+
/* verify the inputs */
if (data == NULL) {
@@ -2740,6 +2738,16 @@
buffer);
JNU_ThrowByName(env, "javax/imageio/IIOException", buffer);
}
+
+ if (scale != NULL) {
+ for (i = 0; i < numBands; i++) {
+ if (scale[i] != NULL) {
+ free(scale[i]);
+ }
+ }
+ free(scale);
+ }
+
free(scanLinePtr);
return data->abortFlag;
}
@@ -2953,7 +2961,7 @@
jobject this,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
if (data == NULL) {
JNU_ThrowByName(env,
@@ -2970,7 +2978,7 @@
(JNIEnv *env,
jobject this,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo;
if (data == NULL) {
@@ -3002,7 +3010,7 @@
jclass writer,
jlong ptr) {
- imageIODataPtr data = (imageIODataPtr) ptr;
+ imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_common_ptr info = destroyImageioData(env, data);
imageio_dispose(info);
--- a/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jdmarker.c Fri Feb 18 12:04:36 2011 -0800
@@ -1325,14 +1325,14 @@
unsigned int length_limit)
{
my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
- long maxlength;
+ size_t maxlength;
jpeg_marker_parser_method processor;
/* Length limit mustn't be larger than what we can allocate
* (should only be a concern in a 16-bit environment).
*/
maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
- if (((long) length_limit) > maxlength)
+ if (length_limit > maxlength)
length_limit = (unsigned int) maxlength;
/* Choose processor routine to use.
--- a/jdk/src/share/native/sun/awt/image/jpeg/jmemmgr.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jmemmgr.c Fri Feb 18 12:04:36 2011 -0800
@@ -133,7 +133,7 @@
jvirt_barray_ptr virt_barray_list;
/* This counts total space obtained from jpeg_get_small/large */
- long total_space_allocated;
+ size_t total_space_allocated;
/* alloc_sarray and alloc_barray set this value for use by virtual
* array routines.
@@ -588,8 +588,8 @@
/* Allocate the in-memory buffers for any unrealized virtual arrays */
{
my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
- long space_per_minheight, maximum_space, avail_mem;
- long minheights, max_minheights;
+ size_t space_per_minheight, maximum_space, avail_mem;
+ size_t minheights, max_minheights;
jvirt_sarray_ptr sptr;
jvirt_barray_ptr bptr;
@@ -1032,7 +1032,7 @@
jinit_memory_mgr (j_common_ptr cinfo)
{
my_mem_ptr mem;
- long max_to_use;
+ size_t max_to_use;
int pool;
size_t test_mac;
@@ -1109,8 +1109,10 @@
if ((memenv = getenv("JPEGMEM")) != NULL) {
char ch = 'x';
+ unsigned int mem_max = 0u;
- if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
+ if (sscanf(memenv, "%u%c", &mem_max, &ch) > 0) {
+ max_to_use = (size_t)mem_max;
if (ch == 'm' || ch == 'M')
max_to_use *= 1000L;
mem->pub.max_memory_to_use = max_to_use * 1000L;
--- a/jdk/src/share/native/sun/awt/image/jpeg/jmemnobs.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jmemnobs.c Fri Feb 18 12:04:36 2011 -0800
@@ -73,9 +73,9 @@
* Here we always say, "we got all you want bud!"
*/
-GLOBAL(long)
-jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
- long max_bytes_needed, long already_allocated)
+GLOBAL(size_t)
+jpeg_mem_available (j_common_ptr cinfo, size_t min_bytes_needed,
+ size_t max_bytes_needed, size_t already_allocated)
{
return max_bytes_needed;
}
@@ -100,7 +100,7 @@
* cleanup required. Here, there isn't any.
*/
-GLOBAL(long)
+GLOBAL(size_t)
jpeg_mem_init (j_common_ptr cinfo)
{
return 0; /* just set max_memory_to_use to 0 */
--- a/jdk/src/share/native/sun/awt/image/jpeg/jmemsys.h Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jmemsys.h Fri Feb 18 12:04:36 2011 -0800
@@ -104,10 +104,10 @@
* Conversely, zero may be returned to always use the minimum amount of memory.
*/
-EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo,
- long min_bytes_needed,
- long max_bytes_needed,
- long already_allocated));
+EXTERN(size_t) jpeg_mem_available JPP((j_common_ptr cinfo,
+ size_t min_bytes_needed,
+ size_t max_bytes_needed,
+ size_t already_allocated));
/*
@@ -198,5 +198,5 @@
* all opened backing-store objects have been closed.
*/
-EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
+EXTERN(size_t) jpeg_mem_init JPP((j_common_ptr cinfo));
EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));
--- a/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jpegdecoder.c Fri Feb 18 12:04:36 2011 -0800
@@ -328,7 +328,7 @@
if ((*env)->ExceptionOccurred(env) || !GET_ARRAYS(env, src)) {
cinfo->err->error_exit((struct jpeg_common_struct *) cinfo);
}
- if (ret <= src->remaining_skip) {
+ if (ret < 0 || (unsigned int)ret <= src->remaining_skip) {
return;
}
if (src->remaining_skip) {
@@ -397,7 +397,7 @@
}
num_bytes += src->remaining_skip;
src->remaining_skip = 0;
- ret = src->pub.bytes_in_buffer;
+ ret = (int)src->pub.bytes_in_buffer; /* this conversion is safe, because capacity of the buffer is limited by jnit */
if (ret >= num_bytes) {
src->pub.next_input_byte += num_bytes;
src->pub.bytes_in_buffer -= num_bytes;
--- a/jdk/src/share/native/sun/awt/image/jpeg/jpeglib.h Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/awt/image/jpeg/jpeglib.h Fri Feb 18 12:04:36 2011 -0800
@@ -800,10 +800,10 @@
* used for virtual-array buffers.) May be changed by outer application
* after creating the JPEG object.
*/
- long max_memory_to_use;
+ size_t max_memory_to_use;
/* Maximum allocation request accepted by alloc_large. */
- long max_alloc_chunk;
+ size_t max_alloc_chunk;
};
--- a/jdk/src/share/native/sun/management/ThreadImpl.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/management/ThreadImpl.c Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -42,9 +42,15 @@
jmm_interface->SetBoolAttribute(env, JMM_THREAD_CPU_TIME, flag);
}
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_setThreadAllocatedMemoryEnabled0
+ (JNIEnv *env, jclass cls, jboolean flag)
+{
+ jmm_interface->SetBoolAttribute(env, JMM_THREAD_ALLOCATED_MEMORY, flag);
+}
JNIEXPORT void JNICALL
-Java_sun_management_ThreadImpl_getThreadInfo0
+Java_sun_management_ThreadImpl_getThreadInfo1
(JNIEnv *env, jclass cls, jlongArray ids, jint maxDepth,
jobjectArray infoArray)
{
@@ -65,6 +71,14 @@
return jmm_interface->GetThreadCpuTimeWithKind(env, tid, JNI_TRUE /* user+sys */);
}
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_getThreadTotalCpuTime1
+ (JNIEnv *env, jclass cls, jlongArray ids, jlongArray timeArray)
+{
+ jmm_interface->GetThreadCpuTimesWithKind(env, ids, timeArray,
+ JNI_TRUE /* user+sys */);
+}
+
JNIEXPORT jlong JNICALL
Java_sun_management_ThreadImpl_getThreadUserCpuTime0
(JNIEnv *env, jclass cls, jlong tid)
@@ -72,6 +86,21 @@
return jmm_interface->GetThreadCpuTimeWithKind(env, tid, JNI_FALSE /* user */);
}
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_getThreadUserCpuTime1
+ (JNIEnv *env, jclass cls, jlongArray ids, jlongArray timeArray)
+{
+ jmm_interface->GetThreadCpuTimesWithKind(env, ids, timeArray,
+ JNI_FALSE /* user */);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_management_ThreadImpl_getThreadAllocatedMemory1
+ (JNIEnv *env, jclass cls, jlongArray ids, jlongArray sizeArray)
+{
+ jmm_interface->GetThreadAllocatedMemory(env, ids, sizeArray);
+}
+
JNIEXPORT jobjectArray JNICALL
Java_sun_management_ThreadImpl_findMonitorDeadlockedThreads0
(JNIEnv *env, jclass cls)
--- a/jdk/src/share/native/sun/management/VMManagementImpl.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/share/native/sun/management/VMManagementImpl.c Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2006, 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,6 +92,9 @@
setStaticBooleanField(env, cls, "objectMonitorUsageSupport", JNI_FALSE);
setStaticBooleanField(env, cls, "synchronizerUsageSupport", JNI_FALSE);
}
+
+ value = mos.isThreadAllocatedMemorySupported;
+ setStaticBooleanField(env, cls, "threadAllocatedMemorySupport", value);
}
JNIEXPORT jobjectArray JNICALL
@@ -201,6 +204,13 @@
return jmm_interface->GetBoolAttribute(env, JMM_THREAD_CPU_TIME);
}
+JNIEXPORT jboolean JNICALL
+Java_sun_management_VMManagementImpl_isThreadAllocatedMemoryEnabled
+ (JNIEnv *env, jobject dummy)
+{
+ return jmm_interface->GetBoolAttribute(env, JMM_THREAD_ALLOCATED_MEMORY);
+}
+
JNIEXPORT jint JNICALL
Java_sun_management_VMManagementImpl_getProcessId
(JNIEnv *env, jobject dummy)
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java Fri Feb 18 12:04:36 2011 -0800
@@ -479,8 +479,7 @@
if (xrpipe == null) {
try {
SunToolkit.awtLock();
- xgc = renderQueue.createGC(xid); // TODO: GC leak? where to
- // clean up?
+ xgc = XCreateGC(getNativeOps());
xrpipe = new XRRenderer(maskBuffer.getMaskBuffer());
xrtxpipe = new PixelToShapeConverter(xrpipe);
--- a/jdk/src/solaris/hpi/export/byteorder_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Solaris-dependent byte order include
- */
-
-#ifndef _JAVASOFT_SOLARIS_BYTE_MD_H_
-#define _JAVASOFT_SOLARIS_BYTE_MD_H_
-
-#include <netinet/in.h>
-
-#endif /* !_JAVASOFT_SOLARIS_BYTE_MD_H_ */
--- a/jdk/src/solaris/hpi/export/hpi_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_HPI_MD_H_
-#define _JAVASOFT_HPI_MD_H_
-
-#include "timeval_md.h"
-#include "io_md.h"
-#include "path_md.h"
-#include "byteorder_md.h"
-
-#define HPI_TIMEOUT_INFINITY ((jlong)(-1))
-
-#endif /* !_JAVASOFT_HPI_MD_H_ */
--- a/jdk/src/solaris/hpi/export/io_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Solaris-dependent I/O
- */
-
-#ifndef _JAVASOFT_SOLARIS_IO_MD_H_
-#define _JAVASOFT_SOLARIS_IO_MD_H_
-
-#include <sys/param.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-#define LINE_SEPARATOR "\n"
-
-/* file system macros moved to sysmacros_md.h */
-
-#endif /* !_JAVASOFT_SOLARIS_IO_MD_H_ */
--- a/jdk/src/solaris/hpi/export/path_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Solaris-dependent search path definitions and API
- */
-
-#ifndef _JAVASOFT_SOLARIS_PATH_MD_H_
-#define _JAVASOFT_SOLARIS_PATH_MD_H_
-
-#define PATH_SEPARATOR ":"
-#define PATH_CURDIR "."
-
-#define DIR_SEPARATOR '/'
-#define LOCAL_DIR_SEPARATOR '/'
-
-#endif /* !_JAVASOFT_SOLARIS_PATH_MD_H_ */
--- a/jdk/src/solaris/hpi/export/timeval_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_SOLARIS_TIMEVAL_H_
-#define _JAVASOFT_SOLARIS_TIMEVAL_H_
-
-typedef struct {
- long tv_sec; /* seconds */
- long tv_usec; /* microseconds (NOT milliseconds) */
-} timeval_t;
-
-#endif /* !_JAVASOFT_SOLARIS_TIMEVAL_H_ */
--- a/jdk/src/solaris/hpi/include/hpi_init.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_SOLARIS_HPI_INIT_H_
-#define _JAVASOFT_SOLARIS_HPI_INIT_H_
-
-#ifndef NATIVE
-extern void InitializeSbrk(void);
-extern void InitializeAsyncIO(void);
-extern void InitializeHelperThreads(void);
-#endif /* NATIVE */
-
-extern void InitializeMem(void);
-
-#endif /* _JAVASOFT_SOLARIS_HPI_INIT_H_ */
--- a/jdk/src/solaris/hpi/include/interrupt.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 1994, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Interrupt dispatch interface
- */
-
-#ifndef _JAVASOFT_INTERRUPT_H_
-#define _JAVASOFT_INTERRUPT_H_
-
-/*
- * Type definitions.
- */
-
-/*-
- * A function that handles interrupt dispatch requests is of type
- * intr_handler_t. This type definition is mostly for convenience.
- * A declaration of a handler function, should look like this:
- *
- * void myHandler(int interrupt, void *siginfo, void *context, void *arg);
- *
- * An intr_handler_t is constrained:
- *
- * - It runs on the exception stack.
- * - It cannot yield.
- * - It cannot allocate/free memory.
- * - It can only call interrupt-safe routines.
- *
- * "arg" is set to the "handlerArg" specified in intrRegister().
- */
-typedef void (*intr_handler_t)(int interrupt, void *siginfo,
- void *context, void *arg);
-
-/*
- * Routines.
- */
-
-/* Initialize the interrupt system */
-void intrInit(void);
-
-/* Set a handler for a particular interrupt */
-signal_handler_t intrRegister(int interrupt, intr_handler_t handler,
- void *handlerArg);
-
-/* Dispatch an interrupt (called from the low-level handlers) */
-void intrDispatch(int interrupt, void *siginfo, void *context);
-
-/*-
- * The target specific header file should define the following
- *
- * Constants
- *
- * N_INTERRUPTS - The number of interrupt channels. These
- * are numbered from 0 to (N_INTERRUPTS - 1).
- */
-#ifdef __linux__
-#define N_INTERRUPTS NSIG /* 0 to NSIG - 1*/
-#else
-#define N_INTERRUPTS 32 /* 0 to 31 */
-#endif
-
-/*-
- * Routines/Macros that control whether interrupts are enabled or
- * not.
- *
- * void intrLock(void) - Disable all interrupts.
- * void intrUnlock(void) - Enable all interrupts.
- *
- * Note: intrLock()/intrUnlock() pairs can be nested.
- *
- */
-
-void intrLock(void);
-void intrUnlock(void);
-
-/*-
- * intrInitMD() --
- * Initialize the machine-dependant interrupt software.
- *
- * This routine should leave the all interrupts disabled as if
- * one (1) intrLock() had been called. At the end of the
- * bootstrap, a single intrUnlock(), will be called to turn
- * interrupts on.
- */
-
-void intrInitMD(void);
-
-#if defined(__solaris__) && !defined(SA_SIGINFO)
-#error signal.h has not been included?
-#endif
-
-#ifdef SA_SIGINFO
-/* Thread implementation dependent interrupt dispatcher. */
-void intrDispatchMD(int sig, siginfo_t *info, void *uc);
-#else
-void intrDispatchMD(int sig);
-#endif
-
-/* Whether the signal is used by the HPI implementation */
-bool_t intrInUse(int sig);
-
-#endif /* !_JAVASOFT_INTERRUPT_H_ */
--- a/jdk/src/solaris/hpi/include/largefile.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1999, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_LARGEFILE_SUPPORT_H_
-#define _JAVASOFT_LARGEFILE_SUPPORT_H_
-
-#ifdef __solaris__
-#include "largefile_solaris.h"
-#endif
-
-#ifdef __linux__
-#include "largefile_linux.h"
-#endif
-
-/*
- * Prototypes for wrappers that we define. These wrapper functions
- * are low-level I/O routines that will use 64 bit versions if
- * available, else revert to the 32 bit ones.
- */
-extern off64_t lseek64_w(int fd, off64_t offset, int whence);
-extern int fstat64_w(int fd, struct stat *buf);
-extern int ftruncate64_w(int fd, off64_t length);
-extern int open64_w(const char *path, int oflag, int mode);
-
-/* This is defined in system_md.c */
-extern int sysFfileMode(int fd, int* mode);
-
-#endif /* _JAVASOFT_LARGEFILE_SUPPORT_H_ */
--- a/jdk/src/solaris/hpi/include/largefile_linux.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 1999, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_
-#define _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_
-
-/*
- * For building on glibc-2.0 we need to define stat64 here.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#endif /* _JAVASOFT_LINUX_LARGEFILE_SUPPORT_H_ */
--- a/jdk/src/solaris/hpi/include/largefile_solaris.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 1998, 1999, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_
-#define _JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-/**
- * This file contains the definitions for providing 64 bit File I/O support.
- */
-
-#if !defined(_LFS_LARGEFILE) || !_LFS_LARGEFILE
-
-#ifdef __GLIBC__
-typedef jlong longlong_t;
-#endif
-
-/*
- * This definition is from Solaris 2.6; it is required by systems that do not
- * support large files (e.g., Solaris 2.5.1).
- */
-
-typedef longlong_t off64_t; /* offsets within files */
-
-
-#ifdef __GLIBC__
-/* Doesn't matter what these are, there is no 64 bit support. */
-typedef int u_longlong_t;
-typedef int timestruc_t;
-#define _ST_FSTYPSZ 1
-#endif /* __GLIBC__ */
-
-/*
- * The stat64 structure must be provided on systems without large file
- * support (e.g., Solaris 2.5.1). These definitions are from Solaris 2.6
- * sys/stat.h and sys/types.h.
- */
-
-typedef u_longlong_t ino64_t; /* expanded inode type */
-typedef longlong_t blkcnt64_t; /* count of file blocks */
-
-struct stat64 {
- dev_t st_dev;
- long st_pad1[3];
- ino64_t st_ino;
- mode_t st_mode;
- nlink_t st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- dev_t st_rdev;
- long st_pad2[2];
- off64_t st_size;
- timestruc_t st_atim;
- timestruc_t st_mtim;
- timestruc_t st_ctim;
- long st_blksize;
- blkcnt64_t st_blocks;
- char st_fstype[_ST_FSTYPSZ];
- long st_pad4[8];
-};
-
-#define O_LARGEFILE 0x2000 /* Solaris 2.6 sys/fcntl.h */
-#endif /* !_LFS_LARGEFILE */
-
-#endif /* !_JAVASOFT_SOLARIS_LARGEFILE_SUPPORT_H_ */
--- a/jdk/src/solaris/hpi/native_threads/include/condvar_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Interface to condition variable HPI implementation for Solaris
- */
-
-#ifndef _JAVASOFT_CONDVAR_MD_H_
-#define _JAVASOFT_CONDVAR_MD_H_
-
-#include "threads_md.h"
-
-typedef struct condvar {
- cond_t cond; /* Manual-reset event for notifications */
- unsigned int counter; /* Current number of notifications */
-} condvar_t;
-
-int condvarInit(condvar_t *);
-int condvarDestroy(condvar_t *);
-int condvarWait(condvar_t *, mutex_t *, thread_state_t wtype);
-int condvarTimedWait(condvar_t *, mutex_t *, jlong millis, thread_state_t wtype);
-int condvarSignal(condvar_t *);
-int condvarBroadcast(condvar_t *);
-
-#endif /* !_JAVASOFT_CONDVAR_MD_H_ */
--- a/jdk/src/solaris/hpi/native_threads/include/monitor_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Monitor interface 10/25/94
- *
- * Private data structures and interfaces used in the monitor code.
- * This file is used to share declarations and such between the different
- * files implementing monitors. It does not contain exported API.
- */
-
-#ifndef _JAVASOFT_SOLARIS_MONITOR_MD_H_
-#define _JAVASOFT_SOLARIS_MONITOR_MD_H_
-
-#include <mutex_md.h>
-#include <condvar_md.h>
-#include <threads_md.h>
-
-/*
- * Type definitions.
- */
-
-typedef struct monitor_waiter monitor_waiter_t;
-typedef struct monitor_wait_queue monitor_wait_queue_t;
-
-/* Element of the MonitorWaitQ - representing thread doing a monitor wait */
-/*
- * The only reason we do the queueing is for sysMonitorDumpInfo.
- * The counting, though, is used to avoid extraneous calls to
- * condvarBroadcast and condvarSignal, for instance.
- */
-struct monitor_waiter {
- monitor_waiter_t *next;
- monitor_waiter_t **prev;
- sys_thread_t *waiting_thread;
-};
-
-struct monitor_wait_queue {
- monitor_waiter_t *head; /* linked list of waiting threads */
- short count; /* number of waiters on the list */
-};
-
-#define ANY_WAITING(mwq) ((mwq).count > 0)
-#define INIT_MONITOR_WAIT_QUEUE(mwq) { (mwq).head = NULL; (mwq).count = 0; }
-
-/* The system-level monitor data structure */
-struct sys_mon {
- mutex_t mutex; /* The monitor's mutex */
- condvar_t cv_monitor; /* Notify those doing monitorWait on
- the monitor */
- /*
- * Threads waiting on either of the above condvars put themselves
- * on one of these lists.
- */
- monitor_wait_queue_t mwait_queue; /* Head of MonitorWaitQ */
-
- /* Thread currently executing in this monitor */
- sys_thread_t *monitor_owner;
- long entry_count; /* Recursion depth */
- int contention_count;
-};
-
-void initializeContentionCountMutex();
-
-typedef enum {
- ASYNC_REGISTER,
- ASYNC_UNREGISTER
-} async_action_t;
-
-/*
- * Macros
- */
-
-#define SYS_MID_NULL ((sys_mon_t *) 0)
-
-typedef enum {
- SYS_ASYNC_MON_ALARM = 1,
- SYS_ASYNC_MON_IO,
- SYS_ASYNC_MON_EVENT,
- SYS_ASYNC_MON_CHILD,
- SYS_ASYNC_MON_MAX
-} async_mon_key_t;
-
-#define SYS_ASYNC_MON_INPUT SYS_ASYNC_MON_IO
-#define SYS_ASYNC_MON_OUTPUT SYS_ASYNC_MON_IO
-
-sys_mon_t *asyncMon(async_mon_key_t);
-
-#endif /* !_JAVASOFT_SOLARIS_MONITOR_MD_H_ */
--- a/jdk/src/solaris/hpi/native_threads/include/mutex_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Interface to mutex HPI implementation for Solaris
- */
-
-#ifndef _JAVASOFT_MUTEX_MD_H_
-#define _JAVASOFT_MUTEX_MD_H_
-
-#include "porting.h"
-
-/*
- * Generally, we would typedef mutex_t to be whatever the system
- * supplies. But Solaris gives us mutex_t directly.
- */
-
-#ifdef USE_PTHREADS
-#define mutexInit(m) pthread_mutex_init(m, 0)
-#else
-#define mutexInit(m) mutex_init(m, USYNC_THREAD, 0)
-#endif
-#define mutexDestroy(m) mutex_destroy(m)
-#define mutexLock(m) mutex_lock(m)
-#define mutexUnlock(m) mutex_unlock(m)
-bool_t mutexLocked(mutex_t *);
-
-#endif /* !_JAVASOFT_MUTEX_MD_H_ */
--- a/jdk/src/solaris/hpi/native_threads/include/np.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 1998, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Non-posix parts of the threads HPI.
- */
-
-#ifndef _JAVASOFT_NP_H_
-#define _JAVASOFT_NP_H_
-
-extern int np_suspend(sys_thread_t *tid);
-extern int np_continue(sys_thread_t *tid);
-
-extern int np_single(void);
-extern void np_multi(void);
-extern int np_stackinfo(void **addr, long *size);
-extern int np_initialize(void);
-extern void np_initialize_thread(sys_thread_t *tid);
-#ifdef __linux__
-extern int np_initial_suspend(sys_thread_t *tid);
-extern void np_free_thread(sys_thread_t *tid);
-#endif
-
-extern void np_profiler_init(sys_thread_t *tid);
-extern int np_profiler_suspend(sys_thread_t *tid);
-extern int np_profiler_continue(sys_thread_t *tid);
-extern bool_t np_profiler_thread_is_running(sys_thread_t *tid);
-
-#endif /* !_JAVASOFT_NP_H_ */
--- a/jdk/src/solaris/hpi/native_threads/include/porting.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 1998, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_PORTING_H_
-#define _JAVASOFT_PORTING_H_
-
-#ifndef USE_PTHREADS
-
-#include <thread.h>
-#include <sys/lwp.h>
-#include <synch.h>
-
-#else /* USE_PTHREADS */
-
-#include <pthread.h>
-
-/* There is a handshake between a newly created thread and its creator
- * at thread startup because the creator thread needs to suspend the
- * new thread. Currently there are two ways to do this -- with
- * semaphores and with mutexes. The semaphore based implementation is
- * cleaner and hence is the default. We wish the mutex based one will
- * go away, but turns out the implementation of semaphores on
- * Linux/ppc etc is flaky, so the mutex based solution lives for now.
- */
-#ifndef USE_MUTEX_HANDSHAKE
-#include <semaphore.h>
-#endif
-
-#undef BOUND_THREADS
-
-#define thread_t pthread_t
-
-#define mutex_t pthread_mutex_t
-#define mutex_lock pthread_mutex_lock
-#define mutex_trylock pthread_mutex_trylock
-#define mutex_unlock pthread_mutex_unlock
-#define mutex_destroy pthread_mutex_destroy
-
-#define cond_t pthread_cond_t
-#define cond_destroy pthread_cond_destroy
-#define cond_wait pthread_cond_wait
-#define cond_timedwait pthread_cond_timedwait
-#define cond_signal pthread_cond_signal
-#define cond_broadcast pthread_cond_broadcast
-
-#define thread_key_t pthread_key_t
-#define thr_setspecific pthread_setspecific
-#define thr_keycreate pthread_key_create
-
-#define thr_sigsetmask pthread_sigmask
-#define thr_self pthread_self
-#define thr_yield sched_yield
-#define thr_kill pthread_kill
-#define thr_exit pthread_exit
-#ifdef __linux__
-void intrHandler(void*);
-#endif
-#endif /* USE_PTHREADS */
-
-#endif /* !_JAVASOFT_PORTING_H_ */
--- a/jdk/src/solaris/hpi/native_threads/include/threads_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 1994, 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Implementation of the Java threads HPI on top of Solaris threads
- */
-
-#ifndef _JAVASOFT_SOLARIS_THREADS_MD_H_
-#define _JAVASOFT_SOLARIS_THREADS_MD_H_
-
-#include "porting.h"
-
-#ifdef sparc
-#define N_TRACED_REGS 12
-#elif i386
-#define N_TRACED_REGS 7
-#elif amd64
-#define N_TRACED_REGS 15
-#elif ppc
-#define N_TRACED_REGS 1
-#elif m68k
-#define N_TRACED_REGS 8
-#elif ia64
-/* [RGV] I don't think this is referenced in the linux code */
-#define N_TRACED_REGS 32
-#else
-// TODO: delete this file - threads_md.[ch] is obsolete. struct sys_thread is
-// never used. Define a value just to keep compiler happy.
-#define N_TRACED_REGS 32
-#endif
-
-/* Turn on if we want all java threads to be bound tolwps */
-/* #define BOUND_THREADS */
-/* Use /proc soln to stop lwps in place of siglwp soln */
-#define PROCLWP
-
-/*
- * Thread C stack overflow check
-#define sysThreadCheckStack(redzone, var) \
- ((var = sysThreadSelf()) && \
- (unsigned int)((char *)&(var) - (char *)(var)->stack_base)\
- < (redzone))
-*/
-/*
- * Forward definition of machine dependent monitor struct
- */
-struct sys_mon;
-
-/*
- * The following thread states are really hints since there is no
- * interface to get at a native thread's true state. The states
- * are maintained by updating the states where ever possible
- * such as a transition to CONDVAR_WAIT occurs in the definition of
- * the routine condvarWait().
- * This state maintenance should disappear once we have a threads interface
- * to obtain a thread's state.
- */
-typedef enum {
- FIRST_THREAD_STATE,
- RUNNABLE = FIRST_THREAD_STATE,
- SUSPENDED,
- CONDVAR_WAIT,
- NUM_THREAD_STATES
-} thread_state_t;
-
-#if defined( USE_PTHREADS) && !defined(__linux__)
-/*
- * Mechanism for starting a new thread suspended.
- */
-typedef enum {
- NEW_THREAD_MUST_REQUEST_SUSPEND,
- NEW_THREAD_REQUESTED_SUSPEND,
- NEW_THREAD_SUSPENDED
-} new_thr_state_t;
-
-typedef struct {
- pthread_mutex_t m;
- pthread_cond_t c;
- new_thr_state_t state;
-} new_thr_cond_t;
-#endif /* USE_PTHREADS */
-
-/*
- * Machine dependent info in a sys_thread_t
- */
-struct sys_thread {
- /*
- * Fields below this point may change on a per-architecture basis
- * depending on how much work is needed to present the sysThread
- * model on any given thread implementation.
- */
- mutex_t mutex; /* per thread lock to protect thread fields */
- thread_t sys_thread; /* The native thread id */
- struct sys_thread *next; /* Pointer to next thread in the */
- /* queue of all threads. */
- thread_state_t state;
-
- /* Thread status flags */
- unsigned int primordial_thread:1;
- unsigned int system_thread:1;
- unsigned int cpending_suspend:1;
-#ifdef __linux__
- unsigned int pending_interrupt:1;
-#endif
- unsigned int interrupted:1;
- unsigned int onproc:1; /* set if thread is on an LWP */
- unsigned int :0;
-
-#ifdef BOUND_THREADS
- lwpid_t lwpid;
-#endif
-
-#ifdef __linux__
- void *sp;
-#else
- unsigned long sp; /* sp at time of last (native) thread switch */
-#endif
- void * stack_bottom; /* The real bottom (high address) of stack */
- void * stack_top; /* should be equal to stack_bottom - stack_size */
- long stack_size; /* The stack size for a native thread */
-
- long regs[N_TRACED_REGS]; /* stores registers as GC roots. */
-
- /* Monitor specific.
-
- Every monitor keeps track of the number of times it is
- entered. When that count goes to 0, the monitor can be
- freed up. But each thread has its own entry count on a
- particular monitor, because multiple threads can be using a
- single monitor (as one does a wait, another enters, etc.).
- Each thread can only be waiting in exactly one monitor.
- That monitor waited on is saved in mon_wait, and the value
- of the monitor's entry_count when the wait was performed is
- saved in monitor_entry_count. That is restored into the
- monitor when this waiting thread is notified. */
-
- long monitor_entry_count; /* For recursive monitor entry */
- struct sys_mon *mon_wait; /* CONDVAR_WAIT'ing */
-
- struct sys_mon *mon_enter; /* blocked waiting to enter */
-
- void (*start_proc)(void *);
- void *start_parm;
- int lwp_id;
- long last_sum;
-
- struct sys_thread *prevBlocked; /* Used by nonblocking close semantics */
- struct sys_thread *nextBlocked;
-#ifdef USE_PTHREADS
- int suspend_count;
-#ifdef __linux__
- sem_t sem_suspended;
- sem_t sem_ready_to_suspend;
- sem_t sem_selfsuspend;
- int selfsuspended;
-#endif
-#ifdef USE_MUTEX_HANDSHAKE
- new_thr_cond_t ntcond;
-#else
- sem_t sem;
-#endif /* USE_MUTEX_HANDSHAKE */
-#endif /* USE_PTHREADS */
-};
-
-#define SYS_THREAD_NULL ((sys_thread_t *) 0)
-
-/*
- * following macro copied from sys/signal.h since inside #ifdef _KERNEL there.
- */
-#ifndef sigmask
-#define sigmask(n) ((unsigned int)1 << (((n) - 1) & (32 - 1)))
-#endif
-
-#ifdef __linux__
-extern thread_key_t intrJmpbufkey;
-#else
-extern thread_key_t sigusr1Jmpbufkey;
-extern sigset_t sigusr1Mask;
-#endif
-
-extern sys_mon_t *_sys_queue_lock;
-
-#define SYS_QUEUE_LOCK(self) sysMonitorEnter(self, _sys_queue_lock)
-#define SYS_QUEUE_LOCKED(self) sysMonitorEntered(self, _sys_queue_lock)
-#define SYS_QUEUE_UNLOCK(self) sysMonitorExit(self, _sys_queue_lock)
-#define SYS_QUEUE_NOTIFYALL(self) sysMonitorNotifyAll(self, _sys_queue_lock)
-#define SYS_QUEUE_WAIT(self) sysMonitorWait(self, _sys_queue_lock, \
- SYS_TIMEOUT_INFINITY)
-
-extern void setFPMode(void);
-
-extern sys_thread_t *ThreadQueue;
-
-extern int ActiveThreadCount; /* All threads */
-
-#endif /* !_JAVASOFT_SOLARIS_THREADS_MD_H_ */
--- a/jdk/src/solaris/hpi/native_threads/src/condvar_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 1994, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Condition variable HPI implementation for Solaris
- */
-
-#include <errno.h>
-#include <time.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <limits.h>
-
-#include "hpi_impl.h"
-
-#include "condvar_md.h"
-#include "mutex_md.h"
-#include "threads_md.h"
-
-int
-condvarInit(condvar_t *condvar)
-{
- int err;
-
-#ifdef USE_PTHREADS
- err = pthread_cond_init(&condvar->cond, NULL);
-#else
- err = cond_init(&condvar->cond, USYNC_THREAD, 0 /* ignored */);
-#endif
- condvar->counter = 0;
- return (err == 0 ? SYS_OK : SYS_ERR);
-}
-
-int
-condvarDestroy(condvar_t *condvar)
-{
- int err;
-
-#ifdef __linux__
- err = pthread_cond_destroy((cond_t *) &condvar->cond);
-#else
- err = cond_destroy((cond_t *) condvar);
-#endif
- return (err == 0 ? SYS_OK : SYS_ERR);
-}
-
-int
-condvarWait(condvar_t *condvar, mutex_t *mutex, thread_state_t wtype)
-{
- sigjmp_buf jmpbuf;
- int err;
-
- sys_thread_t *self = sysThreadSelf();
- /*
- * There is no threads interface to get a thread's state. So, instead,
- * we use this hack so that the debugger agent can get at this thread's
- * state. Of course, this is not very reliable, but when a thread goes
- * to sleep, it *will* be reported as sleeping. During the transition
- * from running to sleep, it may be incorrectly reported, since the
- * setting of the state here is not atomic with the voluntary sleep.
- * The better fix is to extend the Solaris threads interface and have
- * the debugger agent call this interface OR to use libthread_db for
- * intra-process state reporting.
- *
- * Now, condition variables are used either for waiting to enter a
- * monitor (MONITOR_WAIT) or to execute a "wait()" method when already
- * holding a monitor (CONDVAR_WAIT). So, when condvarWait() is called
- * it could be to wait for a monitor or for a condition within a
- * monitor. This is indicated by the "wtype" argument to condvarWait().
- * This type is set in the thread state before going to sleep.
- */
- self->state = wtype;
-
-#ifdef __linux__
- /*
- * Register our intrHandler as a cleanup handler. If we get
- * interrupted (i.e. canceled), we longjmp out of this handler.
- */
- pthread_cleanup_push(intrHandler, NULL);
- if (setjmp(jmpbuf) == 0) {
- /*
- * Set the jmp buf and enable cancellation.
- */
- thr_setspecific(intrJmpbufkey, &jmpbuf);
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-
- /*
- * Note: pthread_cond_wait is _not_ interruptible on Linux
- */
-#else
- thr_setspecific(sigusr1Jmpbufkey, &jmpbuf);
- if (sigsetjmp(jmpbuf, 1) == 0) {
- sigset_t osigset;
-
- thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset);
-again:
-#endif
- err = cond_wait((cond_t *) condvar, (mutex_t *) mutex);
- switch(err) {
- case 0:
- err = SYS_OK;
- break;
-#ifndef __linux__
- case EINTR: /* Signals other than USR1 were received. */
- goto again;
-#endif
- default:
- err = SYS_ERR;
- }
-#ifdef __linux__
- /*
- * Disable cancellation and clear the jump buf.
- */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- thr_setspecific(intrJmpbufkey, NULL);
-#else
- thr_sigsetmask(SIG_SETMASK, &osigset, NULL);
-#endif
- } else {
- /*
- * we've received a SIGUSR1 to interrupt our wait. We just return
- * and something above use notices the change.
- * clear the jump buf just to be paranoid.
- */
-#ifndef __linux__
- thr_setspecific(sigusr1Jmpbufkey, NULL);
-#endif
- err = SYS_INTRPT;
- }
-#ifdef __linux__
- pthread_cleanup_pop(0);
-#endif
- /*
- * After having woken up, change the thread state to RUNNABLE, since
- * it is now runnable.
- */
- self->state = RUNNABLE;
-
- return err;
-}
-
-/*
- * Returns 0 if condition variable became true before timeout expired.
- * Returns 1 if timeout expired first.
- * Returns <0 if wait fails for any other reason.
- */
-int
-condvarTimedWait(condvar_t *condvar, mutex_t *mutex,
- jlong millis, thread_state_t wtype)
-{
-#ifdef __linux__
- jmp_buf jmpbuf;
-#else
- sigjmp_buf jmpbuf;
-#endif
- int err;
- struct timespec timeout;
- sys_thread_t *self;
- jlong end_time;
-
- if (millis < 0)
- return SYS_ERR;
-
- if (millis > (jlong)INT_MAX) {
- return condvarWait(condvar, mutex, wtype);
- }
-
- end_time = sysTimeMillis() + millis;
-
- self = sysThreadSelf();
- self->state = wtype;
-
-#ifdef __linux__
- /*
- * Register our intrHandler as a cleanup handler. If we get
- * interrupted (i.e. canceled), we longjmp out of this handler.
- */
- pthread_cleanup_push(intrHandler, NULL);
- if (setjmp(jmpbuf) == 0) {
- /*
- * Set the jmp buf and enable cancellation.
- */
- thr_setspecific(intrJmpbufkey, &jmpbuf);
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-
- /*
- * Calculate an absolute timeout value.
- */
- timeout.tv_sec = end_time / 1000;
- timeout.tv_nsec = (end_time % 1000) * 1000000;
-
- again:
-#else
- thr_setspecific(sigusr1Jmpbufkey, &jmpbuf);
- if (sigsetjmp(jmpbuf, 1) == 0) {
- sigset_t osigset;
-
- thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset);
-
- again:
- timeout.tv_sec = end_time / 1000;
- timeout.tv_nsec = (end_time % 1000) * 1000000;
-#endif
- err = cond_timedwait((cond_t *)condvar, (mutex_t *)mutex, &timeout);
- switch(err) {
- case 0:
- err = SYS_OK;
- break;
- case EINTR: /* Signals other than USR1 were received. */
- if (sysTimeMillis() < end_time) {
- goto again;
- }
- /*FALLTHRU*/
-#ifdef USE_PTHREADS
- case ETIMEDOUT:
-#else
- case ETIME:
-#endif
- err = SYS_TIMEOUT;
- break;
- default:
- err = SYS_ERR;
- }
-#ifdef __linux__
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- thr_setspecific(intrJmpbufkey, NULL);
-#else
- thr_sigsetmask(SIG_SETMASK, &osigset, NULL);
-#endif
- } else {
- /*
- * we've received a SIGUSR1 to interrupt our wait. We just return
- * and something above use notices the change.
- * clear the jump buf just to be paranoid.
- */
-#ifndef __linux__
- thr_setspecific(sigusr1Jmpbufkey, NULL);
-#endif
- err = SYS_INTRPT;
- }
-#ifdef __linux__
- /* Remove intrHandler without calling it. */
- pthread_cleanup_pop(0);
-
- sysAssert(pthread_mutex_trylock(mutex) == EBUSY);
-
- /*
- * After having woken up, change the thread state to RUNNABLE, since
- * it is now runnable.
- */
-#endif
- self->state = RUNNABLE;
- return err;
-}
-
-int
-condvarSignal(condvar_t *condvar)
-{
- int err;
-
- err = cond_signal((cond_t *) condvar);
- condvar->counter++;
- return (err == 0 ? SYS_OK : SYS_ERR);
-}
-
-int
-condvarBroadcast(condvar_t *condvar)
-{
- int err;
-
- err = cond_broadcast((cond_t *) condvar);
- condvar->counter++;
- return (err == 0 ? SYS_OK : SYS_ERR);
-}
--- a/jdk/src/solaris/hpi/native_threads/src/interrupt_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,229 +0,0 @@
-/*
- * Copyright (c) 1994, 2006, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Solaris 2.X dependant interrupt handling code.
- */
-
-/*
- * Header files.
- */
-#include <stdio.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "hpi_impl.h"
-
-#include "mutex_md.h"
-#include "condvar_md.h"
-#include "monitor_md.h"
-#include "threads_md.h"
-#include "interrupt.h"
-
-static int pending_signals[N_INTERRUPTS];
-
-/* Stubs used from interrupt.c: they are nontrivial on Green */
-void intrLock() {}
-void intrUnlock() {}
-#ifdef __linux__
-extern int sr_sigsusp;
-extern int sr_sigresu;
-#endif
-
-/* We need a special monitor implementation for signals because
- * signal handlers are not necessarily called in a Java thread.
- */
-struct {
- thread_t owner;
- unsigned int count;
- mutex_t mutex;
- condvar_t condvar;
-} userSigMon;
-
-static void sigMonitorInit()
-{
- userSigMon.owner = 0;
- userSigMon.count = 0;
- mutexInit(&userSigMon.mutex);
- condvarInit(&userSigMon.condvar);
-}
-
-static void sigMonitorEnter()
-{
- thread_t self = thr_self();
-
- if (userSigMon.owner == self) {
- userSigMon.count++;
- } else {
- mutex_lock(&userSigMon.mutex);
- userSigMon.owner = self;
- userSigMon.count = 1;
- }
-}
-
-static void sigMonitorExit()
-{
- thread_t self = thr_self();
-
- sysAssert(userSigMon.owner == self);
- sysAssert(userSigMon.count > 0);
- if (--userSigMon.count == 0) {
- userSigMon.owner = 0;
- mutex_unlock(&userSigMon.mutex);
- }
-}
-
-static void sigMonitorNotify()
-{
- thread_t self = thr_self();
-
- sysAssert(userSigMon.owner == self);
- sysAssert(userSigMon.count > 0);
- condvarSignal(&userSigMon.condvar);
-}
-
-static void sigMonitorWait()
-{
- thread_t self = thr_self();
-
- unsigned int saved_count = userSigMon.count;
-
- sysAssert(userSigMon.owner == self);
- sysAssert(userSigMon.count > 0);
-
- userSigMon.count = 0;
- userSigMon.owner = 0;
-
- condvarWait(&userSigMon.condvar, &userSigMon.mutex, CONDVAR_WAIT);
-
- sysAssert(userSigMon.owner == 0);
- sysAssert(userSigMon.count == 0);
-
- userSigMon.count = saved_count;
- userSigMon.owner = self;
-}
-
-static int
-my_sigignore(int sig)
-{
-#ifndef HAVE_SIGIGNORE
- struct sigaction action;
- sigset_t set;
-
- action.sa_handler = SIG_IGN;
- action.sa_flags = 0;
- sigemptyset(&action.sa_mask);
-
- if (sigaction(sig, &action, (struct sigaction *)0) < 0)
- return -1;
- sigemptyset(&set);
- if (sigaddset(&set, sig) < 0)
- return -1;
- return sigprocmask(SIG_UNBLOCK, &set, (sigset_t *)0);
-#else
- return sigignore(sig);
-#endif /* HAVE_SIGIGNORE */
-}
-
-
-/*
- * intrInitMD() -- Target-specific initialization.
- */
-extern void
-intrInitMD()
-{
- memset(pending_signals, 0, sizeof(pending_signals));
- (void)my_sigignore(SIGPIPE);
- sigMonitorInit();
-}
-
-/*-
- * intrDispatchMD() -- Turn our signal into an intrDispatch().
- */
-void
-#ifdef SA_SIGINFO
-intrDispatchMD(int sig, siginfo_t *info, void *uc)
-#else
-intrDispatchMD(int sig)
-#endif /* SA_SIGINFO */
-{
- Log1(1, "signalHandlerDispatch(sig=%d)\n", sig);
-
- sigMonitorEnter();
-#ifdef SA_SIGINFO
-#if defined(__linux__) && defined(__sparc__)
- uc = (((char *)&sig) + 4 + 0x20);
- info = (siginfo_t *)(((char *)uc) + 0x60);
-#endif
- intrDispatch(sig, info, uc);
-#else
- intrDispatch(sig, 0, 0);
-#endif /* SA_SIGINFO */
-
- sigMonitorExit();
-}
-
-bool_t intrInUse(int sig)
-{
- /* Signals used in native threads implementation. */
-#ifdef __linux__
- return sig == SIGPIPE || sig == sr_sigsusp || sig == sr_sigresu;
-#else
- return sig == SIGPIPE || sig == SIGUSR1;
-#endif
-}
-
-void sysSignalNotify(int sig)
-{
- sigMonitorEnter();
- pending_signals[sig]++;
- sigMonitorNotify();
- sigMonitorExit();
-}
-
-static int lookupSignal()
-{
- int i;
- for (i = 0; i < N_INTERRUPTS; i++) {
- if (pending_signals[i]) {
- pending_signals[i]--;
- return i;
- }
- }
- return -1;
-}
-
-int sysSignalWait()
-{
- int sig;
- sigMonitorEnter();
- while ((sig = lookupSignal()) == -1) {
- sigMonitorWait();
- }
- sigMonitorExit();
- return sig;
-}
--- a/jdk/src/solaris/hpi/native_threads/src/monitor_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,365 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Monitor implementation for Native Solaris threads
- *
- * Java Monitors are implemented using one solaris mutex and two
- * condition variables. Because solaris mutex is not re-entrant we
- * cannot simply have a monitor map to a mutex as re-entering a monitor
- * would deadlock an application.
- *
- * Monitor is implemented using:
- * mutex_t mutex;
- * condvar_t cv_monitor;
- * condvar_t cv_waiters;
- *
- * mutex protects the monitor state.
- * cv_monitor is the condtion variable used along with mutex for
- * supporting wait and notify on the monitor.
- * cv_waiters is used for all the threads waiting to acquire the monitor
- * lock.
- *
- * All of the sysMonitorXXX() functions that are passed a sys_mon_t
- * assume that they get something nonnull, and only check when debugging.
- */
-
-#include "hpi_impl.h"
-
-#include "threads_md.h"
-#include "monitor_md.h"
-
-#include <errno.h>
-#include <limits.h>
-
-static mutex_t contention_count_mutex;
-
-void initializeContentionCountMutex()
-{
- mutexInit(&contention_count_mutex);
-}
-
-/*
- * Operations on monitors
- */
-/*
- * Return the size of the lib-dependent portion of monitors. This
- * is done this way so that monitors can be all of one piece,
- * without paying the penalty of an extra level of indirection on
- * each sys_mon reference. This is not how it is done for threads
- * and it might be a good idea to use a pointer the same way that
- * threads do.
- */
-size_t
-sysMonitorSizeof()
-{
- return sizeof(struct sys_mon);
-}
-
-int
-sysMonitorInit(sys_mon_t *mid)
-{
- int ret;
-
- sysAssert(mid != SYS_MID_NULL);
- ret = mutexInit(&mid->mutex);
- ret = (ret == SYS_OK ? condvarInit(&mid->cv_monitor) : ret);
-
- mid->entry_count = 0;
- mid->monitor_owner = SYS_THREAD_NULL;
- mid->contention_count = 0;
- INIT_MONITOR_WAIT_QUEUE( mid->mwait_queue );
-
- return ret;
-}
-
-/*
- * Free any system-dependent resources held by monitors. There is
- * nothing to be done for native Solaris mutexes or condition variables.
- */
-int
-sysMonitorDestroy(sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- return SYS_OK;
-}
-
-static void
-enqueue_me(monitor_waiter_t *mp, monitor_wait_queue_t *queue,
- sys_thread_t *self)
-{
- /*
- * Order does not matter here. It is more convenient to
- * enqueue ourselves at the head of the list, so we do so.
- */
- mp->waiting_thread = self;
- mp->next = queue->head;
- mp->prev = &(queue->head);
- if ( queue->head != NULL ){
- queue->head->prev = &(mp->next);
- }
- queue->head = mp;
- queue->count++;
-}
-
-static void
-dequeue_me(monitor_waiter_t *mp, monitor_wait_queue_t *queue)
-{
- queue->count--;
- *(mp->prev) = mp->next;
- if (mp->next != NULL ){
- mp->next->prev = mp->prev;
- }
- mp->next = NULL;
-}
-
-int
-sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid)
-{
- int err;
-
- sysAssert(mid != SYS_MID_NULL);
- err = mutex_trylock(&mid->mutex);
- if (err == 0) { /* no one owns it */
- mid->monitor_owner = self;
- mid->entry_count = 1;
- return SYS_OK;
- } else if (err == EBUSY) { /* it's already locked */
- if (mid->monitor_owner == self) {
- mid->entry_count++;
- return SYS_OK;
- } else {
- self->mon_enter = mid;
- /* block on it */
- if (profiler_on) {
- VM_CALL(monitorContendedEnter)(self, mid);
- mutexLock(&contention_count_mutex);
- mid->contention_count++;
- mutexUnlock(&contention_count_mutex);
- }
- mutex_lock(&mid->mutex);
- mid->monitor_owner = self;
- mid->entry_count = 1;
- self->mon_enter = NULL;
- if (profiler_on) {
- mutexLock(&contention_count_mutex);
- mid->contention_count--;
- mutexUnlock(&contention_count_mutex);
- VM_CALL(monitorContendedEntered)(self, mid);
- }
- return SYS_OK;
- }
- } else {
- sysAssert(err == 0);
- return SYS_ERR;
- }
-}
-
-/*
- * Return true if we currently own this monitor (and threads have been
- * initialized.
- */
-bool_t
-sysMonitorEntered(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- /* We can only have locked monitors if threads have been initialized */
- return (mid->monitor_owner == self);
-}
-
-int
-sysMonitorExit(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- if (mid->monitor_owner == self) {
- sysAssert(mid->entry_count > 0);
- if (--mid->entry_count == 0) {
- mid->monitor_owner = SYS_THREAD_NULL;
- if (!mid->contention_count || !profiler_on) {
- mutex_unlock(&mid->mutex);
- } else {
- mutex_unlock(&mid->mutex);
- VM_CALL(monitorContendedExit)(self, mid);
- }
- }
- return SYS_OK;
- } else {
- return SYS_ERR;
- }
-}
-
-int
-sysMonitorNotify(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
- if (self == mid->monitor_owner) {
- if (ANY_WAITING(mid->mwait_queue)) {
- /* If there is someone doing a monitor wait */
- condvarSignal(&(mid->cv_monitor));
- }
- return SYS_OK;
- } else
- return SYS_ERR;
-}
-
-int
-sysMonitorNotifyAll(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
- if (self == mid->monitor_owner) {
- if (ANY_WAITING(mid->mwait_queue)) {
- /* If there is someone doing a monitor wait */
- condvarBroadcast(&(mid->cv_monitor));
- }
- return SYS_OK;
- } else
- return SYS_ERR;
-}
-
-int
-sysMonitorWait(sys_thread_t *self, sys_mon_t *mid, jlong millis)
-{
- int ret = SYS_OK;
- monitor_waiter_t me;
- sysAssert(mid != SYS_MID_NULL);
-
- if (self != mid->monitor_owner) {
- return SYS_ERR;
- }
- if (sysThreadIsInterrupted(self, TRUE)) {
- return SYS_INTRPT;
- }
-
- /* Prepare to wait: drop mutex ownership */
- sysAssert(self->monitor_entry_count == 0);
- sysAssert(self->mon_wait == 0);
- self->mon_wait = (sys_mon_t *) mid;
- self->monitor_entry_count = mid->entry_count;
- mid->entry_count = 0;
- mid->monitor_owner = SYS_THREAD_NULL;
-
- /* Add myself to the monitor waitq */
- enqueue_me(&me, &mid->mwait_queue, self);
- if (millis == SYS_TIMEOUT_INFINITY) {
- ret = condvarWait(&mid->cv_monitor, &mid->mutex, CONDVAR_WAIT);
- } else {
- ret = condvarTimedWait(&mid->cv_monitor, &mid->mutex, millis,
- CONDVAR_WAIT);
- }
- dequeue_me(&me, &mid->mwait_queue);
-
- sysAssert(mid->monitor_owner == NULL);
- sysAssert(mid->entry_count == 0);
- mid->monitor_owner = self;
- mid->entry_count = self->monitor_entry_count;
- self->monitor_entry_count = 0;
- self->mon_wait = 0;
-
- /* Did we get interrupted in mid-wait? (IS THIS THE RIGHT PLACE?) */
- if (sysThreadIsInterrupted(self, TRUE)) {
- return SYS_INTRPT;
- }
-
- return ret;
-}
-
-static int
-dumpWaitingQueue(monitor_wait_queue_t *queue, sys_thread_t **waiters, int sz)
-{
- int n;
- monitor_waiter_t * waiter;
- if (queue == NULL || ( waiter = queue->head ) == NULL ) {
- return 0;
- }
- for (n = 0; waiter != 0; waiter = waiter->next, n++, sz--) {
- if (sz > 0) {
- waiters[n] = waiter->waiting_thread;
- }
- }
- return n;
-}
-
-typedef struct {
- sys_mon_t *mid;
- sys_thread_t **waiters;
- int sz;
- int nwaiters;
-} wait_info;
-
-static int
-findWaitersHelper(sys_thread_t *t, void *arg)
-{
- wait_info * winfo = (wait_info *) arg;
- if (t->mon_enter == winfo->mid) {
- if (winfo->sz > 0) {
- winfo->waiters[winfo->nwaiters] = t;
- }
- winfo->sz--;
- winfo->nwaiters++;
- }
- return SYS_OK;
-}
-
-int
-sysMonitorGetInfo(sys_mon_t *mid, sys_mon_info *info)
-{
- wait_info winfo;
-
- sysAssert(mid != SYS_MID_NULL);
- info->owner = mid->monitor_owner;
- if (mid->monitor_owner) {
- info->entry_count = mid->entry_count;
- }
-
- winfo.mid = mid;
- winfo.nwaiters = 0;
- winfo.waiters = info->monitor_waiters;
- winfo.sz = info->sz_monitor_waiters;
- sysThreadEnumerateOver(findWaitersHelper, (void *) &winfo);
- info->n_monitor_waiters = winfo.nwaiters;
-
- info->n_condvar_waiters = dumpWaitingQueue(&mid->mwait_queue,
- info->condvar_waiters,
- info->sz_condvar_waiters);
-
- return SYS_OK;
-}
-
-
-bool_t
-sysMonitorInUse(sys_mon_t * mon)
-{
- return mon->monitor_owner != 0 ||
- mon->mwait_queue.count != 0;
-}
-
-sys_thread_t *
-sysMonitorOwner(sys_mon_t *mon)
-{
- return mon->monitor_owner;
-}
--- a/jdk/src/solaris/hpi/native_threads/src/mutex_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Mutex HPI implementation for Solaris
- *
- * Mutexes are used both by the system-independent monitor implementation and
- * to implement critical regions elsewhere within the runtime.
- */
-
-#include <errno.h>
-
-#include "hpi_impl.h"
-
-#include "mutex_md.h"
-#include "threads_md.h"
-
-/*
- * Return true of the mutex in question is already locked. note:
- * this does not tell if the mutex is already locked by *this*
- * thread, only that is is locked by *some* thread.
- */
-bool_t
-mutexLocked(mutex_t *mutex)
-{
- if (mutex_trylock(mutex) == 0) {
- mutex_unlock(mutex);
- return FALSE;
- }
- return TRUE;
-}
--- a/jdk/src/solaris/hpi/native_threads/src/sys_api_td.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 1997, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Solaris-dependent I/O Note: Routines here are just place holders -
- * eventually we need to put in a solution that involves using
- * setjmp/longjmp to avoid io races. Look at green_threads/io_md.c for
- * more detailed comments on the architechture of the io modules.
- */
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_FILIOH
-#include <sys/filio.h>
-#else
-#include <sys/ioctl.h>
-#endif
-
-#include <sys/socket.h>
-#include <setjmp.h>
-#include <signal.h>
-#ifndef USE_SELECT
-#include <poll.h>
-#endif
-
-#include "hpi_impl.h"
-
-#include "threads_md.h"
-#include "io_md.h"
-#include "largefile.h"
-#include "mutex_md.h"
-
-#if defined(__solaris__) && defined(NO_INTERRUPTIBLE_IO)
-#error If there was no policy change, this could be a makefile error.
-#endif
-
-#ifdef NO_INTERRUPTIBLE_IO
-#undef CLOSEIO
-#else
-#define CLOSEIO
-#endif /* NO_INTERRUPTIBLE_IO */
-
-/* Get typedef for rlim_t */
-#include <sys/resource.h>
-
-#ifdef CLOSEIO
-
-/*
- * Structure for file control block, used by closable IO.
- * We should NOT add more field into the data structure.
- * Otherwise, the sysRead() will only work with sysOpen,
- * and may NOT work with a fd return by open()
- */
-typedef struct
-{
- mutex_t lock; /* lock against the entry */
- sys_thread_t* list; /* blocking list on the fd */
-} file_t;
-
-/*
- * Global data structure for interruptable io.
- * It must be initialized before any IO access.
- */
-static file_t * fd_table = 0;
-static int fd_limit = 0;
-
-/*
- * Initialize global data structure for non-blocking
- * close semantics for Solaris 2.6 and ealier.
- */
-int InitializeIO(rlim_t limit)
-{
- int i;
-
- fd_limit = (int) limit;
-
- fd_table = (file_t *) sysCalloc(fd_limit, sizeof(file_t));
- if (fd_table == 0) {
- return SYS_ERR;
- }
-
- for (i = 0; i < fd_limit; i++) {
- mutexInit(&(fd_table[i].lock));
- }
-
- return SYS_OK;
-}
-
-/*
- * Cleanup the data structure allocated as above.
- * For JDK 1.2, this function is not called ...
- */
-void FinalizeIO() {
- int i;
- for (i = 0; i < fd_limit; i++) {
- mutexDestroy(&fd_table[i].lock);
- }
- sysFree(fd_table);
- fd_table = 0;
-}
-
-/*
- * Non-blocking close semantics on Solaris native thread.
- */
-int sysClose(int fd)
-{
- int ret;
-
- /* Check if it is valid fd. */
- if (fd >= 0 && fd < fd_limit) {
- file_t* file = &fd_table[fd];
- sys_thread_t *thread;
- sys_thread_t *next;
-
- /* Lock the corresponding fd. */
- mutexLock(&file->lock);
-
- /* Read the blocking list. */
- thread = file->list;
-
- /* Iterates the list and interrupt every thread in there. */
- while (thread) {
- /* This is the classic double-linked list operation. */
- if (thread->nextBlocked != thread) {
- next = thread->nextBlocked;
-
- next->prevBlocked = thread->prevBlocked;
- thread->prevBlocked->nextBlocked = next;
- } else {
- next = 0;
- }
-
- thread->nextBlocked = 0;
- thread->prevBlocked = 0;
-
- /*
- * Use current interruptable IO mechanism to
- * implement non-blocking closable IO.
- */
- sysThreadInterrupt(thread);
-
- thread = next;
- }
-
- file->list = 0;
-
- ret = close(fd);
-
- mutexUnlock(&file->lock);
- } else {
- /* It is not a valid fd. */
- errno = EBADF;
- ret = SYS_ERR;
- }
-
- return ret;
-}
-
-/*
- * Called before entering blocking IO. Enqueue the current
- * thread to the fd blocking list. Need fd lock.
- */
-static void BeginIO(sys_thread_t* self, file_t* file) {
- mutexLock(&file->lock);
-
- if (!file->list) {
- file->list = self->nextBlocked = self->prevBlocked = self;
- } else {
- sys_thread_t* head = file->list;
-
- self->prevBlocked = head->prevBlocked;
- self->nextBlocked = head;
- head->prevBlocked->nextBlocked = self;
- head->prevBlocked = self;
- }
- mutexUnlock(&file->lock);
-}
-
-/*
- * Called after finishing blocking IO. Dequeue the current
- * thread from the blocking list. Note: It may be waken up
- * by thread interrupt or fd close operation.
- */
-static ssize_t EndIO(sys_thread_t* self, file_t* file, ssize_t ret) {
- mutexLock(&file->lock);
-
- /*
- * Dequeue the current thread. It is classic double
- * linked list operation.
- */
-#ifdef __linux__
- if (!sysThreadIsInterrupted(self, 1) && self->prevBlocked) {
-#else
- if (self->prevBlocked) {
-#endif
- if (self->nextBlocked != self) {
- self->prevBlocked->nextBlocked = self->nextBlocked;
- self->nextBlocked->prevBlocked = self->prevBlocked;
- file->list = self->nextBlocked;
- } else {
- file->list = 0;
- }
- self->nextBlocked = 0;
- self->prevBlocked = 0;
- } else {
-#ifdef __linux__
- if (self->nextBlocked && self->prevBlocked) {
- if (self->nextBlocked != self) {
- self->prevBlocked->nextBlocked = self->nextBlocked;
- self->nextBlocked->prevBlocked = self->prevBlocked;
- file->list = self->nextBlocked;
- } else {
- file->list = 0;
- }
- }
- self->nextBlocked = 0;
- self->prevBlocked = 0;
-#endif
- /* file got closed during blocking call */
- errno = EBADF;
- ret = SYS_ERR;
- }
-
- mutexUnlock(&file->lock);
-
- return ret;
-}
-
-/*
- * The following is a big macro used to implement the closable IO.
- * Note: It is also used by interruptable IO. If later we need to
- * deprecate interruptable IO, all we need to change the return
- * value and errno to EBADF instead of EINTR. The high level
- * routine will interpret it as IOException instead of
- * InterruptedIOException. No other change is needed.
- * The underlying mechanism is using the SIGUSR1 signal to wake up the
- * blocking thread. This may cause severe conflicts with any other
- * libraries that also use SIGUSR1.
- */
-#ifdef __linux__
-#define INTERRUPT_IO(cmd) \
-{\
- ssize_t ret = 0;\
- file_t* file;\
- sys_thread_t* self = sysThreadSelf();\
-\
- if (fd < 0 || fd >= fd_limit) {\
- errno = EBADF;\
- return SYS_ERR;\
- }\
-\
- file = &fd_table[fd];\
- BeginIO(self, file);\
-\
- {\
- jmp_buf jmpbuf;\
-\
- /*\
- * Register our intrHandler as a cleanup handler. If we get\
- * interrupted (i.e. canceled), we longjmp out of this handler.\
- */\
- pthread_cleanup_push(intrHandler, NULL);\
- if (setjmp(jmpbuf) == 0) {\
- thr_setspecific(intrJmpbufkey, &jmpbuf);\
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);\
- ret = cmd;\
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);\
- thr_setspecific(intrJmpbufkey, NULL);\
- } else {\
- /* [jk] should/can we call sysThreadIsInterrupted(self, 1) here */
-
- self->interrupted = FALSE;\
- errno = EINTR;\
- ret = SYS_INTRPT;\
- }\
- /* Remove intrHandler without calling it. */\
- pthread_cleanup_pop(0);\
- }\
-\
- return EndIO(self, file, ret);\
-}
-#else
-#define INTERRUPT_IO(cmd) \
-{\
- int ret = 0;\
- file_t* file;\
- sys_thread_t* self = sysThreadSelf();\
-\
- if (fd < 0 || fd >= fd_limit) {\
- errno = EBADF;\
- return SYS_ERR;\
- }\
-\
- file = &fd_table[fd];\
- BeginIO(self, file);\
-\
- {\
- sigjmp_buf jmpbuf;\
- sigset_t omask;\
-\
- thr_setspecific(sigusr1Jmpbufkey, &jmpbuf);\
- if (sigsetjmp(jmpbuf, 1) == 0) {\
- thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &omask);\
- ret = cmd;\
- thr_sigsetmask(SIG_SETMASK, &omask, NULL);\
- } else {\
- sysThreadIsInterrupted(self, TRUE);\
- errno = EINTR;\
- ret = SYS_INTRPT;\
- }\
- }\
-\
- return EndIO(self, file, ret);\
-}
-#endif
-
-#else /* CLOSEIO */
-
-#define INTERRUPT_IO(cmd) \
- return cmd;
-
-int sysClose(int fd) {
- return close(fd);
-}
-
-int InitializeIO(rlim_t limit)
-{
- return SYS_OK;
-}
-#endif /* CLOSEIO */
-
-/*
- * sys API for I/O
- */
-
-size_t
-sysRead(int fd, void *buf, unsigned int nBytes) {
- INTERRUPT_IO(read(fd, buf, nBytes))
-}
-
-size_t
-sysWrite(int fd, const void *buf, unsigned int nBytes) {
- INTERRUPT_IO(write(fd, buf, nBytes))
-}
-
-int
-sysSocket(int domain, int type, int protocol) {
- return socket(domain, type, protocol);
-}
-
-ssize_t
-sysRecv(int fd, char *buf, int nBytes, int flags) {
- INTERRUPT_IO(recv(fd, buf, nBytes, flags))
-}
-
-ssize_t
-sysSend(int fd, char *buf, int nBytes, int flags) {
- INTERRUPT_IO(send(fd, buf, nBytes, flags))
-}
-/*
-int
-sysClose(int fd) {
- INTERRUPT_IO(close(fd))
-}
-*/
-jlong
-sysSeek(int fd, jlong offset, int whence) {
- return lseek64_w(fd, offset, whence);
-}
-
-int
-sysSetLength(int fd, jlong length) {
- return ftruncate64_w(fd, length);
-}
-
-int
-sysSync(int fd) {
- /*
- * XXX: Is fsync() interruptible by the interrupt method?
- * Is so, add the TSD, sigsetjmp()/longjmp() code here.
- *
- * This probably shouldn't be throwing an error and should
- * be a macro.
- */
- int ret;
- if ((ret = fsync(fd)) == -1) {
- }
- return ret;
-}
-
-int
-sysAvailable(int fd, jlong *pbytes) {
- jlong cur, end;
- int mode;
-
- if (sysFfileMode(fd, &mode) >= 0) {
- if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
- /*
- * XXX: is the following call interruptible? If so, this might
- * need to go through the INTERRUPT_IO() wrapper as for other
- * blocking, interruptible calls in this file.
- */
- int n;
- if (ioctl(fd, FIONREAD, &n) >= 0) {
- *pbytes = n;
- return 1;
- }
- }
- }
- if ((cur = lseek64_w(fd, 0L, SEEK_CUR)) == -1) {
- return 0;
- } else if ((end = lseek64_w(fd, 0L, SEEK_END)) == -1) {
- return 0;
- } else if (lseek64_w(fd, cur, SEEK_SET) == -1) {
- return 0;
- }
- *pbytes = end - cur;
- return 1;
-}
-
-/* IO routines that take in a FD object */
-
-int
-sysTimeout(int fd, long timeout) {
-#ifndef USE_SELECT
- struct pollfd pfd;
-
-#ifdef __linux__
- jlong end_time = sysTimeMillis() + (jlong) timeout;
- volatile jlong to = (jlong) timeout;
-#endif
-
- pfd.fd = fd;
- pfd.events = POLLIN;
-
-#ifdef __linux__
- INTERRUPT_IO(__extension__ ({
- int __result;
- do {
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
- __result = poll(&pfd, 1, ((int)to));
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
- } while (__result == -1 && errno == EINTR &&
- (to = end_time - sysTimeMillis()) > 0 &&
- ((pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) == 0));
- if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
- __result = -1;
- errno = EBADF;
- }
- (__result == -1 && errno == EINTR) ? 0 : __result;
- }))
-#else
- INTERRUPT_IO(poll(&pfd, 1, (int)timeout))
-#endif
-#else
- fd_set tbl;
- struct timeval t;
-
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
-
- FD_ZERO(&tbl);
- FD_SET(fd, &tbl);
-
-#ifdef __linux__
- INTERRUPT_IO(TEMP_FAILURE_RETRY(select(fd + 1, &tbl, 0, 0, &t)))
-#else
- INTERRUPT_IO(select(fd + 1, &tbl, 0, 0, &t))
-#endif
-#endif
-}
-
-
-/*
- * sys API for networking
- */
-
-long
-sysSocketAvailable(int fd, jint *pbytes) {
- long ret = 1;
- /*
- * An ILP64 port of this code should pass the address of a local int
- * to the ioctl and then convert that to jint with any error handling
- * required for overflows, if overflow is possible.
- */
-
- /*
- * XXX: is the following call interruptible? If so, this might
- * need to go through the INTERRUPT_IO() wrapper as for other
- * blocking, interruptible calls in this file.
- */
- if (fd < 0 || ioctl(fd, FIONREAD, pbytes) < 0) {
- ret = 0;
- }
- return ret;
-}
-
-int
-sysListen(int fd, int count) {
- return listen(fd, count);
-}
-
-int
-sysConnect(int fd, struct sockaddr *addr, int size) {
- INTERRUPT_IO(connect(fd, addr, size))
-}
-
-int
-sysBind(int fd, struct sockaddr *addr, int size) {
- INTERRUPT_IO(bind(fd, addr, size))
-}
-
-int
-sysAccept(int fd, struct sockaddr *him, int *len) {
- INTERRUPT_IO(accept(fd, him, (uint *)len))
-}
-
-int
-sysGetSockName(int fd, struct sockaddr *him, int *len) {
- return getsockname(fd, him, (uint *)len);
-}
-
-int
-sysSocketClose(int fd) {
- return sysClose(fd);
-}
-
-int
-sysSocketShutdown(int fd, int howto) {
- return shutdown(fd, howto);
-}
-
-int
-sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen) {
- return getsockopt(fd, level, optname, optval, optlen);
-}
-
-int
-sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen) {
- return setsockopt(fd, level, optname, optval, optlen);
-}
-
-int
-sysGetHostName(char *hostname, int namelen) {
- return gethostname(hostname, namelen);
-}
-
-struct hostent *
-sysGetHostByAddr(const char *hostname, int len, int type) {
- return gethostbyaddr(hostname, len, type);
-}
-
-struct hostent *
-sysGetHostByName(char *hostname) {
- return gethostbyname(hostname);
-}
-
-struct protoent *
-sysGetProtoByName(char* name) {
- return getprotobyname(name);
-}
-
-/*
- * Routines to do datagrams
- */
-ssize_t
-sysSendTo(int fd, char *buf, int len,
- int flags, struct sockaddr *to, int tolen) {
- INTERRUPT_IO(sendto(fd, buf, len, flags, to, tolen))
-}
-
-ssize_t
-sysRecvFrom(int fd, char *buf, int nBytes,
- int flags, struct sockaddr *from, int *fromlen) {
- INTERRUPT_IO(recvfrom(fd, buf, nBytes, flags, from, (uint *)fromlen))
-}
--- a/jdk/src/solaris/hpi/native_threads/src/threads_linux.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,411 +0,0 @@
-/*
- * Copyright (c) 1999, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Implementation of notposix.h on Linux.
- */
-
-#include <pthread.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <time.h>
-
-#include "hpi_impl.h"
-#include "monitor_md.h"
-#include "threads_md.h"
-#include "np.h"
-
-#undef LOG_THREADS
-
-/* Global lock used when calling np_suspend and np_resume */
-static pthread_mutex_t sr_lock;
-
-/* Semaphore used to acknowledge when the handler has received HANDLER_SIG */
-static sem_t sr_sem;
-
-/* The tid of the thread being suspended/resumed */
-static sys_thread_t *sr_tid;
-
-int sr_sigsusp;
-int sr_sigresu;
-
-static void prtsigset(char *s, sigset_t *set)
-{
- int sig;
- dprintf(2, "%s:", s);
- for (sig = 1; sig < _NSIG; sig++) {
- if (sigismember(set, sig)) {
- dprintf(2, " %d", sig);
- }
- }
- dprintf(2, "\n");
-}
-
-/*
- * Handler function invoked when a thread's execution is suspended
- * We have to be careful that only async-safe functions are
- * called here. I'm not even sure if calling sysThreadSelf is safe so
- * we temporarily stash SP in a global variable instead.
- */
-static void
-#ifdef SA_SIGINFO
-susp_handler(int sig, siginfo_t* info, void* arg)
-#else
-susp_handler(int sig)
-#endif
-{
- sys_thread_t *tid = sr_tid;
- sigset_t set;
- /* Save the current SP */
- tid->sp = &tid;
- sem_post(&sr_sem);
- sigfillset(&set);
- sigdelset(&set,(sr_sigresu));
- /* block until we receive resume signal. */
- sigsuspend(&set);
-}
-
-static void
-#ifdef SA_SIGINFO
-resu_handler(int sig, siginfo_t* info, void* arg)
-#else
-resu_handler(int sig)
-#endif
-{
- return;
-}
-
-/*
- * Initialize signal handlers for suspend and resume}.
- */
-int
-np_initialize()
-{
- struct sigaction act;
- char *s;
- int err;
-
- /* Signal numbers used to suspend and resume */
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ == 0
-#ifdef SIGUNUSED
- sr_sigsusp = SIGUNUSED;
-#else
- sr_sigsusp = SIGLOST;
-#endif
-#ifdef SIGPWR
- sr_sigresu = SIGPWR;
-#else
- sr_sigresu = SIGXFSZ;
-#endif
-#else
- /* use real time signals */
- /* currently __SIGRTMIN, +1, +2 are all used by LinuxThreads */
- sr_sigsusp = SIGRTMIN + 3;
- sr_sigresu = SIGRTMIN + 4;
-#endif
-
- /* Set up signal handler for suspend and resume */
-#if defined(SA_SIGINFO) && !defined(__sparc__)
- act.sa_handler = 0;
- act.sa_sigaction = susp_handler;
-#else
- act.sa_handler = (__sighandler_t) susp_handler;
-#endif
-#ifdef SA_SIGINFO
- act.sa_flags = SA_RESTART | SA_SIGINFO;
-#else
- act.sa_flags = SA_RESTART;
-#endif
- sigfillset(&act.sa_mask);
- if (sigaction(sr_sigsusp, &act, 0) == -1) {
- return -1;
- }
-#if defined(SA_SIGINFO) && !defined(__sparc__)
- act.sa_handler = 0;
- act.sa_sigaction = resu_handler;
-#else
- act.sa_handler = (__sighandler_t) resu_handler;
-#endif
-#ifdef SA_SIGINFO
- act.sa_flags = SA_SIGINFO;
-#else
- act.sa_flags = 0;
-#endif
- sigfillset(&act.sa_mask);
- if (sigaction(sr_sigresu, &act, 0) == -1) {
- return -1;
- }
-
- /* Initialize semaphore used by np_{suspend/resume} */
- if (sem_init(&sr_sem, 0, 0) == -1) {
- return SYS_ERR;
- }
-
- /* Initialize mutex used by np_{suspend/resume} */
- err = mutexInit(&sr_lock);
- sysAssert(err == 0);
-
- return SYS_OK;
-}
-
-int
-np_initial_suspend(sys_thread_t* tid)
-{
- int count;
-
- tid->selfsuspended = (tid == sysThreadSelf());
- sysAssert(tid->selfsuspended);
-
- count = tid->suspend_count++;
- sysAssert(count == 0);
-
-#ifdef LOG_THREADS
- dprintf(2,
- "[Initial self-suspend [tid = %ld, sys_thread = %ld]\n",
- pthread_self(), tid->sys_thread);
-#endif
-
- /* Order should not matter but doing the post first should be faster */
- sem_post(&tid->sem_suspended);
- do {
- sem_wait(&tid->sem_selfsuspend);
- } while (tid->selfsuspended); /* paranoid */
- return 0;
-}
-
-
-int
-np_suspend(sys_thread_t *tid)
-{
- int count, ret = 0;
-
- int err = mutexLock(&sr_lock);
- sysAssert(err == 0);
-
- tid->selfsuspended = (tid == sysThreadSelf());
-
- count = tid->suspend_count++;
-#ifdef LOG_THREADS
- dprintf(2, "[Suspending fromtid = %ld, tid = %ld, pid = %d, count = %d]\n",
- pthread_self(), tid->sys_thread, tid->lwp_id, count);
-#endif
- if (count == 0) {
- if (tid->selfsuspended) {
-#ifdef LOG_THREADS
- dprintf(2,
- "[Self-suspending [tid = %ld, sys_thread = %ld]\n",
- pthread_self(), tid->sys_thread);
-#endif
- mutexUnlock(&sr_lock);
- do {
- sem_wait(&tid->sem_selfsuspend);
- } while (tid->selfsuspended);
- /* [jk] What is the correct return value here?
- There was no error, but when we return the thread
- has already been resumed. */
- return SYS_OK;
-
- } else {
- sr_tid = tid;
- ret = pthread_kill(tid->sys_thread, sr_sigsusp);
- if (ret == 0) {
- sem_wait(&sr_sem);
- }
-#ifdef LOG_THREADS
- dprintf(2,
- "[Suspended fromtid = %ld, pthread_kill(%ld, %d) = %d]\n",
- pthread_self(), tid->sys_thread, sr_sigsusp, ret);
-#endif
- }
- }
-
- err = mutexUnlock(&sr_lock);
- sysAssert(err == 0);
-
- return ret == 0 ? SYS_OK : SYS_ERR;
-}
-
-int
-np_continue(sys_thread_t *tid)
-{
- int count, ret = 0;
-
- int err = mutexLock(&sr_lock);
- sysAssert(err == 0);
-
- count = --tid->suspend_count;
-#ifdef LOG_THREADS
- dprintf(2, "[Resuming fromtid = %ld, tid = %ld, pid = %d, count = %d]\n",
- pthread_self(), tid->sys_thread, tid->lwp_id, count);
-#endif
- if (count == 0) {
- if (tid->selfsuspended) {
- tid->selfsuspended = 0;
- sem_post(&tid->sem_selfsuspend);
- } else {
- sr_tid = tid;
- ret = pthread_kill(tid->sys_thread, sr_sigresu);
- }
-#ifdef LOG_THREADS
- dprintf(2, "[Resumed fromtid = %ld, pthread_kill(%ld, %d) = %d]\n",
- pthread_self(), tid->sys_thread, sr_sigresu, ret);
-#endif
- } else if (count < 0) {
- /* Ignore attempts to resume a thread that has not been suspended */
- tid->suspend_count = 0;
- }
-
- err = mutexUnlock(&sr_lock);
- sysAssert(err == 0);
-
- return ret == 0 ? SYS_OK : SYS_ERR;
-}
-
-/*
- * Get the stack base and size.
- */
-int
-np_stackinfo(void **addr, long *size)
-{
- /* For now assume stack is 2 meg, from internals.h. */
-#define STACK_SIZE (2 * 1024 * 1024)
- void *p;
- char *sp = (char *)&p; /* rougly %esp */
-
- *addr = (void *)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1;
- *size = STACK_SIZE;
-
- return SYS_OK;
-}
-
-typedef unsigned long ulong_t;
-#define VALID_SP(sp, bottom, top) \
- (((ulong_t)(sp)) < ((ulong_t)(bottom)) && ((ulong_t)(sp)) > ((ulong_t)(top)))
-
-/*
- * Go into single threaded mode for GC.
- */
-int
-np_single()
-{
- sys_thread_t *tid;
- pthread_t me = pthread_self();
- int i;
-
-#ifdef LOG_THREADS
- dprintf(2, "[Entering np_single: thread count = %d]\n", ActiveThreadCount);
-#endif
- /* Stop all other threads. */
- tid = ThreadQueue;
- for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
- if ((tid->sys_thread != me) && (tid->state != SUSPENDED)) {
- np_suspend(tid);
- sysAssert(VALID_SP(tid->sp, tid->stack_bottom, tid->stack_top));
- tid->onproc = FALSE; /* REMIND: Might not need this */
- }
- tid = tid->next;
- }
-#ifdef LOG_THREADS
- dprintf(2, "[Leaving np_single]\n");
-#endif
- return SYS_OK;
-}
-
-/*
- * Per thread initialization.
- */
-void
-np_initialize_thread(sys_thread_t *tid)
-{
- sigset_t set;
-
- /* Block SIGQUIT so that it can be handled by the SIGQUIT handler thread */
- sigemptyset(&set);
- sigaddset(&set, SIGQUIT);
- pthread_sigmask(SIG_BLOCK, &set, 0);
- /* Set process id */
- tid->lwp_id = getpid();
- tid->suspend_count = 0;
-
- /* Semaphore used for self-suspension */
- sem_init(&tid->sem_selfsuspend, 0, 0);
- tid->selfsuspended = 0;
-
-#ifdef LOG_THREADS
- dprintf(2, "[Init thread, tid = %ld, pid = %d, base = %p, size = %lu]\n",
- pthread_self(), tid->lwp_id, tid->stack_bottom, tid->stack_size);
-#endif
-}
-
-void
-np_free_thread(sys_thread_t *tid)
-{
- sem_destroy(&tid->sem_selfsuspend);
-}
-
-/*
- * Recover from single threaded mode after GC.
- */
-void
-np_multi()
-{
- int i;
- sys_thread_t *tid;
- pthread_t me = pthread_self();
-
- tid = ThreadQueue;
- for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
- if ((tid->sys_thread != me) && (tid->state != SUSPENDED)) {
- np_continue(tid);
- }
- tid = tid->next;
- }
-}
-
-void
-np_profiler_init(sys_thread_t *tid)
-{
-}
-
-int
-np_profiler_suspend(sys_thread_t *tid)
-{
- return np_suspend(tid);
-}
-
-int
-np_profiler_continue(sys_thread_t *tid)
-{
- return np_continue(tid);
-}
-
-bool_t
-np_profiler_thread_is_running(sys_thread_t *tid)
-{
- return TRUE;
-}
--- a/jdk/src/solaris/hpi/native_threads/src/threads_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1133 +0,0 @@
-/*
- * Copyright (c) 1994, 2002, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Implementation of Java threads HPI on top of native Solaris threads
- *
- * [Sheng 1/18/97] Do not include any JVM-specific header file (such
- * as interpreter.h) here! This file implements the thread-related
- * APIs sys_api.h.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/signal.h>
-#include <sys/resource.h>
-
-#include "hpi_impl.h"
-
-#include "threads_md.h"
-#include "monitor_md.h"
-
-#include "np.h"
-
-extern int InitializeIO(rlim_t limit);
-
-#if defined(__solaris__) && !defined(SA_SIGINFO)
-#error That can NOT possibly be right.
-#endif
-
-#ifdef SA_SIGINFO
-static void sigusr1Handler(int sig, siginfo_t *info, void *uc);
-#else
-static void sigusr1Handler(int sig);
-#endif /* SA_SIGINFO */
-
-static void removeFromActiveQ(sys_thread_t *p);
-static void clear_onproc_flags(void);
-
-sys_thread_t *ThreadQueue;
-int ActiveThreadCount = 0; /* All threads */
-sys_mon_t *_sys_queue_lock;
-
-/* This is explained in linker_md.c. */
-#ifdef __GLIBC__
-#define NEED_DL_LOCK
-#endif /* __GLIBC__ */
-
-#ifdef NEED_DL_LOCK
-extern sys_mon_t _dl_lock;
-#endif /* NEED_DL_LOCK */
-
-/*
- * threads_initialized simplifies the check that has to be done in
- * sysThreadCheckStack(). Otherwise, before sysThreadInit() is called
- * on the primordial thread, we need to handle there being no current
- * thread at all, and there being one with a 0 stack_base.
- */
-static int threads_initialized = 0;
-
-/* The tid_key is a global key to *native* thread-specific data. That is,
- * each native thread has a back pointer to the Java TID associated with it.
- */
-static thread_key_t tid_key = (thread_key_t) -1;
-
-/*
- * The sigusr1Jmpbufkey is used to get at the jmp buffer to longjmp to in a
- * SIGUSR1 handler - used to implement stop(). The jmp buffer
- * should have been allocated off the thread's stack.
- */
-#ifdef __linux__
-thread_key_t intrJmpbufkey;
-static sigset_t squm = {{sigmask(SIGUSR1), 0, 0, 0}};
-#else
-thread_key_t sigusr1Jmpbufkey;
-sigset_t sigusr1Mask = {{sigmask(SIGUSR1), 0, 0, 0}};
-#endif
-
-/*
- * Thread C stack overflow check
- *
- * sysThreadCheckStack() being a function call is unfortunate, as it
- * takes stack space to do, but that is weakly accounted for by the
- * previous stack redzone. In general, where we can't predict stack
- * use by C, thread stack overflow checking doesn't really work.
- */
-
-#define STACK_REDZONE 4096
-
-#ifdef __linux__
-int jdk_waitpid(pid_t pid, int* status, int options);
-int fork1(void);
-int jdk_sem_init(sem_t*, int, unsigned int);
-int jdk_sem_post(sem_t*);
-int jdk_sem_wait(sem_t*);
-int jdk_pthread_sigmask(int, const sigset_t*, sigset_t*);
-pid_t waitpid(pid_t, int*, int);
-
-int jdk_waitpid(pid_t pid, int* status, int options) {
- return waitpid(pid, status, options);
-}
-
-int fork1() {
- return fork();
-}
-
-int
-jdk_sem_init(sem_t *sem, int pshared, unsigned int value) {
- return sem_init(sem, pshared, value);
-}
-
-int
-jdk_sem_post(sem_t *sem) {
- return sem_post(sem);
-}
-
-int
-jdk_sem_wait(sem_t *sem) {
- return sem_wait(sem);
-}
-
-int
-jdk_pthread_sigmask(int how , const sigset_t* newmask, sigset_t* oldmask) {
- return pthread_sigmask(how , newmask, oldmask);
-}
-
-#endif
-
-/* REMIND: port _CurrentThread changes to make process
- of getting the tid more efficient */
-
-int
-sysThreadCheckStack()
-{
- sys_thread_t *tid = sysThreadSelf();
-
- /* Stacks grow toward lower addresses on Solaris... */
- if (!threads_initialized ||
- (char *)(tid)->stack_bottom - (char *)&(tid) + STACK_REDZONE <
- tid->stack_size) {
- return 1;
- } else {
- return 0;
- }
-}
-
-#ifndef __linux__
-static sigset_t squm = {{sigmask(SIGUSR1), 0, 0, 0}};
-#endif
-
-
-/*
- * Allocate and initialize the sys_thread_t structure for an arbitary
- * native thread.
- */
-int
-sysThreadAlloc(sys_thread_t **tidP)
-{
- int err;
- sys_thread_t *tid = allocThreadBlock();
- if (tid == NULL) {
- return SYS_NOMEM;
- }
-#ifdef __linux__
- memset((char *)tid, 0, sizeof(sys_thread_t));
-#endif
-
- if (profiler_on) {
- np_profiler_init(tid);
- }
-
- if (np_stackinfo(&tid->stack_bottom, &tid->stack_size) == SYS_ERR) {
- return SYS_ERR;
- }
-#ifdef __linux__
- tid->stack_top = tid->stack_bottom - tid->stack_size;
-#else
- tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size);
-#endif
-
- tid->primordial_thread = 0;
-#ifdef __linux__
- tid->interrupted = tid->pending_interrupt = FALSE;
-#else
- tid->interrupted = FALSE;
-#endif
- tid->onproc = FALSE;
- tid->sys_thread = thr_self();
-#ifdef __linux__
- /*
- * Disable cancellation. The default cancel type is
- * PTHREAD_CANCEL_DEFERRED, so if we set the cancel state to
- * PTHREAD_CANCEL_ENABLE again, we'll get deferred cancellation.
- */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-#endif
- np_initialize_thread(tid);
-
- /*
- * For the Invocation API:
- * We update the thread-specific storage before locking the
- * queue because sysMonitorEnter will access sysThreadSelf.
- */
- err = thr_setspecific(tid_key, tid);
- /* sys_thread_t * back pointer from native */
-#ifdef __linux__
- thr_setspecific(intrJmpbufkey, NULL); /* paranoid */
-#endif
- assert (err == 0);
-
- if (threads_initialized)
- SYS_QUEUE_LOCK(sysThreadSelf());
- ActiveThreadCount++; /* Count the thread */
- tid->next = ThreadQueue; /* Chain all threads */
- ThreadQueue = tid;
- if (threads_initialized)
- SYS_QUEUE_UNLOCK(sysThreadSelf());
- else
- threads_initialized = TRUE;
-
- /*
- * Ensure that SIGUSR1 is masked for interruptable IO
- * Signal mask inheritance ensures all child threads are masked too.
- */
-#ifndef __linux__
- thr_sigsetmask(SIG_BLOCK, &squm, NULL);
-#endif
-
- setFPMode();
-
- *tidP = tid;
- return SYS_OK;
-}
-
-/*
- * threadBootstrapMD() bootstraps the UNIX process running from main()
- * into a first primordial thread. This thread is distinguishable because
- * it uniquely has the primordial_thread flag on in its private data.
- * However, so that we have to special-case it as little as possible, we
- * set it up to look as closely as possible to a thread that we created.
- * One difference is that its stack is *not* known to us.
- */
-int
-threadBootstrapMD(sys_thread_t **tidP, sys_mon_t **lockP, int nb)
-{
- /* We are running out of file descriptors in fonts. As a temporary
- * fix, bump up the number of open file descriptors to OPEN_MAX.
- */
- struct rlimit nbr_files;
-
- getrlimit(RLIMIT_NOFILE, &nbr_files);
- nbr_files.rlim_cur = nbr_files.rlim_max;
- setrlimit(RLIMIT_NOFILE, &nbr_files);
-
- /*
- * Use the above setting for initialize (closable) IO package.
- */
- if (InitializeIO(nbr_files.rlim_cur) != SYS_OK) {
- return SYS_ERR;
- }
-
- /* Create a thread-private key for a pointer back to the sys_thread_t *.
- * Note that we don't need to worry about the destructor, as that's taken
- * care of elsewhere.
- */
- thr_keycreate(&tid_key, NULL);
-
-#ifdef __linux__
- thr_keycreate(&intrJmpbufkey, NULL);
-#else
- thr_keycreate(&sigusr1Jmpbufkey, NULL);
-#endif
-
-#ifndef NO_INTERRUPTIBLE_IO
- {
- /* initialize SIGUSR1 handler for interruptable IO */
- struct sigaction sigAct;
-
-#ifdef SA_SIGINFO
- sigAct.sa_handler = NULL;
- sigAct.sa_sigaction = sigusr1Handler;
-#else
- sigAct.sa_handler = sigusr1Handler;
-#endif /* SA_SIGINFO */
- memset((char *)&(sigAct.sa_mask), 0, sizeof (sigset_t));
- /* we do not want the restart flag for SIGUSR1 */
- sigAct.sa_flags = 0;
- sigaction(SIGUSR1, &sigAct, (struct sigaction *)0);
- }
-#endif /* NO_INTERRUPTIBLE_IO */
-
- nReservedBytes = (nb + 7) & (~7);
- if (sysThreadAlloc(tidP) < 0) {
- return SYS_NOMEM;
- }
-
- /* profiler_on may have not been setup yet. */
- np_profiler_init(*tidP);
-
-#ifdef NEED_DL_LOCK
- VM_CALL(monitorRegister)(&_dl_lock, "Dynamic loading lock");
-#endif /* NEED_DL_LOCK */
-
- /* Initialize the queue lock monitor */
- _sys_queue_lock = (sys_mon_t *)sysMalloc(sysMonitorSizeof());
- if (_sys_queue_lock == NULL) {
- return SYS_ERR;
- }
- VM_CALL(monitorRegister)(_sys_queue_lock, "Thread queue lock");
- *lockP = _sys_queue_lock;
-
- (*tidP)->primordial_thread = 1;
-
- if (np_initialize() == SYS_ERR) {
- return SYS_ERR;
- }
-
- return SYS_OK;
-}
-
-/*
- * Access to the thread stack pointer of an arbitrary thread (for GC).
- * This information should be legitimately available in Solaris 2.5.
- */
-void *
-sysThreadStackPointer(sys_thread_t * tid)
-{
- char *thread_info;
-
- if (tid == sysThreadSelf()) {
- /*
- * doing this assigment gets around a warning about returning
- * the address of a local variable
- */
- void *aStackAddress = &thread_info;
- return aStackAddress;
- } else {
- return (void *) tid->sp;
- }
-}
-
-/*
- * Get the end of stack (if you step beyond (above or below depending
- * on your architecture) you can die. We refer to the logical top of
- * stack.
- *
- * NOTE! There are restrictions about when you can call this method. If
- * you did a sysThreadAlloc, then you can call this method as soon as
- * sysThreadAlloc returns. If you called sysThreadCreate(start_function),
- * then you must call sysThreadStackTop only inside start_function and not
- * as soon as sysThreadCreate returns.
- */
-void *
-sysThreadStackTop(sys_thread_t *tid)
-{
- return tid->stack_top;
-}
-
-long *
-sysThreadRegs(sys_thread_t * tid, int *nregs)
-{
- *nregs = N_TRACED_REGS;
- return tid->regs;
-}
-
-static void *
-_start(void *tid_)
-{
- sys_thread_t *tid = (sys_thread_t *)tid_;
-
- np_initialize_thread(tid);
-
-#ifdef __linux__
- /*
- * Disable cancellation. The default cancel type is
- * PTHREAD_CANCEL_DEFERRED, so if we set the cancel state to
- * PTHREAD_CANCEL_ENABLE again, we'll get deferred cancellation.
- */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-
- tid->sp = 0;
- thr_setspecific(tid_key, tid);
- thr_setspecific(intrJmpbufkey, NULL); /* paranoid */
- np_stackinfo(&tid->stack_bottom, &tid->stack_size);
- tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size);
-
- /* Wait for resume signal */
- np_initial_suspend(tid);
-#else
-#ifdef USE_PTHREADS
-#ifndef USE_MUTEX_HANDSHAKE
- /* Wait for semaphore to be posted once thread has been suspended */
- sem_wait(&tid->sem);
- sem_destroy(&tid->sem);
-#else
- /* I'm a new thread, and I must co-operate so I can be suspended. */
- pthread_mutex_lock(&tid->ntcond.m);
- tid->ntcond.state = NEW_THREAD_REQUESTED_SUSPEND;
- pthread_cond_signal(&tid->ntcond.c);
- while (tid->ntcond.state != NEW_THREAD_SUSPENDED)
- pthread_cond_wait(&tid->ntcond.c, &tid->ntcond.m);
- pthread_mutex_unlock(&tid->ntcond.m);
-#endif /* USE_MUTEX_HANDSHAKE */
-#endif /* USE_PTHREADS */
-#endif /* !linux */
- if (profiler_on) {
- np_profiler_init(tid);
- }
-
-#ifndef __linux__
- tid->sp = 0;
- thr_setspecific(tid_key, tid);
-#endif
-
- tid->state = RUNNABLE;
-
-#ifndef __linux__
- np_stackinfo(&tid->stack_bottom, &tid->stack_size);
- tid->stack_top = (void *)((char *)(tid->stack_bottom) - tid->stack_size);
-#endif
-
- setFPMode();
- tid->start_proc(tid->start_parm);
-#ifdef __linux__
- /* Paranoid: We don't want to be canceled now, it would have
- unpredictable consequences */
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-#endif
-
- sysThreadFree();
- thr_exit(0);
- /* NOT REACHED */
- return 0;
-}
-
-int
-sysThreadCreate(sys_thread_t **tidP, long ss, void (*start)(void *), void *arg)
-{
- size_t stack_size = ss;
- int err;
- sys_thread_t *tid = allocThreadBlock();
-#ifdef USE_PTHREADS
- pthread_attr_t attr;
-#endif
-
- if (tid == NULL) {
- return SYS_NOMEM;
- }
- *tidP = tid;
-
-#ifdef __linux__
- memset((char *)tid, 0, sizeof(sys_thread_t));
-#endif
- /* Install the backpointer to the Thread object */
-
-#ifdef __linux__
- tid->interrupted = tid->pending_interrupt = FALSE;
-#else
- tid->interrupted = FALSE;
-#endif
- tid->onproc = FALSE;
-
-#ifndef __linux__
- SYS_QUEUE_LOCK(sysThreadSelf());
- ActiveThreadCount++; /* Global thread count */
- tid->next = ThreadQueue; /* Chain all threads */
- ThreadQueue = tid;
- SYS_QUEUE_UNLOCK(sysThreadSelf());
-#endif
-
- tid->start_proc = start;
- tid->start_parm = arg;
-#ifdef __linux__
- tid->state = SUSPENDED;
-#endif
-
-#ifdef __linux__
- tid->primordial_thread = 0;
-
- /* Semaphore used to block thread until np_suspend() is called */
- err = sem_init(&tid->sem_suspended, 0, 0);
- sysAssert(err == 0);
- /* Thread attributes */
- pthread_attr_init(&attr);
-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
- pthread_attr_setstacksize(&attr, stack_size);
-#endif
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (profiler_on) {
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- }
- /* Create the thread. The thread will block waiting to be suspended */
- err = pthread_create(&tid->sys_thread, &attr, _start, (void *)tid);
- sysAssert(err == 0);
- if (err == 0) {
- err = sem_wait(&tid->sem_suspended);
- if (err == 0) {
- sem_destroy(&tid->sem_suspended);
- }
- }
- sysAssert(err == 0);
-
- SYS_QUEUE_LOCK(sysThreadSelf());
- ActiveThreadCount++; /* Global thread count */
- tid->next = ThreadQueue; /* Chain all threads */
- ThreadQueue = tid;
- SYS_QUEUE_UNLOCK(sysThreadSelf());
-#else
-#ifdef USE_PTHREADS
-
-#ifndef USE_MUTEX_HANDSHAKE
- /* Semaphore used to block thread until np_suspend() is called */
- err = sem_init(&tid->sem, 0, 0);
- sysAssert(err == 0);
- /* Thread attributes */
-#else
- /* Setup condition required to suspend the newly created thread. */
- pthread_mutex_init(&tid->ntcond.m, NULL);
- pthread_cond_init(&tid->ntcond.c, NULL);
- tid->ntcond.state = NEW_THREAD_MUST_REQUEST_SUSPEND;
- pthread_mutex_lock(&tid->ntcond.m);
-#endif /* USE_MUTEX_HANDSHAKE */
-
- /* Create the new thread. */
- pthread_attr_init(&attr);
-#ifdef _POSIX_THREAD_ATTR_STACKSIZE
- pthread_attr_setstacksize(&attr, stack_size);
-#endif
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if (profiler_on)
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- err = pthread_create(&tid->sys_thread, &attr, _start, (void *)tid);
-
-#ifndef USE_MUTEX_HANDSHAKE
- if (err == 0) {
- /* Suspend the thread */
- err = np_suspend(tid);
- if (err == SYS_OK) {
- /* Unblock the thread now that it has been suspended */
- err = sem_post(&tid->sem);
- sysAssert(err == 0);
- }
- }
-#else
- /* Wait for the newly created thread to block. */
- while (tid->ntcond.state != NEW_THREAD_REQUESTED_SUSPEND)
- pthread_cond_wait(&tid->ntcond.c, &tid->ntcond.m);
-
- /* So it blocked. Now suspend it and _then_ get it out of the block. */
- np_suspend(tid->sys_thread);
- tid->ntcond.state = NEW_THREAD_SUSPENDED;
- pthread_cond_signal(&tid->ntcond.c);
- pthread_mutex_unlock(&tid->ntcond.m);
-#endif /* USE_MUTEX_HANDSHAKE */
-
-#else
- /* Create the thread */
- err = thr_create(NULL, stack_size, _start, (void *)tid,
- THR_SUSPENDED|THR_DETACHED|
- (profiler_on ? THR_BOUND : 0),
- &tid->sys_thread);
-#endif /* USE_PTHREADS */
-#endif /* !linux */
-
- tid->state = SUSPENDED;
- sysAssert(err != EINVAL); /* Invalid argument: shouldn't happen */
- if (err == EAGAIN) {
- err = SYS_NORESOURCE; /* Will be treated as though SYS_NOMEM */
- } else if (err == ENOMEM) {
- err = SYS_NOMEM;
- } else {
- err = SYS_OK;
- }
-
- return err;
-}
-
-/*
- * Free a system thread block.
- * Remove from the thread queue.
- */
-int
-sysThreadFree()
-{
- sys_thread_t *tid = sysThreadSelf();
- /*
- * remove ourselves from the thread queue. This must be done after
- * the notify above since monitor operations aren't really safe if
- * your thread isn't on the thread queue. (This isn't true of
- * the sysMonitor* functions, only monitor*)
- */
- SYS_QUEUE_LOCK(tid);
- removeFromActiveQ(tid);
- SYS_QUEUE_UNLOCK(tid);
-
- /* For invocation API: later sysThreadSelf() calls will return 0 */
- thr_setspecific(tid_key, 0);
-
-#ifdef __linux__
- np_free_thread(tid);
-#endif
-
- freeThreadBlock(tid);
- return SYS_OK;
-}
-
-/*
- * Current thread yield control
- *
- * Green threads originally supported forcing another thread to yield...
- */
-void
-sysThreadYield()
-{
-#ifndef __linux__
- thr_yield();
-#endif
-}
-
-#ifdef USE_PTHREADS
-/*
- * For POSIX threads, we don't want to use real-time policies SCHED_FIFO or
- * SCHED_RR. That leaves SCHED_OTHER which is implementation defined. We
- * assume Solaris-pthreads like behavior for SCHED_OTHER, and if it doesn't
- * work on your platform, then maybe you want to do turn off thread
- * priorities by setting -DMOOT_PRIORITIES.
- */
-#ifndef MOOT_PRIORITIES
-#define USE_SCHED_OTHER
-#endif /* MOOT_PRIORITIES */
-#endif /* USE_PTHREADS */
-
-/*
- * Get the scheduling priority of a specified thread
- */
-int
-sysThreadGetPriority(sys_thread_t * tid, int *pri)
-{
-#ifdef USE_PTHREADS
-#ifdef USE_SCHED_OTHER
- struct sched_param param;
- int policy = SCHED_OTHER;
- param.sched_priority = *pri;
- return pthread_getschedparam(tid->sys_thread, &policy, ¶m);
-#else
- return 0;
-#endif /* USE_SCHED_OTHER */
-#else
- return thr_getprio(tid->sys_thread, pri);
-#endif /* USE_PTHREADS */
-}
-
-
-/*
- * Set the scheduling priority of a specified thread
- */
-int
-sysThreadSetPriority(sys_thread_t * tid, int pri)
-{
- int err;
-#ifdef USE_PTHREADS
-#ifdef USE_SCHED_OTHER
- struct sched_param param;
- param.sched_priority = pri;
- err = pthread_setschedparam(tid->sys_thread, SCHED_OTHER, ¶m);
-#else
- err = 0;
-#endif /* USE_SCHED_OTHER */
-#else
- err = thr_setprio(tid->sys_thread, pri);
-#endif /* USE_PTHREADS */
- sysAssert(err != ESRCH); /* No such thread: shouldn't happen */
- sysAssert(err != EINVAL); /* Invalid arguments: shouldn't happen */
- return SYS_OK;
-}
-
-/*
- * Suspend execution of the specified thread
- */
-int
-sysThreadSuspend(sys_thread_t * tid)
-{
- int err1 = 0;
- int err2 = 0;
- sys_thread_t *self = sysThreadSelf();
-
- if (tid == self) {
- self->state = SUSPENDED;
- } else {
-#ifndef __linux__
- mutexLock(&tid->mutex);
-#endif
- switch(tid->state) {
- case RUNNABLE:
- tid->state = SUSPENDED;
- break;
- case CONDVAR_WAIT:
- tid->state = SUSPENDED;
- tid->cpending_suspend = 1;
- break;
- case SUSPENDED:
- default:
- err1 = -1; /* Thread in inconsistent state */
- break;
- }
-#ifndef __linux__
- mutexUnlock(&tid->mutex);
-#endif
- }
- if (err1 == 0) {
- err2 = np_suspend(tid);
- }
-
- return ((err1 == 0 && err2 == 0) ? SYS_OK : SYS_ERR);
-}
-
-/*
- * Resume execution of the specified thread
- */
-int
-sysThreadResume(sys_thread_t * tid)
-{
- int err1 = 0;
- int err2 = 0;
-
-#ifndef __linux__
- mutexLock(&tid->mutex);
-#endif
- if (tid->cpending_suspend) {
- tid->cpending_suspend = 0;
- tid->state = CONDVAR_WAIT;
- } else {
- switch(tid->state) {
- case SUSPENDED:
- tid->state = RUNNABLE;
- break;
- case RUNNABLE:
- case CONDVAR_WAIT:
- default:
- err1 = -1; /* Thread in inconsistent state */
- break;
- }
- }
-#ifndef __linux__
- mutexUnlock(&tid->mutex);
-#endif
- if (err1 == 0) {
- err2 = np_continue(tid);
- }
-
- return ((err1 == 0 && err2 == 0) ? SYS_OK : SYS_ERR);
-}
-
-/*
- * Return the sys_thread_t * of the calling thread
- */
-sys_thread_t *
-sysThreadSelf()
-{
-#ifdef USE_PTHREADS
- return pthread_getspecific(tid_key);
-#else
- sys_thread_t * tid=NULL;
- int err = thr_getspecific(tid_key, (void *) &tid);
-
- if (err == 0) {
- return tid;
- }
-
- sysAssert(tid_key == -1 || err != 0);
-
- return NULL;
-#endif
-}
-
-/*
- * Enumerate over all threads, calling a function for each one. A
- * paranoid helper function would be prepared to deal with threads
- * that have not been created by Java.
- */
-
-int
-sysThreadEnumerateOver(int (*func)(sys_thread_t *, void *), void *arg)
-{
- sys_thread_t *tid;
- int err = SYS_OK;
- int i;
-
- sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
-
- tid = ThreadQueue;
- for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
- if ((err = (*func)(tid, arg)) != SYS_OK) {
- break;
- }
- tid = tid->next;
- }
-
- return err;
-}
-
-void *
-sysThreadNativeID(sys_thread_t *tid)
-{
- return (void *) tid->sys_thread;
-}
-
-/*
- * Remove this thread from the list of Active threads.
- */
-static void
-removeFromActiveQ(sys_thread_t * t)
-{
- sys_thread_t *prev;
- sys_thread_t *tid;
-
- sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
-
- ActiveThreadCount--;
-
- prev = 0;
- tid = ThreadQueue;
- while (tid) {
- if (tid == t) {
- if (prev) {
- prev->next = tid->next;
- } else {
- ThreadQueue = tid->next;
- }
- tid->next = 0;
- break;
- }
- prev = tid;
- tid = tid->next;
- }
-}
-
-/*
- * The mechanics of actually signalling an exception (in the future,
- * and Alarm or Interrupt) depend upon what thread implementation you
- * are using.
- */
-void
-sysThreadPostException(sys_thread_t *tid, void *exc)
-{
- /* Thread.stop is deprecated */
- /* No longer wake up the thread if it is sleeping */
- /* thr_kill(tid->sys_thread, SIGUSR1); */
-}
-
-/*
- * Support for (Java-level) interrupts.
- */
-void
-sysThreadInterrupt(sys_thread_t *tid)
-{
-#ifdef __linux__
- tid->pending_interrupt = TRUE;
- pthread_cancel(tid->sys_thread);
-#else
- mutexLock(&tid->mutex);
- tid->interrupted = TRUE;
- mutexUnlock(&tid->mutex);
- thr_kill(tid->sys_thread, SIGUSR1);
-#endif
-}
-
-/* This doesn't need to aquire any locks */
-int
-sysThreadIsInterrupted(sys_thread_t *tid, int ClearInterrupted)
-{
- bool_t interrupted;
-
-#ifndef __linux__
- mutexLock(&tid->mutex);
-#endif
-#ifdef __linux__
- interrupted = tid->pending_interrupt || tid->interrupted;
-
- if (ClearInterrupted == 1 && tid->pending_interrupt) {
- sys_thread_t* self = sysThreadSelf();
-
- if (self == tid && pthread_getspecific(intrJmpbufkey) == NULL) {
- jmp_buf jmpbuf;
-
- /*
- * Register our intrHandler as a cleanup handler. If we get
- * interrupted (i.e. canceled), we longjmp out of this handler.
- */
- pthread_cleanup_push(intrHandler, NULL);
- if (setjmp(jmpbuf) == 0) {
- thr_setspecific(intrJmpbufkey, &jmpbuf);
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- while (1) { pthread_testcancel(); }
- }
- /* Remove intrHandler without calling it. */
- pthread_cleanup_pop(0);
- }
- }
-
- if (ClearInterrupted == 1 && interrupted) {
- /* we have do to this last, otherwise we really would cancel the
- thread */
- tid->interrupted = FALSE;
- }
-#else
- interrupted = tid->interrupted;
- if (ClearInterrupted == 1) {
- tid->interrupted = FALSE;
- mutexUnlock(&tid->mutex);
- if (interrupted) {
- sigset_t osigset;
- /*
- * we were interrupted so we may have a signal pending that
- * we need to clear. We can just temporarily unmask SIGUSR1
- * and the sigusr1Handler to catch and notice that the
- * interrupted flag is not set.
- */
-
- thr_setspecific(sigusr1Jmpbufkey, NULL); /* paranoid */
- thr_sigsetmask(SIG_UNBLOCK, &sigusr1Mask, &osigset);
- thr_sigsetmask(SIG_SETMASK, &osigset, NULL);
- }
- } else { /* Otherwise leave it alone */
- mutexUnlock(&tid->mutex);
- }
-#endif
- return interrupted;
-}
-
-
-
-/*
- * Stop all threads other than the current one. The stopped threads
- * may be restarted with sysThreadMulti(); the operation of this
- * routine is atomic; it either stops all java threads or it stops
- * none of them. Upon success (all threads stopped) this routine
- * returns SYS_OK, otherwise SYS_ERR.
- *
- * In general, sysThreadSingle() should take care of anything below
- * the HPI that needs to be done to safely run single-threaded.
- */
-int
-sysThreadSingle()
-{
- return np_single();
-}
-
-/*
- * Allow multi threaded execution to resume after a
- * sysThreadSingle() call.
- *
- * Note: When this routine is called the scheduler should already
- * have been locked by sysThreadSingle().
- */
-void
-sysThreadMulti()
-{
- np_multi();
-}
-
-#ifdef __linux__
-/*
- * We abuse thread cancellation to interrupt the threads, i.e when an
- * exception is posted against the thread, pthread_cancel(3) is sent to the
- * thread and the canceled thread executes the following cleanup handler
- */
-void
-intrHandler(void* arg)
-{
- jmp_buf* jmpbufp = pthread_getspecific(intrJmpbufkey);
- if (jmpbufp != NULL) {
- volatile sys_thread_t* self = sysThreadSelf();
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
- pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
- self->interrupted = TRUE;
- self->pending_interrupt = FALSE;
- thr_setspecific(intrJmpbufkey, NULL);
- longjmp(*jmpbufp, 1);
- } else {
-#ifdef PARANOID_DEBUG
- sysAssert(0);
-#endif
- }
-}
-
-#else
-/*
- * SIGUSR1 is used to interrupt the threads, i.e when an exception
- * is posted against the thread, SIGUSR1 is sent to the thread and the
- * thread gets the signal, executes the following handler
- */
-
-static void
-#ifdef SA_SIGINFO
-sigusr1Handler(int sig, siginfo_t *info, void *uc)
-#else
-sigusr1Handler(int sig)
-#endif
-{
- sys_thread_t *tid = sysThreadSelf();
-
- if (tid->interrupted) {
- sigjmp_buf *jmpbufp;
-#ifdef USE_PTHREADS
- jmpbufp = pthread_getspecific(sigusr1Jmpbufkey);
-#else
- thr_getspecific(sigusr1Jmpbufkey, (void **)&jmpbufp);
-#endif
- if (jmpbufp != NULL)
- siglongjmp(*jmpbufp, 1);
- }
-}
-#endif
-
-HPI_SysInfo *
-sysGetSysInfo()
-{
- static HPI_SysInfo info = {0, 0};
-
- if (info.name == NULL) {
- /*
- * we want the number of processors configured not the number online
- * since processors may be turned on and off dynamically.
- */
- int cpus = (int) sysconf(_SC_NPROCESSORS_CONF);
-
- info.isMP = (cpus < 0) ? 1 : (cpus > 1);
- info.name = "native threads";
- }
- return &info;
-}
-
-
-jlong
-sysThreadCPUTime()
-{
-#ifdef HAVE_GETHRVTIME
- return gethrvtime();
-#else
- return 0;
-#endif
-}
-
-int
-sysThreadGetStatus(sys_thread_t *tid, sys_mon_t **monitorPtr)
-{
- int status;
- switch (tid->state) {
- case RUNNABLE:
- if (tid->mon_enter) {
- status = SYS_THREAD_MONITOR_WAIT;
- } else {
- status = SYS_THREAD_RUNNABLE;
- }
- break;
- case SUSPENDED:
- if (tid->mon_enter)
- status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT;
- else if (tid->cpending_suspend)
- status = SYS_THREAD_SUSPENDED | SYS_THREAD_CONDVAR_WAIT;
- else
- status = SYS_THREAD_SUSPENDED;
- break;
- case CONDVAR_WAIT:
- status = SYS_THREAD_CONDVAR_WAIT;
- break;
- default:
- return SYS_ERR;
- }
- if (monitorPtr) {
- if (status & SYS_THREAD_MONITOR_WAIT) {
- *monitorPtr = tid->mon_enter;
- } else if (status & SYS_THREAD_CONDVAR_WAIT) {
- *monitorPtr = tid->mon_wait;
- } else {
- *monitorPtr = NULL;
- }
- }
- return status;
-}
-
-int sysAdjustTimeSlice(int new)
-{
- return SYS_ERR;
-}
-
-void sysThreadProfSuspend(sys_thread_t *tid)
-{
- np_profiler_suspend(tid);
-}
-
-void sysThreadProfResume(sys_thread_t *tid)
-{
- np_profiler_continue(tid);
-}
-
-bool_t sysThreadIsRunning(sys_thread_t *tid)
-{
- return np_profiler_thread_is_running(tid);
-}
-
-void *
-sysThreadInterruptEvent()
-{
- return NULL;
-}
--- a/jdk/src/solaris/hpi/native_threads/src/threads_solaris.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,666 +0,0 @@
-/*
- * Copyright (c) 1998, 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Implementation of HPI that can not be expressed with POSIX threads.
- * Note that even if you are building with USE_PTHREADS, we have to
- * explicitly undef it here because pthread.h and thread.h can not be
- * included in the same file, and this file needs only thread.h.
- */
-#undef USE_PTHREADS
-
-#include "hpi_impl.h"
-#include "monitor_md.h"
-#include "threads_md.h"
-#include "np.h"
-
-#include <thread.h>
-#include <sys/lwp.h>
-#include <signal.h>
-#include <sys/signal.h>
-#include <sys/resource.h>
-#include <sys/procfs.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <sys/syscall.h>
-extern int syscall(int, ...);
-
-
-/*
- * Forward declarations.
- */
-static int procfd;
-static void stop_lwps();
-static void clear_onproc_flags();
-static void restart_lwps();
-static void MakeProcName(register char *procname, register pid_t pid);
-static void GC_msec_sleep(int n);
-
-
-/*
- * Make sure that we link against a verion of libthread that has at least
- * the bug fixes and the interface for getting the stack from threads that
- * aren't on LWPs. Otherwise we should exit with some informative message.
- */
-extern ulong_t __gettsp(thread_t);
-
-static const char * gettspMessage =
-"You must install a Solaris patch to run the native threads version of the\n"
-"Java runtime. The green threads version will work without this patch.\n"
-"Please check the native threads release notes for more information.\n"
-"\n"
-"If you are embedding the VM in a native application, please make sure that\n"
-"the native application is linked with libthread.so (-lthread).\n"
-"\n"
-"Exiting.\n";
-
-static void
-checkForCorrectLibthread()
-{
- if (&__gettsp == 0) {
- fprintf(stderr, gettspMessage);
- exit(1);
- }
-}
-#ifdef __GNUC__
-static void checkForCorrectLibthread() __attribute__((constructor));
-#else
-#pragma init(checkForCorrectLibthread)
-#endif
-
-#pragma weak __gettsp
-
-
-/*
- * Suspend said thread. Used to implement java.lang.Thread.suspend(),
- * which is deprecated.
- */
-int
-np_suspend(sys_thread_t *tid)
-{
- return thr_suspend(tid->sys_thread);
-}
-
-
-/*
- * Resume a suspended thread. Used to implement java.lang.Thread.resume(),
- * which is deprecated.
- */
-int
-np_continue(sys_thread_t *tid)
-{
- return thr_continue(tid->sys_thread);
-}
-
-/*
- * If there is any initialization is required by the non-POSIX parts.
- */
-void np_initialize_thread(sys_thread_t *tid)
-{
- return;
-}
-
-
-/*
- * Get the stack start address, and max stack size for the current thread.
- */
-int
-np_stackinfo(void **addr, long *size)
-{
- stack_t stkseg;
-
- if (thr_stksegment(&stkseg) == 0) {
- *addr = (void *)(stkseg.ss_sp);
- if (thr_main()) {
- struct rlimit r;
- getrlimit(RLIMIT_STACK, &r);
- *size = (long)r.rlim_cur;
- } else {
- *size = (long)(stkseg.ss_size);
- }
- return SYS_OK;
- } else {
- return SYS_ERR; /* thr_stksegment failed. */
- }
-}
-
-/*
- * On Solaris when doing CPU profiling, the threads are bound.
- */
-void
-np_profiler_init(sys_thread_t *tid)
-{
- tid->lwp_id = _lwp_self();
-}
-
-int
-np_profiler_suspend(sys_thread_t *tid)
-{
- return _lwp_suspend(tid->lwp_id);
-}
-
-int
-np_profiler_continue(sys_thread_t *tid)
-{
- return _lwp_continue(tid->lwp_id);
-}
-
-bool_t
-np_profiler_thread_is_running(sys_thread_t *tid)
-{
- unsigned long sum = 0;
- int i;
- prstatus_t lwpstatus;
- int lwpfd;
- int res;
-
- lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP, &(tid->lwp_id));
- sysAssert(lwpfd >= 0);
-
- retry:
- res = syscall(SYS_ioctl, lwpfd, PIOCSTATUS, &lwpstatus);
- sysAssert(res >= 0);
-
- if (!(lwpstatus.pr_flags & PR_STOPPED)) {
- GC_msec_sleep(1);
- goto retry;
- }
-
- close(lwpfd);
-
-#if defined(sparc)
- sum += lwpstatus.pr_reg[R_SP];
- sum += lwpstatus.pr_reg[R_PC];
-
- sum += lwpstatus.pr_reg[R_G1];
- sum += lwpstatus.pr_reg[R_G2];
- sum += lwpstatus.pr_reg[R_G3];
- sum += lwpstatus.pr_reg[R_G4];
-
- sum += lwpstatus.pr_reg[R_O0];
- sum += lwpstatus.pr_reg[R_O1];
- sum += lwpstatus.pr_reg[R_O2];
- sum += lwpstatus.pr_reg[R_O3];
- sum += lwpstatus.pr_reg[R_O4];
- sum += lwpstatus.pr_reg[R_O5];
-
- sum += lwpstatus.pr_reg[R_I0];
- sum += lwpstatus.pr_reg[R_I1];
- sum += lwpstatus.pr_reg[R_I2];
- sum += lwpstatus.pr_reg[R_I3];
- sum += lwpstatus.pr_reg[R_I4];
- sum += lwpstatus.pr_reg[R_I5];
- sum += lwpstatus.pr_reg[R_I6];
- sum += lwpstatus.pr_reg[R_I7];
-
- sum += lwpstatus.pr_reg[R_L0];
- sum += lwpstatus.pr_reg[R_L1];
- sum += lwpstatus.pr_reg[R_L2];
- sum += lwpstatus.pr_reg[R_L3];
- sum += lwpstatus.pr_reg[R_L4];
- sum += lwpstatus.pr_reg[R_L5];
- sum += lwpstatus.pr_reg[R_L6];
- sum += lwpstatus.pr_reg[R_L7];
-#elif defined(amd64)
- sum += lwpstatus.pr_reg[REG_RIP];
- sum += lwpstatus.pr_reg[REG_RSP];
-
- sum += lwpstatus.pr_reg[REG_RAX];
- sum += lwpstatus.pr_reg[REG_RCX];
- sum += lwpstatus.pr_reg[REG_RDX];
- sum += lwpstatus.pr_reg[REG_RBX];
- sum += lwpstatus.pr_reg[REG_RBP];
- sum += lwpstatus.pr_reg[REG_RSI];
- sum += lwpstatus.pr_reg[REG_RDI];
-
- sum += lwpstatus.pr_reg[REG_R8];
- sum += lwpstatus.pr_reg[REG_R9];
- sum += lwpstatus.pr_reg[REG_R10];
- sum += lwpstatus.pr_reg[REG_R11];
- sum += lwpstatus.pr_reg[REG_R12];
- sum += lwpstatus.pr_reg[REG_R13];
- sum += lwpstatus.pr_reg[REG_R14];
- sum += lwpstatus.pr_reg[REG_R15];
-#elif defined(i386)
- sum += lwpstatus.pr_reg[EIP];
- sum += lwpstatus.pr_reg[UESP];
-
- sum += lwpstatus.pr_reg[EAX];
- sum += lwpstatus.pr_reg[ECX];
- sum += lwpstatus.pr_reg[EDX];
- sum += lwpstatus.pr_reg[EBX];
- sum += lwpstatus.pr_reg[EBP];
- sum += lwpstatus.pr_reg[ESI];
- sum += lwpstatus.pr_reg[EDI];
-#endif
-
- if (tid->last_sum == sum) {
- return FALSE;
- }
- tid->last_sum = sum;
-
- return TRUE;
-}
-
-
-/*
- * If building for Solaris native threads, open up the /proc file
- * descriptor to be used when doing GC. The open is done at JVM start-up so
- * as to reserve this fd, to prevent GC stall due to exhausted fds. This fd
- * will never be closed, and will alwyas be present.
- */
-int
-np_initialize()
-{
- char procname[32];
- MakeProcName(procname, getpid());
- if ((procfd = open(procname, O_RDONLY, 0)) < 0) {
- VM_CALL(jio_fprintf)(stderr, "Cannot open %s for GC", procname);
- return SYS_ERR;
- }
- return SYS_OK;
-}
-
-static void
-MakeProcName(register char *procname, register pid_t pid)
-{
- register char * s;
-
- (void) strcpy(procname, "/proc/00000");
- s = procname + strlen(procname);
- while (pid) {
- *--s = pid%10 + '0';
- pid /= 10;
- }
-}
-
-/*
- * Suspend all other threads, and record their contexts (register
- * set or stack pointer) into the sys_thread structure, so that a
- * garbage collect can be run.
- */
-int
-np_single(void)
-{
- int ret;
-
- sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
-
- stop_lwps();
- ret = SYS_OK;
- return ret;
-}
-
-/*
- * Continue threads suspended earlier. But clear their context
- * recorded in sys_thread structure first.
- */
-void
-np_multi(void)
-{
- sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
- clear_onproc_flags();
- restart_lwps();
-}
-
-/* /proc solution to stop and restrt lwps */
-/* make sure gc is run as a bound thread */
-/* make sure signals are turned off for gc thread */
-/* what about new lwps getting created in the meantime? */
-
-#define MAX_LWPS 1024
-
-static prstatus_t Mystatus;
-static id_t lwpid_list_buf[MAX_LWPS];
-static id_t oldlwpid_list_buf[MAX_LWPS];
-static sys_thread_t *onproct_list_buf[MAX_LWPS];
-static id_t *lwpid_list = lwpid_list_buf;
-static id_t *oldlwpid_list = oldlwpid_list_buf;
-static sys_thread_t **onproct_list = onproct_list_buf;
-static int lwpid_list_len;
-static int oldlwpid_list_len;
-static int onproct_ix = 0;
-static int gcprio;
-static sigset_t gcmask;
-
-static void
-clear_onproc_flags()
-{
- int i;
-
- for (i = 0; i < onproct_ix; i++) {
- ((sys_thread_t *)(onproct_list[i]))->onproc = FALSE;
- }
- onproct_ix = 0;
-}
-
-
-/* Sleep for n milliseconds, n < 1000 */
-static void
-GC_msec_sleep(int n)
-{
- struct timespec ts;
-
- ts.tv_sec = 0;
- ts.tv_nsec = 1000000*n;
- if (syscall(SYS_nanosleep, &ts, 0) < 0) {
- VM_CALL(jio_fprintf)(stderr, "%d\n", errno);
- }
-}
-
-/*
- * Assumes stacks grow down from high to low memory. True on sparc and Intel.
- */
-#define VALID_SP(sp, bottom, top) \
- (((uintptr_t)(sp)) < ((uintptr_t)(bottom)) && ((uintptr_t)(sp)) > ((uintptr_t)(top)))
-
-static void
-record_lwp_regs(prstatus_t lwpstatus)
-{
- sys_thread_t *tid;
- int i;
-#if defined(sparc)
- register uintptr_t sp = lwpstatus.pr_reg[R_SP];
-#elif defined(amd64)
- register uintptr_t sp = lwpstatus.pr_reg[REG_RSP];
-#elif defined(i386)
- register uintptr_t sp = lwpstatus.pr_reg[UESP];
-#endif
-
- tid = ThreadQueue;
- for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
- if (VALID_SP(sp, tid->stack_bottom, tid->stack_top)) {
- long *regs = tid->regs;
- tid->sp = sp;
- /*
- * The code below relies on N_TRACED_REGS being set
- * correctly for each platform. If you change the
- * number of registers being watched, you should update
- * the define for N_TRACED_REGS
- */
-#if defined(sparc)
- regs[0] = lwpstatus.pr_reg[R_G1];
- regs[1] = lwpstatus.pr_reg[R_G2];
- regs[2] = lwpstatus.pr_reg[R_G3];
- regs[3] = lwpstatus.pr_reg[R_G4];
-
- regs[4] = lwpstatus.pr_reg[R_O0];
- regs[5] = lwpstatus.pr_reg[R_O1];
- regs[6] = lwpstatus.pr_reg[R_O2];
- regs[7] = lwpstatus.pr_reg[R_O3];
- regs[8] = lwpstatus.pr_reg[R_O4];
- regs[9] = lwpstatus.pr_reg[R_O5];
- regs[10] = lwpstatus.pr_reg[R_O6];
- regs[11] = lwpstatus.pr_reg[R_O7];
-#elif defined(amd64)
- regs[0] = lwpstatus.pr_reg[REG_RAX];
- regs[1] = lwpstatus.pr_reg[REG_RCX];
- regs[2] = lwpstatus.pr_reg[REG_RDX];
- regs[3] = lwpstatus.pr_reg[REG_RBX];
- regs[4] = lwpstatus.pr_reg[REG_RBP];
- regs[5] = lwpstatus.pr_reg[REG_RSI];
- regs[6] = lwpstatus.pr_reg[REG_RDI];
- regs[7] = lwpstatus.pr_reg[REG_R8];
- regs[8] = lwpstatus.pr_reg[REG_R9];
- regs[9] = lwpstatus.pr_reg[REG_R10];
- regs[10]= lwpstatus.pr_reg[REG_R11];
- regs[11]= lwpstatus.pr_reg[REG_R12];
- regs[12]= lwpstatus.pr_reg[REG_R13];
- regs[13]= lwpstatus.pr_reg[REG_R14];
- regs[14]= lwpstatus.pr_reg[REG_R15];
-#elif defined(i386)
- regs[0] = lwpstatus.pr_reg[EAX];
- regs[1] = lwpstatus.pr_reg[ECX];
- regs[2] = lwpstatus.pr_reg[EDX];
- regs[3] = lwpstatus.pr_reg[EBX];
- regs[4] = lwpstatus.pr_reg[EBP];
- regs[5] = lwpstatus.pr_reg[ESI];
- regs[6] = lwpstatus.pr_reg[EDI];
-#endif
-
- if (tid->onproc != TRUE) {
- tid->onproc = TRUE;
- onproct_list[onproct_ix++] = tid;
- }
- break;
- }
- tid = tid->next;
- }
-}
-
-static void
-record_thread_regs()
-{
- sys_thread_t *tid;
- int i;
-
- tid = ThreadQueue;
- for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
- if (tid->onproc != TRUE) {
- int i;
-
- if (tid->sys_thread != 0) {
- /* if thread has already been initialized */
- tid->sp = __gettsp(tid->sys_thread);
- } else {
- /*
- * thread is still in the process of being initalized.
- * So GC should not care about this thread. Just
- * set its sp to 0, and this will force GC to ignore it.
- */
- tid->sp = 0;
- }
-
- /*
- * Clear out the registers since they are no longer live
- * and we don't want to garbage collector to think they are.
- */
-
- for (i = 0; i < N_TRACED_REGS; i++)
- tid->regs[i] = 0;
- }
- tid = tid->next;
- }
-}
-
-static void
-wait_stopped_lwps(void)
-{
- int i, lwpfd;
- prstatus_t lwpstatus;
-
- for (i = 0; i < (int) Mystatus.pr_nlwp; i++) {
- /* if its not me */
- if (lwpid_list[i] != _lwp_self()) {
-
- /* open the lwp and check the status */
- if ((lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP,
- &lwpid_list[i])) < 0) {
-#ifdef MY_DEBUG
- VM_CALL(jio_fprintf)(stderr, "lwpid %d was not found in process\n",
- lwpid_list[i]);
-#endif
- continue;
- }
- memset(&lwpstatus, 0, sizeof(lwpstatus));
- while (1) {
- if (syscall(SYS_ioctl,lwpfd, PIOCSTATUS, &lwpstatus)<0) {
- sysAssert(0);
-#ifdef MY_DEBUG
- VM_CALL(jio_fprintf)(stderr, "PIOCSTATUS failed for lwp %d",
- lwpid_list[i]);
-#endif
- break;
- }
- if (lwpstatus.pr_flags & PR_STOPPED) {
- record_lwp_regs(lwpstatus);
- break;
- }
- GC_msec_sleep(1);
- }
-
- close (lwpfd);
- } /* end of if-me */
- } /* end of for */
-}
-
-static void
-suspend_lwps()
-{
- int i;
- /* pioopen all the lwps and stop them - except the one I am running on */
- for (i = 0; i < (int) Mystatus.pr_nlwp; i++) {
-
- /* open and stop the lwp if its not me */
- if (lwpid_list[i] != _lwp_self()) {
-
- /* PIOCSTOP doesn't work without a writable */
- /* descriptor. And that makes the process */
- /* undebuggable. */
- if (_lwp_suspend(lwpid_list[i]) < 0) {
- /* Could happen if the lwp exited */
- lwpid_list[i] = _lwp_self();
- continue;
- }
- }
- }
-}
-
-static void
-print_lwps()
-{
-#ifdef MY_DEBUG
- /* print all the lwps in the process */
- VM_CALL(jio_fprintf)(stdout, "lwpids ");
- for (i = 0; i < (int) Mystatus.pr_nlwp; i++) {
- if (i == 0) {
- VM_CALL(jio_fprintf)(stdout, "%d", lwpid_list[0]);
- } else if (i != Mystatus.pr_nlwp - 1) {
- VM_CALL(jio_fprintf)(stdout, ", %d", lwpid_list[i]);
- } else {
- VM_CALL(jio_fprintf)(stdout, " and %d", lwpid_list[i]);
- }
- }
-#endif
-}
-
-/* routine to iteratively stop all lwps */
-static void
-stop_lwps()
-{
- int i;
- sigset_t set;
- boolean_t changed;
-
- /* mask all signals */
- (void) sigfillset(&set);
- syscall(SYS_sigprocmask, SIG_SETMASK, &set, &gcmask);
-
- /* run at highest prio so I cannot be preempted */
- thr_getprio(thr_self(), &gcprio);
- thr_setprio(thr_self(), 2147483647); /* #define INT_MAX 2147483647 */
-
- oldlwpid_list_len = 0;
-
- while(1) {
- changed = B_FALSE;
-
- /* Get the # of lwps in the process */
- memset(&Mystatus, 0, sizeof(Mystatus));
- syscall(SYS_ioctl, procfd, PIOCSTATUS, &Mystatus);
-
-#ifdef MY_DEBUG
- VM_CALL(jio_fprintf)(stdout, "Number of lwps in the process is %d\n",
- Mystatus.pr_nlwp);
- VM_CALL(jio_fprintf)(stdout, "My lwp id is %d\n", _lwp_self());
-#endif
- lwpid_list_len = Mystatus.pr_nlwp;
- if (syscall(SYS_ioctl, procfd, PIOCLWPIDS, lwpid_list) == -1) {
-#ifdef MY_DEBUG
- VM_CALL(jio_fprintf)(stderr, "Can't read proc's lwpid list");
-#endif
- return;
- }
-
- print_lwps();
-
- /* suspend all the lwps */
- suspend_lwps();
-
- /* make sure all the lwps have actually stopped */
- wait_stopped_lwps();
-
- /* make sure the list has not changed while you were not looking
- else start all over again */
- if (lwpid_list_len != oldlwpid_list_len) changed = B_TRUE;
- else {
- for (i=0; i<lwpid_list_len; ++i) {
- if (lwpid_list[i] != oldlwpid_list[i]) {
- changed = B_TRUE; break;
- }
- }
- }
- if (!changed) break;
-
- {
- id_t *tmplwpid_list = oldlwpid_list;
- oldlwpid_list = lwpid_list; oldlwpid_list_len = lwpid_list_len;
- lwpid_list = 0; lwpid_list_len = 0;
- lwpid_list = tmplwpid_list;
- }
- }
-
- /* record regs for threads that were not on LWPs */
- record_thread_regs();
-
- return;
-}
-
-
-/* Restart all lwps in process. */
-static void
-restart_lwps()
-{
- int i;
-
- for (i = 0; i < Mystatus.pr_nlwp; i++) {
- if (lwpid_list[i] == _lwp_self()) continue;
- if (_lwp_continue(lwpid_list[i]) < 0) {
-#ifdef MY_DEBUG
- VM_CALL(jio_fprintf)(stderr, "Failed to restart lwp %d\n",lwpid_list[i]);
-#endif
- }
- }
-
- /* restore the old priority of the thread */
- thr_setprio(thr_self(), gcprio);
- /* restore the oldmask */
- syscall(SYS_sigprocmask, SIG_SETMASK, &gcmask, NULL);
-
- print_lwps();
-}
--- a/jdk/src/solaris/hpi/src/interrupt.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 1994, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Threads interrupt dispatch
- */
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <signal.h>
-
-#include "hpi_impl.h"
-
-#include "interrupt.h"
-
-/* handler_entry_t is used to keep track of the registered handlers. */
-typedef struct handler_entry {
- intr_handler_t handler;
- void *handlerArg;
-} handler_entry_t;
-
-static handler_entry_t handlerList[N_INTERRUPTS];
-
-/* Initialize the interrupt system */
-void
-intrInit()
-{
- memset(handlerList, 0, sizeof(handlerList));
- /*
- * Target-dependent initialization.
- */
- intrInitMD();
-}
-
-/* Add/Remove a handler for a particular interrupt */
-
-signal_handler_t
-intrRegister(int interrupt, intr_handler_t handler, void *handlerArg)
-{
- struct sigaction sigAct, sigActOld;
-
- intrLock();
-
- if (handler == (intr_handler_t)SYS_SIG_IGN ||
- handler == (intr_handler_t)SYS_SIG_DFL) {
- /* If we get IGN or DFL, register that as the process signal handler,
- * and clear the handlerList entry.
- */
- sigAct.sa_handler = (void (*)(int))handler;
- sigAct.sa_flags = 0;
- sigaction(interrupt, &sigAct, &sigActOld);
- handlerList[interrupt].handler = NULL;
- } else {
- /* Otherwise, we register intrDispatchMD as the common signal handler,
- * and set the real handler in handlerList[interrupt].handler.
- */
-#ifdef SA_SIGINFO
- sigAct.sa_handler = 0;
- sigAct.sa_sigaction = intrDispatchMD;
- sigAct.sa_flags = SA_SIGINFO | SA_RESTART;
-#else
- sigAct.sa_handler = intrDispatchMD;
- sigAct.sa_flags = SA_RESTART;
-#endif
- sigfillset(&sigAct.sa_mask);
- sigaction(interrupt, &sigAct, &sigActOld);
- handlerList[interrupt].handler = handler;
- handlerList[interrupt].handlerArg = handlerArg;
- }
-
- intrUnlock();
-
- /* If SA_SIGINFO is set, sa_sigaction is valid, otherwise sa_handler is. */
-#ifdef SA_SIGINFO
- return (sigActOld.sa_flags & SA_SIGINFO) ?
- (signal_handler_t)sigActOld.sa_sigaction :
- (signal_handler_t)sigActOld.sa_handler;
-#else
- return (signal_handler_t)sigActOld.sa_handler;
-#endif
-}
-
-/*
- * intrDispatch -- Dispatch an interrupt.
- *
- * This routine is called from the low-level handlers
- * at interrupt time.
- */
-void
-intrDispatch(int interrupt, void *siginfo, void *context)
-{
- /*
- * Assumptions:
- * - Each interrupt only has one priority level associated with
- * it.
- * - Each handler will do enough work so that when it returns
- * the source of the interrupt is masked.
- */
- handler_entry_t *entry = &handlerList[interrupt];
- intr_handler_t handler = entry->handler;
-
- if (handler) {
- (*handler)(interrupt, siginfo, context, entry->handlerArg);
- return;
- }
-
- /* No handler for this interrupt, log the error */
- Log1(0, "spurious interrupt %d\n", interrupt);
- return;
-}
-
-static void userSignalHandler(int sig, void *info, void *uc, void *arg)
-{
- signal_handler_t handler = (signal_handler_t)arg;
- /* for now we don't change the disposition of the signal in this case */
- /* sysSignal(sig, SYS_SIG_DFL); */
- handler(sig, info, uc);
-}
-
-signal_handler_t sysSignal(int sig, signal_handler_t newHandler)
-{
- handler_entry_t *entry = &handlerList[sig];
- void *oldHandlerArg = entry->handlerArg;
- signal_handler_t oldHandler;
-
- if (intrInUse(sig)) {
- return SYS_SIG_ERR;
- }
-
-#ifdef __linux__
- oldHandler = intrRegister(sig, (intr_handler_t)userSignalHandler, (void *)newHandler);
-#else
- oldHandler = intrRegister(sig, userSignalHandler, (void *)newHandler);
-#endif
- /* If the old handler is intrDispatchMD, we get the real handler from
- * entry->handlerArg.
- */
- if (oldHandler == (signal_handler_t)intrDispatchMD) {
- oldHandler = (signal_handler_t)oldHandlerArg;
- }
-
- return oldHandler;
-}
-
-void sysRaise(int sig)
-{
- raise(sig);
-}
--- a/jdk/src/solaris/hpi/src/linker_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/*
- * Copyright (c) 1994, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Machine Dependent implementation of the dynamic linking support
- * for java. This routine is Solaris specific.
- */
-
-#include "hpi_impl.h"
-
-#include <stdio.h>
-#include <dlfcn.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "path_md.h"
-#include "monitor_md.h"
-
-#ifndef NATIVE
-#include "iomgr.h"
-#include "threads_md.h"
-#endif
-
-/*
- * This lock protects the dl wrappers, assuring that two threads aren't
- * in libdl at the same time.
- */
-sys_mon_t _dl_lock;
-
-/*
- * Solaris green threads needs to lock around libdl.so.
- */
-#if defined(__solaris__) && !defined(NATIVE)
- #define NEED_DL_LOCK
-#endif
-
-/*
- * create a string for the JNI native function name by adding the
- * appropriate decorations.
- */
-int
-sysBuildFunName(char *name, int nameLen, int args_size, int encodingIndex)
-{
- /* On Solaris, there is only one encoding method. */
- if (encodingIndex == 0)
- return 1;
- return 0;
-}
-
-/*
- * create a string for the dynamic lib open call by adding the
- * appropriate pre and extensions to a filename and the path
- */
-void
-sysBuildLibName(char *holder, int holderlen, char *pname, char *fname)
-{
- const size_t pnamelen = pname ? strlen(pname) : 0;
-
- /* Quietly truncate on buffer overflow. Should be an error. */
- if (pnamelen + strlen(fname) + 10 > (size_t) holderlen) {
- *holder = '\0';
- return;
- }
-
- if (pnamelen == 0) {
- sprintf(holder, "lib%s.so", fname);
- } else {
- sprintf(holder, "%s/lib%s.so", pname, fname);
- }
-}
-
-
-#ifdef __linux__
- static int thr_main(void)
- {
- return -1;
- }
-#else
- #ifndef NATIVE
- extern int thr_main(void);
- #endif
-#endif
-
-void *
-sysLoadLibrary(const char *name, char *err_buf, int err_buflen)
-{
- void * result;
-
-#ifdef NEED_DL_LOCK
- sysMonitorEnter(sysThreadSelf(), &_dl_lock);
- result = dlopen(name, RTLD_NOW);
- sysMonitorExit(sysThreadSelf(), &_dl_lock);
-#else
- result = dlopen(name, RTLD_LAZY);
-#endif
- /*
- * This is a bit of bulletproofing to catch the commonly occurring
- * problem of people loading a library which depends on libthread into
- * the VM. thr_main() should always return -1 which means that libthread
- * isn't loaded.
- */
-#ifndef NATIVE
- if (thr_main() != -1) {
- VM_CALL(panic)("libthread loaded into green threads");
- }
-#endif
- if (result == NULL) {
- strncpy(err_buf, dlerror(), err_buflen-2);
- err_buf[err_buflen-1] = '\0';
- }
- return result;
-}
-
-void
-sysUnloadLibrary(void *handle)
-{
-#ifdef NEED_DL_LOCK
- sysMonitorEnter(sysThreadSelf(), &_dl_lock);
- dlclose(handle);
- sysMonitorExit(sysThreadSelf(), &_dl_lock);
-#else
- dlclose(handle);
-#endif
-}
-
-void *
-sysFindLibraryEntry(void *handle, const char *name)
-{
- void *sym;
-#ifdef NEED_DL_LOCK
- sysMonitorEnter(sysThreadSelf(), &_dl_lock);
- sym = dlsym(handle, name);
- sysMonitorExit(sysThreadSelf(), &_dl_lock);
-#else
- sym = dlsym(handle, name);
-#endif
- return sym;
-}
--- a/jdk/src/solaris/hpi/src/memory_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,439 +0,0 @@
-/*
- * Copyright (c) 1995, 2000, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Implementation of primitive memory allocation.
- *
- * The only thing machine dependent about this allocator is how it
- * initially finds all of the possible memory, and how it implements
- * mapChunk() and unmapChunk().
- *
- * This is all pretty simple stuff. It is not likely to be banged on
- * frequently enough to be a performance issue, unless the underlying
- * primitives are. Implementing things:
- *
- * HPI function Solaris "malloc" Win32
- * --------------------------------------------------------------------
- * sysMapMem() mmap() malloc() VirtualAlloc(...MEM_RESERVE...)
- * sysUnMapMem() munmap() free() VirtualFree(...MEM_RESERVE...)
- * sysCommitMem() no-op no-op VirtualAlloc(...MEM_COMMIT...)
- * sysDecommitMem() no-op no-op VirtualFree(...MEM_COMMIT...)
- *
- * Memory mapping is the default, but compiling with -DUSE_MALLOC gives
- * a system based on malloc().
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h> /* For perror() */
-#include <string.h>
-#include <malloc.h>
-
-#include "hpi_impl.h"
-
-#ifndef USE_MALLOC
-
-#include <sys/mman.h>
-#include <fcntl.h>
-#ifdef __linux__
-#ifndef MAP_ANONYMOUS
-static int devZeroFD;
-#endif
-#else
-static int devZeroFD;
-#endif
-
-#endif /* !USE_MALLOC */
-
-#ifdef __linux__
-#ifndef MAP_FAILED
-#define MAP_FAILED ((caddr_t)-1)
-#endif
-static size_t memGrainSize; /* A page for Linux */
-#else
-static unsigned int memGrainSize; /* A page for Solaris */
-#endif
-
-/*
- * Mem size rounding is done at this level. The calling code asks
- * these routines for literally what it thinks it wants. The size is
- * rounded up to the first multiple of memGrainSize that contains
- * requestedSize bytes.
- */
-
-static long
-roundUpToGrain(long value)
-{
- return (value + memGrainSize - 1) & ~(memGrainSize - 1);
-}
-
-static long
-roundDownToGrain(long value)
-{
- return value & ~(memGrainSize - 1);
-}
-
-void
-InitializeMem(void)
-{
- static int init = 0;
-
- if (init) {
- return; /* Subsequent calls are no-ops */
- }
-
- /*
- * Set system-specific variables used by mem allocator
- */
- if (memGrainSize == 0) {
- memGrainSize = (int) sysconf(_SC_PAGESIZE);
- }
-
-#ifdef __linux__
-#if !defined(USE_MALLOC) && !defined(MAP_ANONYMOUS)
- devZeroFD = open("/dev/zero", O_RDWR);
- if (devZeroFD == -1) {
- perror("devzero");
- exit(1);
- }
-#endif /* !USE_MALLOC MAP_ANONYMOUS*/
-#else
-#ifndef USE_MALLOC
- devZeroFD = open("/dev/zero", O_RDWR);
- if (devZeroFD == -1) {
- perror("devzero");
- exit(1);
- }
-#endif /* !USE_MALLOC */
-#endif
-
- init = 1; /* We're initialized now */
-}
-
-
-#ifndef USE_MALLOC
-
-#define PROT_ALL (PROT_READ|PROT_WRITE|PROT_EXEC)
-
-#ifndef MAP_NORESERVE
-#define MAP_NORESERVE 0
-#endif
-
-/*
- * Map a chunk of memory. Return the address of the base if successful,
- * 0 otherwise. We do not care where the mapped memory is, and can't
- * even express a preference in the current HPI. If any platforms
- * require us to manage addresses of mapped chunks explicitly, that
- * must be done below the HPI.
- */
-static char *
-mapChunk(long length)
-{
- char *ret;
-
-#if defined(__linux__) && defined(MAP_ANONYMOUS)
- ret = (char *) mmap(0, length, PROT_ALL,
- MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS,
- -1, (off_t) 0);
-#else
- ret = (char *) mmap(0, length, PROT_ALL, MAP_NORESERVE|MAP_PRIVATE,
- devZeroFD, (off_t) 0);
-#endif
- return (ret == MAP_FAILED ? 0 : ret);
-}
-
-/*
- * Map a chunk of memory at a specific address and reserve swap space
- * for it. This is currently only used to remap space previously mapped
- * MAP_NORESERVE, reserving swap and getting native error handling. We
- * assume that all alignment and rounding has been done by the caller.
- * Return 1 if successful and 0 otherwise.
- */
-static char *
-mapChunkReserve(char *addr, long length)
-{
- char *ret;
-#if defined(__linux__) && defined(MAP_ANONYMOUS)
- ret = (char *) mmap(addr, length, PROT_ALL,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS,
- -1, (off_t) 0);
-#else
- ret = (char *) mmap(addr, length, PROT_ALL, MAP_FIXED|MAP_PRIVATE,
- devZeroFD, (off_t) 0);
-#endif
- return (ret == MAP_FAILED ? 0 : ret);
-}
-
-/*
- * Map a chunk of memory at a specific address and reserve swap space
- * for it. This is currently only used to remap space previously mapped
- * MAP_RESERVE, unreserving swap and getting native error handling. We
- * assume that all alignment and rounding has been done by the caller.
- * Return 1 if successful and 0 otherwise.
- */
-static char *
-mapChunkNoreserve(char *addr, long length)
-{
- char *ret;
-
-#if defined(__linux__) && defined(MAP_ANONYMOUS)
- ret = (char *) mmap(addr, length, PROT_ALL,
- MAP_FIXED | MAP_PRIVATE |
- MAP_NORESERVE | MAP_ANONYMOUS,
- -1, (off_t) 0);
-#else
- ret = (char *) mmap(addr, length, PROT_ALL,
- MAP_FIXED|MAP_PRIVATE|MAP_NORESERVE,
- devZeroFD, (off_t) 0);
-#endif
- return (ret == MAP_FAILED ? 0 : ret);
-}
-
-/*
- * Unmap a chunk of memory. Return 1 if successful, 0 otherwise. We
- * currently don't do any alignment or rounding, assuming that we only
- * will unmap chunks that have previously been returned by mapChunk().
- */
-static int
-unmapChunk(void *addr, long length)
-{
- return (munmap(addr, length) == 0);
-}
-
-#endif /* !USE_MALLOC */
-
-
-/* HPI Functions: */
-
-/*
- * Map a range of virtual memory. Note that the size asked for here
- * is literally what the upper level has asked for. We need to do
- * any rounding, etc. here. If mapping fails return 0, otherwise
- * return the address of the base of the mapped memory.
- */
-void *
-sysMapMem(size_t requestedSize, size_t *mappedSize)
-{
- void *mappedAddr;
-
- *mappedSize = roundUpToGrain(requestedSize);
-#ifdef USE_MALLOC
- mappedAddr = (void *) sysMalloc(*mappedSize); /* Returns 0 on failure */
-#ifdef __linux__
- if (mappedAddr) {
- memset(mappedAddr, 0, *mappedSize);
- mappedAddr = (void *) roundUpToGrain(mappedAddr);
- }
-#endif
-#else
- mappedAddr = mapChunk(*mappedSize); /* Returns 0 on failure */
-#endif /* USE_MALLOC */
- if (mappedAddr) {
- Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n",
- *mappedSize, mappedAddr, requestedSize);
- } else {
- Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize);
- }
- return mappedAddr;
-}
-
-/*
- * Unmap a range of virtual memory. Note that the size asked for here
- * is literally what the upper level has asked for. We need to do any
- * rounding, etc. here. If unmapping fails return 0, otherwise return
- * the address of the base of the unmapped memory.
- */
-void *
-sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize)
-{
- void *unmappedAddr;
- int ret;
-
- *unmappedSize = roundUpToGrain(requestedSize);
-#ifdef USE_MALLOC
- sysFree(requestedAddr);
- ret = 1;
-#else
- ret = unmapChunk(requestedAddr, *unmappedSize);
-#endif /* USE_MALLOC */
- if (ret) {
- unmappedAddr = requestedAddr;
- Log4(2,
- "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *unmappedSize, unmappedAddr, requestedSize, requestedAddr);
- } else {
- unmappedAddr = 0;
- Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n",
- requestedSize, requestedAddr);
- }
- return unmappedAddr;
-}
-
-/*
- * Commit/decommit backing store to a range of virtual memory. This range
- * needs not be identical to a mapped range, but must be a subset of one.
- * On Solaris, we remap the range to reserve swap for the space on
- * commit. We don't strictly need to do this, as Solaris will demand
- * page pages that we've mapped when we want to access them. But by
- * reserving swap we get reasonable error handling for free where we'd
- * otherwise end up getting a SIGBUS on a random write when we run out
- * of swap. It also emphasizes the general need for shared code to
- * postpone committing to mapped memory for as long as is feasible.
- * When Java really needs space (the thread stacks excepted), it will
- * soon write over it (heap, markbits), so we don't really get much from
- * demand paging.
- *
- * We do not validate that commitment requests cover already-mapped
- * memory, although in principle we could. The size asked for here
- * is what the upper level has asked for. We need to do any platform-
- * dependent rounding here.
- *
- * When you commit, you commit to the entire page (or whatever quantum
- * your O/S requires) containing the pointer, and return the beginning of
- * that page. When you decommit, you decommit starting at the next page
- * *up* from that containing the pointer, except that decommitting from
- * a pointer to the beginning of the page operates on that page.
- */
-
-/*
- * Return the address of the base of the newly committed memory, or 0
- * if committing failed.
- */
-void *
-sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize)
-{
- void *committedAddr;
- char *ret;
-
- *committedSize = roundUpToGrain(requestedSize);
- committedAddr = (void *) roundDownToGrain((long) requestedAddr);
-#ifdef USE_MALLOC
-#ifdef __linux__
- ret = committedAddr;
-#else
- ret = requestedAddr;
-#endif
-#else
- ret = mapChunkReserve(committedAddr, *committedSize);
-#endif
- if (ret) {
- committedAddr = ret;
- Log4(2,
- "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *committedSize, committedAddr, requestedSize, requestedAddr);
- } else {
- committedAddr = 0;
- Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n",
- requestedSize, requestedAddr);
- }
-
- return committedAddr;
-}
-
-/*
- * Return the address of the base of the newly decommitted memory, or 0
- * if decommitting failed.
- */
-void *
-sysDecommitMem(void *requestedAddr, size_t requestedSize,
- size_t *decommittedSize)
-{
- void *decommittedAddr;
- char *ret;
-
- *decommittedSize = roundDownToGrain(requestedSize);
- decommittedAddr = (void *) roundUpToGrain((long) requestedAddr);
-#ifdef USE_MALLOC
- ret = 0;
-#else
- ret = mapChunkNoreserve(decommittedAddr, *decommittedSize);
-#endif
- Log4(2,
- "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *decommittedSize, decommittedAddr, requestedSize, requestedAddr);
-
- return ret;
-}
-
-/*
- * Allocate memory on an alignment boundary. Returns aligned
- * pointer to new memory. Use sysFreeBlock to free the block.
- *
- * sysAllocBlock() is similar to memalign(), except that it also
- * returns a pointer to the beginning of the block returned by the
- * OS, which must be used to deallocate the block. (On some OSes,
- * these two won't be the same.) sysAllocBlock() is also more
- * limited than memalign in that it can only be used to allocate
- * on particular alignments (PAGE_ALIGNMENT) and should be assumed
- * to round the sizes of allocated blocks up to multiples of the
- * alignment value (PAGE_ALIGNMENT*n bytes).
- */
-void *
-sysAllocBlock(size_t size, void** allocHead)
-{
- void* alignedPtr = memalign(PAGE_ALIGNMENT, size);
- *allocHead = alignedPtr;
- return alignedPtr;
-}
-
-/*
- * Wrapper to free block allocated by sysMemAlign.
- */
-void
-sysFreeBlock(void *allocHead)
-{
- free(allocHead);
-}
-
-void * sysMalloc(size_t s)
-{
- if (s == 0)
- return malloc(1);
- return malloc(s);
-}
-
-void * sysRealloc(void *p, size_t s)
-{
- return realloc(p, s);
-}
-
-void sysFree(void *p)
-{
- if (p != NULL)
- free(p);
-}
-
-void * sysCalloc(size_t s1, size_t s2)
-{
- if (s1 == 0 || s2 == 0)
- return calloc(1, 1);
- return calloc(s1, s2);
-}
-
-char * sysStrdup(const char * string)
-{
- return strdup(string);
-}
--- a/jdk/src/solaris/hpi/src/system_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 1994, 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-#include "hpi_impl.h"
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h> /* timeval */
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <netdb.h>
-#include <limits.h>
-#include <errno.h>
-
-#include <dlfcn.h>
-
-#include "jni_md.h"
-#include "mutex_md.h"
-
-#include "hpi_init.h"
-
-#include "interrupt.h"
-#include "threads_md.h"
-#include "monitor_md.h"
-#include "largefile.h"
-
-
-#define O_DELETE 0x10000
-
-int sysThreadBootstrap(sys_thread_t **tidP, sys_mon_t **lockP, int nb)
-{
- threadBootstrapMD(tidP, lockP, nb);
-
- intrInit();
-
-#ifndef NATIVE
- /* Initialize the special case for sbrk on Solaris (see synch.c) */
- InitializeSbrk();
- /* Initialize the async io */
- InitializeAsyncIO();
- InitializeMem();
- /* Initialize Clock and Idle threads */
- InitializeHelperThreads();
-#else /* if NATIVE */
- initializeContentionCountMutex();
- InitializeMem();
-#endif /* NATIVE */
-
- return SYS_OK;
-}
-
-int sysShutdown()
-{
- return SYS_OK;
-}
-
-long
-sysGetMilliTicks()
-{
- struct timeval tv;
-
- (void) gettimeofday(&tv, (void *) 0);
- return((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
-}
-
-jlong
-sysTimeMillis()
-{
- struct timeval t;
- gettimeofday(&t, 0);
- return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000);
-}
-
-int
-sysGetLastErrorString(char *buf, int len)
-{
- if (errno == 0) {
- return 0;
- } else {
- const char *s = strerror(errno);
- int n = strlen(s);
- if (n >= len) n = len - 1;
- strncpy(buf, s, n);
- buf[n] = '\0';
- return n;
- }
-}
-
-/*
- * File system
- *
- * These are all the sys API which implement the straight POSIX
- * API. Those that do not are defined by thread-specific files
- * (i.e. io_md.c)
- */
-
-/*
- * Open a file. Unlink the file immediately after open returns
- * if the specified oflag has the O_DELETE flag set.
- */
-int sysOpen(const char *path, int oflag, int mode)
-{
- int fd;
- int delete = (oflag & O_DELETE);
- oflag = oflag & ~O_DELETE;
- fd = open64_w(path, oflag, mode);
- if (delete != 0) {
- unlink(path);
- }
- return fd;
-}
-
-char *sysNativePath(char *path)
-{
- return path;
-}
-
-int
-sysFileSizeFD(int fd, jlong *size)
-{
- struct stat64 buf64;
- int ret = fstat64(fd, &buf64);
- *size = buf64.st_size;
- return ret;
-}
-
-int
-sysFfileMode(int fd, int *mode)
-{
- struct stat64 buf64;
- int ret = fstat64(fd, &buf64);
- (*mode) = buf64.st_mode;
- return ret;
-}
-
-int
-sysFileType(const char *path)
-{
- int ret;
- struct stat buf;
-
- if ((ret = stat(path, &buf)) == 0) {
- mode_t mode = buf.st_mode & S_IFMT;
- if (mode == S_IFREG) return SYS_FILETYPE_REGULAR;
- if (mode == S_IFDIR) return SYS_FILETYPE_DIRECTORY;
- return SYS_FILETYPE_OTHER;
- }
- return ret;
-}
-
-/*
- * Wrapper functions for low-level I/O routines - use the 64 bit
- * version if available, else revert to the 32 bit versions.
- */
-
-off64_t
-lseek64_w(int fd, off64_t offset, int whence)
-{
- return lseek64(fd, offset, whence);
-}
-
-int
-ftruncate64_w(int fd, off64_t length)
-{
- return ftruncate64(fd, length);
-}
-
-int
-open64_w(const char *path, int oflag, int mode)
-{
- int fd = open64(path, oflag, mode);
- if (fd == -1) return -1;
-
- /* If the open succeeded, the file might still be a directory */
- {
- int st_mode;
- if (sysFfileMode(fd, &st_mode) != -1) {
- if ((st_mode & S_IFMT) == S_IFDIR) {
- errno = EISDIR;
- close(fd);
- return -1;
- }
- } else {
- close(fd);
- return -1;
- }
- }
-
- /*
- * 32-bit Solaris systems suffer from:
- *
- * - an historical default soft limit of 256 per-process file
- * descriptors that is too low for many Java programs.
- *
- * - a design flaw where file descriptors created using stdio
- * fopen must be less than 256, _even_ when the first limit above
- * has been raised. This can cause calls to fopen (but not calls to
- * open, for example) to fail mysteriously, perhaps in 3rd party
- * native code (although the JDK itself uses fopen). One can hardly
- * criticize them for using this most standard of all functions.
- *
- * We attempt to make everything work anyways by:
- *
- * - raising the soft limit on per-process file descriptors beyond
- * 256 (done by hotspot)
- *
- * - As of Solaris 10u4, we can request that Solaris raise the 256
- * stdio fopen limit by calling function enable_extended_FILE_stdio,
- * (also done by hotspot). We check for its availability.
- *
- * - If we are stuck on an old (pre 10u4) Solaris system, we can
- * workaround the bug by remapping non-stdio file descriptors below
- * 256 to ones beyond 256, which is done below.
- *
- * See:
- * 1085341: 32-bit stdio routines should support file descriptors >255
- * 6533291: Work around 32-bit Solaris stdio limit of 256 open files
- * 6431278: Netbeans crash on 32 bit Solaris: need to call
- * enable_extended_FILE_stdio() in VM initialisation
- * Giri Mandalika's blog
- * http://technopark02.blogspot.com/2005_05_01_archive.html
- */
-#if defined(__solaris__) && defined(_ILP32)
- {
- static int needToWorkAroundBug1085341 = -1;
- if (needToWorkAroundBug1085341) {
- if (needToWorkAroundBug1085341 == -1)
- needToWorkAroundBug1085341 =
- (dlsym(RTLD_DEFAULT, "enable_extended_FILE_stdio") == NULL);
- if (needToWorkAroundBug1085341 && fd < 256) {
- int newfd = fcntl(fd, F_DUPFD, 256);
- if (newfd != -1) {
- close(fd);
- fd = newfd;
- }
- }
- }
- }
-#endif /* 32-bit Solaris */
-
- /*
- * All file descriptors that are opened in the JVM and not
- * specifically destined for a subprocess should have the
- * close-on-exec flag set. If we don't set it, then careless 3rd
- * party native code might fork and exec without closing all
- * appropriate file descriptors (e.g. as we do in closeDescriptors in
- * UNIXProcess.c), and this in turn might:
- *
- * - cause end-of-file to fail to be detected on some file
- * descriptors, resulting in mysterious hangs, or
- *
- * - might cause an fopen in the subprocess to fail on a system
- * suffering from bug 1085341.
- *
- * (Yes, the default setting of the close-on-exec flag is a Unix
- * design flaw)
- *
- * See:
- * 1085341: 32-bit stdio routines should support file descriptors >255
- * 4843136: (process) pipe file descriptor from Runtime.exec not being closed
- * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9
- */
-#ifdef FD_CLOEXEC
- {
- int flags = fcntl(fd, F_GETFD);
- if (flags != -1)
- fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
- }
-#endif
- return fd;
-}
-
-void setFPMode(void)
-{
-#if defined(__amd64)
- asm(" pushq $0x1F80");
- /* ldmxcsr (%rsp) */
- asm(" .byte 0x0f,0xae,0x14,0x24");
- asm(" popq %rax");
-#elif defined(i386)
- asm(" pushl $575");
- asm(" fldcw (%esp)");
- asm(" popl %eax");
-#endif
-#if defined(__linux__) && defined(__mc68000__)
- asm(" fmovel #0x80,%fpcr");
-#endif
-}
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Fri Feb 18 12:04:36 2011 -0800
@@ -595,15 +595,16 @@
}
XImage* X11SD_GetSharedImage(X11SDOps *xsdo, jint width, jint height,
- jboolean readBits)
+ jint maxWidth, jint maxHeight, jboolean readBits)
{
XImage * retImage = NULL;
if (cachedXImage != NULL &&
- X11SD_CachedXImageFits(width, height, xsdo->depth, readBits)) {
- /* sync so previous data gets flushed */
- XSync(awt_display, False);
- retImage = cachedXImage;
- cachedXImage = (XImage *)NULL;
+ X11SD_CachedXImageFits(width, height, maxWidth, maxHeight,
+ xsdo->depth, readBits)) {
+ /* sync so previous data gets flushed */
+ XSync(awt_display, False);
+ retImage = cachedXImage;
+ cachedXImage = (XImage *)NULL;
} else if (width * height * xsdo->depth > 0x10000) {
retImage = X11SD_CreateSharedImage(xsdo, width, height);
}
@@ -728,8 +729,8 @@
* it must be close enough to avoid excessive reading from the screen;
* otherwise it should just be at least the size requested.
*/
-jboolean X11SD_CachedXImageFits(jint width, jint height, jint depth,
- jboolean readBits)
+jboolean X11SD_CachedXImageFits(jint width, jint height, jint maxWidth,
+ jint maxHeight, jint depth, jboolean readBits)
{
/* we assume here that the cached image exists */
jint imgWidth = cachedXImage->width;
@@ -747,10 +748,14 @@
return JNI_TRUE;
}
- if ((imgWidth < width + 64) && (imgHeight < height + 64)) {
+ if ((imgWidth < width + 64) && (imgHeight < height + 64)
+ && imgWidth <= maxWidth && imgHeight <= maxHeight)
+ {
/* Cached image's width/height shouldn't be more than 64 pixels
* larger than requested, because the region in XShmGetImage
* can't be specified and we don't want to read too much.
+ * Furthermore it has to be smaller than maxWidth/Height
+ * so drawables are not read out of bounds.
*/
return JNI_TRUE;
}
@@ -1295,7 +1300,7 @@
SurfaceDataBounds *bounds,
jint lockFlags)
{
- int x, y, w, h;
+ int x, y, w, h, maxWidth, maxHeight;
int scan;
XImage * img = NULL;
Drawable drawable;
@@ -1311,10 +1316,31 @@
#ifdef MITSHM
if (useMitShmExt == CAN_USE_MITSHM) {
- if (xsdo->isPixmap && readBits) {
- X11SD_PuntPixmap(xsdo, w, h);
+ if (xsdo->isPixmap) {
+ if (readBits) {
+ X11SD_PuntPixmap(xsdo, w, h);
+ }
+ maxWidth = xsdo->pmWidth;
+ maxHeight = xsdo->pmHeight;
+ } else {
+ XWindowAttributes winAttr;
+ if (XGetWindowAttributes(awt_display,
+ (Window) xsdo->drawable, &winAttr) != 0) {
+ maxWidth = winAttr.width;
+ maxHeight = winAttr.height;
+ } else {
+ /* XGWA failed which isn't a good thing. Defaulting to using
+ * x,y means that after the subtraction of these we will use
+ * w=0, h=0 which is a reasonable default on such a failure.
+ */
+ maxWidth = x;
+ maxHeight = y;
+ }
}
- img = X11SD_GetSharedImage(xsdo, w, h, readBits);
+ maxWidth -= x;
+ maxHeight -= y;
+
+ img = X11SD_GetSharedImage(xsdo, w, h, maxWidth, maxHeight, readBits);
}
#endif /* MITSHM */
drawable = xsdo->drawable;
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.h Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.h Fri Feb 18 12:04:36 2011 -0800
@@ -125,15 +125,21 @@
#define X11SD_LOCK_BY_SHMEM 4 /* surface locked by ShMemExt */
#ifdef MITSHM
-XImage * X11SD_GetSharedImage (X11SDOps *xsdo, jint width, jint height, jboolean readBits);
+XImage * X11SD_GetSharedImage (X11SDOps *xsdo,
+ jint width, jint height,
+ jint maxWidth, jint maxHeight,
+ jboolean readBits);
XImage * X11SD_CreateSharedImage (X11SDOps *xsdo, jint width, jint height);
Drawable X11SD_CreateSharedPixmap (X11SDOps *xsdo);
void X11SD_DropSharedSegment (XShmSegmentInfo *shminfo);
void X11SD_PuntPixmap (X11SDOps *xsdo, jint width, jint height);
void X11SD_UnPuntPixmap (X11SDOps *xsdo);
-jboolean X11SD_CachedXImageFits (jint width, jint height, jint depth, jboolean readBits);
+jboolean X11SD_CachedXImageFits (jint width, jint height,
+ jint maxWidth, jint maxHeight,
+ jint depth, jboolean readBits);
XImage * X11SD_GetCachedXImage (jint width, jint height, jboolean readBits);
#endif /* MITSHM */
+jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo);
void X11SD_DisposeOrCacheXImage (XImage * image);
void X11SD_DisposeXImage(XImage * image);
void X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo);
--- a/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c Fri Feb 18 12:04:36 2011 -0800
@@ -35,48 +35,17 @@
#include "nio_util.h"
#include <dlfcn.h>
-static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */
-
-#ifdef __solaris__
-typedef struct sendfilevec64 {
- int sfv_fd; /* input fd */
- uint_t sfv_flag; /* Flags. see below */
- off64_t sfv_off; /* offset to start reading from */
- size_t sfv_len; /* amount of data */
-} sendfilevec_t;
-
-/* Function pointer for sendfilev on Solaris 8+ */
-typedef ssize_t sendfile_func(int fildes, const struct sendfilevec64 *vec,
- int sfvcnt, size_t *xferred);
-
-sendfile_func* my_sendfile_func = NULL;
+#if defined(__linux__) || defined(__solaris__)
+#include <sys/sendfile.h>
#endif
-#ifdef __linux__
-#include <sys/sendfile.h>
-
-/* Function pointer for sendfile64 on Linux 2.6 (and newer 2.4 kernels) */
-typedef ssize_t sendfile64_func(int out_fd, int in_fd, off64_t *offset, size_t count);
-
-sendfile64_func* my_sendfile64_func = NULL;
-#endif
+static jfieldID chan_fd; /* jobject 'fd' in sun.io.FileChannelImpl */
JNIEXPORT jlong JNICALL
Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz)
{
jlong pageSize = sysconf(_SC_PAGESIZE);
chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");
-
-#ifdef __solaris__
- if (dlopen("/usr/lib/libsendfile.so.1", RTLD_GLOBAL | RTLD_LAZY) != NULL) {
- my_sendfile_func = (sendfile_func*) dlsym(RTLD_DEFAULT, "sendfilev64");
- }
-#endif
-
-#ifdef __linux__
- my_sendfile64_func = (sendfile64_func*) dlsym(RTLD_DEFAULT, "sendfile64");
-#endif
-
return pageSize;
}
@@ -178,22 +147,9 @@
jlong position, jlong count,
jint dstFD)
{
-#ifdef __linux__
- jlong max = (jlong)java_lang_Integer_MAX_VALUE;
- jlong n;
-
- if (my_sendfile64_func == NULL) {
- off_t offset;
- if (position > max)
- return IOS_UNSUPPORTED_CASE;
- if (count > max)
- count = max;
- offset = (off_t)position;
- n = sendfile(dstFD, srcFD, &offset, (size_t)count);
- } else {
- off64_t offset = (off64_t)position;
- n = (*my_sendfile64_func)(dstFD, srcFD, &offset, (size_t)count);
- }
+#if defined(__linux__)
+ off64_t offset = (off64_t)position;
+ jlong n = sendfile64(dstFD, srcFD, &offset, (size_t)count);
if (n < 0) {
if (errno == EAGAIN)
return IOS_UNAVAILABLE;
@@ -206,41 +162,37 @@
return IOS_THROWN;
}
return n;
-#endif
+#elif defined (__solaris__)
+ sendfilevec64_t sfv;
+ size_t numBytes = 0;
+ jlong result;
-#ifdef __solaris__
- if (my_sendfile_func == NULL) {
- return IOS_UNSUPPORTED;
- } else {
- sendfilevec_t sfv;
- size_t numBytes = 0;
- jlong result;
+ sfv.sfv_fd = srcFD;
+ sfv.sfv_flag = 0;
+ sfv.sfv_off = (off64_t)position;
+ sfv.sfv_len = count;
- sfv.sfv_fd = srcFD;
- sfv.sfv_flag = 0;
- sfv.sfv_off = (off64_t)position;
- sfv.sfv_len = count;
-
- result = (*my_sendfile_func)(dstFD, &sfv, 1, &numBytes);
+ result = sendfilev64(dstFD, &sfv, 1, &numBytes);
- /* Solaris sendfilev() will return -1 even if some bytes have been
- * transferred, so we check numBytes first.
- */
- if (numBytes > 0)
- return numBytes;
- if (result < 0) {
- if (errno == EAGAIN)
- return IOS_UNAVAILABLE;
- if (errno == EOPNOTSUPP)
- return IOS_UNSUPPORTED_CASE;
- if ((errno == EINVAL) && ((ssize_t)count >= 0))
- return IOS_UNSUPPORTED_CASE;
- if (errno == EINTR)
- return IOS_INTERRUPTED;
- JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
- return IOS_THROWN;
- }
- return result;
+ /* Solaris sendfilev() will return -1 even if some bytes have been
+ * transferred, so we check numBytes first.
+ */
+ if (numBytes > 0)
+ return numBytes;
+ if (result < 0) {
+ if (errno == EAGAIN)
+ return IOS_UNAVAILABLE;
+ if (errno == EOPNOTSUPP)
+ return IOS_UNSUPPORTED_CASE;
+ if ((errno == EINVAL) && ((ssize_t)count >= 0))
+ return IOS_UNSUPPORTED_CASE;
+ if (errno == EINTR)
+ return IOS_INTERRUPTED;
+ JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
+ return IOS_THROWN;
}
+ return result;
+#else
+ return IOS_UNSUPPORTED_CASE;
#endif
}
--- a/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WPathGraphics.java Fri Feb 18 12:04:36 2011 -0800
@@ -51,9 +51,12 @@
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
+import java.awt.image.ComponentSampleModel;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.SampleModel;
+
import sun.awt.image.ByteComponentRaster;
import sun.awt.image.BytePackedRaster;
-
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
@@ -1272,6 +1275,25 @@
return false;
}
+ int bitsPerPixel = 24;
+ SampleModel sm = deepImage.getSampleModel();
+ if (sm instanceof ComponentSampleModel) {
+ ComponentSampleModel csm = (ComponentSampleModel)sm;
+ bitsPerPixel = csm.getPixelStride() * 8;
+ } else if (sm instanceof MultiPixelPackedSampleModel) {
+ MultiPixelPackedSampleModel mppsm =
+ (MultiPixelPackedSampleModel)sm;
+ bitsPerPixel = mppsm.getPixelBitStride();
+ } else {
+ if (icm != null) {
+ int diw = deepImage.getWidth();
+ int dih = deepImage.getHeight();
+ if (diw > 0 && dih > 0) {
+ bitsPerPixel = data.length*8/diw/dih;
+ }
+ }
+ }
+
/* Because the caller's image has been rotated
* and sheared into our BufferedImage and because
* we will be handing that BufferedImage directly to
@@ -1289,7 +1311,7 @@
(float)Math.rint(scaledBounds.height+0.5),
0f, 0f,
deepImage.getWidth(), deepImage.getHeight(),
- icm);
+ bitsPerPixel, icm);
setClip(holdClip);
}
--- a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java Fri Feb 18 12:04:36 2011 -0800
@@ -1212,13 +1212,14 @@
float destWidth, float destHeight,
float srcX, float srcY,
float srcWidth, float srcHeight,
+ int sampleBitsPerPixel,
IndexColorModel icm) {
int bitCount = 24;
byte[] bmiColors = null;
if (icm != null) {
- bitCount = icm.getPixelSize();
- bmiColors = new byte[(1<<bitCount)*4];
+ bitCount = sampleBitsPerPixel;
+ bmiColors = new byte[(1<<icm.getPixelSize())*4];
for (int i=0;i<icm.getMapSize(); i++) {
bmiColors[i*4+0]=(byte)(icm.getBlue(i)&0xff);
bmiColors[i*4+1]=(byte)(icm.getGreen(i)&0xff);
--- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Fri Feb 18 12:04:36 2011 -0800
@@ -228,31 +228,29 @@
sun.java2d.Disposer.addRecord(anchor, new ToolkitDisposer());
- synchronized (this) {
- // Fix for bug #4046430 -- Race condition
- // where notifyAll can be called before
- // the "AWT-Windows" thread's parent thread is
- // waiting, resulting in a deadlock on startup.
-
- /*
- * Fix for 4701990.
- * AWTAutoShutdown state must be changed before the toolkit thread
- * starts to avoid race condition.
- */
- AWTAutoShutdown.notifyToolkitThreadBusy();
+ /*
+ * Fix for 4701990.
+ * AWTAutoShutdown state must be changed before the toolkit thread
+ * starts to avoid race condition.
+ */
+ AWTAutoShutdown.notifyToolkitThreadBusy();
- if (!startToolkitThread(this)) {
- Thread toolkitThread = new Thread(this, "AWT-Windows");
- toolkitThread.setDaemon(true);
- toolkitThread.start();
- }
+ if (!startToolkitThread(this)) {
+ Thread toolkitThread = new Thread(this, "AWT-Windows");
+ toolkitThread.setDaemon(true);
+ toolkitThread.start();
+ }
- try {
- wait();
+ try {
+ synchronized(this) {
+ while(!inited) {
+ wait();
+ }
}
- catch (InterruptedException x) {
- }
+ } catch (InterruptedException x) {
+ // swallow the exception
}
+
SunToolkit.setDataTransfererClassName(DATA_TRANSFERER_CLASS_NAME);
// Enabled "live resizing" by default. It remains controlled
@@ -265,33 +263,38 @@
setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled);
}
+ private final void registerShutdownHook() {
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ ThreadGroup currentTG =
+ Thread.currentThread().getThreadGroup();
+ ThreadGroup parentTG = currentTG.getParent();
+ while (parentTG != null) {
+ currentTG = parentTG;
+ parentTG = currentTG.getParent();
+ }
+ Thread shutdown = new Thread(currentTG, new Runnable() {
+ public void run() {
+ shutdown();
+ }
+ });
+ shutdown.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(shutdown);
+ return null;
+ }
+ });
+ }
+
public void run() {
Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
boolean startPump = init();
if (startPump) {
- AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- ThreadGroup currentTG =
- Thread.currentThread().getThreadGroup();
- ThreadGroup parentTG = currentTG.getParent();
- while (parentTG != null) {
- currentTG = parentTG;
- parentTG = currentTG.getParent();
- }
- Thread shutdown = new Thread(currentTG, new Runnable() {
- public void run() {
- shutdown();
- }
- });
- shutdown.setContextClassLoader(null);
- Runtime.getRuntime().addShutdownHook(shutdown);
- return null;
- }
- });
+ registerShutdownHook();
}
synchronized(this) {
+ inited = true;
notifyAll();
}
@@ -309,6 +312,8 @@
* eventLoop() should Dispose the toolkit and exit.
*/
private native boolean init();
+ private boolean inited = false;
+
private native void eventLoop();
private native void shutdown();
--- a/jdk/src/windows/demo/jvmti/hprof/hprof_md.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/windows/demo/jvmti/hprof/hprof_md.c Fri Feb 18 12:04:36 2011 -0800
@@ -29,12 +29,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+// To ensure winsock2.h is used, it has to be included ahead of
+// windows.h, which includes winsock.h by default.
+#include <winsock2.h>
#include <windows.h>
#include <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <mmsystem.h>
-#include <winsock2.h>
#include <fcntl.h>
#include <process.h>
@@ -147,7 +149,7 @@
void
md_close(int filedes)
{
- (void)close(filedes);
+ (void)closesocket(filedes);
}
int
--- a/jdk/src/windows/hpi/export/byteorder_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*-
- * Win32 dependent machine byte ordering (actually intel ordering)
- */
-
-#ifndef _JAVASOFT_WIN32_BYTEORDER_MD_H_
-#define _JAVASOFT_WIN32_BYTEORDER_MD_H_
-
-#ifdef x86
-#define ntohl(x) ((x << 24) | \
- ((x & 0x0000ff00) << 8) | \
- ((x & 0x00ff0000) >> 8) | \
- (((unsigned long)(x & 0xff000000)) >> 24))
-#define ntohs(x) (((x & 0xff) << 8) | ((x >> 8) & (0xff)))
-#define htonl(x) ntohl(x)
-#define htons(x) ntohs(x)
-#else /* x86 */
-#define ntohl(x) (x)
-#define ntohs(x) (x)
-#define htonl(x) (x)
-#define htons(x) (x)
-#endif /* x86 */
-
-#endif /* !_JAVASOFT_WIN32_BYTEORDER_MD_H_ */
--- a/jdk/src/windows/hpi/export/hpi_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_HPI_MD_H_
-#define _JAVASOFT_HPI_MD_H_
-
-#include "timeval_md.h"
-#include "io_md.h"
-#include "path_md.h"
-#include "byteorder_md.h"
-
-#define HPI_TIMEOUT_INFINITY ((jlong)(-1))
-
-#endif /* !_JAVASOFT_HPI_MD_H_ */
--- a/jdk/src/windows/hpi/export/io_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Win32 system dependent low level io definitions
- */
-
-#ifndef _JAVASOFT_WIN32_IO_MD_H_
-#define _JAVASOFT_WIN32_IO_MD_H_
-
-#include <stdio.h>
-#include <io.h> /* For read(), lseek() etc. */
-#include <direct.h> /* For mkdir() */
-#include <windows.h>
-#include <winsock.h>
-#include <sys/types.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#include "jvm_md.h"
-
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#define F_OK 0
-
-#define MAXPATHLEN _MAX_PATH
-
-#define S_ISFIFO(mode) (((mode) & _S_IFIFO) == _S_IFIFO)
-#define S_ISCHR(mode) (((mode) & _S_IFCHR) == _S_IFCHR)
-#define S_ISDIR(mode) (((mode) & _S_IFDIR) == _S_IFDIR)
-#define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG)
-
-#define LINE_SEPARATOR "\r\n"
-
-#endif /* !_JAVASOFT_WIN32_IO_MD_H_ */
--- a/jdk/src/windows/hpi/export/path_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*-
- * Win32 dependent search path definitions and API
- */
-
-#ifndef _JAVASOFT_WIN32_PATH_MD_H_
-#define _JAVASOFT_WIN32_PATH_MD_H_
-
-#define PATH_SEPARATOR ";"
-#define PATH_CURDIR "."
-
-#define DIR_SEPARATOR '/'
-#define LOCAL_DIR_SEPARATOR '\\'
-
-#endif /* !_JAVASOFT_WIN32_PATH_MD_H_ */
--- a/jdk/src/windows/hpi/export/timeval_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef _JAVASOFT_WIN32_TIMEVAL_H_
-#define _JAVASOFT_WIN32_TIMEVAL_H_
-
-typedef struct {
- long tv_sec;
- long tv_usec;
-} timeval_t;
-
-/*
- * Operations on timevals.
- *
- * NB: timercmp does not work for >=, <= or ==.
- */
-#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
-#define timercmp(tvp, uvp, cmp) \
- ((tvp)->tv_sec cmp (uvp)->tv_sec || \
- (tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec cmp (uvp)->tv_usec)
-#define timereq(tvp, uvp) \
- ((tvp)->tv_sec == (uvp)->tv_sec && (tvp)->tv_usec == (uvp)->tv_usec)
-#define timerclear(tvp) (tvp)->tv_sec = (tvp)->tv_usec = 0
-
-void timeradd(timeval_t*, timeval_t*);
-void timersub(timeval_t*, timeval_t*);
-
-#endif /* !_JAVASOFT_WIN32_TIMEVAL_H_ */
--- a/jdk/src/windows/hpi/include/monitor_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Win32 implementation of Java monitors
- */
-
-#ifndef _JAVASOFT_WIN32_MONITOR_MD_H_
-#define _JAVASOFT_WIN32_MONITOR_MD_H_
-
-#include <windows.h>
-
-#include "threads_md.h"
-#include "mutex_md.h"
-
-#define SYS_MID_NULL ((sys_mon_t *) 0)
-
-typedef struct sys_mon {
- long atomic_count; /* Variable for atomic compare swap */
- HANDLE semaphore; /* Semaphore used for the contention */
- sys_thread_t *monitor_owner; /* Current owner of this monitor */
- long entry_count; /* Recursion depth */
- sys_thread_t *monitor_waiter; /* Monitor waiting queue head */
- long waiter_count; /* For debugging purpose */
-} sys_mon_t;
-
-#endif /* !_JAVASOFT_WIN32_MONITOR_MD_H_ */
--- a/jdk/src/windows/hpi/include/mutex_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1994, 1998, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Win32 implementation of mutexes. Here we use critical sections as
- * our mutexes. We could have used mutexes, but mutexes are heavier
- * weight than critical sections. Mutexes and critical sections are
- * semantically identical, the only difference being that mutexes
- * can operate between processes (i.e. address spaces).
- *
- * It's worth noting that the Win32 functions supporting critical
- * sections do not provide any error information whatsoever (i.e.
- * all critical section routines return (void)).
- */
-
-#ifndef _JAVASOFT_WIN32_MUTEX_MD_H_
-#define _JAVASOFT_WIN32_MUTEX_MD_H_
-
-#include <windows.h>
-
-typedef CRITICAL_SECTION mutex_t;
-
-#define mutexInit(m) InitializeCriticalSection(m)
-#define mutexDestroy(m) DeleteCriticalSection(m)
-#define mutexLock(m) EnterCriticalSection(m)
-#define mutexUnlock(m) LeaveCriticalSection(m)
-
-#endif /* !_JAVASOFT_WIN32_MUTEX_MD_H_ */
--- a/jdk/src/windows/hpi/include/threads_md.h Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 1994, 1999, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Win32 implementation of Java threads
- */
-
-#ifndef _JAVASOFT_WIN32_THREADS_MD_H_
-#define _JAVASOFT_WIN32_THREADS_MD_H_
-
-#include <windows.h>
-
-#define N_TRACED_REGS 7
-
-#define SYS_THREAD_NULL ((sys_thread_t *) 0)
-
-/*
- * Machine dependent info in a sys_thread_t: Keep these values in
- * sync with the string array used by sysThreadDumpInfo() in threads_md.c!
- */
-typedef enum {
- FIRST_THREAD_STATE,
- RUNNABLE = FIRST_THREAD_STATE,
- SUSPENDED,
- MONITOR_WAIT,
- CONDVAR_WAIT,
- MONITOR_SUSPENDED,
- NUM_THREAD_STATES
-} thread_state_t;
-
-struct sys_mon;
-
-/*
- * Machine dependent thread data structure
- */
-typedef struct sys_thread {
- HANDLE handle; /* Win32 thread handle */
- unsigned long id; /* Win32 thread id */
- long regs[N_TRACED_REGS]; /* Registers */
- thread_state_t state; /* Current thread state */
- bool_t system_thread; /* TRUE if this is a system thread */
- bool_t interrupted; /* Shadow thread interruption */
- short suspend_flags;
- HANDLE interrupt_event; /* Event signaled on thread interrupt */
- struct sys_mon *wait_monitor; /* Monitor the thread is waiting for */
- struct sys_thread *next_waiter; /* Next thread in the waiting queue */
- struct sys_mon *enter_monitor; /* Monitor thread is waiting to enter */
- void (*start_proc)(void *); /* Thread start routine address */
- void *start_parm; /* Thread start routine parameter */
- struct sys_thread *next; /* Next thread in active thread queue */
- void *stack_ptr; /* Pointer into the stack segment */
- unsigned int last_sum;
- PNT_TIB nt_tib; /* Pointer to NT thread-local block */
-} sys_thread_t;
-
-#define MONITOR_WAIT_SUSPENDED 0x0001
-#define CONDVAR_WAIT_SUSPENDED 0x0002
-
-extern bool_t ThreadsInitialized;
-
-extern sys_mon_t *_sys_queue_lock;
-
-#define SYS_QUEUE_LOCK(self) sysMonitorEnter(self, _sys_queue_lock)
-#define SYS_QUEUE_LOCKED(self) sysMonitorEntered(self, _sys_queue_lock)
-#define SYS_QUEUE_UNLOCK(self) sysMonitorExit(self, _sys_queue_lock)
-#define SYS_QUEUE_NOTIFYALL(self) sysMonitorNotifyAll(self, _sys_queue_lock)
-#define SYS_QUEUE_WAIT(self) sysMonitorWait(self, _sys_queue_lock, \
- SYS_TIMEOUT_INFINITY)
-
-#endif /* !_JAVASOFT_WIN32_THREADS_MD_H_ */
--- a/jdk/src/windows/hpi/src/linker_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * Copyright (c) 1994, 2005, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Maintains a list of currently loaded DLLs (Dynamic Link Libraries)
- * and their associated handles. Library names are case-insensitive.
- */
-
-#include <windows.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "hpi_impl.h"
-
-#include "path_md.h"
-
-/*
- * create a string for the JNI native function name by adding the
- * appropriate decorations.
- *
- * On Win32, "__stdcall" functions are exported differently, depending
- * on the compiler. In MSVC 4.0, they are decorated with a "_" in the
- * beginning, and @nnn in the end, where nnn is the number of bytes in
- * the arguments (in decimal). Borland C++ exports undecorated names.
- *
- * sysBuildFunName handles different encodings depending on the value
- * of encodingIndex. It returns 0 when handed an out-of-range
- * encodingIndex.
- */
-int
-sysBuildFunName(char *name, int nameMax, int args_size, int encodingIndex)
-{
- if (encodingIndex == 0) {
- /* For Microsoft MSVC 4.0 */
- char suffix[6]; /* This is enough since Java never has more than
- 256 words of arguments. */
- int nameLen;
- int i;
-
- sprintf(suffix, "@%d", args_size * 4);
-
- nameLen = strlen(name);
- if (nameLen >= nameMax - 7)
- return 1;
- for(i = nameLen; i > 0; i--)
- name[i] = name[i-1];
- name[0] = '_';
-
- sprintf(name + nameLen + 1, "%s", suffix);
- return 1;
- } else if (encodingIndex == 1)
- /* For Borland, etc. */
- return 1;
- else
- return 0;
-}
-
-/*
- * Build a machine dependent library name out of a path and file name.
- */
-void
-sysBuildLibName(char *holder, int holderlen, char *pname, char *fname)
-{
- const int pnamelen = pname ? strlen(pname) : 0;
- const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
-
- /* Quietly truncates on buffer overflow. Should be an error. */
- if (pnamelen + strlen(fname) + 10 > holderlen) {
- *holder = '\0';
- return;
- }
-
- if (pnamelen == 0) {
- sprintf(holder, "%s.dll", fname);
- } else if (c == ':' || c == '\\') {
- sprintf(holder, "%s%s.dll", pname, fname);
- } else {
- sprintf(holder, "%s\\%s.dll", pname, fname);
- }
-}
-
-void *
-sysLoadLibrary(const char * name, char *err_buf, int err_buflen)
-{
- void *result = LoadLibrary(name);
- if (result == NULL) {
- /* Error message is pretty lame, try to make a better guess. */
- long errcode = GetLastError();
- if (errcode == ERROR_MOD_NOT_FOUND) {
- strncpy(err_buf, "Can't find dependent libraries", err_buflen-2);
- err_buf[err_buflen-1] = '\0';
- } else {
- sysGetLastErrorString(err_buf, err_buflen);
- }
- }
- return result;
-}
-
-void sysUnloadLibrary(void *handle)
-{
- FreeLibrary(handle);
-}
-
-void * sysFindLibraryEntry(void *handle, const char *name)
-{
- return GetProcAddress(handle, name);
-}
--- a/jdk/src/windows/hpi/src/memory_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,296 +0,0 @@
-/*
- * Copyright (c) 1995, 2002, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Implementation of primitive memory allocation.
- *
- * The only thing machine dependent about this allocator is how it
- * initially finds all of the possible memory, and how it implements
- * mapChunk() and unmapChunk().
- *
- * This is all pretty simple stuff. It is not likely to be banged on
- * frequently enough to be a performance issue, unless the underlying
- * primitives are. Implementing things:
- *
- * HPI function Solaris "malloc" Win32
- * --------------------------------------------------------------------
- * sysMapMem() mmap() malloc() VirtualAlloc(...MEM_RESERVE...)
- * sysUnMapMem() munmap() free() VirtualFree(...MEM_RESERVE...)
- * sysCommitMem() no-op no-op VirtualAlloc(...MEM_COMMIT...)
- * sysDecommitMem() no-op no-op VirtualFree(...MEM_COMMIT...)
- *
- * Memory mapping is the default, but compiling with -DUSE_MALLOC gives
- * a system based on malloc().
- */
-
-#include <windows.h>
-#include <sys/types.h>
-
-#include "hpi_impl.h"
-
-static size_t
-roundUp(size_t n, size_t m)
-{
- return (n + m - 1) & ~(m - 1);
-}
-
-static size_t
-roundDown(size_t n, size_t m)
-{
- return n & ~(m - 1);
-}
-
-#define RESERVE_SIZE 65536 /* Memory is reserved in 64KB chunks */
-
-static size_t pageSize; /* Machine page size */
-
-void
-InitializeMem()
-{
- SYSTEM_INFO si;
-
- GetSystemInfo(&si);
- pageSize = si.dwPageSize;
-}
-
-/* HPI Functions: */
-
-/*
- * Map a range of virtual memory. Note that the size asked for here
- * is literally what the upper level has asked for. We need to do
- * any rounding, etc. here. If mapping fails return 0, otherwise
- * return the address of the base of the mapped memory.
- */
-void *
-sysMapMem(size_t requestedSize, size_t *mappedSize)
-{
- void *mappedAddr;
-
-#ifdef USE_MALLOC
- *mappedSize = roundUp(requestedSize, pageSize);
- mappedAddr = (void *)malloc(*mappedSize);
-#else
- *mappedSize = roundUp(requestedSize, RESERVE_SIZE);
- mappedAddr = VirtualAlloc(NULL, *mappedSize, MEM_RESERVE, PAGE_READWRITE);
-#endif
- if (mappedAddr != NULL) {
- Log3(2, "sysMapMem: 0x%x bytes at 0x%x (request: 0x%x bytes)\n",
- *mappedSize, mappedAddr, requestedSize);
- } else {
- Log1(2, "sysMapMem failed: (request: 0x%x bytes)\n", requestedSize);
- }
- return mappedAddr;
-}
-
-/*
- * Unmap a range of virtual memory. Note that the size asked for here
- * is literally what the upper level has asked for. We need to do any
- * rounding, etc. here. If unmapping fails return 0, otherwise return
- * the address of the base of the unmapped memory.
- */
-void *
-sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize)
-{
- void *unmappedAddr;
- int ret;
-
-#ifdef USE_MALLOC
- *unmappedSize = roundUp(requestedSize, pageSize);
- free(requestedAddr);
- ret = TRUE;
-#else
- *unmappedSize = roundUp(requestedSize, RESERVE_SIZE);
- ret = VirtualFree(requestedAddr, 0, MEM_RELEASE);
-#endif
- if (ret) {
- unmappedAddr = requestedAddr;
- Log4(2,
- "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *unmappedSize, unmappedAddr, requestedSize, requestedAddr);
- } else {
- unmappedAddr = NULL;
- Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n",
- requestedSize, requestedAddr);
- }
- return unmappedAddr;
-}
-
-/*
- * Commit/decommit backing store to a range of virtual memory. This range
- * needs not be identical to a mapped range, but must be a subset of one.
- * On Solaris, we remap the range to reserve swap for the space on
- * commit. We don't strictly need to do this, as Solaris will demand
- * page pages that we've mapped when we want to access them. But by
- * reserving swap we get reasonable error handling for free where we'd
- * otherwise end up getting a SIGBUS on a random write when we run out
- * of swap. It also emphasizes the general need for shared code to
- * postpone committing to mapped memory for as long as is feasible.
- * When Java really needs space (the thread stacks excepted), it will
- * soon write over it (heap, markbits), so we don't really get much from
- * demand paging.
- *
- * We do not validate that commitment requests cover already-mapped
- * memory, although in principle we could. The size asked for here
- * is what the upper level has asked for. We need to do any platform-
- * dependent rounding here.
- *
- * When you commit, you commit to the entire page (or whatever quantum
- * your O/S requires) containing the pointer, and return the beginning of
- * that page. When you decommit, you decommit starting at the next page
- * *up* from that containing the pointer, except that decommitting from
- * a pointer to the beginning of the page operates on that page.
- */
-
-/*
- * Return the address of the base of the newly committed memory, or 0
- * if committing failed.
- */
-void *
-sysCommitMem(void *requestedAddr, size_t requestedSize, size_t *committedSize)
-{
- void *committedAddr;
-
- *committedSize = roundUp(requestedSize, pageSize);
- committedAddr = VirtualAlloc(requestedAddr, *committedSize, MEM_COMMIT,
- PAGE_READWRITE);
- if (committedAddr != NULL) {
- Log4(2,
- "sysCommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *committedSize, committedAddr, requestedSize, requestedAddr);
- } else {
- Log2(2, "sysCommitMem failed: (request: 0x%x bytes at 0x%x)\n",
- requestedSize, requestedAddr);
- }
- return committedAddr;
-}
-
-/*
- * Return the address of the base of the newly decommitted memory, or 0
- * if decommitting failed.
- */
-void *
-sysDecommitMem(void *requestedAddr, size_t requestedSize,
- size_t *decommittedSize)
-{
- void *decommittedAddr;
-
- /*
- * We round the size down to a multiple of the page size and
- * round the address up. This ensures that we never decommit
- * more that we intend to.
- */
- *decommittedSize = roundDown(requestedSize, pageSize);
- decommittedAddr = (void *)roundUp((size_t)requestedAddr, pageSize);
-
- /*
- * If the rounded size is equal to zero we simply fail. Passing
- * 0 to VirtualFree seems to cause the entire region to be released,
- * which is definitely not what we want, since that probably means
- * that decommittedAddr is at the end of the current mapping which
- * may be the beginning of the next mapping.
- */
- if (*decommittedSize != 0 &&
- VirtualFree(decommittedAddr, *decommittedSize, MEM_DECOMMIT)) {
- Log4(2,
- "sysDecommitMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *decommittedSize, decommittedAddr, requestedSize, requestedAddr);
- } else {
- Log4(2,
- "sysDecommitMem: failed 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n",
- *decommittedSize, decommittedAddr, requestedSize, requestedAddr);
- decommittedAddr = NULL;
- }
- return decommittedAddr;
-}
-
-#define PAGED_HEAPS
-
-#ifdef PAGED_HEAPS
-
-/*
- * Allocate memory on an alignment boundary. Returns aligned
- * pointer to new memory. Use sysFreeBlock to free the block.
- *
- * sysAllocBlock() is similar to memalign(), except that it also
- * returns a pointer to the beginning of the block returned by the
- * OS, which must be used to deallocate the block. (On some OSes,
- * these two won't be the same.) sysAllocBlock() is also more
- * limited than memalign in that it can only be used to allocate
- * on particular alignments (PAGE_ALIGNMENT) and should be assumed
- * to round the sizes of allocated blocks up to multiples of the
- * alignment value (PAGE_ALIGNMENT*n bytes).
- *
- * Note that the use of VirtualAlloc on Win32 is closely tied in to
- * the decision for paged heap pages on Win32 to be 64K (that is,
- * PAGE_ALIGNMENT is 64K), a reasonable choice in any case.
- */
-void *
-sysAllocBlock(size_t size, void** allocHead)
-{
- void* alignedPtr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
- *allocHead = alignedPtr;
- return alignedPtr;
-}
-
-/*
- * Wrapper to free block allocated by sysMemAlign.
- */
-void
-sysFreeBlock(void *allocHead)
-{
- VirtualFree(allocHead, 0, MEM_RELEASE);
-}
-
-#endif /* PAGED_HEAPS */
-
-void * sysMalloc(size_t s)
-{
- if (s == 0)
- return malloc(1);
- return malloc(s);
-}
-
-void * sysRealloc(void *p, size_t s)
-{
- return realloc(p, s);
-}
-
-void sysFree(void *p)
-{
- if (p != NULL)
- free(p);
-}
-
-void * sysCalloc(size_t s1, size_t s2)
-{
- if (s1 == 0 || s2 == 0)
- return calloc(1, 1);
- return calloc(s1, s2);
-}
-
-char * sysStrdup(const char * string)
-{
- return strdup(string);
-}
--- a/jdk/src/windows/hpi/src/monitor_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,517 +0,0 @@
-/*
- * Copyright (c) 1994, 2002, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Win32 implementation of Java monitors
- */
-
-#include <windows.h>
-
-#include "hpi_impl.h"
-
-#include "threads_md.h"
-#include "monitor_md.h"
-
-/*
- * Use this information to improve performance for single CPU machine.
- */
-static int systemIsMP;
-
-static mutex_t semaphore_init_mutex;
-static mutex_t *semaphore_init_mutex_p = NULL;
-/*
- * Create and initialize monitor. This can be called before threads have
- * been initialized.
- */
-int
-sysMonitorInit(sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- if (semaphore_init_mutex_p == NULL) {
- systemIsMP = sysGetSysInfo()->isMP;
- mutexInit(&semaphore_init_mutex);
- semaphore_init_mutex_p = &semaphore_init_mutex;
- }
-
- mid->atomic_count = -1; /* -1 for no thread, 0 means 1 thread */
- mid->semaphore = NULL; /* No semaphore until needed */
- mid->monitor_owner = SYS_THREAD_NULL;
- mid->entry_count = 0; /* Recursion count */
- mid->monitor_waiter = 0; /* First waiting thread */
- mid->waiter_count = 0; /* Count of waiting and wake-up thread */
-
- return SYS_OK;
-}
-
-/*
- * Free any system-dependent resources held by monitors. On Win32 this
- * means releasing the critical section (mutex) and condition variable
- * that are part of each monitor.
- */
-int
-sysMonitorDestroy(sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- CloseHandle(mid->semaphore);
-
- return SYS_OK;
-}
-
-static void initializeSemaphore(HANDLE *pSema)
-{
- mutexLock(semaphore_init_mutex_p);
- if (*pSema == NULL) {
- *pSema = CreateSemaphore(0,0,1,0);
- }
- mutexUnlock(semaphore_init_mutex_p);
-}
-
-/*
- * Take ownership of monitor. This can be called before threads have
- * been initialized, in which case we do nothing since locked monitors
- * are not yet needed.
-
- * The actual code is split into two functions, the assembler routine
- * handles the fast path, while the C routine handle the slow path,
- * including the lazy initialization of monitor semaphore.
- *
- * REMIND: It is EXTREMELY RISKY to change any of the code without
- * thorough understanding of the system, compiler and call convention.
- */
-
-static int __fastcall sysMonitorEnter2(sys_thread_t *self, sys_mon_t *mid)
-{
- if (mid->semaphore == NULL) {
- initializeSemaphore(&(mid->semaphore));
- if (mid->semaphore == NULL) {
- return SYS_NORESOURCE;
- }
- }
-
- self->enter_monitor = mid;
- if (profiler_on) {
- VM_CALL(monitorContendedEnter)(self, mid);
- }
- WaitForSingleObject(mid->semaphore, INFINITE);
- self->enter_monitor = NULL;
-
- mid->monitor_owner = self;
- mid->entry_count = 1;
-
- if (profiler_on) {
- VM_CALL(monitorContendedEntered)(self, mid);
- }
- return SYS_OK;
-}
-
-/*
- * The following assembler routine is highly compiler specific.
- * Because of the complexity, there is no debug error check.
- */
-
-#ifndef _WIN64
-int __cdecl
-sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid)
-{
- __asm
- {
- mov edx, dword ptr [esp+8]; // load mid
- mov ecx, dword ptr [esp+4]; // load self
- mov eax, dword ptr [edx+8]; // load mid->monitor_owner
-
- cmp eax, ecx; // if ( self == mid->monitor_owner )
- je RECURSION; // goto RECURSION;
-
- mov eax, dword ptr [systemIsMP];
- test eax, eax;
- jne MPM;
-
- inc dword ptr [edx]; /* atomic increment mid->atomic_count */
- jne ACQUIRE_SEMAPHORE; /* if there is an owner already */
-
- mov dword ptr [edx+8], ecx; /* mid->monitor_owner = self */
- mov dword ptr [edx+12], 1; /* mid->entry_count = 1 */
- xor eax, eax; /* return SYS_OK */
- ret;
-
-MPM:
- lock inc dword ptr [edx]; /* atomic increment mid->atomic_count */
- jne ACQUIRE_SEMAPHORE; /* if there is an owner already */
-
- mov dword ptr [edx+8], ecx; /* mid->monitor_owner = self */
- mov dword ptr [edx+12], 1; /* mid->entry_count = 1 */
- xor eax, eax; /* return SYS_OK */
- ret;
-
-RECURSION:
- inc dword ptr [edx+12]; /* Increment mid->entry_count */
- xor eax, eax; /* return SYS_OK */
- ret;
-
-ACQUIRE_SEMAPHORE:
- /* The self is passed by ECX, mid is passed by EDX */
- jmp sysMonitorEnter2;
- }
-}
-#else
-int __cdecl
-sysMonitorEnter(sys_thread_t *self, sys_mon_t *mid)
-{
-return (SYS_NORESOURCE);
-}
-#endif
-
-/*
- * Return TRUE if this thread currently owns the monitor. This can be
- * called before threads have been initialized, in which case we always
- * return TRUE.
- */
-bool_t
-sysMonitorEntered(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
- sysAssert(self != 0);
- sysAssert(ThreadsInitialized);
-
- return (mid->monitor_owner == self);
-}
-
-/*
- * Release ownership of monitor. This can be called before threads have
- * been initialized, in which case we do nothing as locked monitors are
- * not yet needed.
- *
- * The actual code is split into two functions, the assembler routine
- * handles the fast path, while the C routine handle the slow path.
- *
- * REMIND: It is EXTREMELY RISKY to change any of the code without
- * thorough understanding of the system, compiler and call convention.
- */
-
-static int __fastcall
-sysMonitorExit2(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid->entry_count == 0);
- sysAssert(mid->atomic_count >= 0);
- sysAssert(mid->monitor_owner == 0);
-
- if (mid->semaphore == NULL) {
- initializeSemaphore(&(mid->semaphore));
- if (mid->semaphore == NULL) {
- return SYS_NORESOURCE;
- }
- }
-
- ReleaseSemaphore(mid->semaphore, 1, 0);
-
- if (profiler_on) {
- VM_CALL(monitorContendedExit)(self, mid);
- }
-
- return SYS_OK;
-}
-
-#ifndef _WIN64
-__declspec(naked) int __cdecl
-sysMonitorExit(sys_thread_t *self, sys_mon_t *mid)
-{
- __asm
- {
- mov edx, dword ptr [esp+8]; /* load mid */
- mov ecx, dword ptr [esp+4]; /* load self */
- mov eax, dword ptr [edx+8]; /* load mid->monitor_owner */
-
- cmp eax, ecx; /* if ( self != mid->monitor_owner ) */
- jne ERR_RET; /* goto ERROR_RET */
-
- dec dword ptr [edx+12]; /* dec mid->entry_count */
- jne OK_RET; /* entry_count != 0 */
-
- mov dword ptr [edx+8], 0; /* mid->monitor_owner = 0 */
-
- mov eax, dword ptr [systemIsMP];
- test eax, eax;
- jne MPM;
-
- dec dword ptr [edx]; /* atomic decrement mid->atomic_count */
- jge RELEASE_SEMAPHORE; /* if ( atomic_variable < 0 ) */
- xor eax, eax; /* return SYS_OK */
- ret;
-
-MPM:
- lock dec dword ptr [edx]; /* atomic decrement mid->atomic_count */
- jge RELEASE_SEMAPHORE; /* if ( atomic_variable < 0 ) */
-OK_RET:
- xor eax, eax;
- ret;
-
-ERR_RET:
- mov eax, 0FFFFFFFFH;
- ret;
-
-RELEASE_SEMAPHORE:
- jmp sysMonitorExit2; /* forwading call */
- }
-}
-#else
-int __cdecl
-sysMonitorExit(sys_thread_t *self, sys_mon_t *mid)
-{
-return (-1);
-}
-#endif
-
-/*
- * Notify single thread waiting on condition variable.
- */
-int
-sysMonitorNotify(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- if (mid->monitor_owner != self) {
- return SYS_ERR;
- }
-
- if (mid->monitor_waiter != SYS_THREAD_NULL)
- {
- sys_thread_t *thread = mid->monitor_waiter;
- mid->monitor_waiter = thread->next_waiter;
-
- thread->next_waiter = SYS_THREAD_NULL;
- thread->wait_monitor = SYS_MID_NULL;
-
- SetEvent(thread->interrupt_event);
- }
-
- return SYS_OK;
-}
-
-/*
- * Notify all threads waiting on condition variable.
- */
-int
-sysMonitorNotifyAll(sys_thread_t *self, sys_mon_t *mid)
-{
- sysAssert(mid != SYS_MID_NULL);
-
- if (mid->monitor_owner != self) {
- return SYS_ERR;
- }
-
- while (mid->monitor_waiter != SYS_THREAD_NULL)
- {
- sys_thread_t *thread = mid->monitor_waiter;
- mid->monitor_waiter = thread->next_waiter;
-
- thread->next_waiter = SYS_THREAD_NULL;
- thread->wait_monitor = SYS_MID_NULL;
-
- SetEvent(thread->interrupt_event);
- }
-
- return SYS_OK;
-}
-
-/*
- * Atomically drop mutex and wait for notification.
- */
-int
-sysMonitorWait(sys_thread_t *self, sys_mon_t *mid, jlong millis)
-{
- long entry_count;
- DWORD timeout;
-
- sysAssert(mid != SYS_MID_NULL);
-
- if (mid->monitor_owner != self) {
- return SYS_ERR;
- }
-
- if ( sysThreadIsInterrupted(self, 1) ) {
- return SYS_INTRPT;
- }
-
- entry_count = mid->entry_count;
- mid->entry_count = 1;
-
- self->wait_monitor = mid;
- self->next_waiter = 0;
-
- if (mid->monitor_waiter == 0) {
- mid->monitor_waiter = self;
- } else {
- sys_thread_t *thread = mid->monitor_waiter;
- while (thread->next_waiter != 0) {
- thread = thread->next_waiter;
- }
- thread->next_waiter = self;
- }
-
- if ( millis == SYS_TIMEOUT_INFINITY ||
- millis > (jlong)((unsigned int)0xffffffff) ) {
- timeout = INFINITE;
- } else {
- timeout = (long) millis;
- }
-
- mid->waiter_count++;
-
- sysMonitorExit(self, mid);
-
- self->state = CONDVAR_WAIT;
-
- WaitForSingleObject(self->interrupt_event, timeout);
-
- self->state = RUNNABLE;
-
- sysMonitorEnter(self, mid);
-
- mid->waiter_count--;
-
- mid->entry_count = entry_count;
- /* Reset event anyway, prevent racing the timeout */
- ResetEvent(self->interrupt_event);
-
- if (self->wait_monitor != SYS_MID_NULL) {
- sys_thread_t *head;
-
- sysAssert( self->wait_monitor == mid );
- sysAssert( mid->monitor_waiter != SYS_THREAD_NULL );
-
- head = mid->monitor_waiter;
-
- if (head == self) {
- mid->monitor_waiter = self->next_waiter;
- } else {
- while (head != SYS_THREAD_NULL) {
- if (head->next_waiter == self) {
- head->next_waiter = self->next_waiter;
- break;
- } else {
- head = head->next_waiter;
- }
- }
- }
-
- self->next_waiter = SYS_THREAD_NULL;
- self->wait_monitor = SYS_MID_NULL;
- }
-
- if ( sysThreadIsInterrupted(self, 1) ) {
- return SYS_INTRPT;
- }
-
- return SYS_OK;
-}
-
-static int
-dumpWaitingQueue(sys_thread_t *tid, sys_thread_t **waiters, int sz)
-{
- int n;
- for (n = 0; tid != 0; tid = tid->next_waiter, n++, sz--) {
- if (sz > 0) {
- waiters[n] = tid;
- }
- }
- return n;
-}
-
-typedef struct {
- sys_mon_t *mid;
- sys_thread_t **waiters;
- int sz;
- int nwaiters;
-} wait_info;
-
-static int
-findWaitersHelper(sys_thread_t *t, void *arg)
-{
- wait_info * winfo = (wait_info *) arg;
- if (t->enter_monitor == winfo->mid) {
- if (winfo->sz > 0) {
- winfo->waiters[winfo->nwaiters] = t;
- }
- winfo->sz--;
- winfo->nwaiters++;
- }
- return SYS_OK;
-}
-
-int
-sysMonitorGetInfo(sys_mon_t *mid, sys_mon_info *info)
-{
- wait_info winfo;
-
- sysAssert(mid != SYS_MID_NULL);
- info->owner = mid->monitor_owner;
- if (mid->monitor_owner) {
- info->entry_count = mid->entry_count;
- }
-
- winfo.mid = mid;
- winfo.nwaiters = 0;
- winfo.waiters = info->monitor_waiters;
- winfo.sz = info->sz_monitor_waiters;
- sysThreadEnumerateOver(findWaitersHelper, (void *) &winfo);
- info->n_monitor_waiters = winfo.nwaiters;
-
- info->n_condvar_waiters = dumpWaitingQueue(mid->monitor_waiter,
- info->condvar_waiters,
- info->sz_condvar_waiters);
-
- return SYS_OK;
-}
-
-/*
- * Return size of system-dependent monitor structure.
- */
-size_t
-sysMonitorSizeof(void)
-{
- return sizeof(struct sys_mon);
-}
-
-
-/*
- * Return true if there are any threads inside this monitor.
- */
-bool_t
-sysMonitorInUse(sys_mon_t *mid)
-{
- return (mid->atomic_count != -1
- || mid->waiter_count != 0
- || mid->monitor_owner != SYS_THREAD_NULL
- || mid->monitor_waiter != SYS_THREAD_NULL);
-}
-
-
-sys_thread_t *
-sysMonitorOwner(sys_mon_t *mon)
-{
- return mon->monitor_owner;
-}
--- a/jdk/src/windows/hpi/src/path_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 1994, 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Machine dependent path name and file name manipulation code
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/stat.h>
-
-#include <windows.h>
-#include <errno.h>
-
-#include "hpi_impl.h"
-
-#undef DEBUG_PATH /* Define this to debug path code */
-
-#define isfilesep(c) ((c) == '/' || (c) == '\\')
-#define islb(c) (IsDBCSLeadByte((BYTE)(c)))
-
-
-/* Convert a pathname to native format. On win32, this involves forcing all
- separators to be '\\' rather than '/' (both are legal inputs, but Win95
- sometimes rejects '/') and removing redundant separators. The input path is
- assumed to have been converted into the character encoding used by the local
- system. Because this might be a double-byte encoding, care is taken to
- treat double-byte lead characters correctly.
-
- This procedure modifies the given path in place, as the result is never
- longer than the original. There is no error return; this operation always
- succeeds. */
-
-char *
-sysNativePath(char *path)
-{
- char *src = path, *dst = path, *end = path;
- char *colon = NULL; /* If a drive specifier is found, this will
- point to the colon following the drive
- letter */
-
- /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */
- sysAssert(!islb('/') && !islb('\\') && !islb(':'));
-
- /* Check for leading separators */
- while (isfilesep(*src)) src++;
- if (isalpha(*src) && !islb(*src) && src[1] == ':') {
- /* Remove leading separators if followed by drive specifier. This
- hack is necessary to support file URLs containing drive
- specifiers (e.g., "file://c:/path"). As a side effect,
- "/c:/path" can be used as an alternative to "c:/path". */
- *dst++ = *src++;
- colon = dst;
- *dst++ = ':'; src++;
- } else {
- src = path;
- if (isfilesep(src[0]) && isfilesep(src[1])) {
- /* UNC pathname: Retain first separator; leave src pointed at
- second separator so that further separators will be collapsed
- into the second separator. The result will be a pathname
- beginning with "\\\\" followed (most likely) by a host name. */
- src = dst = path + 1;
- path[0] = '\\'; /* Force first separator to '\\' */
- }
- }
-
- end = dst;
-
- /* Remove redundant separators from remainder of path, forcing all
- separators to be '\\' rather than '/'. Also, single byte space
- characters are removed from the end of the path because those
- are not legal ending characters on this operating system.
- */
- while (*src != '\0') {
- if (isfilesep(*src)) {
- *dst++ = '\\'; src++;
- while (isfilesep(*src)) src++;
- if (*src == '\0') { /* Check for trailing separator */
- end = dst;
- if (colon == dst - 2) break; /* "z:\\" */
- if (dst == path + 1) break; /* "\\" */
- if (dst == path + 2 && isfilesep(path[0])) {
- /* "\\\\" is not collapsed to "\\" because "\\\\" marks the
- beginning of a UNC pathname. Even though it is not, by
- itself, a valid UNC pathname, we leave it as is in order
- to be consistent with the path canonicalizer as well
- as the win32 APIs, which treat this case as an invalid
- UNC pathname rather than as an alias for the root
- directory of the current drive. */
- break;
- }
- end = --dst; /* Path does not denote a root directory, so
- remove trailing separator */
- break;
- }
- end = dst;
- } else {
- if (islb(*src)) { /* Copy a double-byte character */
- *dst++ = *src++;
- if (*src) {
- *dst++ = *src++;
- }
- end = dst;
- } else { /* Copy a single-byte character */
- char c = *src++;
- *dst++ = c;
- /* Space is not a legal ending character */
- if (c != ' ')
- end = dst;
- }
- }
- }
-
- *end = '\0';
-
- /* For "z:", add "." to work around a bug in the C runtime library */
- if (colon == dst - 1) {
- path[2] = '.';
- path[3] = '\0';
- }
-
-#ifdef DEBUG_PATH
- jio_fprintf(stderr, "sysNativePath: %s\n", path);
-#endif DEBUG_PATH
- return path;
-}
--- a/jdk/src/windows/hpi/src/socket_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,537 +0,0 @@
-/*
- * Copyright (c) 1997, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-#include <windef.h>
-#include <winsock.h>
-
-#include "hpi_impl.h"
-
-#include "mutex_md.h"
-
-struct sockaddr;
-
-#define FN_RECV 0
-#define FN_SEND 1
-#define FN_LISTEN 2
-#define FN_BIND 3
-#define FN_ACCEPT 4
-#define FN_RECVFROM 5
-#define FN_SENDTO 6
-#define FN_SELECT 7
-#define FN_CONNECT 8
-#define FN_CLOSESOCKET 9
-#define FN_SHUTDOWN 10
-#define FN_GETHOSTNAME 11
-#define FN_GETHOSTBYADDR 12
-#define FN_GETHOSTBYNAME 13
-#define FN_HTONS 14
-#define FN_HTONL 15
-#define FN_NTOHS 16
-#define FN_NTOHL 17
-#define FN_GETSOCKOPT 18
-#define FN_SETSOCKOPT 19
-#define FN_GETPROTOBYNAME 20
-#define FN_GETSOCKNAME 21
-#define FN_SOCKET 22
-#define FN_WSASENDDISCONNECT 23
-#define FN_SOCKETAVAILABLE 24
-
-static int (PASCAL FAR *sockfnptrs[])() =
- {NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL,
- };
-
-static bool_t sockfnptrs_initialized = FALSE;
-static mutex_t sockFnTableMutex;
-
-/* is Winsock2 loaded? better to be explicit than to rely on sockfnptrs */
-static bool_t winsock2Available = FALSE;
-
-/* Winsock2 options at the IPPROTO_IP level
- We need the following translation in order to deal with the multiple
- definitions for IPPROTO_IP level options in different winsock versions.
-
-in winsock.h vs. ws2tcpip.h
-#define IP_OPTIONS 1 1
-#define IP_MULTICAST_IF 2 9
-#define IP_MULTICAST_TTL 3 10
-#define IP_MULTICAST_LOOP 4 11
-#define IP_ADD_MEMBERSHIP 5 12
-#define IP_DROP_MEMBERSHIP 6 13
-#define IP_TTL 7 4
-#define IP_TOS 8 3
-#define IP_DONTFRAGMENT 9 14
-*/
-static int IPPROTO_OPTIONS[] = {-1, 1, 9, 10, 11, 12, 13, 4, 3, 14};
-
-/* IMPORTANT: whenever possible, we want to use Winsock2 (ws2_32.dll)
- * instead of Winsock (wsock32.dll). Other than the fact that it is
- * newer, less buggy and faster than Winsock, Winsock2 lets us to work
- * around the following problem:
- *
- * Generally speaking, it is important to shutdown a socket before
- * closing it, since failing to do so can sometimes result in a TCP
- * RST (abortive close) which is disturbing to the peer of the
- * connection.
- *
- * The Winsock way to shutdown a socket is the Berkeley call
- * shutdown(). We do not want to call it on Win95, since it
- * sporadically leads to an OS crash in IFS_MGR.VXD. Complete hull
- * breach. Blue screen. Ugly.
- *
- * So, in initSockTable we look for Winsock 2, and if we find it we
- * assign wsassendisconnectfn function pointer. When we close, we
- * first check to see if it's bound, and if it is, we call it. Winsock
- * 2 will always be there on NT, and we recommend that win95 user
- * install it.
- *
- * - br 10/11/97
- */
-
-static void
-initSockFnTable() {
- int (PASCAL FAR* WSAStartupPtr)(WORD, LPWSADATA);
- WSADATA wsadata;
- OSVERSIONINFO info;
-
- mutexInit(&sockFnTableMutex);
- mutexLock(&sockFnTableMutex);
- if (sockfnptrs_initialized == FALSE) {
- HANDLE hWinsock;
-
- /* try to load Winsock2, and if that fails, load Winsock */
- hWinsock = LoadLibrary("ws2_32.dll");
- if (hWinsock == NULL) {
- hWinsock = LoadLibrary("wsock32.dll");
- winsock2Available = FALSE;
- } else {
- winsock2Available = TRUE;
- }
-
- if (hWinsock == NULL) {
- VM_CALL(jio_fprintf)(stderr, "Could not load Winsock 1 or 2 (error: %d)\n",
- GetLastError());
- }
-
- /* If we loaded a DLL, then we might as well initialize it. */
- WSAStartupPtr = (int (PASCAL FAR *)(WORD, LPWSADATA))
- GetProcAddress(hWinsock, "WSAStartup");
- if (WSAStartupPtr(MAKEWORD(1,1), &wsadata) != 0) {
- VM_CALL(jio_fprintf)(stderr, "Could not initialize Winsock\n");
- }
-
- sockfnptrs[FN_RECV]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "recv");
- sockfnptrs[FN_SEND]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "send");
- sockfnptrs[FN_LISTEN]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "listen");
- sockfnptrs[FN_BIND]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "bind");
- sockfnptrs[FN_ACCEPT]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "accept");
- sockfnptrs[FN_RECVFROM]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "recvfrom");
- sockfnptrs[FN_SENDTO]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "sendto");
- sockfnptrs[FN_SELECT]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "select");
- sockfnptrs[FN_CONNECT]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "connect");
- sockfnptrs[FN_CLOSESOCKET]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "closesocket");
- /* we don't use this */
- sockfnptrs[FN_SHUTDOWN]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "shutdown");
- sockfnptrs[FN_GETHOSTNAME]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostname");
- sockfnptrs[FN_GETHOSTBYADDR]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostbyaddr");
- sockfnptrs[FN_GETHOSTBYNAME]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "gethostbyname");
- sockfnptrs[FN_HTONS]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "htons");
- sockfnptrs[FN_HTONL]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "htonl");
- sockfnptrs[FN_NTOHS]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "ntohs");
- sockfnptrs[FN_NTOHL]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "ntohl");
- sockfnptrs[FN_GETSOCKOPT]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getsockopt");
- sockfnptrs[FN_SETSOCKOPT]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "setsockopt");
- sockfnptrs[FN_GETPROTOBYNAME]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getprotobyname");
- sockfnptrs[FN_GETSOCKNAME]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "getsockname");
-
- sockfnptrs[FN_SOCKET]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock, "socket");
- /* in winsock 1, this will simply be 0 */
- sockfnptrs[FN_WSASENDDISCONNECT]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock,
- "WSASendDisconnect");
- sockfnptrs[FN_SOCKETAVAILABLE]
- = (int (PASCAL FAR *)())GetProcAddress(hWinsock,
- "ioctlsocket");
- }
-
- sysAssert(sockfnptrs[FN_RECV] != NULL);
- sysAssert(sockfnptrs[FN_SEND] != NULL);
- sysAssert(sockfnptrs[FN_LISTEN] != NULL);
- sysAssert(sockfnptrs[FN_BIND] != NULL);
- sysAssert(sockfnptrs[FN_ACCEPT] != NULL);
- sysAssert(sockfnptrs[FN_RECVFROM] != NULL);
- sysAssert(sockfnptrs[FN_SENDTO] != NULL);
- sysAssert(sockfnptrs[FN_SELECT] != NULL);
- sysAssert(sockfnptrs[FN_CONNECT] != NULL);
- sysAssert(sockfnptrs[FN_CLOSESOCKET] != NULL);
- sysAssert(sockfnptrs[FN_SHUTDOWN] != NULL);
- sysAssert(sockfnptrs[FN_GETHOSTNAME] != NULL);
- sysAssert(sockfnptrs[FN_GETHOSTBYADDR] != NULL);
- sysAssert(sockfnptrs[FN_GETHOSTBYNAME] != NULL);
- sysAssert(sockfnptrs[FN_HTONS] != NULL);
- sysAssert(sockfnptrs[FN_HTONL] != NULL);
- sysAssert(sockfnptrs[FN_NTOHS] != NULL);
- sysAssert(sockfnptrs[FN_NTOHL] != NULL);
- sysAssert(sockfnptrs[FN_GETSOCKOPT] != NULL);
- sysAssert(sockfnptrs[FN_SETSOCKOPT] != NULL);
- sysAssert(sockfnptrs[FN_GETPROTOBYNAME] != NULL);
- sysAssert(sockfnptrs[FN_GETSOCKNAME] != NULL);
- sysAssert(sockfnptrs[FN_SOCKET] != NULL);
-
- if (winsock2Available) {
- sysAssert(sockfnptrs[FN_WSASENDDISCONNECT] != NULL);
- }
-
- sysAssert(sockfnptrs[FN_SOCKETAVAILABLE] != NULL);
-
- sockfnptrs_initialized = TRUE;
- mutexUnlock(&sockFnTableMutex);
-}
-
-/*
- * If we get a nonnull function pointer it might still be the case
- * that some other thread is in the process of initializing the socket
- * function pointer table, but our pointer should still be good.
- */
-int
-sysListen(int fd, int count) {
- int (PASCAL FAR *listenfn)();
- if ((listenfn = sockfnptrs[FN_LISTEN]) == NULL) {
- initSockFnTable();
- listenfn = sockfnptrs[FN_LISTEN];
- }
- sysAssert(sockfnptrs_initialized == TRUE && listenfn != NULL);
- return (*listenfn)(fd, (long)count);
-}
-
-int
-sysConnect(int fd, struct sockaddr *name, int namelen) {
- int (PASCAL FAR *connectfn)();
- if ((connectfn = sockfnptrs[FN_CONNECT]) == NULL) {
- initSockFnTable();
- connectfn = sockfnptrs[FN_CONNECT];
- }
- sysAssert(sockfnptrs_initialized == TRUE);
- sysAssert(connectfn != NULL);
- return (*connectfn)(fd, name, namelen);
-}
-
-int
-sysBind(int fd, struct sockaddr *name, int namelen) {
- int (PASCAL FAR *bindfn)();
- if ((bindfn = sockfnptrs[FN_BIND]) == NULL) {
- initSockFnTable();
- bindfn = sockfnptrs[FN_BIND];
- }
- sysAssert(sockfnptrs_initialized == TRUE);
- sysAssert(bindfn != NULL);
- return (*bindfn)(fd, name, namelen);
-}
-
-int
-sysAccept(int fd, struct sockaddr *name, int *namelen) {
- int (PASCAL FAR *acceptfn)();
- if ((acceptfn = sockfnptrs[FN_ACCEPT]) == NULL) {
- initSockFnTable();
- acceptfn = sockfnptrs[FN_ACCEPT];
- }
- sysAssert(sockfnptrs_initialized == TRUE && acceptfn != NULL);
- return (*acceptfn)(fd, name, namelen);
-}
-
-int
-sysRecvFrom(int fd, char *buf, int nBytes,
- int flags, struct sockaddr *from, int *fromlen) {
- int (PASCAL FAR *recvfromfn)();
- if ((recvfromfn = sockfnptrs[FN_RECVFROM]) == NULL) {
- initSockFnTable();
- recvfromfn = sockfnptrs[FN_RECVFROM];
- }
- sysAssert(sockfnptrs_initialized == TRUE && recvfromfn != NULL);
- return (*recvfromfn)(fd, buf, nBytes, flags, from, fromlen);
-}
-
-int
-sysSendTo(int fd, char *buf, int len,
- int flags, struct sockaddr *to, int tolen) {
- int (PASCAL FAR *sendtofn)();
- if ((sendtofn = sockfnptrs[FN_SENDTO]) == NULL) {
- initSockFnTable();
- sendtofn = sockfnptrs[FN_SENDTO];
- }
- sysAssert(sockfnptrs_initialized == TRUE && sendtofn != NULL);
- return (*sendtofn)(fd, buf, len, flags, to, tolen);
-}
-
-int
-sysRecv(int fd, char *buf, int nBytes, int flags) {
- int (PASCAL FAR *recvfn)();
- if ((recvfn = sockfnptrs[FN_RECV]) == NULL) {
- initSockFnTable();
- recvfn = sockfnptrs[FN_RECV];
- }
- sysAssert(sockfnptrs_initialized == TRUE && recvfn != NULL);
- return (*recvfn)(fd, buf, nBytes, flags);
-}
-
-int
-sysSend(int fd, char *buf, int nBytes, int flags) {
- int (PASCAL FAR *sendfn)();
- if ((sendfn = sockfnptrs[FN_SEND]) == NULL) {
- initSockFnTable();
- sendfn = sockfnptrs[FN_SEND];
- }
- sysAssert(sockfnptrs_initialized == TRUE && sendfn != NULL);
- return (*sendfn)(fd, buf, nBytes, flags);
-}
-
-
-int
-sysGetHostName(char *hostname, int namelen) {
- int (PASCAL FAR *fn)();
- if ((fn = sockfnptrs[FN_GETHOSTNAME]) == NULL) {
- initSockFnTable();
- fn = sockfnptrs[FN_GETHOSTNAME];
- }
- sysAssert(sockfnptrs_initialized == TRUE && fn != NULL);
- return (*fn)(hostname, namelen);
-}
-
-struct hostent *
-sysGetHostByAddr(const char *hostname, int len, int type) {
- struct hostent * (PASCAL FAR *fn)();
- if ((fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYADDR]) == NULL) {
- initSockFnTable();
- fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYADDR];
- }
- sysAssert(sockfnptrs_initialized == TRUE && fn != NULL);
- return (*fn)(hostname, len, type);
-}
-
-struct hostent *
-sysGetHostByName(char *hostname) {
- struct hostent * (PASCAL FAR *fn)();
- if ((fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYNAME]) == NULL) {
- initSockFnTable();
- fn = (struct hostent * (PASCAL FAR *)()) sockfnptrs[FN_GETHOSTBYNAME];
- }
- sysAssert(sockfnptrs_initialized == TRUE && fn != NULL);
- return (*fn)(hostname);
-}
-
-int
-sysSocket(int domain, int type, int protocol) {
- int sock;
- int (PASCAL FAR *socketfn)();
- if ((socketfn = sockfnptrs[FN_SOCKET]) == NULL) {
- initSockFnTable();
- socketfn = sockfnptrs[FN_SOCKET];
- }
- sysAssert(sockfnptrs_initialized == TRUE && socketfn != NULL);
- sock = (*socketfn)(domain, type, protocol);
- if (sock != INVALID_SOCKET) {
- SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE);
- }
- return sock;
-}
-
-int sysSocketShutdown(int fd, int how) {
- if (fd > 0) {
- int (PASCAL FAR *shutdownfn)();
- if ((shutdownfn = sockfnptrs[FN_SHUTDOWN]) == NULL) {
- initSockFnTable();
- shutdownfn = sockfnptrs[FN_SHUTDOWN];
- }
- /* At this point we are guaranteed the sockfnptrs are initialized */
- sysAssert(sockfnptrs_initialized == TRUE && shutdownfn != NULL);
- (void) (*shutdownfn)(fd, how);
- }
-return TRUE;
-}
-
-/*
- * This function is carefully designed to work around a bug in Windows
- * 95's networking winsock. Please see the beginning of this file for
- * a complete description of the problem.
- */
-int sysSocketClose(int fd) {
-
- if (fd > 0) {
- int (PASCAL FAR *closesocketfn)();
- int (PASCAL FAR *wsasenddisconnectfn)();
- int dynamic_ref = -1;
-
- if ((closesocketfn = sockfnptrs[FN_CLOSESOCKET]) == NULL) {
- initSockFnTable();
- }
- /* At this point we are guaranteed the sockfnptrs are initialized */
- sysAssert(sockfnptrs_initialized == TRUE);
-
- closesocketfn = sockfnptrs[FN_CLOSESOCKET];
- sysAssert(closesocketfn != NULL);
-
- if (winsock2Available) {
- struct linger l;
- int len = sizeof(l);
-
- if (sysGetSockOpt(fd, SOL_SOCKET, SO_LINGER, (char *)&l, &len) == 0) {
- if (l.l_onoff == 0) {
- wsasenddisconnectfn = sockfnptrs[FN_WSASENDDISCONNECT];
- (*wsasenddisconnectfn)(fd, NULL);
- }
- }
- }
- (void) (*closesocketfn)(fd);
- }
- return TRUE;
-}
-
-/*
- * Poll the fd for reading for timeout ms. Returns 1 if something's
- * ready, 0 if it timed out, -1 on error, -2 if interrupted (although
- * interruption isn't implemented yet). Timeout in milliseconds. */
-int
-sysTimeout(int fd, long timeout) {
- int res;
- fd_set tbl;
- struct timeval t;
- int (PASCAL FAR *selectfn)();
-
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
- FD_ZERO(&tbl);
- FD_SET(fd, &tbl);
-
- if ((selectfn = sockfnptrs[FN_SELECT]) == NULL) {
- initSockFnTable();
- selectfn = sockfnptrs[FN_SELECT];
- }
- sysAssert(sockfnptrs_initialized == TRUE && selectfn != NULL);
- res = (*selectfn)(fd + 1, &tbl, 0, 0, &t);
- return res;
-}
-
-long
-sysSocketAvailable(int fd, jint *pbytes)
-{
- int (PASCAL FAR *socketfn)();
- if ((socketfn = sockfnptrs[FN_SOCKETAVAILABLE]) == NULL) {
- initSockFnTable();
- socketfn = sockfnptrs[FN_SOCKETAVAILABLE];
- }
- sysAssert(sockfnptrs_initialized == TRUE && socketfn != NULL);
- return (*socketfn)(fd, FIONREAD, pbytes);
-}
-
-int
-sysGetSockName(int fd, struct sockaddr *name, int *namelen) {
- int (PASCAL FAR *getsocknamefn)();
- if ((getsocknamefn = sockfnptrs[FN_GETSOCKNAME]) == NULL) {
- initSockFnTable();
- getsocknamefn = sockfnptrs[FN_GETSOCKNAME];
- }
- sysAssert(sockfnptrs_initialized == TRUE);
- sysAssert(getsocknamefn != NULL);
- return (*getsocknamefn)(fd, name, namelen);
-}
-
-int
-sysGetSockOpt(int fd, int level, int optname, char *optval, int *optlen ) {
- int (PASCAL FAR *getsockoptfn)();
- if ((getsockoptfn = sockfnptrs[FN_GETSOCKOPT]) == NULL) {
- initSockFnTable();
- getsockoptfn = sockfnptrs[FN_GETSOCKOPT];
- }
- sysAssert(sockfnptrs_initialized == TRUE);
- sysAssert(getsockoptfn != NULL);
-
- /* We need the following translation in order to deal with the multiple
- definitions for IPPROTO_IP level options in different winsock versions
- */
- if (winsock2Available && level == IPPROTO_IP &&
- optname >= IP_OPTIONS && optname <= IP_DONTFRAGMENT) {
- optname = IPPROTO_OPTIONS[optname];
- }
- return (*getsockoptfn)(fd, level, optname, optval, optlen);
-}
-
-int
-sysSetSockOpt(int fd, int level, int optname, const char *optval, int optlen ) {
- int (PASCAL FAR *setsockoptfn)();
- if ((setsockoptfn = sockfnptrs[FN_SETSOCKOPT]) == NULL) {
- initSockFnTable();
- setsockoptfn = sockfnptrs[FN_SETSOCKOPT];
- }
- sysAssert(sockfnptrs_initialized == TRUE);
- sysAssert(setsockoptfn != NULL);
-
- /* We need the following translation in order to deal with the multiple
- definitions for IPPROTO_IP level options in different winsock versions
- */
- if (winsock2Available && level == IPPROTO_IP &&
- optname >= IP_OPTIONS && optname <= IP_DONTFRAGMENT) {
- optname = IPPROTO_OPTIONS[optname];
- }
-
- return (*setsockoptfn)(fd, level, optname, optval, optlen);
-}
-
-struct protoent *
-sysGetProtoByName(char *name) {
- struct protoent * (PASCAL FAR *getprotobynamefn)();
- if ((getprotobynamefn = (struct protoent * (PASCAL FAR *)()) sockfnptrs[FN_GETPROTOBYNAME]) == NULL) {
- initSockFnTable();
- getprotobynamefn = (struct protoent * (PASCAL FAR *)()) sockfnptrs[FN_GETPROTOBYNAME];
- }
- sysAssert(sockfnptrs_initialized == TRUE);
- sysAssert(getprotobynamefn != NULL);
- return (*getprotobynamefn)(name);
-}
--- a/jdk/src/windows/hpi/src/sys_api_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 1997, 2004, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-#include <io.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <limits.h>
-
-#include "hpi_impl.h"
-
-#include "path_md.h"
-
-static int MAX_INPUT_EVENTS = 2000;
-
-int
-sysOpen(const char *path, int oflag, int mode)
-{
- char pathbuf[MAX_PATH];
-
- if (strlen(path) > MAX_PATH - 1) {
- errno = ENAMETOOLONG;
- return -1;
- }
- return open(sysNativePath(strcpy(pathbuf, path)),
- oflag | O_BINARY | O_NOINHERIT, mode);
-}
-
-
-static int
-nonSeekAvailable(int, long *);
-static int
-stdinAvailable(int, long *);
-
-int
-sysAvailable(int fd, jlong *pbytes) {
- jlong cur, end;
- struct _stati64 stbuf64;
-
- if (_fstati64(fd, &stbuf64) >= 0) {
- int mode = stbuf64.st_mode;
- if (S_ISCHR(mode) || S_ISFIFO(mode)) {
- int ret;
- long lpbytes;
- if (fd == 0) {
- ret = stdinAvailable(fd, &lpbytes);
- } else {
- ret = nonSeekAvailable(fd, &lpbytes);
- }
- (*pbytes) = (jlong)(lpbytes);
- return ret;
- }
- if ((cur = _lseeki64(fd, 0L, SEEK_CUR)) == -1) {
- return FALSE;
- } else if ((end = _lseeki64(fd, 0L, SEEK_END)) == -1) {
- return FALSE;
- } else if (_lseeki64(fd, cur, SEEK_SET) == -1) {
- return FALSE;
- }
- *pbytes = end - cur;
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static int
-nonSeekAvailable(int fd, long *pbytes) {
- /* This is used for available on non-seekable devices
- * (like both named and anonymous pipes, such as pipes
- * connected to an exec'd process).
- * Standard Input is a special case.
- *
- */
- HANDLE han;
-
- if ((han = (HANDLE) _get_osfhandle(fd)) == (HANDLE)(-1)) {
- return FALSE;
- }
-
- if (! PeekNamedPipe(han, NULL, 0, NULL, pbytes, NULL)) {
- /* PeekNamedPipe fails when at EOF. In that case we
- * simply make *pbytes = 0 which is consistent with the
- * behavior we get on Solaris when an fd is at EOF.
- * The only alternative is to raise an Exception,
- * which isn't really warranted.
- */
- if (GetLastError() != ERROR_BROKEN_PIPE) {
- return FALSE;
- }
- *pbytes = 0;
- }
- return TRUE;
-}
-
-static int
-stdinAvailable(int fd, long *pbytes) {
- HANDLE han;
- DWORD numEventsRead = 0; /* Number of events read from buffer */
- DWORD numEvents = 0; /* Number of events in buffer */
- DWORD i = 0; /* Loop index */
- DWORD curLength = 0; /* Position marker */
- DWORD actualLength = 0; /* Number of bytes readable */
- BOOL error = FALSE; /* Error holder */
- INPUT_RECORD *lpBuffer; /* Pointer to records of input events */
-
- if ((han = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {
- return FALSE;
- }
-
- /* Construct an array of input records in the console buffer */
- error = GetNumberOfConsoleInputEvents(han, &numEvents);
- if (error == 0) {
- return nonSeekAvailable(fd, pbytes);
- }
-
- /* lpBuffer must fit into 64K or else PeekConsoleInput fails */
- if (numEvents > MAX_INPUT_EVENTS) {
- numEvents = MAX_INPUT_EVENTS;
- }
-
- lpBuffer = sysMalloc(numEvents * sizeof(INPUT_RECORD));
- if (lpBuffer == NULL) {
- return FALSE;
- }
-
- error = PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead);
- if (error == 0) {
- sysFree(lpBuffer);
- return FALSE;
- }
-
- /* Examine input records for the number of bytes available */
- for(i=0; i<numEvents; i++) {
- if (lpBuffer[i].EventType == KEY_EVENT) {
- KEY_EVENT_RECORD *keyRecord = (KEY_EVENT_RECORD *)
- &(lpBuffer[i].Event);
- if (keyRecord->bKeyDown == TRUE) {
- CHAR *keyPressed = (CHAR *) &(keyRecord->uChar);
- curLength++;
- if (*keyPressed == '\r')
- actualLength = curLength;
- }
- }
- }
- if(lpBuffer != NULL)
- sysFree(lpBuffer);
- *pbytes = (long) actualLength;
- return TRUE;
-}
-
-/*
- * This is documented to succeed on read-only files, but Win32's
- * FlushFileBuffers functions fails with "access denied" in such a
- * case. So we only signal an error if the error is *not* "access
- * denied".
- */
-
-int
-sysSync(int fd) {
- /*
- * From the documentation:
- *
- * On Windows NT, the function FlushFileBuffers fails if hFile
- * is a handle to console output. That is because console
- * output is not buffered. The function returns FALSE, and
- * GetLastError returns ERROR_INVALID_HANDLE.
- *
- * On the other hand, on Win95, it returns without error. I cannot
- * assume that 0, 1, and 2 are console, because if someone closes
- * System.out and then opens a file, they might get file descriptor
- * 1. An error on *that* version of 1 should be reported, whereas
- * an error on System.out (which was the original 1) should be
- * ignored. So I use isatty() to ensure that such an error was due
- * to this bogosity, and if it was, I ignore the error.
- */
-
- HANDLE handle = (HANDLE)_get_osfhandle(fd);
-
- if (!FlushFileBuffers(handle)) {
- if (GetLastError() != ERROR_ACCESS_DENIED) { /* from winerror.h */
- return -1;
- }
- }
- return 0;
-}
-
-
-int
-sysSetLength(int fd, jlong length) {
- HANDLE h = (HANDLE)_get_osfhandle(fd);
- long high = (long)(length >> 32);
- DWORD ret;
-
- if (h == (HANDLE)(-1)) return -1;
- ret = SetFilePointer(h, (long)(length), &high, FILE_BEGIN);
- if (ret == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
- return -1;
- }
- if (SetEndOfFile(h) == FALSE) return -1;
- return 0;
-}
-
-int
-sysFileSizeFD(int fd, jlong *size)
-{
- struct _stati64 buf64;
-
- if(_fstati64(fd, &buf64) < 0) {
- return -1;
- }
- (*size) = buf64.st_size;
-
- if (*size & 0xFFFFFFFF00000000) {
- /*
- * On Win98 accessing a non-local file we have observed a
- * bogus file size of 0x100000000. So if upper 32 bits
- * are non-zero we re-calculate the size using lseek. This
- * should work for any file size, but it might have a
- * performance impact relative to fstati64. Note: Hotspot
- * doesn't have this problem because it uses stat rather
- * than fstat or fstati64.
- */
-
- jlong curpos;
- jlong endpos;
- jlong newpos;
-
- curpos = _lseeki64(fd, 0, SEEK_CUR);
- if (curpos < 0) {
- return -1;
- }
- endpos = _lseeki64(fd, 0, SEEK_END);
- if (endpos < 0) {
- return -1;
- }
- newpos = _lseeki64(fd, curpos, SEEK_SET);
- if (newpos != curpos) {
- return -1;
- }
- (*size) = endpos;
-
- }
- return 0;
-}
-
-int
-sysFfileMode(int fd, int *mode)
-{
- int ret;
- struct _stati64 buf64;
- ret = _fstati64(fd, &buf64);
- (*mode) = buf64.st_mode;
- return ret;
-}
-
-int
-sysFileType(const char *path)
-{
- int ret;
- struct _stati64 buf;
-
- if ((ret = _stati64(path, &buf)) == 0) {
- int mode = buf.st_mode & S_IFMT;
- if (mode == S_IFREG) return SYS_FILETYPE_REGULAR;
- if (mode == S_IFDIR) return SYS_FILETYPE_DIRECTORY;
- return SYS_FILETYPE_OTHER;
- }
- return ret;
-}
-
-size_t sysRead(int fd, void *buf, unsigned int nBytes)
-{
- return read(fd, buf, nBytes);
-}
-
-size_t sysWrite(int fd, const void *buf, unsigned int nBytes)
-{
- return write(fd, buf, nBytes);
-}
-
-int sysClose(int fd)
-{
- return close(fd);
-}
-
-jlong sysSeek(int fd, jlong offset, int whence)
-{
- return _lseeki64(fd, offset, whence);
-}
--- a/jdk/src/windows/hpi/src/system_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-/*
- * Copyright (c) 1994, 2002, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-#include <windows.h>
-#include <float.h> /* For constants for _control87() */
-#include <signal.h>
-#include <time.h> /* For _tzset() and _ftime() */
-#include <errno.h>
-
-#include "hpi_impl.h"
-
-#include "jni_md.h"
-#include "monitor_md.h"
-
-
-static int pending_signals[NSIG];
-static HANDLE sigEvent;
-static CRITICAL_SECTION userSigMon;
-
-
-void sysSignalNotify(int sig)
-{
- sys_thread_t *self = sysThreadSelf();
- EnterCriticalSection(&userSigMon);
- pending_signals[sig]++;
- LeaveCriticalSection(&userSigMon);
- SetEvent(sigEvent);
-}
-
-static int lookupSignal()
-{
- int i;
- EnterCriticalSection(&userSigMon);
- for (i = 0; i < NSIG; i++) {
- if (pending_signals[i]) {
- pending_signals[i]--;
- LeaveCriticalSection(&userSigMon);
- return i;
- }
- }
- LeaveCriticalSection(&userSigMon);
- return -1;
-}
-
-int sysSignalWait()
-{
- int sig;
- while ((sig = lookupSignal()) == -1) {
- WaitForSingleObject(sigEvent, INFINITE);
- }
- return sig;
-}
-
-signal_handler_t sysSignal(int sig, signal_handler_t newHandler)
-{
- return (signal_handler_t)signal(sig, (void (*)(int))newHandler);
-}
-
-void sysRaise(int sig)
-{
- raise(sig);
-}
-
-int sysThreadBootstrap(sys_thread_t **tidP, sys_mon_t **lockP, int nb)
-{
- extern void InitializeMem(void);
-
- threadBootstrapMD(tidP, lockP, nb);
-
- sigEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
- InitializeCriticalSection(&userSigMon);
- memset(pending_signals, 0, sizeof(pending_signals));
-
- /*
- * Change default for std. streams stdout, stderr,
- * stdin to be O_BINARY not O_TEXT. The `\r` characters
- * corrupt binary files.
- */
-
- _setmode(0, O_BINARY);
- _setmode(1, O_BINARY);
- _setmode(2, O_BINARY);
-
- /*
- * Set floating point processor to no floating point exceptions.
- * See bug 4027374. Should be the same values VC++ would set them
- * to, but by doing this here we ensure other dll's don't override.
- */
- _control87(_MCW_EM | _RC_NEAR | _PC_53, _MCW_EM | _MCW_RC | _MCW_PC);
-
- InitializeMem();
-
- return SYS_OK;
-}
-
-long
-sysGetMilliTicks(void)
-{
- return(GetTickCount());
-}
-
-#define FT2INT64(ft) \
- ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime)
-
-jlong
-sysTimeMillis(void)
-{
- static jlong fileTime_1_1_70 = 0;
- SYSTEMTIME st0;
- FILETIME ft0;
-
- if (fileTime_1_1_70 == 0) {
- /* Initialize fileTime_1_1_70 -- the Win32 file time of midnight
- * 1/1/70.
- */
-
- memset(&st0, 0, sizeof(st0));
- st0.wYear = 1970;
- st0.wMonth = 1;
- st0.wDay = 1;
- SystemTimeToFileTime(&st0, &ft0);
- fileTime_1_1_70 = FT2INT64(ft0);
- }
-
- GetSystemTime(&st0);
- SystemTimeToFileTime(&st0, &ft0);
-
- return (FT2INT64(ft0) - fileTime_1_1_70) / 10000;
-}
-
-void *
-sysAllocateMem(long size)
-{
- return malloc(size);
-}
-
-int sysShutdown()
-{
- return SYS_OK;
-}
-
-unsigned
-sleep(unsigned seconds)
-{
- Sleep(seconds * 1000);
- return 0;
-}
-
-int
-sysGetLastErrorString(char *buf, int len)
-{
- long errval;
-
- if ((errval = GetLastError()) != 0) {
- /* DOS error */
- int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, errval,
- 0, buf, len, NULL);
- if (n > 3) {
- /* Drop final '.', CR, LF */
- if (buf[n - 1] == '\n') n--;
- if (buf[n - 1] == '\r') n--;
- if (buf[n - 1] == '.') n--;
- buf[n] = '\0';
- }
- return n;
- }
-
- if (errno != 0) {
- /* C runtime error that has no corresponding DOS error code */
- const char *s = strerror(errno);
- int n = strlen(s);
- if (n >= len) n = len - 1;
- strncpy(buf, s, n);
- buf[n] = '\0';
- return n;
- }
-
- return 0;
-}
--- a/jdk/src/windows/hpi/src/threads_md.c Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,831 +0,0 @@
-/*
- * Copyright (c) 1994, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-/*
- * Win32 implementation of Java threads
- */
-
-#include "hpi_impl.h"
-
-#include <windows.h>
-#include <process.h> /* for _beginthreadex(), _endthreadex() */
-#include <stdlib.h>
-
-#include "threads_md.h"
-#include "monitor_md.h"
-
-
-/*
- * Queue of active Java threads
- */
-static sys_thread_t *ThreadQueue;
-sys_mon_t *_sys_queue_lock;
-
-static int ActiveThreadCount = 0; /* All threads */
-
-/*
- * Set to TRUE once threads have been bootstrapped
- */
-bool_t ThreadsInitialized = FALSE;
-
-/*
- * Are we running under Window NT
- */
-static bool_t windowsNT = FALSE;
-
-/*
- * Thread local storage index used for looking up sys_thread_t struct
- * (tid) associated with the current thread.
- */
-#define TLS_INVALID_INDEX 0xffffffffUL
-static unsigned long tls_index = TLS_INVALID_INDEX;
-
-static void RecordNTTIB(sys_thread_t *tid)
-{
-#ifndef _WIN64
- PNT_TIB nt_tib;
- __asm {
- mov eax, dword ptr fs:[18h];
- mov nt_tib, eax;
- }
- tid->nt_tib = nt_tib;
-#else
- tid->nt_tib = 0;
-#endif
-}
-
-/*
- * Add thread to queue of active threads.
- */
-static void
-queueInsert(sys_thread_t *tid)
-{
- if (ThreadsInitialized)
- SYS_QUEUE_LOCK(sysThreadSelf());
- ActiveThreadCount++;
- tid->next = ThreadQueue;
- ThreadQueue = tid;
- if (ThreadsInitialized)
- SYS_QUEUE_UNLOCK(sysThreadSelf());
- else
- ThreadsInitialized = TRUE;
-}
-
-/*
- * Remove thread from queue of active threads.
- */
-static void
-removefromActiveQ(sys_thread_t *tid)
-{
- sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
- --ActiveThreadCount;
-
- if (ThreadQueue == tid) {
- ThreadQueue = tid->next;
- } else {
- sys_thread_t *p;
- for (p = ThreadQueue; p->next != 0; p = p->next) {
- if (p->next == tid) {
- p->next = tid->next;
- break;
- }
- }
- }
-}
-
-/*
- * Allocate and initialize the sys_thread_t structure for an arbitary
- * native thread.
- */
-int
-sysThreadAlloc(sys_thread_t **tidP)
-{
- HANDLE hnd = GetCurrentProcess();
- sys_thread_t *tid = allocThreadBlock();
- if (tid == NULL) {
- return SYS_NOMEM;
- }
-
- tid->state = RUNNABLE;
- tid->interrupted = FALSE;
- tid->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL);
- tid->id = GetCurrentThreadId();
- DuplicateHandle(hnd, GetCurrentThread(), hnd, &tid->handle, 0, FALSE,
- DUPLICATE_SAME_ACCESS);
-
- RecordNTTIB(tid);
- /* For the Invocation API:
- We update the thread-specific storage before locking the
- queue because sysMonitorEnter will access sysThreadSelf.
- */
- TlsSetValue(tls_index, tid);
-
- queueInsert(tid);
- tid->stack_ptr = &tid;
- *tidP = tid;
- return SYS_OK;
-}
-
-/*
- * Bootstrap the Java thread system by making the current thread the
- * "primordial" thread.
- */
-int threadBootstrapMD(sys_thread_t **tidP, sys_mon_t **lockP, int nb)
-{
- OSVERSIONINFO windowsVersion;
- HANDLE hnd = GetCurrentProcess();
-
- nReservedBytes = (nb + 7) & (~7);
- /*
- * Allocate TLS index for thread-specific data.
- */
- tls_index = TlsAlloc();
- if (tls_index == TLS_INVALID_INDEX) {
- VM_CALL(jio_fprintf)(stderr, "TlsAlloc failed (errcode = %x)\n",
- GetLastError());
- return SYS_NOMEM;
- }
-
- /* OS properties */
- windowsVersion.dwOSVersionInfoSize = sizeof(windowsVersion);
- GetVersionEx(&windowsVersion);
- windowsNT = windowsVersion.dwPlatformId == VER_PLATFORM_WIN32_NT;
-
- /* Initialize the queue lock monitor */
- _sys_queue_lock = (sys_mon_t *)sysMalloc(sysMonitorSizeof());
- if (_sys_queue_lock == NULL) {
- return SYS_ERR;
- }
- VM_CALL(monitorRegister)(_sys_queue_lock, "Thread queue lock");
- *lockP = _sys_queue_lock;
-
- return sysThreadAlloc(tidP);
-}
-
-/*
- * Return current stack pointer of specified thread.
- */
-void *
-sysThreadStackPointer(sys_thread_t *tid)
-{
-#ifndef _WIN64
- CONTEXT context;
- WORD __current_SS;
-
- /* REMIND: Need to fix this for Win95 */
- context.ContextFlags = CONTEXT_CONTROL;
- if (!GetThreadContext(tid->handle, &context)) {
- VM_CALL(jio_fprintf)(stderr, "GetThreadContext failed (errcode = %x)\n",
- GetLastError());
- return 0;
- }
-
- /* With the NT TIB stuff that Hong came up with, I don't think we
- * need any of the complicated VirtualQuery calls anymore. If
- * context.Esp is within the stack limit and base, we return
- * context.Esp, otherwise, we can simply return nt_tib->StackLimit.
- * To minimize code changes, though, I'm keeping the code the way
- * it was.
- */
- if (tid->nt_tib == NULL) {
- /* thread hasn't started yet. */
- return 0;
- }
-
- __asm {
- mov ax, ss;
- mov __current_SS, ax;
- }
-
- if (context.SegSs == __current_SS &&
- context.Esp >= (uintptr_t)(tid->nt_tib->StackLimit) &&
- context.Esp < (uintptr_t)(tid->nt_tib->StackBase)) {
- MEMORY_BASIC_INFORMATION mbi;
-
- VirtualQuery((PBYTE) context.Esp, &mbi, sizeof(mbi));
-
- if (!(mbi.Protect & PAGE_GUARD)) {
- return (void *) context.Esp;
- } else {
- SYSTEM_INFO si;
- char *Esp = (char*) context.Esp;
- DWORD dwPageSize;
-
- GetSystemInfo(&si);
- dwPageSize = si.dwPageSize;
- Esp -= (((DWORD) Esp) % dwPageSize);
- do {
- Esp += dwPageSize;
- VirtualQuery((PBYTE) Esp, &mbi, sizeof(mbi));
- } while (mbi.Protect & PAGE_GUARD);
- return Esp;
- }
- } else {
- /* segment selectors don't match - thread is in some weird context */
- MEMORY_BASIC_INFORMATION mbi;
- PBYTE pbStackHwm, pbStackBase;
- SYSTEM_INFO si;
- DWORD dwPageSize;
- stackp_t stack_ptr = tid->stack_ptr;
-
- if (stack_ptr == 0) {
- return 0;
- }
- GetSystemInfo(&si);
- dwPageSize = si.dwPageSize;
- VirtualQuery((PBYTE)stack_ptr - 1, &mbi, sizeof(mbi));
- pbStackBase = (PBYTE)mbi.AllocationBase;
- /* step backwards till beginning of segment, non-RW page, or guard
- page (guard pages only on WinNT) */
- do {
- pbStackHwm = (PBYTE)mbi.BaseAddress;
- if (pbStackHwm <= pbStackBase) {
- break;
- }
- VirtualQuery(pbStackHwm - dwPageSize, &mbi, sizeof(mbi));
- }
- while ((mbi.Protect & PAGE_READWRITE) &&
- !(mbi.Protect & PAGE_GUARD));
- /* the best we can do for now is the first page of stack
- storage - it should be a stack high-water mark, anyway */
- return (void *)pbStackHwm;
- }
-#else
- return 0;
-#endif
-}
-
-/*
- * Get the end of stack (if you step beyond (above or below depending
- * on your architecture) you can die. We refer to the logical top of
- * stack.
- *
- * NOTE! There are restrictions about when you can call this method. If
- * you did a sysThreadAlloc, then you can call this method as soon as
- * sysThreadAlloc returns. If you called sysThreadCreate(start_function),
- * then you must call sysThreadStackTop only inside start_function and not
- * as soon as sysThreadCreate returns.
- */
-void *
-sysThreadStackTop(sys_thread_t *tid)
-{
- return 0; /* FIXME: Unimplemented. */
-}
-
-long *
-sysThreadRegs(sys_thread_t *tid, int *nregs)
-{
- *nregs = N_TRACED_REGS;
- return tid->regs;
-}
-
-/*
- * Thread start routine for new Java threads
- */
-static unsigned __stdcall
-_start(sys_thread_t *tid)
-{
- /* Should thread suspend itself at this point? */
-
- tid->state = RUNNABLE;
- RecordNTTIB(tid);
- TlsSetValue(tls_index, tid);
- tid->stack_ptr = &tid;
- tid->start_proc(tid->start_parm);
- sysThreadFree();
- _endthreadex(0);
- /* not reached */
- return 0;
-}
-
-/*
- * Create a new Java thread. The thread is initially suspended.
- */
-int
-sysThreadCreate(sys_thread_t **tidP, long stack_size,
- void (*proc)(void *), void *arg)
-{
- sys_thread_t *tid = allocThreadBlock();
- if (tid == NULL) {
- return SYS_NOMEM;
- }
- tid->state = SUSPENDED;
- tid->start_proc = proc;
- tid->start_parm = arg;
-
- tid->interrupt_event = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- /*
- * Start the new thread.
- */
- tid->handle = (HANDLE)_beginthreadex(NULL, stack_size, _start, tid,
- CREATE_SUSPENDED, &tid->id);
- if (tid->handle == 0) {
- return SYS_NORESOURCE; /* Will be treated as though SYS_NOMEM */
- }
-
- queueInsert(tid);
- *tidP = tid;
- return SYS_OK;
-}
-
-/*
- * Free a system thread block.
- * Remove from the thread queue.
- */
-int
-sysThreadFree()
-{
- sys_thread_t *tid = sysThreadSelf();
-
- /*
- * remove ourselves from the thread queue. This must be done after
- * the notify above since monitor operations aren't really safe if
- * your thread isn't on the thread queue. (This isn't true of
- * the sysMonitor* functions, only monitor*)
- */
- SYS_QUEUE_LOCK(tid);
- removefromActiveQ(tid);
- SYS_QUEUE_UNLOCK(tid);
-
- /* For invocation API: later sysThreadSelf() calls will return 0 */
- TlsSetValue(tls_index, 0);
-
- /*
- * Close the thread and interrupt event handles, and free the
- * sys_thread_t structure.
- */
- CloseHandle(tid->handle);
- CloseHandle(tid->interrupt_event);
- freeThreadBlock(tid);
- return SYS_OK;
-}
-
-/*
- * Yield control to another thread.
- */
-void
-sysThreadYield(void)
-{
- Sleep(0);
-}
-
-/*
- * Suspend execution of the specified thread.
- */
-int
-sysThreadSuspend(sys_thread_t *tid)
-{
- /* REMIND: Fix for Win95 */
- /* Set state first so state is reflected before this thread */
- /* returns. Fix suggested by ARB of SAS */
- thread_state_t oldstate = tid->state;
- sys_thread_t *self = sysThreadSelf();
-
- if (tid == self) {
- self->state = SUSPENDED;
- } else {
- switch(tid->state) {
- case RUNNABLE:
- tid->state = SUSPENDED;
- break;
- case MONITOR_WAIT:
- tid->state = SUSPENDED;
- tid->suspend_flags |= MONITOR_WAIT_SUSPENDED;
- break;
- case CONDVAR_WAIT:
- tid->state = SUSPENDED;
- tid->suspend_flags |= CONDVAR_WAIT_SUSPENDED;
- break;
- case SUSPENDED:
- case MONITOR_SUSPENDED:
- default:
- return SYS_ERR;
- }
- }
- if (SuspendThread(tid->handle) == 0xffffffffUL) {
- tid->state = oldstate;
- tid->suspend_flags = 0;
- return SYS_ERR;
- }
- return SYS_OK;
-}
-
-/*
- * Continue execution of the specified thread.
- */
-int
-sysThreadResume(sys_thread_t *tid)
-{
- unsigned long n;
-
- if (tid->suspend_flags & MONITOR_WAIT_SUSPENDED) {
- tid->suspend_flags = 0;
- tid->state = MONITOR_WAIT;
- } else if (tid->suspend_flags & CONDVAR_WAIT_SUSPENDED) {
- tid->suspend_flags = 0;
- tid->state = CONDVAR_WAIT;
- } else {
- switch(tid->state) {
- case SUSPENDED:
- tid->state = RUNNABLE;
- break;
- case MONITOR_SUSPENDED:
- tid->state = MONITOR_WAIT;
- break;
- case RUNNABLE:
- case MONITOR_WAIT:
- case CONDVAR_WAIT:
- default:
- return SYS_ERR;
- break;
- }
- }
-
- /* Decrement thread's suspend count until no longer suspended */
- while ((n = ResumeThread(tid->handle)) > 1) {
- if (n == 0xffffffffUL) {
- return SYS_ERR;
- }
- }
- return SYS_OK;
-}
-
-/*
- * Return priority of specified thread.
- */
-int
-sysThreadGetPriority(sys_thread_t *tid, int *pp)
-{
- switch (GetThreadPriority(tid->handle)) {
- case THREAD_PRIORITY_IDLE:
- *pp = 0; break;
- case THREAD_PRIORITY_LOWEST:
- *pp = 2; break;
- case THREAD_PRIORITY_BELOW_NORMAL:
- *pp = 4; break;
- case THREAD_PRIORITY_NORMAL:
- *pp = 5; break;
- case THREAD_PRIORITY_ABOVE_NORMAL:
- *pp = 6; break;
- case THREAD_PRIORITY_HIGHEST:
- *pp = 8; break;
- case THREAD_PRIORITY_TIME_CRITICAL:
- *pp = 10; break;
- case THREAD_PRIORITY_ERROR_RETURN:
- return SYS_ERR;
- }
- return SYS_OK;
-}
-
-/*
- * Set priority of specified thread.
- */
-int
-sysThreadSetPriority(sys_thread_t *tid, int p)
-{
- int priority;
-
- switch (p) {
- case 0:
- priority = THREAD_PRIORITY_IDLE;
- break;
- case 1: case 2:
- priority = THREAD_PRIORITY_LOWEST;
- break;
- case 3: case 4:
- priority = THREAD_PRIORITY_BELOW_NORMAL;
- break;
- case 5:
- priority = THREAD_PRIORITY_NORMAL;
- break;
- case 6: case 7:
- priority = THREAD_PRIORITY_ABOVE_NORMAL;
- break;
- case 8: case 9:
- priority = THREAD_PRIORITY_HIGHEST;
- break;
- case 10:
- priority = THREAD_PRIORITY_TIME_CRITICAL;
- break;
- default:
- return SYS_ERR;
- }
- return SetThreadPriority(tid->handle, priority) ? SYS_OK : SYS_ERR;
-}
-
-/*
- * Return the thread information block of the calling thread.
- */
-sys_thread_t *
-sysThreadSelf(void)
-{
- return tls_index == 0xffffffffUL ? 0 : TlsGetValue(tls_index);
-}
-
-/*
- * Enumerate over all threads in active queue calling a function for
- * each one. Expects the caller to lock _queue_lock
- */
-int
-sysThreadEnumerateOver(int (*func)(sys_thread_t *, void *), void *arg)
-{
- sys_thread_t *tid;
- int ret = SYS_OK;
- sys_thread_t *self = sysThreadSelf();
-
- sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
-
- for (tid = ThreadQueue; tid != 0; tid = tid->next) {
- if ((ret = (*func)(tid, arg)) != SYS_OK) {
- break;
- }
- }
- return ret;
-}
-
-/*
- * Helper function for sysThreadSingle()
- */
-static int
-threadSingleHelper(sys_thread_t *tid, void *self)
-{
- if (tid == self) {
- return SYS_OK;
- }
- if (SuspendThread(tid->handle) == 0xffffffffUL) {
- return SYS_ERR;
- }
- {
- CONTEXT context;
- DWORD *esp = (DWORD *)tid->regs;
-
- context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
- if (!GetThreadContext(tid->handle, &context)) {
- VM_CALL(jio_fprintf)
- (stderr, "GetThreadContext failed (errcode = %x)\n",
- GetLastError());
- return SYS_ERR;
- }
-#ifdef _M_AMD64
- *esp++ = context.Rax;
- *esp++ = context.Rbx;
- *esp++ = context.Rcx;
- *esp++ = context.Rdx;
- *esp++ = context.Rsi;
- *esp++ = context.Rdi;
- *esp = context.Rbp;
-#else
- *esp++ = context.Eax;
- *esp++ = context.Ebx;
- *esp++ = context.Ecx;
- *esp++ = context.Edx;
- *esp++ = context.Esi;
- *esp++ = context.Edi;
- *esp = context.Ebp;
-#endif
- }
- return SYS_OK;
-}
-
-/*
- * Puts each thread in the active thread queue to sleep except for the
- * calling thread. The threads must be later woken up with a corresponding
- * call to 'sysThreadMulti'. Returns SYS_OK on success, or SYS_ERR if any
- * of the threads could not be suspended.
- */
-int
-sysThreadSingle(void)
-{
- return sysThreadEnumerateOver(threadSingleHelper, sysThreadSelf());
-}
-
-/*
- * Helper function for sysThreadMulti(): Only ResumeThread once, unlike
- * sysThreadResume(), which will repeatedly call ResumeThread until the
- * thread is really resumed. That is, Thread.resume will unwind any
- * number of Thread.suspend invocations, but sysThreadMulti() calls must
- * be strictly matched with sysThreadSingle() calls. Doing this keeps
- * the garbage collector, which uses thread suspension to stop threads
- * while it operates, from waking up threads that were already suspended
- * when GC was invoked.
- */
-static int
-threadMultiHelper(sys_thread_t *tid, void *self)
-{
- if (tid == self || ResumeThread(tid->handle) != 0xffffffffUL) {
- return SYS_OK;
- } else {
- return SYS_ERR;
- }
-}
-
-/*
- * Wakes up each thread in active thread queue except for the calling
- * thread. The mechanism uses thread suspension, and will not wake a
- * thread that was already suspended. Must be matched 1-1 with calls
- * to sysThreadSingle(). Returns SYS_ERR if not all threads could be
- * woken up.
- */
-void
-sysThreadMulti(void)
-{
- sysThreadEnumerateOver(threadMultiHelper, sysThreadSelf());
-}
-
-/*
- * Dump system-specific information about threads.
- */
-void *
-sysThreadNativeID(sys_thread_t *tid)
-{
- return (void *)(uintptr_t)tid->id;
-}
-
-int
-sysThreadCheckStack(void)
-{
- return 1;
-}
-
-/*
- * The mechanics of actually signalling an exception (in the future,
- * and Alarm or Interrupt) depend upon what thread implementation you
- * are using.
- */
-void
-sysThreadPostException(sys_thread_t *tid, void *exc)
-{
- /* Interrupt the thread if it's waiting; REMIND: race??? */
- SetEvent(tid->interrupt_event);
-}
-
-/*
- * Support for (Java-level) interrupts.
- */
-void
-sysThreadInterrupt(sys_thread_t *tid)
-{
- if (tid->interrupted == FALSE) {
- tid->interrupted = TRUE;
- SetEvent(tid->interrupt_event);
- }
-}
-
-int
-sysThreadIsInterrupted(sys_thread_t *tid, int ClearInterrupted)
-{
- bool_t interrupted = tid->interrupted;
- if (interrupted && ClearInterrupted) {
- tid->interrupted = FALSE;
- ResetEvent(tid->interrupt_event);
- }
- return interrupted;
-}
-
-HPI_SysInfo *
-sysGetSysInfo()
-{
- static HPI_SysInfo info = {0, 0};
-
- if (info.name == NULL) {
- SYSTEM_INFO sysinfo;
- GetSystemInfo(&sysinfo);
- info.isMP = sysinfo.dwNumberOfProcessors > 1;
- info.name = "native threads";
- }
- return &info;
-}
-
-#define FT2INT64(ft) \
- ((jlong)(ft).dwHighDateTime << 32 | (jlong)(ft).dwLowDateTime)
-
-jlong
-sysThreadCPUTime()
-{
- if (windowsNT) {
- FILETIME CreationTime;
- FILETIME ExitTime;
- FILETIME KernelTime;
- FILETIME UserTime;
-
- GetThreadTimes(GetCurrentThread(),
- &CreationTime, &ExitTime, &KernelTime, &UserTime);
- return FT2INT64(UserTime) * 100;
- } else {
- return (jlong)sysGetMilliTicks() * 1000000;
- }
-}
-
-int
-sysThreadGetStatus(sys_thread_t *tid, sys_mon_t **monitorPtr)
-{
- int status;
- switch (tid->state) {
- case RUNNABLE:
- if (tid->enter_monitor)
- status = SYS_THREAD_MONITOR_WAIT;
- else
- status = SYS_THREAD_RUNNABLE;
- break;
- case SUSPENDED:
- if (tid->enter_monitor)
- status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT;
- else if (tid->suspend_flags & CONDVAR_WAIT_SUSPENDED)
- status = SYS_THREAD_SUSPENDED | SYS_THREAD_CONDVAR_WAIT;
- else
- status = SYS_THREAD_SUSPENDED;
- break;
- case MONITOR_SUSPENDED:
- status = SYS_THREAD_SUSPENDED | SYS_THREAD_MONITOR_WAIT;
- break;
- case CONDVAR_WAIT:
- status = SYS_THREAD_CONDVAR_WAIT;
- break;
- case MONITOR_WAIT:
- /*
- * this flag should never be in used on win32 since the
- * state is actually signalled by setting self->enter_monitor
- * to point at the monitor the thread is waiting to enter
- */
- sysAssert(FALSE);
- default:
- return SYS_ERR;
- }
- if (monitorPtr) {
- if (status & SYS_THREAD_MONITOR_WAIT) {
- *monitorPtr = tid->enter_monitor;
- } else if (status & SYS_THREAD_CONDVAR_WAIT) {
- *monitorPtr = tid->wait_monitor;
- } else {
- *monitorPtr = NULL;
- }
- }
- return status;
-}
-
-int sysAdjustTimeSlice(int i)
-{
- return JNI_ERR;
-}
-
-void sysThreadProfSuspend(sys_thread_t *tid)
-{
- SuspendThread(tid->handle);
-}
-
-void sysThreadProfResume(sys_thread_t *tid)
-{
- ResumeThread(tid->handle);
-}
-
-bool_t sysThreadIsRunning(sys_thread_t *tid)
-{
-#ifndef _M_AMD64
- unsigned int sum = 0;
- unsigned int *p;
- CONTEXT context;
-
- context.ContextFlags = CONTEXT_FULL;
- GetThreadContext(tid->handle, &context);
- p = &context.SegGs;
- while (p <= &context.SegSs) {
- sum += *p;
- p++;
- }
-
- if (sum == tid->last_sum) {
- return FALSE;
- }
- tid->last_sum = sum;
-#endif
- return TRUE;
-}
-
-void *
-sysThreadInterruptEvent()
-{
- return sysThreadSelf()->interrupt_event;
-}
--- a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Fri Feb 18 12:04:36 2011 -0800
@@ -1032,21 +1032,20 @@
* SO_BINDADDR isn't a socket option
*/
if (opt == java_net_SocketOptions_SO_BINDADDR) {
- SOCKET_ADDRESS him;
+ SOCKETADDRESS him;
int len;
int port;
jobject iaObj;
jclass iaCntrClass;
jfieldID iaFieldID;
- len = sizeof(struct sockaddr_in);
+ len = sizeof(him);
if (fd == -1) {
/* must be an IPV6 only socket. Case where both sockets are != -1
* is handled in java
*/
fd = getFD1 (env, this);
- len = sizeof(struct SOCKADDR_IN6);
}
if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
--- a/jdk/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/src/windows/native/sun/java2d/windows/GDIBlitLoops.cpp Fri Feb 18 12:04:36 2011 -0800
@@ -107,8 +107,16 @@
// could retain their own DIB info and we would not need to
// recreate it every time.
+ // GetRasInfo implicitly calls GetPrimitiveArrayCritical
+ // and since GetDC uses JNI it needs to be called first.
+ HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0);
+ if (hDC == NULL) {
+ SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
+ return;
+ }
srcOps->GetRasInfo(env, srcOps, &srcInfo);
if (srcInfo.rasBase == NULL) {
+ dstOps->ReleaseDC(env, dstOps, hDC);
SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
return;
}
@@ -174,13 +182,6 @@
bmi.colors.dwMasks[2] = bmask;
}
- HDC hDC = dstOps->GetDC(env, dstOps, 0, NULL, clip, NULL, 0);
- if (hDC == NULL) {
- SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
- SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
- return;
- }
-
if (fastBlt) {
// Window could go away at any time, leaving bits on the screen
// from this GDI call, so make sure window still exists
--- a/jdk/test/ProblemList.txt Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/ProblemList.txt Fri Feb 18 12:04:36 2011 -0800
@@ -439,6 +439,9 @@
java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java generic-all
java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java generic-all
+java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java generic-all
+java/rmi/transport/dgcDeadLock/TestImpl_Stub.java generic-all
+
# Address already in use, othervm mode, solaris
java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java generic-all
java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java generic-all
@@ -718,9 +721,6 @@
# 11 separate stacktraces created... file reuse problem?
java/util/zip/ZipFile/ReadLongZipFileName.java generic-all
-# Failing on all -client 32bit platforms starting with b77? See 6908348.
-java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java generic-all
-
# Assert error, failures, on Linux Fedora 9 -server
# Windows samevm failure, assert error "Passed = 134, failed = 2"
java/util/Arrays/ArrayObjectMethods.java generic-all
@@ -737,11 +737,5 @@
# Fails on solaris-sparc -server (Set not equal to copy. 1)
java/util/EnumSet/EnumSetBash.java solaris-sparc
-# Failing to close an input stream? "foo", triggers samevm windows failures
-java/util/Formatter/Constructors.java generic-all
-
-# Need to be marked othervm, or changed to be samevm safe
-java/util/WeakHashMap/GCDuringIteration.java generic-all
-
############################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/NativeInstanceFilter.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,122 @@
+/*
+ * 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 6426034
+ * @summary Instance filter doesn't filter event if it occurs in native method
+ *
+ * @author Keith McGuigan
+ *
+ * @library scaffold
+ * @run build JDIScaffold VMConnection
+ * @compile -XDignore.symbol.file NativeInstanceFilterTarg.java
+ * @run main/othervm NativeInstanceFilter
+ */
+
+/*
+ * This test tests instance filters for events generated from a native method
+ */
+
+import java.util.*;
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+public class NativeInstanceFilter extends JDIScaffold {
+
+ static int unfilteredEvents = 0;
+
+ public static void main(String args[]) throws Exception {
+ new NativeInstanceFilter().startTests();
+ }
+
+ public NativeInstanceFilter() {
+ super();
+ }
+
+ static EventRequestManager requestManager = null;
+ static MethodExitRequest request = null;
+
+ private void listen() {
+ TargetAdapter adapter = new TargetAdapter() {
+ EventSet set = null;
+ ObjectReference instance = null;
+
+ public boolean eventSetReceived(EventSet set) {
+ this.set = set;
+ return false;
+ }
+
+ public boolean methodExited(MethodExitEvent event) {
+ String name = event.method().name();
+ if (instance == null && name.equals("latch")) {
+ // Grab the instance (return value) and set up as filter
+ System.out.println("Setting up instance filter");
+ instance = (ObjectReference)event.returnValue();
+ requestManager.deleteEventRequest(request);
+ request = requestManager.createMethodExitRequest();
+ request.addInstanceFilter(instance);
+ request.enable();
+ } else if (instance != null && name.equals("intern")) {
+ // If not for the filter, this will be called twice
+ System.out.println("method exit event (String.intern())");
+ ++unfilteredEvents;
+ }
+ set.resume();
+ return false;
+ }
+ };
+ addListener(adapter);
+ }
+
+
+ protected void runTests() throws Exception {
+ String[] args = new String[2];
+ args[0] = "-connect";
+ args[1] = "com.sun.jdi.CommandLineLaunch:main=NativeInstanceFilterTarg";
+
+ connect(args);
+ waitForVMStart();
+
+ // VM has started, but hasn't started running the test program yet.
+ requestManager = vm().eventRequestManager();
+ ReferenceType referenceType =
+ resumeToPrepareOf("NativeInstanceFilterTarg").referenceType();
+
+ request = requestManager.createMethodExitRequest();
+ request.enable();
+
+ listen();
+
+ vm().resume();
+
+ waitForVMDeath();
+
+ if (unfilteredEvents != 1) {
+ throw new Exception(
+ "Failed: Event from native frame not filtered out.");
+ }
+ System.out.println("Passed: Event filtered out.");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/NativeInstanceFilterTarg.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+import sun.misc.Version;
+
+public class NativeInstanceFilterTarg {
+
+ public static void main(String args[]) {
+ boolean runTest = jvmSupportsJVMTI_12x();
+ String s1 = "abc";
+ String s2 = "def";
+ latch(s1);
+ s1.intern();
+ if (runTest) {
+ s2.intern(); // this is the call that generates events that ought
+ // to be filtered out.
+ } else {
+ System.out.println("Neutering test since JVMTI 1.2 not supported");
+ }
+ }
+
+ // Used by debugger to get an instance to filter with
+ public static String latch(String s) { return s; }
+
+ public static boolean jvmSupportsJVMTI_12x() {
+ // This fix requires the JVM to support JVMTI 1.2, which doesn't
+ // happen until HSX 20.0, build 05.
+ int major = Version.jvmMajorVersion();
+ int minor = Version.jvmMinorVersion();
+ int micro = Version.jvmMicroVersion();
+ int build = Version.jvmBuildNumber();
+
+ return (major > 20 || major == 20 &&
+ (minor > 0 || micro > 0 || build >= 5));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemory.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,247 @@
+/*
+ * 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 6173675
+ * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes
+ * @author Paul Hohensee
+ */
+
+import java.lang.management.*;
+
+public class ThreadAllocatedMemory {
+ private static com.sun.management.ThreadMXBean mbean =
+ (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
+ private static boolean testFailed = false;
+ private static boolean done = false;
+ private static boolean done1 = false;
+ private static Object obj = new Object();
+ private static final int NUM_THREADS = 10;
+ private static Thread[] threads = new Thread[NUM_THREADS];
+ private static long[] sizes = new long[NUM_THREADS];
+
+ public static void main(String[] argv)
+ throws Exception {
+
+ if (!mbean.isThreadAllocatedMemorySupported()) {
+ return;
+ }
+
+ // disable allocated memory measurement
+ if (mbean.isThreadAllocatedMemoryEnabled()) {
+ mbean.setThreadAllocatedMemoryEnabled(false);
+ }
+
+ if (mbean.isThreadAllocatedMemoryEnabled()) {
+ throw new RuntimeException(
+ "ThreadAllocatedMemory is expected to be disabled");
+ }
+
+ Thread curThread = Thread.currentThread();
+ long id = curThread.getId();
+
+ long s = mbean.getThreadAllocatedBytes(id);
+ if (s != -1) {
+ throw new RuntimeException(
+ "Invalid ThreadAllocatedBytes returned = " +
+ s + " expected = -1");
+ }
+
+ // enable allocated memory measurement
+ if (!mbean.isThreadAllocatedMemoryEnabled()) {
+ mbean.setThreadAllocatedMemoryEnabled(true);
+ }
+
+ if (!mbean.isThreadAllocatedMemoryEnabled()) {
+ throw new RuntimeException(
+ "ThreadAllocatedMemory is expected to be enabled");
+ }
+
+ long size = mbean.getThreadAllocatedBytes(id);
+ // implementation could have started measurement when
+ // measurement was enabled, in which case size can be 0
+ if (size < 0) {
+ throw new RuntimeException(
+ "Invalid allocated bytes returned = " + size);
+ }
+
+ doit();
+
+ // Expected to be size1 >= size
+ long size1 = mbean.getThreadAllocatedBytes(id);
+ if (size1 < size) {
+ throw new RuntimeException("Allocated bytes " + size1 +
+ " expected >= " + size);
+ }
+ System.out.println(curThread.getName() +
+ " Current thread allocated bytes = " + size +
+ " allocated bytes = " + size1);
+
+
+ // start threads, wait for them to block
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i] = new MyThread("MyThread-" + i);
+ threads[i].start();
+ }
+
+ // threads block after doing some allocation
+ waitUntilThreadBlocked();
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ sizes[i] = mbean.getThreadAllocatedBytes(threads[i].getId());
+ }
+
+ // let threads go and do some more allocation
+ synchronized (obj) {
+ done = true;
+ obj.notifyAll();
+ }
+
+ // wait for threads to get going again. we don't care if we
+ // catch them in mid-execution or if some of them haven't
+ // restarted after we're done sleeping.
+ goSleep(400);
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long newSize = mbean.getThreadAllocatedBytes(threads[i].getId());
+ if (sizes[i] > newSize) {
+ throw new RuntimeException("TEST FAILED: " +
+ threads[i].getName() +
+ " previous allocated bytes = " + sizes[i] +
+ " > current allocated bytes = " + newSize);
+ }
+ System.out.println(threads[i].getName() +
+ " Previous allocated bytes = " + sizes[i] +
+ " Current allocated bytes = " + newSize);
+ }
+
+ // let threads exit
+ synchronized (obj) {
+ done1 = true;
+ obj.notifyAll();
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+ if (testFailed) {
+ throw new RuntimeException("TEST FAILED");
+ }
+
+ System.out.println("Test passed");
+ }
+
+
+ private static void goSleep(long ms) throws Exception {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ throw e;
+ }
+ }
+
+ private static void waitUntilThreadBlocked()
+ throws Exception {
+ int count = 0;
+ while (count != NUM_THREADS) {
+ goSleep(100);
+ count = 0;
+ for (int i = 0; i < NUM_THREADS; i++) {
+ ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
+ if (info.getThreadState() == Thread.State.WAITING) {
+ count++;
+ }
+ }
+ }
+ }
+
+ public static void doit() {
+ String tmp = "";
+ long hashCode = 0;
+ for (int counter = 0; counter < 1000; counter++) {
+ tmp += counter;
+ hashCode = tmp.hashCode();
+ }
+ System.out.println(Thread.currentThread().getName() +
+ " hashcode: " + hashCode);
+ }
+
+ static class MyThread extends Thread {
+ public MyThread(String name) {
+ super(name);
+ }
+
+ public void run() {
+ ThreadAllocatedMemory.doit();
+
+ synchronized (obj) {
+ while (!done) {
+ try {
+ obj.wait();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+ }
+
+ long size1 = mbean.getThreadAllocatedBytes(getId());
+ ThreadAllocatedMemory.doit();
+ long size2 = mbean.getThreadAllocatedBytes(getId());
+
+ System.out.println(getName() + ": " +
+ "ThreadAllocatedBytes = " + size1 +
+ " ThreadAllocatedBytes = " + size2);
+
+ if (size1 > size2) {
+ throw new RuntimeException("TEST FAILED: " + getName() +
+ " ThreadAllocatedBytes = " + size1 +
+ " > ThreadAllocatedBytes = " + size2);
+ }
+
+ synchronized (obj) {
+ while (!done1) {
+ try {
+ obj.wait();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/management/ThreadMXBean/ThreadAllocatedMemoryArray.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,249 @@
+/*
+ * 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 6173675
+ * @summary Basic test of ThreadMXBean.getThreadAllocatedBytes(long[])
+ * @author Paul Hohensee
+ */
+
+import java.lang.management.*;
+
+public class ThreadAllocatedMemoryArray {
+ private static com.sun.management.ThreadMXBean mbean =
+ (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
+ private static boolean testFailed = false;
+ private static boolean done = false;
+ private static boolean done1 = false;
+ private static Object obj = new Object();
+ private static final int NUM_THREADS = 10;
+ private static Thread[] threads = new Thread[NUM_THREADS];
+
+ public static void main(String[] argv)
+ throws Exception {
+
+ if (!mbean.isThreadAllocatedMemorySupported()) {
+ return;
+ }
+
+
+ // start threads, wait for them to block
+ long[] ids = new long[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i] = new MyThread("MyThread-" + i);
+ threads[i].start();
+ ids[i] = threads[i].getId();
+ }
+
+ waitUntilThreadBlocked();
+
+
+ // disable allocated memory measurement
+ if (mbean.isThreadAllocatedMemoryEnabled()) {
+ mbean.setThreadAllocatedMemoryEnabled(false);
+ }
+
+ if (mbean.isThreadAllocatedMemoryEnabled()) {
+ throw new RuntimeException(
+ "ThreadAllocatedMemory is expected to be disabled");
+ }
+
+ long sizes[] = mbean.getThreadAllocatedBytes(ids);
+
+ if (sizes == null) {
+ throw new RuntimeException("Null ThreadAllocatedBytes array returned");
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long s = sizes[i];
+ if (s != -1) {
+ throw new RuntimeException(
+ "Invalid ThreadAllocatedBytes returned for thread " +
+ threads[i].getName() + " = " + s + " expected = -1");
+ }
+ }
+
+ // Enable allocated memory measurement
+ if (!mbean.isThreadAllocatedMemoryEnabled()) {
+ mbean.setThreadAllocatedMemoryEnabled(true);
+ }
+
+ if (!mbean.isThreadAllocatedMemoryEnabled()) {
+ throw new RuntimeException(
+ "ThreadAllocatedMemory is expected to be enabled");
+ }
+
+ sizes = mbean.getThreadAllocatedBytes(ids);
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long s = sizes[i];
+ if (s < 0) {
+ throw new RuntimeException(
+ "Invalid allocated bytes returned for thread " +
+ threads[i].getName() + " = " + s);
+ }
+ }
+
+ // let threads go and do some more allocation
+ synchronized (obj) {
+ done = true;
+ obj.notifyAll();
+ }
+
+ // wait for threads to get going again. we don't care if we
+ // catch them in mid-execution or if some of them haven't
+ // restarted after we're done sleeping.
+ goSleep(400);
+
+ long[] sizes1 = mbean.getThreadAllocatedBytes(ids);
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long newSize = sizes1[i];
+ if (sizes[i] > newSize) {
+ throw new RuntimeException("TEST FAILED: " +
+ threads[i].getName() +
+ " previous allocated bytes = " + sizes[i] +
+ " > current allocated bytes = " + newSize);
+ }
+ System.out.println(threads[i].getName() +
+ " Previous allocated bytes = " + sizes[i] +
+ " Current allocated bytes = " + newSize);
+ }
+
+ try {
+ sizes = mbean.getThreadAllocatedBytes(null);
+ } catch (NullPointerException e) {
+ System.out.println(
+ "Caught expected NullPointerException: " + e.getMessage());
+ }
+
+ try {
+ ids[0] = 0;
+ sizes = mbean.getThreadAllocatedBytes(ids);
+ } catch (IllegalArgumentException e) {
+ System.out.println(
+ "Caught expected IllegalArgumentException: " + e.getMessage());
+ }
+
+
+ // let threads exit
+ synchronized (obj) {
+ done1 = true;
+ obj.notifyAll();
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+
+ if (testFailed) {
+ throw new RuntimeException("TEST FAILED");
+ }
+
+ System.out.println("Test passed");
+ }
+
+
+ private static void goSleep(long ms) throws Exception {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ throw e;
+ }
+ }
+
+ private static void waitUntilThreadBlocked()
+ throws Exception {
+ int count = 0;
+ while (count != NUM_THREADS) {
+ goSleep(100);
+ count = 0;
+ for (int i = 0; i < NUM_THREADS; i++) {
+ ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
+ if (info.getThreadState() == Thread.State.WAITING) {
+ count++;
+ }
+ }
+ }
+ }
+
+ public static void doit() {
+ String tmp = "";
+ long hashCode = 0;
+ for (int counter = 0; counter < 1000; counter++) {
+ tmp += counter;
+ hashCode = tmp.hashCode();
+ }
+ System.out.println(Thread.currentThread().getName() +
+ " hashcode: " + hashCode);
+ }
+
+ static class MyThread extends Thread {
+ public MyThread(String name) {
+ super(name);
+ }
+
+ public void run() {
+ ThreadAllocatedMemoryArray.doit();
+
+ synchronized (obj) {
+ while (!done) {
+ try {
+ obj.wait();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+ }
+
+ ThreadAllocatedMemoryArray.doit();
+
+ synchronized (obj) {
+ while (!done1) {
+ try {
+ obj.wait();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+ }
+
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/management/ThreadMXBean/ThreadCpuTimeArray.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,259 @@
+/*
+ * 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 6173675
+ * @summary Basic test of ThreadMXBean.getThreadCpuTime(long[]) and
+ * getThreadUserTime(long[]).
+ * @author Paul Hohensee
+ */
+
+import java.lang.management.*;
+
+public class ThreadCpuTimeArray {
+ private static com.sun.management.ThreadMXBean mbean =
+ (com.sun.management.ThreadMXBean)ManagementFactory.getThreadMXBean();
+ private static boolean testFailed = false;
+ private static boolean done = false;
+ private static Object obj = new Object();
+ private static final int NUM_THREADS = 10;
+ private static Thread[] threads = new Thread[NUM_THREADS];
+
+ // careful about this value
+ private static final int DELTA = 100;
+
+ public static void main(String[] argv)
+ throws Exception {
+
+ if (!mbean.isThreadCpuTimeSupported()) {
+ return;
+ }
+
+
+ // disable CPU time
+ if (mbean.isThreadCpuTimeEnabled()) {
+ mbean.setThreadCpuTimeEnabled(false);
+ }
+
+ if (mbean.isThreadCpuTimeEnabled()) {
+ throw new RuntimeException("ThreadCpuTime is expected to be disabled");
+ }
+
+ // start threads, wait for them to block
+ long[] ids = new long[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ threads[i] = new MyThread("MyThread-" + i);
+ threads[i].start();
+ ids[i] = threads[i].getId();
+ }
+
+ // threads block after doing some computation
+ waitUntilThreadBlocked();
+
+
+ long times[] = mbean.getThreadCpuTime(ids);
+ long userTimes[] = mbean.getThreadUserTime(ids);
+
+ if (times == null) {
+ throw new RuntimeException("Null ThreadCpuTime array returned");
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long t = times[i];
+ if (t != -1) {
+ throw new RuntimeException(
+ "Invalid ThreadCpuTime returned for thread " +
+ threads[i].getName() + " = " + t + " expected = -1");
+ }
+ long ut = userTimes[i];
+ if (ut != -1) {
+ throw new RuntimeException(
+ "Invalid ThreadUserTime returned for thread " +
+ threads[i].getName() + " = " + ut + " expected = -1");
+ }
+ }
+
+
+ // Enable CPU Time measurement
+ if (!mbean.isThreadCpuTimeEnabled()) {
+ mbean.setThreadCpuTimeEnabled(true);
+ }
+
+ if (!mbean.isThreadCpuTimeEnabled()) {
+ throw new RuntimeException("ThreadCpuTime is expected to be enabled");
+ }
+
+ times = mbean.getThreadCpuTime(ids);
+ userTimes = mbean.getThreadUserTime(ids);
+
+ goSleep(200);
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long t = times[i];
+ if (t < 0) {
+ throw new RuntimeException(
+ "Invalid CPU time returned for thread " +
+ threads[i].getName() + " = " + t);
+ }
+ long ut = userTimes[i];
+ if (ut < 0) {
+ throw new RuntimeException(
+ "Invalid user time returned for thread " +
+ threads[i].getName() + " = " + ut);
+ }
+ }
+
+ long[] times1 = mbean.getThreadCpuTime(ids);
+ long[] userTimes1 = mbean.getThreadUserTime(ids);
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ long newTime = times1[i];
+ long newUserTime = userTimes1[i];
+
+ if (times[i] > newTime) {
+ throw new RuntimeException("TEST FAILED: " +
+ threads[i].getName() +
+ " previous CPU time = " + times[i] +
+ " > current CPU time = " + newTime);
+ }
+ if ((times[i] + DELTA) < newTime) {
+ throw new RuntimeException("TEST FAILED: " +
+ threads[i].getName() +
+ " CPU time = " + newTime +
+ " previous CPU time " + times[i] +
+ " out of expected range");
+ }
+
+ System.out.println(threads[i].getName() +
+ " Previous Cpu Time = " + times[i] +
+ " Current CPU time = " + newTime);
+
+ System.out.println(threads[i].getName() +
+ " Previous User Time = " + userTimes[i] +
+ " Current User time = " + newUserTime);
+ }
+
+
+ try {
+ times = mbean.getThreadCpuTime(null);
+ } catch (NullPointerException e) {
+ System.out.println(
+ "Caught expected NullPointerException: " + e.getMessage());
+ }
+
+ try {
+ ids[0] = 0;
+ times = mbean.getThreadCpuTime(ids);
+ } catch (IllegalArgumentException e) {
+ System.out.println(
+ "Caught expected IllegalArgumentException: " + e.getMessage());
+ }
+
+
+ // let threads exit
+ synchronized (obj) {
+ done = true;
+ obj.notifyAll();
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+
+ if (testFailed) {
+ throw new RuntimeException("TEST FAILED");
+ }
+
+ System.out.println("Test passed");
+ }
+
+
+ private static void goSleep(long ms) throws Exception {
+ try {
+ Thread.sleep(ms);
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ throw e;
+ }
+ }
+
+ private static void waitUntilThreadBlocked()
+ throws Exception {
+ int count = 0;
+ while (count != NUM_THREADS) {
+ goSleep(100);
+ count = 0;
+ for (int i = 0; i < NUM_THREADS; i++) {
+ ThreadInfo info = mbean.getThreadInfo(threads[i].getId());
+ if (info.getThreadState() == Thread.State.WAITING) {
+ count++;
+ }
+ }
+ }
+ }
+
+ public static void doit() {
+ double sum = 0;
+ for (int i = 0; i < 5000; i++) {
+ double r = Math.random();
+ double x = Math.pow(3, r);
+ sum += x - r;
+ }
+ System.out.println(Thread.currentThread().getName() +
+ " sum = " + sum);
+ }
+
+ static class MyThread extends Thread {
+ public MyThread(String name) {
+ super(name);
+ }
+
+ public void run() {
+ ThreadCpuTimeArray.doit();
+
+ synchronized (obj) {
+ while (!done) {
+ try {
+ obj.wait();
+ } catch (InterruptedException e) {
+ System.out.println("Unexpected exception is thrown.");
+ e.printStackTrace(System.out);
+ testFailed = true;
+ break;
+ }
+ }
+ }
+
+ ThreadCpuTimeArray.doit();
+ }
+ }
+}
--- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckConfigs.java Fri Feb 18 12:04:36 2011 -0800
@@ -178,7 +178,7 @@
public SearchFirstMode() {
super();
- Map<String, String> options = new HashMap<String, String>(4);
+ Map<String, String> options = new HashMap<>(4);
options.put("userProvider", "ldap://localhost:23456/dc=example,dc=com");
options.put("userFilter",
"(&(uid={USERNAME})(objectClass=inetOrgPerson))");
@@ -213,7 +213,7 @@
public AuthFirstMode() {
super();
- Map<String, String> options = new HashMap<String, String>(5);
+ Map<String, String> options = new HashMap<>(5);
options.put("userProvider", "ldap://localhost:23456/dc=example,dc=com");
options.put("authIdentity", "{USERNAME}");
options.put("userFilter",
@@ -248,7 +248,7 @@
public AuthOnlyMode() {
super();
- Map<String, String> options = new HashMap<String, String>(4);
+ Map<String, String> options = new HashMap<>(4);
options.put("userProvider",
"ldap://localhost:23456 ldap://localhost:23457");
options.put("authIdentity",
--- a/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/com/sun/security/auth/module/LdapLoginModule/CheckOptions.java Fri Feb 18 12:04:36 2011 -0800
@@ -73,7 +73,7 @@
// bad value for userProvider option
- Map<String, String> options = new HashMap<String, String>();
+ Map<String, String> options = new HashMap<>();
options.put(USER_PROVIDER_OPTION, "ldap://localhost:23456");
ldap.initialize(subject, null, null, options);
@@ -93,7 +93,7 @@
LdapLoginModule ldap = new LdapLoginModule();
Subject subject = new Subject();
- Map<String, String> options = new HashMap<String, String>();
+ Map<String, String> options = new HashMap<>();
ldap.initialize(subject, null, null, options);
try {
@@ -110,7 +110,7 @@
LdapLoginModule ldap = new LdapLoginModule();
Subject subject = new Subject();
- Map<String, String> options = new HashMap<String, String>();
+ Map<String, String> options = new HashMap<>();
CallbackHandler goodHandler = new MyCallbackHandler(true);
ldap.initialize(subject, goodHandler, null, options);
--- a/jdk/test/demo/zipfs/PathOps.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/demo/zipfs/PathOps.java Fri Feb 18 12:04:36 2011 -0800
@@ -193,6 +193,17 @@
return this;
}
+ PathOps isSameFile(String target) {
+ try {
+ out.println("check two paths are same");
+ checkPath();
+ check(path.isSameFile(test(target).path()), true);
+ } catch (IOException ioe) {
+ fail();
+ }
+ return this;
+ }
+
PathOps invalid() {
if (!(exc instanceof InvalidPathException)) {
out.println("InvalidPathException not thrown as expected");
@@ -344,7 +355,12 @@
.normalize("foo");
test("/foo/bar/gus/../..")
.normalize("/foo");
-
+ test("/./.")
+ .normalize("/");
+ test("/.")
+ .normalize("/");
+ test("/./abc")
+ .normalize("/abc");
// invalid
test("foo\u0000bar")
.invalid();
@@ -365,6 +381,10 @@
.root("/")
.parent("/foo")
.name("bar");
+
+ // isSameFile
+ test("/fileDoesNotExist")
+ .isSameFile("/fileDoesNotExist");
}
static void npes() {
--- a/jdk/test/demo/zipfs/ZipFSTester.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/demo/zipfs/ZipFSTester.java Fri Feb 18 12:04:36 2011 -0800
@@ -28,6 +28,7 @@
import java.nio.file.attribute.*;
import java.net.*;
import java.util.*;
+import java.util.zip.*;
import static java.nio.file.StandardOpenOption.*;
import static java.nio.file.StandardCopyOption.*;
@@ -42,7 +43,8 @@
FileSystem fs = null;
try {
fs = newZipFileSystem(Paths.get(args[0]), new HashMap<String, Object>());
- test(fs);
+ test0(fs);
+ test1(fs);
test2(fs); // more tests
} finally {
if (fs != null)
@@ -50,11 +52,31 @@
}
}
- static void test(FileSystem fs)
+ static void test0(FileSystem fs)
+ throws Exception
+ {
+ List<String> list = new LinkedList<>();
+ try (ZipFile zf = new ZipFile(fs.toString())) {
+ Enumeration<? extends ZipEntry> zes = zf.entries();
+ while (zes.hasMoreElements()) {
+ list.add(zes.nextElement().getName());
+ }
+ for (String pname : list) {
+ Path path = fs.getPath(pname);
+ if (!path.exists())
+ throw new RuntimeException("path existence check failed!");
+ while ((path = path.getParent()) != null) {
+ if (!path.exists())
+ throw new RuntimeException("parent existence check failed!");
+ }
+ }
+ }
+ }
+
+ static void test1(FileSystem fs)
throws Exception
{
Random rdm = new Random();
-
// clone a fs and test on it
Path tmpfsPath = getTempPath();
Map<String, Object> env = new HashMap<String, Object>();
--- a/jdk/test/demo/zipfs/basic.sh Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/demo/zipfs/basic.sh Fri Feb 18 12:04:36 2011 -0800
@@ -21,7 +21,7 @@
# questions.
#
# @test
-# @bug 6990846
+# @bug 6990846 7009092 7009085
# @summary Test ZipFileSystem demo
# @build Basic PathOps ZipFSTester
# @run shell basic.sh
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/StyledMetrics/BoldSpace.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2008, 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 6686365 7017637
+ @summary Confirm that styling does not affect metrics of zero advance glyphs
+*/
+
+import java.awt.*;
+import java.awt.image.*;
+
+public class BoldSpace {
+ public static void main(String[] s) {
+ BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
+
+ String errMsg = "ZWJ Space char should have 0 advance\n";
+
+ Graphics g = bi.getGraphics();
+
+ // It turns out that some fonts inexplicably treat this as
+ // a standard character. In this 14 pt font, if we see an advance
+ // that's clearly bigger than we'd have introduced in bolding we'll
+ // not error out this test, presuming that its a consequence of
+ // the actual font data. A Linux font 'TLwg Type Bold' is the case
+ // in point.
+ int errorMargin = 4;
+ g.setFont(new Font("monospaced", Font.BOLD, 14));
+ //g.setFont(new Font("Lucida Sans Regular", Font.BOLD, 14));
+ FontMetrics fm = g.getFontMetrics();
+ System.out.println("Bold: " + fm.charWidth('\u200b'));
+ int cwid = fm.charWidth('\u200b');
+ if (cwid > 0 && cwid < errorMargin) {
+ throw new RuntimeException(errMsg);
+ }
+
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
+ fm = g.getFontMetrics();
+ System.out.println("Bold + LCD: "+fm.charWidth('\u200b'));
+ cwid = fm.charWidth('\u200b');
+ if (cwid > 0 && cwid < errorMargin) {
+ throw new RuntimeException(errMsg);
+ }
+
+
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ fm = g.getFontMetrics();
+ System.out.println("Bold FM OFF + AA: " + fm.charWidth('\u200b'));
+ cwid = fm.charWidth('\u200b');
+ if (cwid > 0 && cwid < errorMargin) {
+ throw new RuntimeException(errMsg);
+ }
+
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ fm = g.getFontMetrics();
+ System.out.println("Bold FM ON + AA: " + fm.charWidth('\u200b'));
+ cwid = fm.charWidth('\u200b');
+ if (cwid > 0 && cwid < errorMargin) {
+ throw new RuntimeException(errMsg);
+ }
+
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
+ RenderingHints.VALUE_FRACTIONALMETRICS_ON);
+ ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
+ fm = g.getFontMetrics();
+ System.out.println("Bold FM ON + nonAA: " + fm.charWidth('\u200b'));
+ cwid = fm.charWidth('\u200b');
+ if (cwid > 0 && cwid < errorMargin) {
+ throw new RuntimeException(errMsg);
+ }
+
+ System.out.println("All printed values should be 0 to PASS");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/ImagePrinting/ImageTypes.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,272 @@
+/*
+ * 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
+ * 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 4521945 7006865
+ * @summary Test printing images of different types.
+ * @author prr
+ * @run main/manual=yesno/timeout=900 ImageTypes
+ */
+
+import java.io.*;
+import static java.awt.Color.*;
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.event.*;
+import java.awt.print.*;
+import java.awt.image.*;
+import static java.awt.image.BufferedImage.*;
+import javax.print.*;
+import javax.print.attribute.*;
+import javax.print.attribute.standard.*;
+
+public class ImageTypes extends Frame implements ActionListener {
+
+ private ImageCanvas c;
+
+ public static void main(String args[]) {
+
+ ImageTypes f = new ImageTypes();
+ f.show();
+ }
+
+ public ImageTypes () {
+ super("Image Types Printing Test");
+ c = new ImageCanvas();
+ add("Center", c);
+
+ Button printThisButton = new Button("Print");
+ printThisButton.addActionListener(this);
+ Panel p = new Panel();
+ p.add(printThisButton);
+ add("South", p);
+ add("North", getInstructions());
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ pack();
+ }
+
+ private TextArea getInstructions() {
+ TextArea ta = new TextArea(10, 60);
+ ta.setFont(new Font("Dialog", Font.PLAIN, 11));
+ ta.setText
+ ("This is a manual test as it requires that you compare "+
+ "the on-screen rendering with the printed output.\n"+
+ "Select the 'Print' button to print out the test.\n"+
+ "For each image compare the printed one to the on-screen one.\n"+
+ "The test PASSES if the onscreen and printed rendering match.");
+ return ta;
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ PrinterJob pj = PrinterJob.getPrinterJob();
+
+ PrintRequestAttributeSet attrs = new HashPrintRequestAttributeSet();
+ if (pj != null && pj.printDialog(attrs)) {
+ pj.setPrintable(c);
+ try {
+ pj.print(attrs);
+ } catch (PrinterException pe) {
+ pe.printStackTrace();
+ throw new RuntimeException("Exception whilst printing.");
+ } finally {
+ System.out.println("PRINT RETURNED OK.");
+ }
+ }
+ }
+}
+
+class ImageCanvas extends Component implements Printable {
+
+ IndexColorModel icm2 = null;
+ IndexColorModel icm4 = null;
+ BufferedImage opaqueImg = null;
+ BufferedImage transImg = null;
+ int sw=99, sh=99;
+
+ void paintImage(BufferedImage bi, Color c1, Color c2) {
+
+ GradientPaint tp= new GradientPaint(0.0f, 0.0f, c1, 10f, 8f, c2, true);
+ Graphics2D g2d = (Graphics2D)bi.getGraphics();
+ g2d.setPaint(tp);
+ g2d.fillRect(0, 0, sw, sh);
+ g2d.setColor(gray);
+ int cnt=0;
+ Font font = new Font("Serif", Font.PLAIN, 11);
+ g2d.setFont(font);
+ FontMetrics fm = g2d.getFontMetrics();
+ for (int y=12;y<sh;y+=12) {
+ int x = 0;
+ while (x < sw) {
+ String s = (new Integer(++cnt)).toString();
+ g2d.drawString(s, x, y);
+ x+= fm.stringWidth(s);
+ }
+ }
+ }
+
+ ImageCanvas() {
+
+ opaqueImg = new BufferedImage(sw, sh, TYPE_INT_RGB);
+ Color o1 = new Color(0, 0, 0);
+ Color o2 = new Color(255, 255, 255);
+ paintImage(opaqueImg, o1, o2);
+
+ transImg = new BufferedImage(sw, sh, TYPE_INT_ARGB);
+ Color t1 = new Color(255, 255, 255, 220);
+ Color t2 = new Color(255, 200, 0, 220);
+ paintImage(transImg, t1, t2);
+
+ /* greyscale 2bpp */
+ byte[] arr2bpp = {(byte)0, (byte)0x55, (byte)0xaa, (byte)0xff};
+ icm2 = new IndexColorModel(2, 4, arr2bpp, arr2bpp, arr2bpp);
+
+ /* color 4bpp */
+ int[] cmap = new int[16];
+ cmap[0] = black.getRGB();
+ cmap[1] = white.getRGB();
+ cmap[2] = gray.getRGB();
+ cmap[3] = lightGray.getRGB();
+ cmap[4] = red.getRGB();
+ cmap[5] = green.getRGB();
+ cmap[6] = blue.getRGB();
+ cmap[7] = yellow.getRGB();
+ cmap[8] = cyan.getRGB();
+ cmap[9] = magenta.getRGB();
+ cmap[10] = orange.getRGB();
+ cmap[11] = pink.getRGB();
+ cmap[12] = darkGray.getRGB();
+ cmap[13] = 192 << 16 ; // dark red.
+ cmap[14] = 192 << 8; // dark green
+ cmap[15] = 192; // dark blue
+
+ icm4 = new IndexColorModel(4, 16, cmap, 0, false, -1,
+ DataBuffer.TYPE_BYTE);
+
+ }
+
+
+ public int print(Graphics g, PageFormat pgFmt, int pgIndex) {
+
+ if (pgIndex > 0) {
+ return Printable.NO_SUCH_PAGE;
+ }
+ Graphics2D g2d = (Graphics2D)g;
+ g2d.translate(pgFmt.getImageableX(), pgFmt.getImageableY());
+ paint(g2d);
+ return Printable.PAGE_EXISTS;
+ }
+
+ private void drawImage(Graphics g, int biType, IndexColorModel icm) {
+
+ BufferedImage bi;
+ if (icm != null) {
+ bi = new BufferedImage(sw, sh, biType, icm);
+ } else {
+ bi = new BufferedImage(sw, sh, biType);
+ }
+
+ Graphics big = bi.getGraphics();
+ if (bi.getColorModel().getPixelSize() <=2) {
+ big.drawImage(opaqueImg, 0, 0, null);
+ } else {
+ big.drawImage(transImg, 0, 0, null);
+ }
+ g.drawImage(bi, 0, 0, null);
+ }
+
+ public void paint(Graphics g) {
+
+ int incX = sw+10, incY = sh+10;
+
+ g.translate(10, 10);
+
+ drawImage(g, TYPE_INT_RGB, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_INT_BGR, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_INT_ARGB, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_INT_ARGB_PRE, null);
+ g.translate(-3*incX, incY);
+
+ drawImage(g, TYPE_3BYTE_BGR, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_4BYTE_ABGR, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_4BYTE_ABGR_PRE, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_USHORT_555_RGB, null);
+ g.translate(-3*incX, incY);
+
+ drawImage(g, TYPE_USHORT_555_RGB, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_USHORT_GRAY, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_BYTE_GRAY, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_BYTE_INDEXED, null);
+ g.translate(-3*incX, incY);
+
+ drawImage(g, TYPE_BYTE_BINARY, null);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_BYTE_BINARY, icm2);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_BYTE_BINARY, icm4);
+ g.translate(incX, 0);
+
+ drawImage(g, TYPE_BYTE_INDEXED, icm2);
+ g.translate(-3*incX, incY);
+
+ drawImage(g, TYPE_BYTE_INDEXED, icm4);
+ g.translate(incX, 0);
+ }
+
+
+
+ /* Size is chosen to match default imageable width of a NA letter
+ * page. This means there will be clipping, what is clipped will
+ * depend on PageFormat orientation.
+ */
+ public Dimension getPreferredSize() {
+ return new Dimension(468, 600);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/PrintStream/FailingConstructors.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,133 @@
+/*
+ * 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 7000511
+ * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when
+ * exception thrown
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+public class FailingConstructors {
+ static final String fileName = "FailingConstructorsTest";
+ static final String UNSUPPORTED_CHARSET = "unknownCharset";
+ static final String FILE_CONTENTS = "This is a small file!";
+
+ private static void realMain(String[] args) throws Throwable {
+ test(false, new File(fileName));
+
+ /* create the file and write its contents */
+ File file = File.createTempFile(fileName, null);
+ file.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(FILE_CONTENTS.getBytes());
+ fos.close();
+
+ test(true, file);
+ file.delete();
+ }
+
+ private static void test(boolean exists, File file) throws Throwable {
+ /* PrintStream(File file, String csn) */
+ try {
+ new PrintStream(file, UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|UnsupportedEncodingException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new PrintStream(file, null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ /* PrintStream(String fileName, String csn) */
+ try {
+ new PrintStream(file.getName(), UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|UnsupportedEncodingException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new PrintStream(file.getName(), null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+ }
+
+ private static void check(boolean exists, File file) {
+ if (exists) {
+ /* the file should be unchanged */
+ verifyContents(file);
+ } else {
+ /* the file should not have been created */
+ if (file.exists()) { fail(file + " should not have been created"); }
+ }
+ }
+
+ private static void verifyContents(File file) {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ byte[] contents = FILE_CONTENTS.getBytes();
+ int read, count = 0;
+ while ((read = fis.read()) != -1) {
+ if (read != contents[count++]) {
+ fail("file contents have been altered");
+ return;
+ }
+ }
+ } catch (IOException ioe) {
+ unexpected(ioe);
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String message) {System.out.println(message); fail(); }
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/PrintWriter/FailingConstructors.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,133 @@
+/*
+ * 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 7000511
+ * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when
+ * exception thrown
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+public class FailingConstructors {
+ static final String fileName = "FailingConstructorsTest";
+ static final String UNSUPPORTED_CHARSET = "unknownCharset";
+ static final String FILE_CONTENTS = "This is a small file!";
+
+ private static void realMain(String[] args) throws Throwable {
+ test(false, new File(fileName));
+
+ /* create the file and write its contents */
+ File file = File.createTempFile(fileName, null);
+ file.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(FILE_CONTENTS.getBytes());
+ fos.close();
+
+ test(true, file);
+ file.delete();
+ }
+
+ private static void test(boolean exists, File file) throws Throwable {
+ /* PrintWriter(File file, String csn) */
+ try {
+ new PrintWriter(file, UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|UnsupportedEncodingException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new PrintWriter(file, null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ /* PrintWriter(String fileName, String csn) */
+ try {
+ new PrintWriter(file.getName(), UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|UnsupportedEncodingException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new PrintWriter(file.getName(), null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+ }
+
+ private static void check(boolean exists, File file) {
+ if (exists) {
+ /* the file should be unchanged */
+ verifyContents(file);
+ } else {
+ /* the file should not have been created */
+ if (file.exists()) { fail(file + " should not have been created"); }
+ }
+ }
+
+ private static void verifyContents(File file) {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ byte[] contents = FILE_CONTENTS.getBytes();
+ int read, count = 0;
+ while ((read = fis.read()) != -1) {
+ if (read != contents[count++]) {
+ fail("file contents have been altered");
+ return;
+ }
+ }
+ } catch (IOException ioe) {
+ unexpected(ioe);
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String message) {System.out.println(message); fail(); }
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/net/InetAddress/B4762344.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2007, 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 4762344
- * @summary 2nd nameservice provider is non functional
- * @build B4762344 SimpleNameService Simple1NameServiceDescriptor Simple2NameServiceDescriptor
- * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun B4762344
- */
-
-import java.net.*;
-import java.util.*;
-
-
-public class B4762344 {
- private static String[][] hostnames = new String[][] {
- // both providers know this host, but with different address
- new String[] {"blade", "10.0.0.1"},
- // provider1 knwos this host
- new String[] {"blade.domain1", "10.0.0.2"},
- // provider2 knows this host
- new String[] {"blade.domain2", "20.0.0.2"}
- };
- private static String[][] hostaddrs = new String[][] {
- new String[] {"10.0.0.1", "blade"},
- new String[] {"10.0.0.2", "blade.domain1"},
- new String[] {"20.0.0.2", "blade.domain2"}
- };
-
- public static void main(String[] args) throws Exception {
- for (int i = 0; i < hostnames.length; i++) {
- doLookup(hostnames[i][0], hostnames[i][1]);
- }
- for (int i = 0; i < hostaddrs.length; i++) {
- doReverseLookup(hostaddrs[i][0], hostaddrs[i][1]);
- }
- }
-
- private static void doLookup(String host, String addr) throws Exception {
- String res = InetAddress.getByName(host).getHostAddress();
- if (!res.equals(addr)) {
- throw new RuntimeException("Test failed: wrong address for host " + host);
- }
- }
-
- private static void doReverseLookup(String addr, String host) throws Exception {
- StringTokenizer tokenizer = new StringTokenizer(addr, ".");
- byte addrs[] = new byte[4];
- for (int i = 0; i < 4; i++) {
- addrs[i] = (byte)Integer.parseInt(tokenizer.nextToken());
- }
- String res = InetAddress.getByAddress(addrs).getHostName();
- if (!res.equals(host)) {
- throw new RuntimeException("Test failed: wrong host name for address " + addr);
- }
- }
-}
--- a/jdk/test/java/net/InetAddress/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-Simple1NameServiceDescriptor
-Simple2NameServiceDescriptor
--- a/jdk/test/java/net/InetAddress/Simple1NameServiceDescriptor.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- */
-
-import sun.net.spi.nameservice.*;
-
-
-public class Simple1NameServiceDescriptor implements NameServiceDescriptor {
- public NameService createNameService() {
- SimpleNameService ns = new SimpleNameService();
-
- // both providers know this host, but the address is different
- ns.put("blade", "10.0.0.1");
- // only this provider knows this host
- ns.put("blade.domain1", "10.0.0.2");
-
- return ns;
- }
-
- public String getProviderName() {
- return "sun";
- }
-
- public String getType() {
- return "simple1";
- }
-}
--- a/jdk/test/java/net/InetAddress/Simple2NameServiceDescriptor.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- */
-
-import sun.net.spi.nameservice.*;
-
-
-public class Simple2NameServiceDescriptor implements NameServiceDescriptor {
- public NameService createNameService() {
- SimpleNameService ns = new SimpleNameService();
- // both providers know this host, but the address of it is different
- ns.put("blade", "20.0.0.1");
- // only this provider knows this host
- ns.put("blade.domain2", "20.0.0.2");
-
- return ns;
- }
-
- public String getProviderName() {
- return "sun";
- }
-
- public String getType() {
- return "simple2";
- }
-}
--- a/jdk/test/java/net/InetAddress/SimpleNameService.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- */
-
-import java.net.*;
-import java.util.*;
-import sun.net.spi.nameservice.*;
-
-
-public class SimpleNameService implements NameService {
- // host name <-> host addr mapping
- private HashMap<String, String> hosts = new LinkedHashMap<String, String>();
-
- public void put(String host, String addr) {
- hosts.put(host, addr);
- }
-
- private static String addrToString(byte addr[]) {
- return Byte.toString(addr[0]) + "." +
- Byte.toString(addr[1]) + "." +
- Byte.toString(addr[2]) + "." +
- Byte.toString(addr[3]);
- }
-
- public SimpleNameService() {
- }
-
- public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
- String addr = hosts.get(host);
- if (addr == null) {
- throw new UnknownHostException(host);
- }
-
- StringTokenizer tokenizer = new StringTokenizer(addr, ".");
- byte addrs[] = new byte[4];
- for (int i = 0; i < 4; i++) {
- addrs[i] = (byte)Integer.parseInt(tokenizer.nextToken());
- }
- InetAddress[] ret = new InetAddress[1];
- ret[0] = InetAddress.getByAddress(host, addrs);
- return ret;
- }
-
- public String getHostByAddr(byte[] addr) throws UnknownHostException {
- String addrString = addrToString(addr);
- Iterator i = hosts.keySet().iterator();
- while (i.hasNext()) {
- String host = (String)i.next();
- String value = (String)hosts.get(host);
- if (value.equals(addrString)) {
- return host;
- }
- }
- throw new UnknownHostException();
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/NetworkInterface/Equals.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,65 @@
+/*
+ * 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 7003398
+ * @run main/othervm Equals
+ */
+import java.net.NetworkInterface;
+import java.net.InetAddress;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+public class Equals {
+
+ public static void main(String args[]) throws Exception {
+
+ Enumeration nifs1 = NetworkInterface.getNetworkInterfaces();
+ HashMap<String,Integer> hashes = new HashMap<>();
+ HashMap<String,NetworkInterface> nicMap = new HashMap<>();
+
+ while (nifs1.hasMoreElements()) {
+ NetworkInterface ni = (NetworkInterface)nifs1.nextElement();
+ hashes.put(ni.getName(),ni.hashCode());
+ nicMap.put(ni.getName(),ni);
+ }
+
+ System.setSecurityManager(new SecurityManager());
+
+ Enumeration nifs2 = NetworkInterface.getNetworkInterfaces();
+ while (nifs2.hasMoreElements()) {
+ NetworkInterface ni = (NetworkInterface)nifs2.nextElement();
+ NetworkInterface niOrig = nicMap.get(ni.getName());
+
+ int h = hashes.get(ni.getName());
+ if (h != ni.hashCode()) {
+ throw new RuntimeException ("Hashcodes different for " +
+ ni.getName());
+ }
+ if (!ni.equals(niOrig)) {
+ throw new RuntimeException ("equality different for " +
+ ni.getName());
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/Socks/SocksProxyVersion.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,98 @@
+/*
+ * 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 6964547
+ * @run main/othervm SocksProxyVersion
+ * @summary test socksProxyVersion system property
+ */
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+public class SocksProxyVersion implements Runnable {
+ ServerSocket ss;
+ volatile boolean failed;
+
+ public static void main(String[] args) throws Exception {
+ new SocksProxyVersion();
+ }
+
+ public SocksProxyVersion() throws Exception {
+ ss = new ServerSocket(0);
+ int port = ss.getLocalPort();
+ Thread serverThread = new Thread(this);
+ serverThread.start();
+
+ System.setProperty("socksProxyHost", "localhost");
+ System.setProperty("socksProxyPort", Integer.toString(port));
+
+ // SOCKS V4
+ System.setProperty("socksProxyVersion", Integer.toString(4));
+ try (Socket s = new Socket()) {
+ s.connect(new InetSocketAddress("localhost", port));
+ } catch (SocketException e) {
+ // java.net.SocketException: Malformed reply from SOCKS server
+ // This exception is OK, since the "server" does not implement
+ // the socks protocol. It just verifies the version and closes.
+ }
+
+ // SOCKS V5
+ System.setProperty("socksProxyVersion", Integer.toString(5));
+ try (Socket s = new Socket()) {
+ s.connect(new InetSocketAddress("localhost", port));
+ } catch (SocketException e) { /* OK */ }
+
+ serverThread.join();
+ if (failed) {
+ throw new RuntimeException("socksProxyVersion not being set correctly");
+ }
+ }
+
+ public void run() {
+ try (ss) {
+ Socket s = ss.accept();
+ int version = (s.getInputStream()).read();
+ if (version != 4) {
+ System.out.println("Got " + version + ", expected 4");
+ failed = true;
+ }
+ s.close();
+
+ s = ss.accept();
+ version = (s.getInputStream()).read();
+ if (version != 5) {
+ System.out.println("Got " + version + ", expected 5");
+ failed = true;
+ }
+ s.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/URLClassLoader/B6896088.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,130 @@
+/*
+ * 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 6896088
+ * @run main/othervm B6896088
+ * @summary URLClassLoader.close() apparently not working for JAR URLs on Windows
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.file.Path;
+
+public class B6896088 {
+
+ public static void main(String[] args) throws Exception {
+
+ String dir = System.getProperty ("test.classes");
+ File jarf = new File (dir, "foo.jar");
+ FileOutputStream fos = new FileOutputStream (jarf);
+ fos.write(bytes(nums));
+ fos.close();
+
+ // Create URL using JAR protocol
+ String jarName = (jarf.toURI()).toString();
+ URL url = new URL("jar", "", jarName + "!/");
+
+ // Create URLClassLoader from the URL
+ URLClassLoader loader = new URLClassLoader(new URL[]{url});
+ Class c = loader.loadClass("Foo");
+
+ // Close the URLClassLoader so we can delete/update the jar file
+ loader.close();
+
+ // Now try to delete the jar file
+
+ if (jarf.delete() && !jarf.exists()) {
+ System.out.println(jarf.getName()+" File Deleted");
+ } else {
+ System.out.println(jarf.getName()+" File Not Deleted");
+ throw new RuntimeException ("File not deleted");
+ }
+ }
+
+ static byte[] bytes (int[] i) {
+ byte[] buf = new byte [i.length];
+
+ for (int j=0; j<i.length; j++) {
+ buf[j] = (byte)i[j];
+ }
+ return buf;
+ }
+
+ /* contents of foo.jar */
+
+ static final int nums[] = {
+ 0x50,0x4b,0x03,0x04,0x14,0x00,0x08,0x08,0x08,0x00,0xc8,0x61,
+ 0x90,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x09,0x00,0x04,0x00,0x4d,0x45,0x54,0x41,0x2d,0x49,
+ 0x4e,0x46,0x2f,0xfe,0xca,0x00,0x00,0x03,0x00,0x50,0x4b,0x07,
+ 0x08,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x50,0x4b,0x03,0x04,0x14,0x00,0x08,0x08,0x08,0x00,0xc8,
+ 0x61,0x90,0x3d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x4d,0x45,0x54,0x41,0x2d,
+ 0x49,0x4e,0x46,0x2f,0x4d,0x41,0x4e,0x49,0x46,0x45,0x53,0x54,
+ 0x2e,0x4d,0x46,0xf3,0x4d,0xcc,0xcb,0x4c,0x4b,0x2d,0x2e,0xd1,
+ 0x0d,0x4b,0x2d,0x2a,0xce,0xcc,0xcf,0xb3,0x52,0x30,0xd4,0x33,
+ 0xe0,0xe5,0x72,0x2e,0x4a,0x4d,0x2c,0x49,0x4d,0xd1,0x75,0xaa,
+ 0x04,0x09,0x98,0xeb,0x19,0xe8,0x66,0xe6,0x95,0xa4,0x16,0xe5,
+ 0x25,0xe6,0x28,0x68,0xf8,0x17,0x25,0x26,0xe7,0xa4,0x2a,0x38,
+ 0xe7,0x17,0x15,0xe4,0x17,0x25,0x96,0x00,0x35,0x69,0xf2,0x72,
+ 0xf1,0x72,0x01,0x00,0x50,0x4b,0x07,0x08,0x4c,0xd8,0x5e,0x68,
+ 0x49,0x00,0x00,0x00,0x4a,0x00,0x00,0x00,0x50,0x4b,0x03,0x04,
+ 0x14,0x00,0x08,0x08,0x08,0x00,0xbd,0x61,0x90,0x3d,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x00,
+ 0x00,0x00,0x46,0x6f,0x6f,0x2e,0x63,0x6c,0x61,0x73,0x73,0x3b,
+ 0xf5,0x6f,0xd7,0x3e,0x06,0x06,0x06,0x63,0x06,0x5e,0x2e,0x06,
+ 0x66,0x06,0x2e,0x76,0x06,0x6e,0x76,0x06,0x1e,0x46,0x06,0x36,
+ 0x9b,0xcc,0xbc,0xcc,0x12,0x3b,0x46,0x06,0x66,0x0d,0xcd,0x30,
+ 0x46,0x06,0x16,0xe7,0xfc,0x94,0x54,0x46,0x06,0x7e,0x9f,0xcc,
+ 0xbc,0x54,0xbf,0xd2,0xdc,0xa4,0xd4,0xa2,0x90,0xc4,0xa4,0x1c,
+ 0xa0,0x08,0x57,0x70,0x7e,0x69,0x51,0x72,0xaa,0x5b,0x26,0x88,
+ 0xc3,0xe1,0x96,0x9f,0xaf,0x97,0x95,0x58,0x96,0xc8,0xc3,0xc0,
+ 0xc2,0xc0,0x0a,0xd4,0x0b,0xe4,0x33,0x32,0x08,0x80,0x44,0xf4,
+ 0x73,0x12,0xf3,0xd2,0xf5,0xfd,0x93,0xb2,0x52,0x93,0x4b,0x18,
+ 0x14,0x19,0x98,0x80,0x76,0x81,0x00,0x23,0x10,0x02,0x95,0x02,
+ 0x49,0x36,0x20,0x4f,0x16,0xcc,0x67,0x60,0x60,0xd5,0xda,0xce,
+ 0xc0,0xb8,0x11,0x2c,0xcd,0x0e,0x24,0xd9,0xc0,0x82,0x20,0x29,
+ 0x0e,0x20,0xcd,0xc4,0xc0,0x09,0x00,0x50,0x4b,0x07,0x08,0x3e,
+ 0x0a,0xdc,0x88,0x98,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x50,
+ 0x4b,0x01,0x02,0x14,0x00,0x14,0x00,0x08,0x08,0x08,0x00,0xc8,
+ 0x61,0x90,0x3d,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x09,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x45,0x54,
+ 0x41,0x2d,0x49,0x4e,0x46,0x2f,0xfe,0xca,0x00,0x00,0x50,0x4b,
+ 0x01,0x02,0x14,0x00,0x14,0x00,0x08,0x08,0x08,0x00,0xc8,0x61,
+ 0x90,0x3d,0x4c,0xd8,0x5e,0x68,0x49,0x00,0x00,0x00,0x4a,0x00,
+ 0x00,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x3d,0x00,0x00,0x00,0x4d,0x45,0x54,0x41,
+ 0x2d,0x49,0x4e,0x46,0x2f,0x4d,0x41,0x4e,0x49,0x46,0x45,0x53,
+ 0x54,0x2e,0x4d,0x46,0x50,0x4b,0x01,0x02,0x14,0x00,0x14,0x00,
+ 0x08,0x08,0x08,0x00,0xbd,0x61,0x90,0x3d,0x3e,0x0a,0xdc,0x88,
+ 0x98,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x09,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x00,
+ 0x00,0x00,0x46,0x6f,0x6f,0x2e,0x63,0x6c,0x61,0x73,0x73,0x50,
+ 0x4b,0x05,0x06,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0xb4,
+ 0x00,0x00,0x00,0x97,0x01,0x00,0x00,0x00,0x00,0x00
+ };
+}
--- a/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/net/URLClassLoader/closetest/CloseTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -36,94 +36,7 @@
import java.lang.reflect.*;
import com.sun.net.httpserver.*;
-public class CloseTest {
-
- static void copyFile (String src, String dst) {
- copyFile (new File(src), new File(dst));
- }
-
- static void copyDir (String src, String dst) {
- copyDir (new File(src), new File(dst));
- }
-
- static void copyFile (File src, File dst) {
- try {
- if (!src.isFile()) {
- throw new RuntimeException ("File not found: " + src.toString());
- }
- dst.delete();
- dst.createNewFile();
- FileInputStream i = new FileInputStream (src);
- FileOutputStream o = new FileOutputStream (dst);
- byte[] buf = new byte [1024];
- int count;
- while ((count=i.read(buf)) >= 0) {
- o.write (buf, 0, count);
- }
- i.close();
- o.close();
- } catch (IOException e) {
- throw new RuntimeException (e);
- }
- }
-
- static void rm_minus_rf (File path) {
- if (!path.exists()) {
- return;
- }
- if (path.isFile()) {
- if (!path.delete()) {
- throw new RuntimeException ("Could not delete " + path);
- }
- } else if (path.isDirectory ()) {
- String[] names = path.list();
- File[] files = path.listFiles();
- for (int i=0; i<files.length; i++) {
- rm_minus_rf (new File(path, names[i]));
- }
- if (!path.delete()) {
- throw new RuntimeException ("Could not delete " + path);
- }
- } else {
- throw new RuntimeException ("Trying to delete something that isn't a file or a directory");
- }
- }
-
- static void copyDir (File src, File dst) {
- if (!src.isDirectory()) {
- throw new RuntimeException ("Dir not found: " + src.toString());
- }
- if (dst.exists()) {
- throw new RuntimeException ("Dir exists: " + dst.toString());
- }
- dst.mkdir();
- String[] names = src.list();
- File[] files = src.listFiles();
- for (int i=0; i<files.length; i++) {
- String f = names[i];
- if (files[i].isDirectory()) {
- copyDir (files[i], new File (dst, f));
- } else {
- copyFile (new File (src, f), new File (dst, f));
- }
- }
- }
-
- /* expect is true if you expect to find it, false if you expect not to */
- static Class loadClass (String name, URLClassLoader loader, boolean expect){
- try {
- Class clazz = Class.forName (name, true, loader);
- if (!expect) {
- throw new RuntimeException ("loadClass: "+name+" unexpected");
- }
- return clazz;
- } catch (ClassNotFoundException e) {
- if (expect) {
- throw new RuntimeException ("loadClass: " +name + " not found");
- }
- }
- return null;
- }
+public class CloseTest extends Common {
//
// needs two jar files test1.jar and test2.jar with following structure
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/URLClassLoader/closetest/Common.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+import java.io.*;
+import java.net.*;
+
+public class Common {
+
+ static void copyFile (String src, String dst) {
+ copyFile (new File(src), new File(dst));
+ }
+
+ static void copyDir (String src, String dst) {
+ copyDir (new File(src), new File(dst));
+ }
+
+ static void copyFile (File src, File dst) {
+ try {
+ if (!src.isFile()) {
+ throw new RuntimeException ("File not found: " + src.toString());
+ }
+ dst.delete();
+ dst.createNewFile();
+ FileInputStream i = new FileInputStream (src);
+ FileOutputStream o = new FileOutputStream (dst);
+ byte[] buf = new byte [1024];
+ int count;
+ while ((count=i.read(buf)) >= 0) {
+ o.write (buf, 0, count);
+ }
+ i.close();
+ o.close();
+ } catch (IOException e) {
+ throw new RuntimeException (e);
+ }
+ }
+
+ static void rm_minus_rf (File path) {
+ if (!path.exists()) {
+ return;
+ }
+ if (path.isFile()) {
+ if (!path.delete()) {
+ throw new RuntimeException ("Could not delete " + path);
+ }
+ } else if (path.isDirectory ()) {
+ String[] names = path.list();
+ File[] files = path.listFiles();
+ for (int i=0; i<files.length; i++) {
+ rm_minus_rf (new File(path, names[i]));
+ }
+ if (!path.delete()) {
+ throw new RuntimeException ("Could not delete " + path);
+ }
+ } else {
+ throw new RuntimeException ("Trying to delete something that isn't a file or a directory");
+ }
+ }
+
+ static void copyDir (File src, File dst) {
+ if (!src.isDirectory()) {
+ throw new RuntimeException ("Dir not found: " + src.toString());
+ }
+ if (dst.exists()) {
+ throw new RuntimeException ("Dir exists: " + dst.toString());
+ }
+ dst.mkdir();
+ String[] names = src.list();
+ File[] files = src.listFiles();
+ for (int i=0; i<files.length; i++) {
+ String f = names[i];
+ if (files[i].isDirectory()) {
+ copyDir (files[i], new File (dst, f));
+ } else {
+ copyFile (new File (src, f), new File (dst, f));
+ }
+ }
+ }
+
+ /* expect is true if you expect to find it, false if you expect not to */
+ static Class loadClass (String name, URLClassLoader loader, boolean expect){
+ try {
+ Class clazz = Class.forName (name, true, loader);
+ if (!expect) {
+ throw new RuntimeException ("loadClass: "+name+" unexpected");
+ }
+ return clazz;
+ } catch (ClassNotFoundException e) {
+ if (expect) {
+ throw new RuntimeException ("loadClass: " +name + " not found");
+ }
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/URLClassLoader/closetest/GetResourceAsStream.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,108 @@
+/*
+ * 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 6899919
+ * @run shell build2.sh
+ * @run main/othervm GetResourceAsStream
+ */
+
+import java.io.*;
+import java.net.*;
+
+public class GetResourceAsStream extends Common {
+
+/*
+ * We simply test various scenarios with class/resource files
+ * and make sure the files can be deleted after closing
+ * the loader. Therefore, the test will only really be verified
+ * on Windows. It will still run correctly on other platforms
+ */
+ public static void main (String args[]) throws Exception {
+
+ String workdir = System.getProperty("test.classes");
+ if (workdir == null) {
+ workdir = args[0];
+ }
+
+ /* the jar we copy for each test */
+ File srcfile = new File (workdir, "foo.jar");
+
+ /* the jar we use for the test */
+ File testfile = new File (workdir, "test.jar");
+
+ copyFile (srcfile, testfile);
+ test (testfile, false, false);
+
+ copyFile (srcfile, testfile);
+ test (testfile, true, false);
+
+ copyFile (srcfile, testfile);
+ test (testfile, true, true);
+
+ // repeat test using a directory of files
+
+ File testdir= new File (workdir, "testdir");
+ File srcdir= new File (workdir, "test3");
+
+ copyDir (srcdir, testdir);
+ test (testdir, true, false);
+
+ }
+
+ // create a loader on jarfile (or directory)
+ // load a class , then look for a resource
+ // then close the loader
+ // check further new classes/resources cannot be loaded
+ // check jar (or dir) can be deleted
+
+ static void test (File file, boolean loadclass, boolean readall)
+ throws Exception
+ {
+ URL[] urls = new URL[] {file.toURL()};
+ System.out.println ("Doing tests with URL: " + urls[0]);
+ URLClassLoader loader = new URLClassLoader (urls);
+ if (loadclass) {
+ Class testclass = loadClass ("com.foo.TestClass", loader, true);
+ }
+ InputStream s = loader.getResourceAsStream ("hello.txt");
+ s.read();
+ if (readall) {
+ while (s.read() != -1) ;
+ s.close();
+ }
+
+ loader.close ();
+
+ // shouuld not find bye.txt now
+ InputStream s1 = loader.getResourceAsStream("bye.txt");
+ if (s1 != null) {
+ throw new RuntimeException ("closed loader returned resource");
+ }
+
+ // now check we can delete the path
+ rm_minus_rf (file);
+ System.out.println (" ... OK");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/URLClassLoader/closetest/build2.sh Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# 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.
+#
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTSRC=${TESTSRC}"
+
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+
+JAVAC="${TESTJAVA}/bin/javac"
+JAR="${TESTJAVA}/bin/jar"
+
+rm -rf ${TESTCLASSES}/test3
+mkdir -p ${TESTCLASSES}/test3
+
+echo "Hello world" > ${TESTCLASSES}/test3/hello.txt
+echo "Bye world" > ${TESTCLASSES}/test3/bye.txt
+cp ${TESTSRC}/test1/com/foo/TestClass.java ${TESTCLASSES}/test3
+cd ${TESTCLASSES}/test3
+${JAVAC} -d . TestClass.java
+
+${JAR} cvf foo.jar hello.txt bye.txt com/foo/TestClass.class
+rm -f ../foo.jar
+mv foo.jar ..
--- a/jdk/test/java/util/Formatter/Constructors.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/Formatter/Constructors.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4981811 4984465 5064492 6240171
+ * @bug 4981811 4984465 5064492 6240171 7000511
* @summary Unit test for all constructors introduced by the formatter feature
*/
@@ -85,10 +85,8 @@
}
public static void main(String [] args) {
-
// Formatter()
- try {
- Formatter f = new Formatter();
+ try (Formatter f = new Formatter()) {
pass();
out(f, StringBuilder.class);
locale(f);
@@ -97,8 +95,7 @@
}
// Formatter(Appendable a)
- try {
- Formatter f = new Formatter((Appendable) null);
+ try (Formatter f = new Formatter((Appendable) null)) {
pass();
out(f, StringBuilder.class);
locale(f);
@@ -107,8 +104,7 @@
}
// Formatter(Locale l)
- try {
- Formatter f = new Formatter((Locale) null);
+ try (Formatter f = new Formatter((Locale) null)) {
pass();
out(f, StringBuilder.class);
locale(f, null);
@@ -117,8 +113,7 @@
}
// Formatter(Appendable a, Locale l)
- try {
- Formatter f = new Formatter((Appendable) null, (Locale) null);
+ try (Formatter f = new Formatter((Appendable) null, (Locale) null)) {
pass();
out(f, StringBuilder.class);
locale(f, null);
@@ -127,8 +122,7 @@
}
// Formatter(String fileName)
- try {
- Formatter f = new Formatter("foo");
+ try (Formatter f = new Formatter("foo")) {
pass();
out(f, BufferedWriter.class);
locale(f);
@@ -137,7 +131,7 @@
}
try {
- Formatter f = new Formatter((String)null);
+ new Formatter((String)null);
fail("new Formatter((String)null)");
} catch (NullPointerException x) {
pass();
@@ -146,8 +140,7 @@
}
// Formatter(String fileName, String csn)
- try {
- Formatter f = new Formatter("foo", "UTF-8");
+ try (Formatter f = new Formatter("foo", "UTF-8")) {
pass();
out(f, BufferedWriter.class);
locale(f);
@@ -167,15 +160,14 @@
try {
new Formatter(".", "bar");
fail("new Formatter(\".\", \"bar\")");
- } catch (FileNotFoundException x) {
+ } catch (FileNotFoundException|UnsupportedEncodingException x) {
pass();
} catch (Exception x) {
fail("new Formatter(\".\", \"bar\")", x);
}
// Formatter(String fileName, String csn, Locale l)
- try {
- Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY);
+ try (Formatter f = new Formatter("foo", "ISO-8859-1", Locale.GERMANY)) {
pass();
out(f, BufferedWriter.class);
locale(f, Locale.GERMANY);
@@ -183,8 +175,7 @@
fail("new Formatter(\"foo\", \"ISO-8859-1\", Locale.GERMANY)", x);
}
- try {
- Formatter f = new Formatter("foo", "ISO-8859-1", null);
+ try (Formatter f = new Formatter("foo", "ISO-8859-1", null)) {
pass();
locale(f, null);
out(f, BufferedWriter.class);
@@ -193,8 +184,7 @@
}
// Formatter(File)
- try {
- Formatter f = new Formatter(new File("foo"));
+ try (Formatter f = new Formatter(new File("foo"))) {
pass();
locale(f);
out(f, BufferedWriter.class);
@@ -203,7 +193,7 @@
}
try {
- Formatter f = new Formatter((File)null);
+ new Formatter((File)null);
fail("new Formatter((File)null)");
} catch (NullPointerException x) {
pass();
@@ -231,8 +221,7 @@
fail("new Formatter((PrintStream) null)", x);
}
- try {
- Formatter f = new Formatter(new PrintStream("foo"));
+ try (Formatter f = new Formatter(new PrintStream("foo"))) {
pass();
locale(f);
out(f, PrintStream.class);
@@ -242,9 +231,8 @@
fail("new Formatter(new PrintStream(\"foo\")", x);
}
- try {
- Formatter f = new Formatter(new PrintStream("foo"),
- Locale.JAPANESE);
+ try (Formatter f = new Formatter(new PrintStream("foo"),
+ Locale.JAPANESE)) {
pass();
locale(f, Locale.JAPANESE);
out(f, PrintStream.class);
@@ -254,12 +242,11 @@
fail("new Formatter(new PrintStream(\"foo\")", x);
}
- try {
+ try (PrintStream ps = new PrintStream("foo")) {
// The cast here is necessary to avoid an ambiguity error
// between Formatter(Appendable a, Locale l)
- // and Formatter(OutputStream os, String csn)
- Formatter f = new Formatter(new PrintStream("foo"),
- (String)null);
+ // and Formatter(OutputStream os, String csn)
+ new Formatter(ps, (String)null);
fail("new Formatter(new PrintStream(\"foo\"), (String)null)");
} catch (FileNotFoundException x) {
fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x);
@@ -271,12 +258,11 @@
fail("new Formatter(new PrintStream(\"foo\"), (String)null)", x);
}
- try {
- // The cast here is necessary to avoid an ambiguity error
- // between Formatter(Appendable a, Locale l)
- // and Formatter(OutputStream os, String csn)
- Formatter f = new Formatter(new PrintStream("foo"),
- (Locale)null);
+ // The cast here is necessary to avoid an ambiguity error
+ // between Formatter(Appendable a, Locale l)
+ // and Formatter(OutputStream os, String csn)
+ try (Formatter f = new Formatter(new PrintStream("foo"),
+ (Locale)null)) {
pass();
locale(f, null);
out(f, PrintStream.class);
@@ -286,9 +272,8 @@
fail("new Formatter(new PrintStream(\"foo\"), (Locale)null)", x);
}
- try {
- Formatter f = new Formatter(new PrintStream("foo"),
- Locale.KOREAN);
+ try (Formatter f = new Formatter(new PrintStream("foo"),
+ Locale.KOREAN)) {
pass();
locale(f, Locale.KOREAN);
out(f, PrintStream.class);
@@ -298,9 +283,8 @@
fail("new Formatter(new PrintStream(\"foo\"), Locale.KOREAN)", x);
}
- try {
- Formatter f = new Formatter(new PrintStream("foo"),
- "UTF-16BE", null);
+ try (Formatter f = new Formatter(new PrintStream("foo"),
+ "UTF-16BE", null)) {
pass();
locale(f, null);
out(f, BufferedWriter.class);
@@ -312,9 +296,8 @@
fail("new Formatter(new PrintStream(\"foo\"), \"UTF-16BE\", null");
}
- try {
- Formatter f = new Formatter(new PrintStream("foo"),
- "UTF-16BE", Locale.ITALIAN);
+ try (Formatter f = new Formatter(new PrintStream("foo"),
+ "UTF-16BE", Locale.ITALIAN)) {
pass();
locale(f, Locale.ITALIAN);
out(f, BufferedWriter.class);
@@ -361,8 +344,7 @@
fail("new Formatter((OutputStream) null)", x);
}
- try {
- Formatter f = new Formatter((OutputStream) new PrintStream("foo"));
+ try (Formatter f = new Formatter((OutputStream) new PrintStream("foo"))) {
pass();
locale(f);
out(f, BufferedWriter.class);
@@ -380,8 +362,8 @@
fail("new Formatter((OutputStream) null, \"ISO-8859-1\")", x);
}
- try {
- new Formatter((OutputStream) new PrintStream("foo"), null);
+ try (PrintStream ps = new PrintStream("foo")) {
+ new Formatter((OutputStream) ps, null);
fail("new Formatter((OutputStream) new PrintStream(\"foo\"), null");
} catch (NullPointerException x) {
pass();
@@ -390,8 +372,8 @@
x);
}
- try {
- new Formatter(new PrintStream("foo"), "bar");
+ try (PrintStream ps = new PrintStream("foo")) {
+ new Formatter(ps, "bar");
fail("new Formatter(new PrintStream(\"foo\"), \"bar\")");
} catch (UnsupportedEncodingException x) {
pass();
@@ -399,8 +381,7 @@
fail("new Formatter(new PrintStream(\"foo\"), \"bar\")", x);
}
- try {
- Formatter f = new Formatter(new PrintStream("foo"), "UTF-8");
+ try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8")) {
pass();
locale(f);
out(f, BufferedWriter.class);
@@ -419,8 +400,8 @@
x);
}
- try {
- new Formatter(new PrintStream("foo"), null, Locale.UK);
+ try (PrintStream ps = new PrintStream("foo")) {
+ new Formatter(ps, null, Locale.UK);
fail("new Formatter(new PrintStream(\"foo\"), null, Locale.UK)");
} catch (NullPointerException x) {
pass();
@@ -429,8 +410,8 @@
x);
}
- try {
- new Formatter(new PrintStream("foo"), "bar", Locale.UK);
+ try (PrintStream ps = new PrintStream("foo")) {
+ new Formatter(ps, "bar", Locale.UK);
fail("new Formatter(new PrintStream(\"foo\"), \"bar\", Locale.UK)");
} catch (UnsupportedEncodingException x) {
pass();
@@ -439,9 +420,7 @@
x);
}
- try {
- Formatter f
- = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK);
+ try (Formatter f = new Formatter(new PrintStream("foo"), "UTF-8", Locale.UK)) {
pass();
out(f, BufferedWriter.class);
locale(f, Locale.UK);
@@ -451,8 +430,7 @@
}
// PrintStream(String fileName)
- try {
- new PrintStream("foo");
+ try (PrintStream ps = new PrintStream("foo")) {
pass();
} catch (Exception x) {
fail("new PrintStream(\"foo\")", x);
@@ -469,8 +447,7 @@
}
// PrintStream(File file)
- try {
- new PrintStream(new File("foo"));
+ try (PrintStream ps = new PrintStream(new File("foo"))) {
pass();
} catch (Exception x) {
fail("new PrintStream(new File(\"foo\"))", x);
@@ -487,8 +464,7 @@
}
// PrintWriter(String fileName)
- try {
- new PrintWriter("foo");
+ try (PrintWriter pw = new PrintWriter("foo")) {
pass();
} catch (Exception x) {
fail("new PrintWriter(\"foo\")", x);
@@ -505,8 +481,7 @@
}
// PrintWriter(File file)
- try {
- new PrintWriter(new File("foo"));
+ try (PrintWriter pw = new PrintWriter(new File("foo"))) {
pass();
} catch (Exception x) {
fail("new PrintWriter(new File(\"foo\"))", x);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Formatter/FailingConstructors.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,133 @@
+/*
+ * 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 7000511
+ * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when
+ * exception thrown
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Formatter;
+
+public class FailingConstructors {
+ static final String fileName = "FailingConstructorsTest";
+ static final String UNSUPPORTED_CHARSET = "unknownCharset";
+ static final String FILE_CONTENTS = "This is a small file!";
+
+ private static void realMain(String[] args) throws Throwable {
+ test(false, new File(fileName));
+
+ /* create the file and write its contents */
+ File file = File.createTempFile(fileName, null);
+ file.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(FILE_CONTENTS.getBytes());
+ fos.close();
+
+ test(true, file);
+ file.delete();
+ }
+
+ private static void test(boolean exists, File file) throws Throwable {
+ /* Formatter(File file, String csn) */
+ try {
+ new Formatter(file, UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|UnsupportedEncodingException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new Formatter(file, null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ /* Formatter(String fileName, String csn) */
+ try {
+ new Formatter(file.getName(), UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|UnsupportedEncodingException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new Formatter(file.getName(), null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+ }
+
+ private static void check(boolean exists, File file) {
+ if (exists) {
+ /* the file should be unchanged */
+ verifyContents(file);
+ } else {
+ /* the file should not have been created */
+ if (file.exists()) { fail(file + " should not have been created"); }
+ }
+ }
+
+ private static void verifyContents(File file) {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ byte[] contents = FILE_CONTENTS.getBytes();
+ int read, count = 0;
+ while ((read = fis.read()) != -1) {
+ if (read != contents[count++]) {
+ fail("file contents have been altered");
+ return;
+ }
+ }
+ } catch (IOException ioe) {
+ unexpected(ioe);
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String message) {System.out.println(message); fail(); }
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Scanner/FailingConstructors.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,132 @@
+/*
+ * 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 7000511
+ * @summary PrintStream, PrintWriter, Formatter, Scanner leave files open when
+ * exception thrown
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Scanner;
+
+public class FailingConstructors {
+ static final String fileName = "FailingConstructorsTest";
+ static final String UNSUPPORTED_CHARSET = "unknownCharset";
+ static final String FILE_CONTENTS = "This is a small file!";
+
+ private static void realMain(String[] args) throws Throwable {
+ test(false, new File(fileName));
+
+ /* create the file and write its contents */
+ File file = File.createTempFile(fileName, null);
+ file.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(file);
+ fos.write(FILE_CONTENTS.getBytes());
+ fos.close();
+
+ test(true, file);
+ file.delete();
+ }
+
+ private static void test(boolean exists, File file) throws Throwable {
+ /* Scanner(File source, String charsetName) */
+ try {
+ new Scanner(file, UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|IllegalArgumentException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new Scanner(file, null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ /* Scanner(FileRef source, String charsetName) */
+ try {
+ new Scanner(file.toPath(), UNSUPPORTED_CHARSET);
+ fail();
+ } catch(FileNotFoundException|IllegalArgumentException e) {
+ pass();
+ }
+
+ check(exists, file);
+
+ try {
+ new Scanner(file.toPath(), null);
+ fail();
+ } catch(FileNotFoundException|NullPointerException e) {
+ pass();
+ }
+
+ check(exists, file);
+ }
+
+ private static void check(boolean exists, File file) {
+ if (exists) {
+ /* the file should be unchanged */
+ verifyContents(file);
+ } else {
+ /* the file should not have been created */
+ if (file.exists()) { fail(file + " should not have been created"); }
+ }
+ }
+
+ private static void verifyContents(File file) {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ byte[] contents = FILE_CONTENTS.getBytes();
+ int read, count = 0;
+ while ((read = fis.read()) != -1) {
+ if (read != contents[count++]) {
+ fail("file contents have been altered");
+ return;
+ }
+ }
+ } catch (IOException ioe) {
+ unexpected(ioe);
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String message) {System.out.println(message); fail(); }
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java Fri Feb 18 12:04:36 2011 -0800
@@ -33,18 +33,17 @@
import java.util.concurrent.CountDownLatch;
public class GCDuringIteration {
- static void finalizeTillYouDrop() {
- System.gc(); // Enqueue all finalizables
-
- System.runFinalization(); // Drain finalizer queue
+ private static void waitForFinalizersToRun() {
+ for (int i = 0; i < 2; i++)
+ tryWaitForFinalizersToRun();
+ }
- // There may be a straggler finalizable object still being
- // finalized by the dedicated finalizer thread. Enqueue one
- // more finalizable object, and wait for it to be finalized.
- final CountDownLatch latch = new CountDownLatch(1);
- new Object() { protected void finalize() { latch.countDown(); }};
+ private static void tryWaitForFinalizersToRun() {
System.gc();
- try { latch.await(); }
+ final CountDownLatch fin = new CountDownLatch(1);
+ new Object() { protected void finalize() { fin.countDown(); }};
+ System.gc();
+ try { fin.await(); }
catch (InterruptedException ie) { throw new Error(ie); }
}
@@ -101,7 +100,9 @@
{
int first = firstValue(map);
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
- foos[first] = null; finalizeTillYouDrop();
+ foos[first] = null;
+ for (int i = 0; i < 10 && map.size() != first; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), first);
checkIterator(it, first-1);
equal(map.size(), first);
@@ -113,11 +114,14 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
- foos[first] = null; finalizeTillYouDrop();
+ foos[first] = null;
+ tryWaitForFinalizersToRun()
equal(map.size(), first+1);
System.out.println(map.values());
checkIterator(it, first-1);
- finalizeTillYouDrop(); // first entry no longer protected
+ // first entry no longer protected
+ for (int i = 0; i < 10 && map.size() != first; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), first);
equal(firstValue(map), first-1);
}
@@ -127,12 +131,15 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
- foos[first] = foos[first-1] = null; finalizeTillYouDrop();
+ foos[first] = foos[first-1] = null;
+ tryWaitForFinalizersToRun();
equal(map.size(), first);
equal(firstValue(map), first);
System.out.println(map.values());
checkIterator(it, first-2);
- finalizeTillYouDrop(); // first entry no longer protected
+ // first entry no longer protected
+ for (int i = 0; i < 10 && map.size() != first-1; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), first-1);
equal(firstValue(map), first-2);
}
@@ -143,12 +150,15 @@
it.next(); // protects first entry
it.hasNext(); // protects second entry
System.out.println(map.values());
- foos[first] = foos[first-1] = null; finalizeTillYouDrop();
+ foos[first] = foos[first-1] = null;
+ tryWaitForFinalizersToRun();
equal(firstValue(map), first);
equal(map.size(), first+1);
System.out.println(map.values());
checkIterator(it, first-1);
- finalizeTillYouDrop(); // first entry no longer protected
+ // first entry no longer protected
+ for (int i = 0; i < 10 && map.size() != first-1; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), first-1);
equal(firstValue(map), first-2);
}
@@ -158,13 +168,16 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.next(); // protects first entry
System.out.println(map.values());
- foos[first] = foos[first-1] = null; finalizeTillYouDrop();
+ foos[first] = foos[first-1] = null;
+ tryWaitForFinalizersToRun();
it.remove();
equal(firstValue(map), first-2);
equal(map.size(), first-1);
System.out.println(map.values());
checkIterator(it, first-2);
- finalizeTillYouDrop();
+ // first entry no longer protected
+ for (int i = 0; i < 10 && map.size() != first-1; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), first-1);
equal(firstValue(map), first-2);
}
@@ -176,12 +189,14 @@
it.remove();
it.hasNext(); // protects second entry
System.out.println(map.values());
- foos[first] = foos[first-1] = null; finalizeTillYouDrop();
+ foos[first] = foos[first-1] = null;
+ tryWaitForFinalizersToRun();
equal(firstValue(map), first-1);
equal(map.size(), first);
System.out.println(map.values());
checkIterator(it, first-1);
- finalizeTillYouDrop();
+ for (int i = 0; i < 10 && map.size() != first-1; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), first-1);
equal(firstValue(map), first-2);
}
@@ -191,12 +206,13 @@
final Iterator<Map.Entry<Foo,Integer>> it = map.entrySet().iterator();
it.hasNext(); // protects first entry
Arrays.fill(foos, null);
- finalizeTillYouDrop();
+ tryWaitForFinalizersToRun();
equal(map.size(), 1);
System.out.println(map.values());
equal(it.next().getValue(), first);
check(! it.hasNext());
- finalizeTillYouDrop();
+ for (int i = 0; i < 10 && map.size() != 0; i++)
+ tryWaitForFinalizersToRun();
equal(map.size(), 0);
check(map.isEmpty());
}
--- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java Fri Feb 18 12:04:36 2011 -0800
@@ -34,7 +34,7 @@
/*
* @test
* @bug 4486658
- * @compile CancelledProducerConsumerLoops.java
+ * @compile -source 1.5 CancelledProducerConsumerLoops.java
* @run main/timeout=7000 CancelledProducerConsumerLoops
* @summary Checks for responsiveness of blocking queues to cancellation.
* Runs under the assumption that ITERS computations require more than
@@ -119,48 +119,24 @@
}
}
- static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
- LTQasSQ() { super(); }
- public void put(T x) {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- private final static long serialVersionUID = 42;
- }
-
- static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
- HalfSyncLTQ() { super(); }
- public void put(T x) {
- if (ThreadLocalRandom.current().nextBoolean())
- super.put(x);
- else {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- }
- private final static long serialVersionUID = 42;
- }
-
static void oneTest(int pairs, int iters) throws Exception {
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
+ oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
oneRun(new SynchronousQueue<Integer>(), pairs, iters / 8);
- /* TODO: unbounded queue implementations are prone to OOME
+ /* PriorityBlockingQueue is unbounded
oneRun(new PriorityBlockingQueue<Integer>(iters / 2 * pairs), pairs, iters / 4);
- oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
- oneRun(new LTQasSQ<Integer>(), pairs, iters);
- oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
*/
}
- static abstract class Stage implements Callable<Integer> {
+ abstract static class Stage implements Callable<Integer> {
final BlockingQueue<Integer> queue;
final CyclicBarrier barrier;
final int iters;
- Stage (BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
+ Stage(BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
queue = q;
barrier = b;
this.iters = iters;
--- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java Fri Feb 18 12:04:36 2011 -0800
@@ -34,7 +34,7 @@
/*
* @test
* @bug 4486658
- * @compile MultipleProducersSingleConsumerLoops.java
+ * @compile -source 1.5 MultipleProducersSingleConsumerLoops.java
* @run main/timeout=3600 MultipleProducersSingleConsumerLoops
* @summary multiple producers and single consumer using blocking queues
*/
@@ -87,35 +87,11 @@
throw new Error();
}
- static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
- LTQasSQ() { super(); }
- public void put(T x) {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- private final static long serialVersionUID = 42;
- }
-
- static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
- HalfSyncLTQ() { super(); }
- public void put(T x) {
- if (ThreadLocalRandom.current().nextBoolean())
- super.put(x);
- else {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- }
- private final static long serialVersionUID = 42;
- }
-
static void oneTest(int producers, int iters) throws Exception {
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), producers, iters);
oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), producers, iters);
oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), producers, iters);
oneRun(new LinkedTransferQueue<Integer>(), producers, iters);
- oneRun(new LTQasSQ<Integer>(), producers, iters);
- oneRun(new HalfSyncLTQ<Integer>(), producers, iters);
// Don't run PBQ since can legitimately run out of memory
// if (print)
@@ -129,11 +105,11 @@
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY, true), producers, iters);
}
- static abstract class Stage implements Runnable {
+ abstract static class Stage implements Runnable {
final int iters;
final BlockingQueue<Integer> queue;
final CyclicBarrier barrier;
- Stage (BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
+ Stage(BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
queue = q;
barrier = b;
this.iters = iters;
--- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java Fri Feb 18 12:04:36 2011 -0800
@@ -34,7 +34,7 @@
/*
* @test
* @bug 4486658
- * @compile ProducerConsumerLoops.java
+ * @compile -source 1.5 ProducerConsumerLoops.java
* @run main/timeout=3600 ProducerConsumerLoops
* @summary multiple producers and consumers using blocking queues
*/
@@ -87,35 +87,11 @@
throw new Error();
}
- static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
- LTQasSQ() { super(); }
- public void put(T x) {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- private final static long serialVersionUID = 42;
- }
-
- static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
- HalfSyncLTQ() { super(); }
- public void put(T x) {
- if (ThreadLocalRandom.current().nextBoolean())
- super.put(x);
- else {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- }
- private final static long serialVersionUID = 42;
- }
-
static void oneTest(int pairs, int iters) throws Exception {
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), pairs, iters);
oneRun(new LinkedTransferQueue<Integer>(), pairs, iters);
- oneRun(new LTQasSQ<Integer>(), pairs, iters);
- oneRun(new HalfSyncLTQ<Integer>(), pairs, iters);
oneRun(new PriorityBlockingQueue<Integer>(), pairs, iters);
oneRun(new SynchronousQueue<Integer>(), pairs, iters);
@@ -126,11 +102,11 @@
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY, true), pairs, iters);
}
- static abstract class Stage implements Runnable {
+ abstract static class Stage implements Runnable {
final int iters;
final BlockingQueue<Integer> queue;
final CyclicBarrier barrier;
- Stage (BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
+ Stage(BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
queue = q;
barrier = b;
this.iters = iters;
--- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java Fri Feb 18 12:04:36 2011 -0800
@@ -34,7 +34,7 @@
/*
* @test
* @bug 4486658
- * @compile SingleProducerMultipleConsumerLoops.java
+ * @compile -source 1.5 SingleProducerMultipleConsumerLoops.java
* @run main/timeout=600 SingleProducerMultipleConsumerLoops
* @summary check ordering for blocking queues with 1 producer and multiple consumers
*/
@@ -73,35 +73,11 @@
throw new Error();
}
- static final class LTQasSQ<T> extends LinkedTransferQueue<T> {
- LTQasSQ() { super(); }
- public void put(T x) {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- private final static long serialVersionUID = 42;
- }
-
- static final class HalfSyncLTQ<T> extends LinkedTransferQueue<T> {
- HalfSyncLTQ() { super(); }
- public void put(T x) {
- if (ThreadLocalRandom.current().nextBoolean())
- super.put(x);
- else {
- try { super.transfer(x); }
- catch (InterruptedException ex) { throw new Error(); }
- }
- }
- private final static long serialVersionUID = 42;
- }
-
static void oneTest(int consumers, int iters) throws Exception {
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY), consumers, iters);
oneRun(new LinkedBlockingQueue<Integer>(CAPACITY), consumers, iters);
oneRun(new LinkedBlockingDeque<Integer>(CAPACITY), consumers, iters);
oneRun(new LinkedTransferQueue<Integer>(), consumers, iters);
- oneRun(new LTQasSQ<Integer>(), consumers, iters);
- oneRun(new HalfSyncLTQ<Integer>(), consumers, iters);
oneRun(new PriorityBlockingQueue<Integer>(), consumers, iters);
oneRun(new SynchronousQueue<Integer>(), consumers, iters);
if (print)
@@ -110,12 +86,12 @@
oneRun(new ArrayBlockingQueue<Integer>(CAPACITY, true), consumers, iters);
}
- static abstract class Stage implements Runnable {
+ abstract static class Stage implements Runnable {
final int iters;
final BlockingQueue<Integer> queue;
final CyclicBarrier barrier;
volatile int result;
- Stage (BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
+ Stage(BlockingQueue<Integer> q, CyclicBarrier b, int iters) {
queue = q;
barrier = b;
this.iters = iters;
--- a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java Fri Feb 18 12:04:36 2011 -0800
@@ -53,7 +53,9 @@
test(new LinkedTransferQueue());
// Other concurrent queues (e.g. ArrayBlockingQueue) do not
// currently have weakly consistent iterators.
- // test(new ArrayBlockingQueue(20));
+ // As of 2010-09, ArrayBlockingQueue passes this test, but
+ // does not fully implement weak consistency.
+ test(new ArrayBlockingQueue(20));
}
void test(Queue q) {
--- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Fri Feb 18 12:04:36 2011 -0800
@@ -24,6 +24,7 @@
/*
* @test
* @bug 6399443
+ * @run main/othervm AutoShutdown
* @summary Check for auto-shutdown and gc of singleThreadExecutors
* @author Martin Buchholz
*/
--- a/jdk/test/java/util/concurrent/Phaser/Basic.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/Phaser/Basic.java Fri Feb 18 12:04:36 2011 -0800
@@ -52,15 +52,16 @@
check(phaser.isTerminated());
int unarriverParties = phaser.getUnarrivedParties();
int registeredParties = phaser.getRegisteredParties();
- equal(phaser.arrive(), -1);
- equal(phaser.arriveAndDeregister(), -1);
- equal(phaser.arriveAndAwaitAdvance(), -1);
- equal(phaser.bulkRegister(10), -1);
- equal(phaser.getPhase(), -1);
- equal(phaser.register(), -1);
+ int phase = phaser.getPhase();
+ check(phase < 0);
+ equal(phase, phaser.arrive());
+ equal(phase, phaser.arriveAndDeregister());
+ equal(phase, phaser.arriveAndAwaitAdvance());
+ equal(phase, phaser.bulkRegister(10));
+ equal(phase, phaser.register());
try {
- equal(phaser.awaitAdvanceInterruptibly(0), -1);
- equal(phaser.awaitAdvanceInterruptibly(0, 10, SECONDS), -1);
+ equal(phase, phaser.awaitAdvanceInterruptibly(0));
+ equal(phase, phaser.awaitAdvanceInterruptibly(0, 10, SECONDS));
} catch (Exception ie) {
unexpected(ie);
}
@@ -94,10 +95,9 @@
}
int phase = atTheStartingGate.getPhase();
equal(phase, atTheStartingGate.arrive());
- int AwaitPhase = atTheStartingGate.awaitAdvanceInterruptibly(phase,
- 10,
- SECONDS);
- if (expectNextPhase) check(AwaitPhase == (phase + 1));
+ int awaitPhase = atTheStartingGate.awaitAdvanceInterruptibly
+ (phase, 10, SECONDS);
+ if (expectNextPhase) check(awaitPhase == (phase + 1));
pass();
} catch (Throwable t) {
@@ -271,18 +271,19 @@
// Phaser is terminated while threads are waiting
//----------------------------------------------------------------
try {
- Phaser phaser = new Phaser(3);
- Iterator<Awaiter> awaiters = awaiterIterator(phaser);
for (int i = 0; i < 4; i++) {
+ Phaser phaser = new Phaser(3);
+ Iterator<Awaiter> awaiters = awaiterIterator(phaser);
Arriver a1 = awaiters.next(); a1.start();
Arriver a2 = awaiters.next(); a2.start();
toTheStartingGate();
while (phaser.getArrivedParties() < 2) Thread.yield();
+ equal(0, phaser.getPhase());
phaser.forceTermination();
a1.join();
a2.join();
- check(a1.phase == -1);
- check(a2.phase == -1);
+ equal(0 + Integer.MIN_VALUE, a1.phase);
+ equal(0 + Integer.MIN_VALUE, a2.phase);
int arrivedParties = phaser.getArrivedParties();
checkTerminated(phaser);
equal(phaser.getArrivedParties(), arrivedParties);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/Phaser/FickleRegister.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @summary stress test for register/arriveAndDeregister
+ * @run main FickleRegister 300
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+public class FickleRegister {
+ final AtomicLong count = new AtomicLong(0);
+ final long testDurationMillisDefault = 10L * 1000L;
+ final long testDurationMillis;
+ final long quittingTimeNanos;
+ final int chunkSize = 1000;
+
+ FickleRegister(String[] args) {
+ testDurationMillis = (args.length > 0) ?
+ Long.valueOf(args[0]) : testDurationMillisDefault;
+ quittingTimeNanos = System.nanoTime() +
+ testDurationMillis * 1000L * 1000L;
+ }
+
+ class Runner extends CheckedRunnable {
+ final Phaser p;
+ Runner(Phaser phaser) { p = phaser; }
+ public void realRun() {
+ int prevPhase = -1;
+ for (int k = 1;; k++) {
+ for (int i = 0; i < chunkSize; i++) {
+ int phase = p.register();
+ if (phase < 0) break;
+ check(phase > prevPhase);
+ prevPhase = phase;
+ equal(phase, p.arriveAndDeregister());
+ check(phase < p.awaitAdvance(phase));
+ }
+ if (System.nanoTime() - quittingTimeNanos > 0) {
+ count.getAndAdd(k * chunkSize);
+ break;
+ }
+ }
+ }
+ }
+
+ void test(String[] args) throws Throwable {
+ final Phaser parent = new Phaser() {
+ protected boolean onAdvance(int phase, int parties) {
+ return false;
+ }
+ };
+
+ final Phaser child1 = new Phaser(parent);
+ final Phaser child2 = new Phaser(parent);
+ final Phaser subchild1 = new Phaser(child1);
+ final Phaser subchild2 = new Phaser(child2);
+ final Phaser[] phasers = {
+ parent, child1, child2, subchild1, subchild2
+ };
+
+ int reps = 4;
+ ArrayList<Thread> threads = new ArrayList<Thread>();
+ for (int j = 0; j < reps; ++j) {
+ threads.add(new Thread(new Runner(subchild1)));
+ threads.add(new Thread(new Runner(child1)));
+ threads.add(new Thread(new Runner(parent)));
+ threads.add(new Thread(new Runner(child2)));
+ threads.add(new Thread(new Runner(subchild2)));
+ }
+
+ for (Thread thread : threads)
+ thread.start();
+
+ for (Thread thread : threads)
+ thread.join();
+
+ System.out.println("Parent: " + parent);
+ System.out.println("Child1: " + child1);
+ System.out.println("Child2: " + child2);
+ System.out.println("Subchild1: " + subchild1);
+ System.out.println("Subchild2: " + subchild2);
+ System.out.println("Iterations:" + count.get());
+
+ for (Phaser phaser : phasers) {
+ check(phaser.getPhase() > 0);
+ equal(0, phaser.getRegisteredParties());
+ equal(0, phaser.getUnarrivedParties());
+ equal(parent.getPhase(), phaser.getPhase());
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new FickleRegister(args).instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+
+ abstract class CheckedRunnable implements Runnable {
+ protected abstract void realRun() throws Throwable;
+
+ public final void run() {
+ try {realRun();} catch (Throwable t) {unexpected(t);}
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/Phaser/PhaseOverflow.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Martin Buchholz and Doug Lea with assistance from
+ * members of JCP JSR-166 Expert Group and released to the public
+ * domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @summary Test Phaser phase integer overflow behavior
+ */
+
+import java.util.concurrent.Phaser;
+import java.lang.reflect.Field;
+
+public class PhaseOverflow {
+ Field stateField;
+
+ void checkState(Phaser phaser,
+ int phase, int parties, int unarrived) {
+ equal(phase, phaser.getPhase());
+ equal(parties, phaser.getRegisteredParties());
+ equal(unarrived, phaser.getUnarrivedParties());
+ }
+
+ void test(String[] args) throws Throwable {
+ stateField = Phaser.class.getDeclaredField("state");
+ stateField.setAccessible(true);
+ testLeaf();
+ testTiered();
+ }
+
+ void testLeaf() throws Throwable {
+ Phaser phaser = new Phaser();
+ // this is extremely dependent on internal representation
+ stateField.setLong(phaser, ((Integer.MAX_VALUE - 1L) << 32) | 1L);
+ checkState(phaser, Integer.MAX_VALUE - 1, 0, 0);
+ phaser.register();
+ checkState(phaser, Integer.MAX_VALUE - 1, 1, 1);
+ phaser.arrive();
+ checkState(phaser, Integer.MAX_VALUE, 1, 1);
+ phaser.arrive();
+ checkState(phaser, 0, 1, 1);
+ phaser.arrive();
+ checkState(phaser, 1, 1, 1);
+ }
+
+ int phaseInc(int phase) { return (phase + 1) & Integer.MAX_VALUE; }
+
+ void testTiered() throws Throwable {
+ Phaser root = new Phaser();
+ // this is extremely dependent on internal representation
+ stateField.setLong(root, ((Integer.MAX_VALUE - 1L) << 32) | 1L);
+ checkState(root, Integer.MAX_VALUE - 1, 0, 0);
+ Phaser p1 = new Phaser(root, 1);
+ checkState(root, Integer.MAX_VALUE - 1, 1, 1);
+ checkState(p1, Integer.MAX_VALUE - 1, 1, 1);
+ Phaser p2 = new Phaser(root, 2);
+ checkState(root, Integer.MAX_VALUE - 1, 2, 2);
+ checkState(p2, Integer.MAX_VALUE - 1, 2, 2);
+ int ph = Integer.MAX_VALUE - 1;
+ for (int k = 0; k < 5; k++) {
+ checkState(root, ph, 2, 2);
+ checkState(p1, ph, 1, 1);
+ checkState(p2, ph, 2, 2);
+ p1.arrive();
+ checkState(root, ph, 2, 1);
+ checkState(p1, ph, 1, 0);
+ checkState(p2, ph, 2, 2);
+ p2.arrive();
+ checkState(root, ph, 2, 1);
+ checkState(p1, ph, 1, 0);
+ checkState(p2, ph, 2, 1);
+ p2.arrive();
+ ph = phaseInc(ph);
+ checkState(root, ph, 2, 2);
+ checkState(p1, ph, 1, 1);
+ checkState(p2, ph, 2, 2);
+ }
+ equal(3, ph);
+ }
+
+ void xtestTiered() throws Throwable {
+ Phaser root = new Phaser();
+ stateField.setLong(root, ((Integer.MAX_VALUE - 1L) << 32) | 1L);
+ checkState(root, Integer.MAX_VALUE - 1, 0, 0);
+ Phaser p1 = new Phaser(root, 1);
+ checkState(root, Integer.MAX_VALUE - 1, 1, 1);
+ checkState(p1, Integer.MAX_VALUE - 1, 1, 1);
+ Phaser p2 = new Phaser(root, 2);
+ checkState(root, Integer.MAX_VALUE - 1, 2, 2);
+ checkState(p2, Integer.MAX_VALUE - 1, 2, 2);
+ int ph = Integer.MAX_VALUE - 1;
+ for (int k = 0; k < 5; k++) {
+ checkState(root, ph, 2, 2);
+ checkState(p1, ph, 1, 1);
+ checkState(p2, ph, 2, 2);
+ p1.arrive();
+ checkState(root, ph, 2, 1);
+ checkState(p1, ph, 1, 0);
+ checkState(p2, ph, 2, 2);
+ p2.arrive();
+ checkState(root, ph, 2, 1);
+ checkState(p1, ph, 1, 0);
+ checkState(p2, ph, 2, 1);
+ p2.arrive();
+ ph = phaseInc(ph);
+ checkState(root, ph, 2, 2);
+ checkState(p1, ph, 1, 1);
+ checkState(p2, ph, 2, 2);
+ }
+ equal(3, ph);
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new PhaseOverflow().instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/Phaser/TieredArriveLoops.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @summary stress test for arrivals in a tiered phaser
+ * @run main TieredArriveLoops 300
+ */
+import java.util.*;
+import java.util.concurrent.*;
+
+public class TieredArriveLoops {
+ final long testDurationMillisDefault = 10L * 1000L;
+ final long testDurationMillis;
+ final long quittingTimeNanos;
+
+ TieredArriveLoops(String[] args) {
+ testDurationMillis = (args.length > 0) ?
+ Long.valueOf(args[0]) : testDurationMillisDefault;
+ quittingTimeNanos = System.nanoTime() +
+ testDurationMillis * 1000L * 1000L;
+ }
+
+ Runnable runner(final Phaser p) {
+ return new CheckedRunnable() { public void realRun() {
+ int prevPhase = p.register();
+ while (!p.isTerminated()) {
+ int phase = p.awaitAdvance(p.arrive());
+ if (phase < 0)
+ return;
+ equal(phase, (prevPhase + 1) & Integer.MAX_VALUE);
+ int ph = p.getPhase();
+ check(ph < 0 || ph == phase);
+ prevPhase = phase;
+ }
+ }};
+ }
+
+ void test(String[] args) throws Throwable {
+ final Phaser parent = new Phaser();
+ final Phaser child1 = new Phaser(parent);
+ final Phaser child2 = new Phaser(parent);
+
+ Thread t1 = new Thread(runner(child1));
+ Thread t2 = new Thread(runner(child2));
+ t1.start();
+ t2.start();
+
+ for (int prevPhase = 0, phase; ; prevPhase = phase) {
+ phase = child2.getPhase();
+ check(phase >= prevPhase);
+ if (System.nanoTime() - quittingTimeNanos > 0) {
+ System.err.printf("phase=%d%n", phase);
+ child1.forceTermination();
+ break;
+ }
+ }
+
+ t1.join();
+ t2.join();
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new TieredArriveLoops(args).instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+
+ abstract class CheckedRunnable implements Runnable {
+ protected abstract void realRun() throws Throwable;
+
+ public final void run() {
+ try {realRun();} catch (Throwable t) {unexpected(t);}
+ }
+ }
+}
--- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java Fri Feb 18 12:04:36 2011 -0800
@@ -31,47 +31,79 @@
import java.util.concurrent.*;
public class CoreThreadTimeOut {
- static volatile int passed = 0, failed = 0;
- static void pass() { passed++; }
- static void fail() { failed++; Thread.dumpStack(); }
- static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
- static void check(boolean cond) { if (cond) pass(); else fail(); }
- static void equal(Object x, Object y) {
- if (x == null ? y == null : x.equals(y)) pass();
- else {System.out.println(x + " not equal to " + y); fail(); }}
+
+ static class IdentifiableThreadFactory implements ThreadFactory {
+ static ThreadFactory defaultThreadFactory
+ = Executors.defaultThreadFactory();
- static int countExecutorThreads() {
+ public Thread newThread(Runnable r) {
+ Thread t = defaultThreadFactory.newThread(r);
+ t.setName("CoreThreadTimeOut-" + t.getName());
+ return t;
+ }
+ }
+
+ int countExecutorThreads() {
Thread[] threads = new Thread[Thread.activeCount()+100];
Thread.enumerate(threads);
int count = 0;
for (Thread t : threads)
- if (t != null && t.getName().matches("pool-[0-9]+-thread-[0-9]+"))
+ if (t != null &&
+ t.getName().matches
+ ("CoreThreadTimeOut-pool-[0-9]+-thread-[0-9]+"))
count++;
return count;
}
- public static void main(String[] args) throws Throwable {
+ long millisElapsedSince(long t0) {
+ return (System.nanoTime() - t0) / (1000L * 1000L);
+ }
+
+ void test(String[] args) throws Throwable {
final int threadCount = 10;
+ final int timeoutMillis = 30;
BlockingQueue<Runnable> q
= new ArrayBlockingQueue<Runnable>(2*threadCount);
ThreadPoolExecutor tpe
= new ThreadPoolExecutor(threadCount, threadCount,
- 30, TimeUnit.MILLISECONDS,
- q);
+ timeoutMillis, TimeUnit.MILLISECONDS,
+ q, new IdentifiableThreadFactory());
equal(tpe.getCorePoolSize(), threadCount);
check(! tpe.allowsCoreThreadTimeOut());
tpe.allowCoreThreadTimeOut(true);
check(tpe.allowsCoreThreadTimeOut());
equal(countExecutorThreads(), 0);
+ long t0 = System.nanoTime();
for (int i = 0; i < threadCount; i++)
tpe.submit(new Runnable() { public void run() {}});
- equal(countExecutorThreads(), threadCount);
- Thread.sleep(500);
+ int count = countExecutorThreads();
+ if (millisElapsedSince(t0) < timeoutMillis)
+ equal(count, threadCount);
+ while (countExecutorThreads() > 0 &&
+ millisElapsedSince(t0) < 10 * 1000);
equal(countExecutorThreads(), 0);
tpe.shutdown();
check(tpe.allowsCoreThreadTimeOut());
+ check(tpe.awaitTermination(10, TimeUnit.SECONDS));
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
if (failed > 0) throw new Exception("Some tests failed");
}
+
+ //--------------------- Infrastructure ---------------------------
+ volatile int passed = 0, failed = 0;
+ void pass() {passed++;}
+ void fail() {failed++; Thread.dumpStack();}
+ void fail(String msg) {System.err.println(msg); fail();}
+ void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ void check(boolean cond) {if (cond) pass(); else fail();}
+ void equal(Object x, Object y) {
+ if (x == null ? y == null : x.equals(y)) pass();
+ else fail(x + " not equal to " + y);}
+ public static void main(String[] args) throws Throwable {
+ new CoreThreadTimeOut().instanceMain(args);}
+ public void instanceMain(String[] args) throws Throwable {
+ try {test(args);} catch (Throwable t) {unexpected(t);}
+ System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/script/CauseExceptionTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,49 @@
+/*
+ * 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 6869617
+ * @summary RhinoScriptEngine bug : ScriptException cause not set (with fix)
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class CauseExceptionTest {
+ public static void main(String[] args) throws ScriptException, NoSuchMethodException {
+ ScriptEngineManager sem = new ScriptEngineManager();
+ ScriptEngine engine = sem.getEngineByName("js");
+ engine.eval("function hello_world() { println('hello world'); throw 'out of here'; } ");
+ Invocable invocable = (Invocable) engine;
+ try {
+ invocable.invokeFunction("hello_world", (Object[])null);
+ } catch (ScriptException se) {
+ Throwable cause = se.getCause();
+ if (cause == null) {
+ throw new RuntimeException("null cause");
+ }
+ System.out.println(cause);
+ }
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/script/StringWriterPrintTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,44 @@
+/*
+ * 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 6759414
+ * @summary javascript engine can not write to StringWriter.
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class StringWriterPrintTest {
+ public static void main(String[] args) throws ScriptException {
+ ScriptEngineManager sem = new ScriptEngineManager();
+ ScriptEngine engine = sem.getEngineByName("js");
+ StringWriter sw = new StringWriter();
+ engine.eval("print(\"hello world 1\\n\")");
+ engine.getContext().setWriter(sw);
+ // the following "print" call throws exception
+ engine.eval("print(\"hello world 2\\n\")");
+ System.out.println(sw.toString());
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/script/UnescapedBracketRegExTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,40 @@
+/*
+ * 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 7012701
+ * @summary 7012701 Add a test to check that Rhino's RegExp parser accepts unescaped '['
+ */
+
+import javax.script.*;
+import java.io.*;
+
+public class UnescapedBracketRegExTest {
+ public static void main(String[] args) throws ScriptException {
+ ScriptEngineManager sem = new ScriptEngineManager();
+ ScriptEngine engine = sem.getEngineByName("js");
+ // the following throws exception
+ engine.eval("var x = /[a-zA-Z+/=]/;");
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/6342301/bug6342301.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,65 @@
+/*
+ * 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 6342301
+ @summary Bad interaction between setting the ui and file filters in JFileChooser
+ @author Pavel Porvatov
+*/
+
+import javax.swing.*;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.metal.MetalFileChooserUI;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import java.io.File;
+
+public class bug6342301 {
+ private static String tempDir;
+
+ public static void main(String[] args) throws Exception {
+ tempDir = System.getProperty("java.io.tmpdir");
+
+ if (tempDir.length() == 0) { //'java.io.tmpdir' isn't guaranteed to be defined
+ tempDir = System.getProperty("user.home");
+ }
+
+ System.out.println("Temp directory: " + tempDir);
+
+ UIManager.setLookAndFeel(new MetalLookAndFeel());
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ HackedFileChooser openChooser = new HackedFileChooser();
+
+ openChooser.setUI(new MetalFileChooserUI(openChooser));
+ openChooser.setCurrentDirectory(new File(tempDir));
+ }
+ });
+ }
+
+ private static class HackedFileChooser extends JFileChooser {
+ public void setUI(ComponentUI newUI) {
+ super.setUI(newUI);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JLabel/7004134/bug7004134.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,136 @@
+/*
+ * 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 7004134
+ @summary JLabel containing a ToolTipText does no longer show ToolTip after browser refresh
+ @author Pavel Porvatov
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+import java.lang.reflect.Field;
+
+public class bug7004134 {
+ private static volatile JFrame frame;
+
+ private static volatile JLabel label;
+
+ private static volatile int toolTipWidth;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ label = new JLabel("A JLabel used as object for an HTML-formatted tooltip");
+ label.setToolTipText("<html><body bgcolor=FFFFE1>An HTML-formatted ToolTip</body></html>");
+
+ frame = new JFrame();
+
+ frame.add(label);
+ frame.pack();
+ frame.setVisible(true);
+
+ ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
+
+ toolTipManager.setInitialDelay(0);
+ toolTipManager.mouseMoved(new MouseEvent(label, 0, 0, 0, 0, 0, 0, false));
+ }
+ });
+
+ Thread.sleep(500);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ toolTipWidth = getTipWindow().getWidth();
+
+ frame.dispose();
+ }
+ });
+
+ Thread thread = new Thread(new ThreadGroup("Some ThreadGroup"), new Runnable() {
+ public void run() {
+ SunToolkit.createNewAppContext();
+
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ frame = new JFrame();
+
+ frame.add(label);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.pack();
+ frame.setVisible(true);
+
+ ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
+
+ toolTipManager.setInitialDelay(0);
+ toolTipManager.mouseMoved(new MouseEvent(label, 0, 0, 0, 0, 0, 0, false));
+ }
+ });
+
+ Thread.sleep(500);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ int newToolTipWidth = getTipWindow().getWidth();
+
+ frame.dispose();
+
+ if (toolTipWidth != newToolTipWidth) {
+ throw new RuntimeException("Tooltip width is different. Initial: " + toolTipWidth +
+ ", new: " + newToolTipWidth);
+ }
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+ });
+
+ thread.start();
+ thread.join();
+ }
+
+ private static Component getTipWindow() {
+ try {
+ Field tipWindowField = ToolTipManager.class.getDeclaredField("tipWindow");
+
+ tipWindowField.setAccessible(true);
+
+ Popup value = (Popup) tipWindowField.get(ToolTipManager.sharedInstance());
+
+ Field componentField = Popup.class.getDeclaredField("component");
+
+ componentField.setAccessible(true);
+
+ return (Component) componentField.get(value);
+ } catch (Exception e) {
+ throw new RuntimeException("getToolTipComponent failed", e);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/NavigationFilter/6735293/bug6735293.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,88 @@
+/*
+ * 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 6735293
+ * @summary javax.swing.text.NavigationFilter.getNextVisualPositionFrom() not always throws BadLocationException
+ * @author Pavel Porvatov
+ */
+
+import javax.swing.*;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.NavigationFilter;
+import javax.swing.text.Position;
+
+public class bug6735293 {
+ private static volatile JFormattedTextField jtf;
+
+ private static volatile NavigationFilter nf;
+
+ private static volatile JFrame jFrame;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ jtf = new JFormattedTextField();
+ nf = new NavigationFilter();
+ jtf.setText("A text message");
+
+ jFrame = new JFrame();
+ jFrame.getContentPane().add(jtf);
+ jFrame.pack();
+ jFrame.setVisible(true);
+ }
+ });
+
+ Thread.sleep(1000);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ Position.Bias[] biasRet = {Position.Bias.Forward};
+
+ for (int direction : new int[]{
+ SwingConstants.EAST,
+ SwingConstants.WEST,
+ // the following constants still will lead to "BadLocationException: Length must be positive"
+ SwingConstants.SOUTH,
+ SwingConstants.NORTH,
+ }) {
+ for (int position : new int[]{-100, Integer.MIN_VALUE}) {
+ for (Position.Bias bias : new Position.Bias[]{Position.Bias.Backward, Position.Bias.Forward}) {
+ try {
+ nf.getNextVisualPositionFrom(jtf, position, bias, direction, biasRet);
+
+ throw new RuntimeException("BadLocationException was not thrown: position = " +
+ position + ", bias = " + bias + ", direction = " + direction);
+ } catch (BadLocationException e) {
+ // Ok
+ }
+ }
+ }
+ }
+
+ jFrame.dispose();
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/html/parser/Parser/6990651/bug6990651.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,63 @@
+/*
+ * 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 6990651
+ @summary Regression: NPE when refreshing applet since 6u22-b01
+ @author Pavel Porvatov
+*/
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+
+public class bug6990651 {
+ private static volatile JEditorPane editor;
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ editor = new JEditorPane("text/html", "Hello world!");
+ }
+ });
+
+ Thread thread = new Thread(new ThreadGroup("Some ThreadGroup"), new Runnable() {
+ public void run() {
+ SunToolkit.createNewAppContext();
+
+ try {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ editor.setText("Hello world!");
+ }
+ });
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+ });
+
+ thread.start();
+ thread.join();
+ }
+}
--- a/jdk/test/sun/net/InetAddress/nameservice/B6442088.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2006, 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 6442088
- * @summary Change default DNS caching behavior for code not running under
- * security manager.
- *
- * @build B6442088 SimpleNameService SimpleNameServiceDescriptor
- * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun B6442088
- */
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.security.Security;
-
-public class B6442088 {
-
- public static void main(String args[]) throws Exception {
-
- // name service needs to resolve this.
- SimpleNameService.put("theclub", "129.156.220.219");
-
- test ("theclub", "129.156.220.219", true); // lk: 1
- test ("luster", "1.16.20.2", false); // lk: 2
-
- // name service now needs to know about luster
- SimpleNameService.put("luster", "10.5.18.21");
-
- test ("luster", "1.16.20.2", false); // lk: 2
- sleep (10+1);
- test("luster", "10.5.18.21", true, 3); // lk: 3
- sleep (5);
-
- SimpleNameService.put("foo", "10.5.18.22");
- SimpleNameService.put("theclub", "129.156.220.1");
-
- test ("theclub", "129.156.220.219", true, 3);
- test ("luster", "10.5.18.21", true, 3);
- test ("bar", "10.5.18.22", false, 4);
- test ("foo", "10.5.18.22", true, 5);
-
- // now delay to see if theclub has expired
- sleep (5);
-
- test ("foo", "10.5.18.22", true, 5);
- test ("theclub", "129.156.220.1", true, 6);
-
- sleep (11);
- // now see if luster has expired
- test ("luster", "10.5.18.21", true, 7);
- test ("theclub", "129.156.220.1", true, 7);
-
- // now delay to see if 3rd has expired
- sleep (10+6);
-
- test ("theclub", "129.156.220.1", true, 8);
- test ("luster", "10.5.18.21", true, 8);
- test ("foo", "10.5.18.22", true, 9);
- }
-
- /* throws RuntimeException if it fails */
-
- static void test (String host, String address,
- boolean shouldSucceed, int count) {
- test (host, address, shouldSucceed);
- int got = SimpleNameService.lookupCalls();
- if (got != count) {
- throw new RuntimeException ("lookups exp/got: " + count+"/"+got);
- }
- }
-
- static void sleep (int seconds) {
- try {
- Thread.sleep (seconds * 1000);
- } catch (InterruptedException e) {}
- }
-
- static void test (String host, String address, boolean shouldSucceed) {
- InetAddress addr = null;
- try {
- addr = InetAddress.getByName (host);
- if (!shouldSucceed) {
- throw new RuntimeException (host+":"+address+": should fail");
-
- }
- if (!address.equals(addr.getHostAddress())) {
- throw new RuntimeException(host+":"+address+": compare failed");
- }
- } catch (UnknownHostException e) {
- if (shouldSucceed) {
- throw new RuntimeException(host+":"+address+": should succeed");
- }
- }
- }
-
-}
--- a/jdk/test/sun/net/InetAddress/nameservice/CacheTest.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2002, 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 4292867
- * @summary Check that InetAddress doesn't continue to throw UHE
- * after the name service has recovered and the negative ttl
- * on the initial lookup has expired.
- *
- * @build CacheTest SimpleNameService SimpleNameServiceDescriptor
- * @run main/othervm/timeout=200 -Dsun.net.spi.nameservice.provider.1=simple,sun CacheTest
- */
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.security.Security;
-
-public class CacheTest {
-
-
- public static void main(String args[]) throws Exception {
-
- /*
- * First check the ttl on negative lookups is in the <15 second
- * range. If the ttl is <=0 it means we cache forever or always
- * consult the name service. For ttl > 15 the test would take
- * too long so we skip it (need to coordinate jtreg timeout
- * with negative ttl)
- */
- String ttlProp = "networkaddress.cache.negative.ttl";
- int ttl = 0;
- String policy = Security.getProperty(ttlProp);
- if (policy != null) {
- ttl = Integer.parseInt(policy);
- }
- if (ttl <= 0 || ttl > 15) {
- System.err.println("Security property " + ttlProp + " needs to " +
- " in 1-15 second range to execute this test");
- return;
-
- }
-
- /*
- * The following outlines how the test works :-
- *
- * 1. Do a lookup via InetAddress.getByName that it guaranteed
- * to succeed. This forces at least one entry into the cache
- * that will not expire.
- *
- * 2. Do a lookup via InetAddress.getByName that is guarnateed
- * to fail. This results in a negative lookup cached for
- * for a short period to time.
- *
- * 3. Wait for the cache entry to expire.
- *
- * 4. Do a lookup (which should consult the name service) and
- * the lookup should succeed.
- */
-
- // name service needs to resolve this.
- SimpleNameService.put("theclub", "129.156.220.219");
-
- // this lookup will succeed
- InetAddress.getByName("theclub");
-
- // lookup "luster" - this should throw UHE as name service
- // doesn't know anything about this host.
-
- try {
- InetAddress.getByName("luster");
- throw new RuntimeException("Test internal error " +
- " - luster is bring resolved by name service");
- } catch (UnknownHostException x) {
- }
-
- // name service now needs to know about luster
- SimpleNameService.put("luster", "10.5.18.21");
-
- // wait for the cache entry to expire and lookup should
- // succeed.
- Thread.currentThread().sleep(ttl*1000 + 1000);
- InetAddress.getByName("luster");
- }
-
-}
--- a/jdk/test/sun/net/InetAddress/nameservice/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-# name service provider descriptor
-SimpleNameServiceDescriptor
--- a/jdk/test/sun/net/InetAddress/nameservice/SimpleNameService.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2002, 2006, 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.
- */
-
-/*
- * A simple name service based on an in-memory HashMap.
- */
-import java.net.UnknownHostException;
-import java.net.InetAddress;
-import sun.net.spi.nameservice.*;
-import java.util.*;
-
-public final class SimpleNameService implements NameService {
-
- private static LinkedHashMap hosts = new LinkedHashMap();
-
- private static String addrToString(byte addr[]) {
- return Byte.toString(addr[0]) + "." +
- Byte.toString(addr[1]) + "." +
- Byte.toString(addr[2]) + "." +
- Byte.toString(addr[3]);
- }
-
- // ------------
-
- public static void put(String host, String addr) {
- hosts.put(host, addr);
- }
-
- public static void put(String host, byte addr[]) {
- hosts.put(host, addrToString(addr));
- }
-
- public static void remove(String host) {
- hosts.remove(host);
- }
-
- public static int entries () {
- return hosts.size();
- }
-
- public static int lookupCalls() {
- return lookupCalls;
- }
-
- static int lookupCalls = 0;
-
- // ------------
-
- public SimpleNameService() throws Exception {
- }
-
- public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
-
- lookupCalls ++;
-
- String value = (String)hosts.get(host);
- if (value == null) {
- throw new UnknownHostException(host);
- }
- StringTokenizer st = new StringTokenizer(value, ".");
- byte addr[] = new byte[4];
- for (int i=0; i<4; i++) {
- addr[i] = (byte)Integer.parseInt(st.nextToken());
- }
- InetAddress[] res = new InetAddress[1];
- res[0] = InetAddress.getByAddress(host, addr);
- return res;
- }
-
- public String getHostByAddr(byte[] addr) throws UnknownHostException {
- String addrString = addrToString(addr);
- Iterator i = hosts.keySet().iterator();
- while (i.hasNext()) {
- String host = (String)i.next();
- String value = (String)hosts.get(host);
- if (value.equals(addrString)) {
- return host;
- }
- }
- throw new UnknownHostException();
- }
-}
--- a/jdk/test/sun/net/InetAddress/nameservice/SimpleNameServiceDescriptor.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2002, 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.
- */
-
-/*
- * Descriptor for the simple name service
- */
-import sun.net.spi.nameservice.*;
-
-public final class SimpleNameServiceDescriptor implements NameServiceDescriptor {
- /**
- * Create a new instance of the corresponding name service.
- */
- public NameService createNameService() throws Exception {
- return new SimpleNameService();
- }
-
- /**
- * Returns this service provider's name
- *
- */
- public String getProviderName() {
- return "sun";
- }
-
- /**
- * Returns this name service type
- * "dns" "nis" etc
- */
- public String getType() {
- return "simple";
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,23 @@
+# 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
+
+Simple1NameServiceDescriptor
+Simple2NameServiceDescriptor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/Providers.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 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 4762344
+ * @summary 2nd nameservice provider is non functional
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * Simple1NameServiceDescriptor.java
+ * Simple2NameServiceDescriptor.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=simple1,sun -Dsun.net.spi.nameservice.provider.2=simple2,sun Providers
+ */
+
+import java.net.*;
+import java.util.*;
+
+
+public class Providers {
+ private static String[][] hostnames = new String[][] {
+ // both providers know this host, but with different address
+ new String[] {"blade", "10.0.0.1"},
+ // provider1 knwos this host
+ new String[] {"blade.domain1", "10.0.0.2"},
+ // provider2 knows this host
+ new String[] {"blade.domain2", "20.0.0.2"}
+ };
+ private static String[][] hostaddrs = new String[][] {
+ new String[] {"10.0.0.1", "blade"},
+ new String[] {"10.0.0.2", "blade.domain1"},
+ new String[] {"20.0.0.2", "blade.domain2"}
+ };
+
+ public static void main(String[] args) throws Exception {
+ for (int i = 0; i < hostnames.length; i++) {
+ doLookup(hostnames[i][0], hostnames[i][1]);
+ }
+ for (int i = 0; i < hostaddrs.length; i++) {
+ doReverseLookup(hostaddrs[i][0], hostaddrs[i][1]);
+ }
+ }
+
+ private static void doLookup(String host, String addr) throws Exception {
+ String res = InetAddress.getByName(host).getHostAddress();
+ if (!res.equals(addr)) {
+ throw new RuntimeException("Test failed: wrong address for host " + host);
+ }
+ }
+
+ private static void doReverseLookup(String addr, String host) throws Exception {
+ StringTokenizer tokenizer = new StringTokenizer(addr, ".");
+ byte addrs[] = new byte[4];
+ for (int i = 0; i < 4; i++) {
+ addrs[i] = (byte)Integer.parseInt(tokenizer.nextToken());
+ }
+ String res = InetAddress.getByAddress(addrs).getHostName();
+ if (!res.equals(host)) {
+ throw new RuntimeException("Test failed: wrong host name for address " + addr);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/Simple1NameServiceDescriptor.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ */
+
+import sun.net.spi.nameservice.*;
+
+
+public class Simple1NameServiceDescriptor implements NameServiceDescriptor {
+ public NameService createNameService() {
+ SimpleNameService ns = new SimpleNameService();
+
+ // both providers know this host, but the address is different
+ ns.put("blade", "10.0.0.1");
+ // only this provider knows this host
+ ns.put("blade.domain1", "10.0.0.2");
+
+ return ns;
+ }
+
+ public String getProviderName() {
+ return "sun";
+ }
+
+ public String getType() {
+ return "simple1";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/Simple2NameServiceDescriptor.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ */
+
+import sun.net.spi.nameservice.*;
+
+
+public class Simple2NameServiceDescriptor implements NameServiceDescriptor {
+ public NameService createNameService() {
+ SimpleNameService ns = new SimpleNameService();
+ // both providers know this host, but the address of it is different
+ ns.put("blade", "20.0.0.1");
+ // only this provider knows this host
+ ns.put("blade.domain2", "20.0.0.2");
+
+ return ns;
+ }
+
+ public String getProviderName() {
+ return "sun";
+ }
+
+ public String getType() {
+ return "simple2";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/chaining/SimpleNameService.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ */
+
+import java.net.*;
+import java.util.*;
+import sun.net.spi.nameservice.*;
+
+
+public class SimpleNameService implements NameService {
+ // host name <-> host addr mapping
+ private HashMap<String, String> hosts = new LinkedHashMap<String, String>();
+
+ public void put(String host, String addr) {
+ hosts.put(host, addr);
+ }
+
+ private static String addrToString(byte addr[]) {
+ return Byte.toString(addr[0]) + "." +
+ Byte.toString(addr[1]) + "." +
+ Byte.toString(addr[2]) + "." +
+ Byte.toString(addr[3]);
+ }
+
+ public SimpleNameService() {
+ }
+
+ public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
+ String addr = hosts.get(host);
+ if (addr == null) {
+ throw new UnknownHostException(host);
+ }
+
+ StringTokenizer tokenizer = new StringTokenizer(addr, ".");
+ byte addrs[] = new byte[4];
+ for (int i = 0; i < 4; i++) {
+ addrs[i] = (byte)Integer.parseInt(tokenizer.nextToken());
+ }
+ InetAddress[] ret = new InetAddress[1];
+ ret[0] = InetAddress.getByAddress(host, addrs);
+ return ret;
+ }
+
+ public String getHostByAddr(byte[] addr) throws UnknownHostException {
+ String addrString = addrToString(addr);
+ Iterator i = hosts.keySet().iterator();
+ while (i.hasNext()) {
+ String host = (String)i.next();
+ String value = (String)hosts.get(host);
+ if (value.equals(addrString)) {
+ return host;
+ }
+ }
+ throw new UnknownHostException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/Hang.java Fri Feb 18 12:04:36 2011 -0800
@@ -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 7012768
+ * @compile -XDignore.symbol.file=true ThrowingNameService.java
+ * ThrowingNameServiceDescriptor.java
+ * @run main/othervm/timeout=30 -Dsun.net.spi.nameservice.provider.1=throwing,sun Hang
+ * @summary InetAddress lookupTable leaks/deadlocks when using unsupported
+ * name service spi
+ */
+
+import java.net.InetAddress;
+
+public class Hang {
+ public static void main(String[] args) throws Exception {
+ try {
+ // 1st attempt - IllegalStateException caught below
+ InetAddress.getByName("host.company.com");
+ } catch (IllegalStateException e) { }
+
+ // 2nd attempt - Stuck here forever if bug exists
+ InetAddress.getByName("host.company.com");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,22 @@
+# 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.
+
+ThrowingNameServiceDescriptor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameService.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import sun.net.spi.nameservice.NameService;
+
+public class ThrowingNameService implements NameService {
+ static boolean firstCall = true;
+
+ @Override
+ public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
+ if (firstCall) {
+ firstCall = false;
+ // throw unchecked exception first time round
+ throw new IllegalStateException();
+ }
+
+ // return any valid address
+ return new InetAddress[] { InetAddress.getLoopbackAddress() };
+ }
+
+ @Override
+ public String getHostByAddr(byte[] addr) throws UnknownHostException {
+ throw new IllegalStateException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/deadlock/ThrowingNameServiceDescriptor.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+import sun.net.spi.nameservice.*;
+
+public class ThrowingNameServiceDescriptor implements NameServiceDescriptor {
+ public NameService createNameService() {
+ return new ThrowingNameService();
+ }
+
+ @Override
+ public String getProviderName() {
+ return "sun";
+ }
+
+ @Override
+ public String getType() {
+ return "throwing";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/CacheTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2002, 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 4292867
+ * @summary Check that InetAddress doesn't continue to throw UHE
+ * after the name service has recovered and the negative ttl
+ * on the initial lookup has expired.
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * SimpleNameServiceDescriptor.java
+ * @run main/othervm/timeout=200 -Dsun.net.spi.nameservice.provider.1=simple,sun CacheTest
+ */
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.Security;
+
+public class CacheTest {
+
+
+ public static void main(String args[]) throws Exception {
+
+ /*
+ * First check the ttl on negative lookups is in the <15 second
+ * range. If the ttl is <=0 it means we cache forever or always
+ * consult the name service. For ttl > 15 the test would take
+ * too long so we skip it (need to coordinate jtreg timeout
+ * with negative ttl)
+ */
+ String ttlProp = "networkaddress.cache.negative.ttl";
+ int ttl = 0;
+ String policy = Security.getProperty(ttlProp);
+ if (policy != null) {
+ ttl = Integer.parseInt(policy);
+ }
+ if (ttl <= 0 || ttl > 15) {
+ System.err.println("Security property " + ttlProp + " needs to " +
+ " in 1-15 second range to execute this test");
+ return;
+
+ }
+
+ /*
+ * The following outlines how the test works :-
+ *
+ * 1. Do a lookup via InetAddress.getByName that it guaranteed
+ * to succeed. This forces at least one entry into the cache
+ * that will not expire.
+ *
+ * 2. Do a lookup via InetAddress.getByName that is guarnateed
+ * to fail. This results in a negative lookup cached for
+ * for a short period to time.
+ *
+ * 3. Wait for the cache entry to expire.
+ *
+ * 4. Do a lookup (which should consult the name service) and
+ * the lookup should succeed.
+ */
+
+ // name service needs to resolve this.
+ SimpleNameService.put("theclub", "129.156.220.219");
+
+ // this lookup will succeed
+ InetAddress.getByName("theclub");
+
+ // lookup "luster" - this should throw UHE as name service
+ // doesn't know anything about this host.
+
+ try {
+ InetAddress.getByName("luster");
+ throw new RuntimeException("Test internal error " +
+ " - luster is bring resolved by name service");
+ } catch (UnknownHostException x) {
+ }
+
+ // name service now needs to know about luster
+ SimpleNameService.put("luster", "10.5.18.21");
+
+ // wait for the cache entry to expire and lookup should
+ // succeed.
+ Thread.currentThread().sleep(ttl*1000 + 1000);
+ InetAddress.getByName("luster");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/DefaultCaching.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2006, 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 6442088
+ * @summary Change default DNS caching behavior for code not running under
+ * security manager.
+ * @compile -XDignore.symbol.file=true SimpleNameService.java
+ * SimpleNameServiceDescriptor.java
+ * @run main/othervm/timeout=200 -Dsun.net.inetaddr.ttl=20 -Dsun.net.spi.nameservice.provider.1=simple,sun DefaultCaching
+ */
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.Security;
+
+public class DefaultCaching {
+
+ public static void main(String args[]) throws Exception {
+
+ // name service needs to resolve this.
+ SimpleNameService.put("theclub", "129.156.220.219");
+
+ test ("theclub", "129.156.220.219", true); // lk: 1
+ test ("luster", "1.16.20.2", false); // lk: 2
+
+ // name service now needs to know about luster
+ SimpleNameService.put("luster", "10.5.18.21");
+
+ test ("luster", "1.16.20.2", false); // lk: 2
+ sleep (10+1);
+ test("luster", "10.5.18.21", true, 3); // lk: 3
+ sleep (5);
+
+ SimpleNameService.put("foo", "10.5.18.22");
+ SimpleNameService.put("theclub", "129.156.220.1");
+
+ test ("theclub", "129.156.220.219", true, 3);
+ test ("luster", "10.5.18.21", true, 3);
+ test ("bar", "10.5.18.22", false, 4);
+ test ("foo", "10.5.18.22", true, 5);
+
+ // now delay to see if theclub has expired
+ sleep (5);
+
+ test ("foo", "10.5.18.22", true, 5);
+ test ("theclub", "129.156.220.1", true, 6);
+
+ sleep (11);
+ // now see if luster has expired
+ test ("luster", "10.5.18.21", true, 7);
+ test ("theclub", "129.156.220.1", true, 7);
+
+ // now delay to see if 3rd has expired
+ sleep (10+6);
+
+ test ("theclub", "129.156.220.1", true, 8);
+ test ("luster", "10.5.18.21", true, 8);
+ test ("foo", "10.5.18.22", true, 9);
+ }
+
+ /* throws RuntimeException if it fails */
+
+ static void test (String host, String address,
+ boolean shouldSucceed, int count) {
+ test (host, address, shouldSucceed);
+ int got = SimpleNameService.lookupCalls();
+ if (got != count) {
+ throw new RuntimeException ("lookups exp/got: " + count+"/"+got);
+ }
+ }
+
+ static void sleep (int seconds) {
+ try {
+ Thread.sleep (seconds * 1000);
+ } catch (InterruptedException e) {}
+ }
+
+ static void test (String host, String address, boolean shouldSucceed) {
+ InetAddress addr = null;
+ try {
+ addr = InetAddress.getByName (host);
+ if (!shouldSucceed) {
+ throw new RuntimeException (host+":"+address+": should fail");
+
+ }
+ if (!address.equals(addr.getHostAddress())) {
+ throw new RuntimeException(host+":"+address+": compare failed");
+ }
+ } catch (UnknownHostException e) {
+ if (shouldSucceed) {
+ throw new RuntimeException(host+":"+address+": should succeed");
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/META-INF/services/sun.net.spi.nameservice.NameServiceDescriptor Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,22 @@
+# 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.
+
+SimpleNameServiceDescriptor # name service provider descriptor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/SimpleNameService.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2002, 2006, 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.
+ */
+
+/*
+ * A simple name service based on an in-memory HashMap.
+ */
+import java.net.UnknownHostException;
+import java.net.InetAddress;
+import sun.net.spi.nameservice.*;
+import java.util.*;
+
+public final class SimpleNameService implements NameService {
+
+ private static LinkedHashMap hosts = new LinkedHashMap();
+
+ private static String addrToString(byte addr[]) {
+ return Byte.toString(addr[0]) + "." +
+ Byte.toString(addr[1]) + "." +
+ Byte.toString(addr[2]) + "." +
+ Byte.toString(addr[3]);
+ }
+
+ // ------------
+
+ public static void put(String host, String addr) {
+ hosts.put(host, addr);
+ }
+
+ public static void put(String host, byte addr[]) {
+ hosts.put(host, addrToString(addr));
+ }
+
+ public static void remove(String host) {
+ hosts.remove(host);
+ }
+
+ public static int entries () {
+ return hosts.size();
+ }
+
+ public static int lookupCalls() {
+ return lookupCalls;
+ }
+
+ static int lookupCalls = 0;
+
+ // ------------
+
+ public SimpleNameService() throws Exception {
+ }
+
+ public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
+
+ lookupCalls ++;
+
+ String value = (String)hosts.get(host);
+ if (value == null) {
+ throw new UnknownHostException(host);
+ }
+ StringTokenizer st = new StringTokenizer(value, ".");
+ byte addr[] = new byte[4];
+ for (int i=0; i<4; i++) {
+ addr[i] = (byte)Integer.parseInt(st.nextToken());
+ }
+ InetAddress[] res = new InetAddress[1];
+ res[0] = InetAddress.getByAddress(host, addr);
+ return res;
+ }
+
+ public String getHostByAddr(byte[] addr) throws UnknownHostException {
+ String addrString = addrToString(addr);
+ Iterator i = hosts.keySet().iterator();
+ while (i.hasNext()) {
+ String host = (String)i.next();
+ String value = (String)hosts.get(host);
+ if (value.equals(addrString)) {
+ return host;
+ }
+ }
+ throw new UnknownHostException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/InetAddress/nameservice/simple/SimpleNameServiceDescriptor.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2002, 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.
+ */
+
+/*
+ * Descriptor for the simple name service
+ */
+import sun.net.spi.nameservice.*;
+
+public final class SimpleNameServiceDescriptor implements NameServiceDescriptor {
+ /**
+ * Create a new instance of the corresponding name service.
+ */
+ public NameService createNameService() throws Exception {
+ return new SimpleNameService();
+ }
+
+ /**
+ * Returns this service provider's name
+ *
+ */
+ public String getProviderName() {
+ return "sun";
+ }
+
+ /**
+ * Returns this name service type
+ * "dns" "nis" etc
+ */
+ public String getType() {
+ return "simple";
+ }
+}
--- a/jdk/test/sun/security/krb5/IPv6.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/IPv6.java Fri Feb 18 12:04:36 2011 -0800
@@ -78,8 +78,8 @@
try {
Subject subject = new Subject();
Krb5LoginModule krb5 = new Krb5LoginModule();
- Map<String, String> map = new HashMap<String, String>();
- Map<String, Object> shared = new HashMap<String, Object>();
+ Map<String, String> map = new HashMap<>();
+ Map<String, Object> shared = new HashMap<>();
map.put("debug", "true");
map.put("doNotPrompt", "true");
--- a/jdk/test/sun/security/krb5/auto/CleanState.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/auto/CleanState.java Fri Feb 18 12:04:36 2011 -0800
@@ -49,11 +49,11 @@
final char[] password = OneKDC.PASS;
char[] badpassword = "hellokitty".toCharArray();
- Map<String,String> map = new HashMap<String,String>();
+ Map<String,String> map = new HashMap<>();
map.put("useTicketCache", "false");
map.put("doNotPrompt", "false");
map.put("tryFirstPass", "true");
- Map<String,Object> shared = new HashMap<String,Object>();
+ Map<String,Object> shared = new HashMap<>();
shared.put("javax.security.auth.login.name", name);
shared.put("javax.security.auth.login.password", badpassword);
--- a/jdk/test/sun/security/krb5/auto/Context.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/auto/Context.java Fri Feb 18 12:04:36 2011 -0800
@@ -117,8 +117,8 @@
out.name = user;
out.s = new Subject();
Krb5LoginModule krb5 = new Krb5LoginModule();
- Map<String, String> map = new HashMap<String, String>();
- Map<String, Object> shared = new HashMap<String, Object>();
+ Map<String, String> map = new HashMap<>();
+ Map<String, Object> shared = new HashMap<>();
if (pass != null) {
map.put("useFirstPass", "true");
@@ -151,7 +151,7 @@
out.name = user;
out.s = new Subject();
Krb5LoginModule krb5 = new Krb5LoginModule();
- Map<String, String> map = new HashMap<String, String>();
+ Map<String, String> map = new HashMap<>();
map.put("doNotPrompt", "true");
map.put("useTicketCache", "false");
--- a/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/auto/HttpNegotiateServer.java Fri Feb 18 12:04:36 2011 -0800
@@ -297,8 +297,8 @@
}
Krb5LoginModule krb5 = new Krb5LoginModule();
- Map<String, String> map = new HashMap<String, String>();
- Map<String, Object> shared = new HashMap<String, Object>();
+ Map<String, String> map = new HashMap<>();
+ Map<String, Object> shared = new HashMap<>();
map.put("storeKey", "true");
map.put("isInitiator", "false");
--- a/jdk/test/sun/security/krb5/auto/KDC.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/auto/KDC.java Fri Feb 18 12:04:36 2011 -0800
@@ -132,7 +132,7 @@
// Principal db. principal -> pass. A case-insensitive TreeMap is used
// so that even if the client provides a name with different case, the KDC
// can still locate the principal and give back correct salt.
- private TreeMap<String,char[]> passwords = new TreeMap<String,char[]>
+ private TreeMap<String,char[]> passwords = new TreeMap<>
(String.CASE_INSENSITIVE_ORDER);
// Realm name
@@ -142,9 +142,9 @@
// Service port number
private int port;
// The request/response job queue
- private BlockingQueue<Job> q = new ArrayBlockingQueue<Job>(100);
+ private BlockingQueue<Job> q = new ArrayBlockingQueue<>(100);
// Options
- private Map<Option,Object> options = new HashMap<Option,Object>();
+ private Map<Option,Object> options = new HashMap<>();
private Thread thread1, thread2, thread3;
DatagramSocket u1 = null;
@@ -537,7 +537,7 @@
}
}
- private Map<String,String> policies = new HashMap<String,String>();
+ private Map<String,String> policies = new HashMap<>();
public void setPolicy(String rule, String value) {
if (value == null) {
@@ -760,7 +760,7 @@
private byte[] processAsReq(byte[] in) throws Exception {
ASReq asReq = new ASReq(in);
int[] eTypes = null;
- List<PAData> outPAs = new ArrayList<PAData>();
+ List<PAData> outPAs = new ArrayList<>();
try {
System.out.println(realm + "> " + asReq.reqBody.cname +
--- a/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/auto/LoginModuleOptions.java Fri Feb 18 12:04:36 2011 -0800
@@ -135,8 +135,8 @@
throws Exception {
Krb5LoginModule krb5 = new Krb5LoginModule();
Subject subject = new Subject();
- Map<String, String> map = new HashMap<String, String>();
- Map<String, Object> shared = new HashMap<String, Object>();
+ Map<String, String> map = new HashMap<>();
+ Map<String, Object> shared = new HashMap<>();
int count = options.length / 2;
for (int i = 0; i < count; i++) {
--- a/jdk/test/sun/security/krb5/tools/KtabCheck.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/krb5/tools/KtabCheck.java Fri Feb 18 12:04:36 2011 -0800
@@ -39,7 +39,7 @@
public static void main(String[] args) throws Exception {
System.out.println("Checking " + Arrays.toString(args));
KeyTab ktab = KeyTab.getInstance(args[0]);
- Set<String> expected = new HashSet<String>();
+ Set<String> expected = new HashSet<>();
for (int i=1; i<args.length; i += 2) {
expected.add(args[i]+":"+args[i+1]);
}
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java Fri Feb 18 11:15:40 2011 -0800
+++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/CookieHandlerTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -300,8 +300,8 @@
getCalled = true;
// returns cookies[0]
// they will be include in request
- Map<String,List<String>> map = new HashMap<String,List<String>>();
- List<String> l = new ArrayList<String>();
+ Map<String,List<String>> map = new HashMap<>();
+ List<String> l = new ArrayList<>();
l.add(cookies.get("Cookie"));
map.put("Cookie",l);
return Collections.unmodifiableMap(map);
--- a/langtools/.hgtags Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/.hgtags Fri Feb 18 12:04:36 2011 -0800
@@ -100,3 +100,5 @@
a3b5b531542a372f30e014b1543a619a15a90780 jdk7-b123
4868a36f6fd8972505c466013813eeb28f0482ea jdk7-b124
4b0560c72b529d4b952924b2da94d8436af79d05 jdk7-b125
+438a8ad60f7ae7aa897663148fd43fe85ef05e5b jdk7-b126
+1e6094c33187f6c3dca55ced3701ee1f9d73a77d jdk7-b127
--- a/langtools/make/build.xml Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/make/build.xml Fri Feb 18 12:04:36 2011 -0800
@@ -352,6 +352,45 @@
</java>
</target>
+ <!-- a patching facility to speed up incorporating the langtools' classfiles
+ into a jdk of your choice. Either target.java.home or patch.jdk can be
+ set on the command line; setting target.java.home has the advantage of
+ patching the jdk used for jtreg and other tests.
+ -->
+ <target name="patch" depends="build-all-classes">
+ <condition property="patch.jdk" value="${target.java.home}">
+ <available file="${target.java.home}" type="dir"/>
+ </condition>
+ <fail message="patch.jdk or target.java.home is not set, please set target.java.home, or patch.jdk for an alternate jdk image to patch">
+ <condition>
+ <not>
+ <isset property="patch.jdk"/>
+ </not>
+ </condition>
+ </fail>
+ <property name="patch.tools.jar" location="${patch.jdk}/lib/tools.jar"/>
+ <property name="patch.rt.jar" location="${patch.jdk}/jre/lib/rt.jar"/>
+ <fail message="patch.jdk or target.java.home must point to a valid jdk image: missing tools.jar">
+ <condition>
+ <not>
+ <available file="${patch.tools.jar}" type="file"/>
+ </not>
+ </condition>
+ </fail>
+ <fail message="patch.jdk or target.java.home must point to a valid jdk image: missing rt.jar">
+ <condition>
+ <not>
+ <available file="${patch.rt.jar}" type="file"/>
+ </not>
+ </condition>
+ </fail>
+ <zip zipfile="${patch.tools.jar}" update="true">
+ <zipfileset dir="${build.classes.dir}" includes="com/**"/>
+ </zip>
+ <zip zipfile="${patch.rt.jar}" update="true">
+ <zipfileset dir="${build.classes.dir}" includes="javax/**"/>
+ </zip>
+ </target>
<!--
**** Debugging/diagnostic targets.
--- a/langtools/src/share/classes/com/sun/source/tree/MethodTree.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/source/tree/MethodTree.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -53,7 +53,6 @@
Tree getReturnType();
List<? extends TypeParameterTree> getTypeParameters();
List<? extends VariableTree> getParameters();
-//308 List<? extends AnnotationTree> getReceiverAnnotations();
List<? extends ExpressionTree> getThrows();
BlockTree getBody();
Tree getDefaultValue(); // for annotation types
--- a/langtools/src/share/classes/com/sun/source/tree/Tree.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/source/tree/Tree.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -46,8 +46,6 @@
*/
public enum Kind {
-//308 ANNOTATED_TYPE(AnnotatedTypeTree.class),
-
/**
* Used for instances of {@link AnnotationTree}.
*/
--- a/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/source/tree/TreeVisitor.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -57,7 +57,6 @@
* @since 1.6
*/
public interface TreeVisitor<R,P> {
-//308 R visitAnnotatedType(AnnotatedTypeTree node, P p);
R visitAnnotation(AnnotationTree node, P p);
R visitMethodInvocation(MethodInvocationTree node, P p);
R visitAssert(AssertTree node, P p);
--- a/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/source/tree/TypeParameterTree.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -47,5 +47,4 @@
public interface TypeParameterTree extends Tree {
Name getName();
List<? extends Tree> getBounds();
-//308 List<? extends AnnotationTree> getAnnotations();
}
--- a/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -248,10 +248,6 @@
return defaultAction(node, p);
}
-//308 public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
-//308 return defaultAction(node, p);
-//308 }
-
public R visitErroneous(ErroneousTree node, P p) {
return defaultAction(node, p);
}
--- a/langtools/src/share/classes/com/sun/source/util/TreeScanner.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/source/util/TreeScanner.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -138,7 +138,6 @@
r = scanAndReduce(node.getReturnType(), p, r);
r = scanAndReduce(node.getTypeParameters(), p, r);
r = scanAndReduce(node.getParameters(), p, r);
-//308 r = scanAndReduce(node.getReceiverAnnotations(), p, r);
r = scanAndReduce(node.getThrows(), p, r);
r = scanAndReduce(node.getBody(), p, r);
r = scanAndReduce(node.getDefaultValue(), p, r);
@@ -362,7 +361,6 @@
public R visitTypeParameter(TypeParameterTree node, P p) {
R r = scan(node.getBounds(), p);
-//308 R r = scanAndReduce(node.getAnnotations(), p, r);
return r;
}
@@ -380,12 +378,6 @@
return r;
}
-//308 public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
-//308 R r = scan(node.getAnnotations(), p);
-//308 r = scanAndReduce(node.getUnderlyingType(), p, r);
-//308 return r;
-//308 }
-
public R visitOther(Tree node, P p) {
return null;
}
--- a/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Attribute.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -39,6 +39,7 @@
public abstract class Attribute {
public static final String AnnotationDefault = "AnnotationDefault";
+ public static final String BootstrapMethods = "BootstrapMethods";
public static final String CharacterRangeTable = "CharacterRangeTable";
public static final String Code = "Code";
public static final String ConstantValue = "ConstantValue";
@@ -54,8 +55,6 @@
public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
public static final String RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
- public static final String RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations";
- public static final String RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations";
public static final String Signature = "Signature";
public static final String SourceDebugExtension = "SourceDebugExtension";
public static final String SourceFile = "SourceFile";
@@ -101,6 +100,7 @@
protected void init() {
standardAttributes = new HashMap<String,Class<? extends Attribute>>();
standardAttributes.put(AnnotationDefault, AnnotationDefault_attribute.class);
+ standardAttributes.put(BootstrapMethods, BootstrapMethods_attribute.class);
standardAttributes.put(CharacterRangeTable, CharacterRangeTable_attribute.class);
standardAttributes.put(Code, Code_attribute.class);
standardAttributes.put(ConstantValue, ConstantValue_attribute.class);
@@ -118,8 +118,6 @@
standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations_attribute.class);
- standardAttributes.put(RuntimeVisibleTypeAnnotations, RuntimeVisibleTypeAnnotations_attribute.class);
- standardAttributes.put(RuntimeInvisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations_attribute.class);
standardAttributes.put(Signature, Signature_attribute.class);
standardAttributes.put(SourceID, SourceID_attribute.class);
}
@@ -159,6 +157,7 @@
public interface Visitor<R,P> {
+ R visitBootstrapMethods(BootstrapMethods_attribute attr, P p);
R visitDefault(DefaultAttribute attr, P p);
R visitAnnotationDefault(AnnotationDefault_attribute attr, P p);
R visitCharacterRangeTable(CharacterRangeTable_attribute attr, P p);
@@ -176,8 +175,6 @@
R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p);
- R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p);
- R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p);
R visitSignature(Signature_attribute attr, P p);
R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p);
R visitSourceFile(SourceFile_attribute attr, P p);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/classfile/BootstrapMethods_attribute.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,90 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.classfile;
+
+import java.io.IOException;
+
+/**
+ * See JVMS3 <TBD>
+ * http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-mlvm/
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class BootstrapMethods_attribute extends Attribute {
+ public final BootstrapMethodSpecifier[] bootstrap_method_specifiers;
+
+ BootstrapMethods_attribute(ClassReader cr, int name_index, int length)
+ throws IOException, AttributeException {
+ super(name_index, length);
+ int bootstrap_method_count = cr.readUnsignedShort();
+ bootstrap_method_specifiers = new BootstrapMethodSpecifier[bootstrap_method_count];
+ for (int i = 0; i < bootstrap_method_specifiers.length; i++)
+ bootstrap_method_specifiers[i] = new BootstrapMethodSpecifier(cr);
+ }
+
+ public BootstrapMethods_attribute(int name_index, BootstrapMethodSpecifier[] bootstrap_method_specifiers) {
+ super(name_index, length(bootstrap_method_specifiers));
+ this.bootstrap_method_specifiers = bootstrap_method_specifiers;
+ }
+
+ public static int length(BootstrapMethodSpecifier[] bootstrap_method_specifiers) {
+ int n = 2;
+ for (BootstrapMethodSpecifier b : bootstrap_method_specifiers)
+ n += b.length();
+ return n;
+ }
+
+ @Override
+ public <R, P> R accept(Visitor<R, P> visitor, P p) {
+ return visitor.visitBootstrapMethods(this, p);
+ }
+
+ public static class BootstrapMethodSpecifier {
+ public int bootstrap_method_ref;
+ public int[] bootstrap_arguments;
+
+ public BootstrapMethodSpecifier(int bootstrap_method_ref, int[] bootstrap_arguments) {
+ this.bootstrap_method_ref = bootstrap_method_ref;
+ this.bootstrap_arguments = bootstrap_arguments;
+ }
+ BootstrapMethodSpecifier(ClassReader cr) throws IOException {
+ bootstrap_method_ref = cr.readUnsignedShort();
+ int method_count = cr.readUnsignedShort();
+ bootstrap_arguments = new int[method_count];
+ for (int i = 0; i < bootstrap_arguments.length; i++) {
+ bootstrap_arguments[i] = cr.readUnsignedShort();
+ }
+ }
+
+ int length() {
+ // u2 (method_ref) + u2 (argc) + u2 * argc
+ return 2 + 2 + (bootstrap_arguments.length * 2);
+ }
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/classfile/ClassTranslator.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/classfile/ClassTranslator.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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,7 +31,10 @@
import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_Integer_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_InterfaceMethodref_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_Long_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodType_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_Methodref_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_NameAndType_info;
import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info;
@@ -304,6 +307,20 @@
return info;
}
+ public CPInfo visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Map<Object, Object> translations) {
+ CONSTANT_InvokeDynamic_info info2 = (CONSTANT_InvokeDynamic_info) translations.get(info);
+ if (info2 == null) {
+ ConstantPool cp2 = translate(info.cp, translations);
+ if (cp2 == info.cp) {
+ info2 = info;
+ } else {
+ info2 = new CONSTANT_InvokeDynamic_info(cp2, info.bootstrap_method_attr_index, info.name_and_type_index);
+ }
+ translations.put(info, info2);
+ }
+ return info;
+ }
+
public CPInfo visitLong(CONSTANT_Long_info info, Map<Object, Object> translations) {
CONSTANT_Long_info info2 = (CONSTANT_Long_info) translations.get(info);
if (info2 == null) {
@@ -339,6 +356,34 @@
return info;
}
+ public CPInfo visitMethodHandle(CONSTANT_MethodHandle_info info, Map<Object, Object> translations) {
+ CONSTANT_MethodHandle_info info2 = (CONSTANT_MethodHandle_info) translations.get(info);
+ if (info2 == null) {
+ ConstantPool cp2 = translate(info.cp, translations);
+ if (cp2 == info.cp) {
+ info2 = info;
+ } else {
+ info2 = new CONSTANT_MethodHandle_info(cp2, info.reference_kind, info.reference_index);
+ }
+ translations.put(info, info2);
+ }
+ return info;
+ }
+
+ public CPInfo visitMethodType(CONSTANT_MethodType_info info, Map<Object, Object> translations) {
+ CONSTANT_MethodType_info info2 = (CONSTANT_MethodType_info) translations.get(info);
+ if (info2 == null) {
+ ConstantPool cp2 = translate(info.cp, translations);
+ if (cp2 == info.cp) {
+ info2 = info;
+ } else {
+ info2 = new CONSTANT_MethodType_info(cp2, info.descriptor_index);
+ }
+ translations.put(info, info2);
+ }
+ return info;
+ }
+
public CPInfo visitString(CONSTANT_String_info info, Map<Object, Object> translations) {
CONSTANT_String_info info2 = (CONSTANT_String_info) translations.get(info);
if (info2 == null) {
--- a/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/classfile/ClassWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -267,6 +267,12 @@
return 1;
}
+ public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ClassOutputStream out) {
+ out.writeShort(info.bootstrap_method_attr_index);
+ out.writeShort(info.name_and_type_index);
+ return 1;
+ }
+
public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
out.writeLong(info.value);
return 2;
@@ -278,6 +284,17 @@
return 1;
}
+ public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, ClassOutputStream out) {
+ out.writeByte(info.reference_kind.tag);
+ out.writeShort(info.reference_index);
+ return 1;
+ }
+
+ public Integer visitMethodType(CONSTANT_MethodType_info info, ClassOutputStream out) {
+ out.writeShort(info.descriptor_index);
+ return 1;
+ }
+
public Integer visitMethodref(CONSTANT_Methodref_info info, ClassOutputStream out) {
return writeRef(info, out);
}
@@ -332,6 +349,19 @@
return null;
}
+ public Void visitBootstrapMethods(BootstrapMethods_attribute attr, ClassOutputStream out) {
+ out.writeShort(attr.bootstrap_method_specifiers.length);
+ for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsm : attr.bootstrap_method_specifiers) {
+ out.writeShort(bsm.bootstrap_method_ref);
+ int bsm_args_count = bsm.bootstrap_arguments.length;
+ out.writeShort(bsm_args_count);
+ for (int i : bsm.bootstrap_arguments) {
+ out.writeShort(i);
+ }
+ }
+ return null;
+ }
+
public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, ClassOutputStream out) {
out.writeShort(attr.character_range_table.length);
for (CharacterRangeTable_attribute.Entry e: attr.character_range_table)
@@ -459,16 +489,6 @@
return null;
}
- public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
- annotationWriter.write(attr.annotations, out);
- return null;
- }
-
- public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
- annotationWriter.write(attr.annotations, out);
- return null;
- }
-
public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
out.writeByte(attr.parameter_annotations.length);
for (Annotation[] annos: attr.parameter_annotations)
@@ -628,12 +648,6 @@
write(anno, out);
}
- public void write(ExtendedAnnotation[] annos, ClassOutputStream out) {
- out.writeShort(annos.length);
- for (ExtendedAnnotation anno: annos)
- write(anno, out);
- }
-
public void write(Annotation anno, ClassOutputStream out) {
out.writeShort(anno.type_index);
out.writeShort(anno.element_value_pairs.length);
@@ -641,11 +655,6 @@
write(p, out);
}
- public void write(ExtendedAnnotation anno, ClassOutputStream out) {
- write(anno.annotation, out);
- write(anno.position, out);
- }
-
public void write(element_value_pair pair, ClassOutputStream out) {
out.writeShort(pair.element_name_index);
write(pair.value, out);
@@ -684,95 +693,5 @@
return null;
}
- private void write(ExtendedAnnotation.Position p, ClassOutputStream out) {
- out.writeByte(p.type.targetTypeValue());
- switch (p.type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- out.writeShort(p.offset);
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- int table_length = p.lvarOffset.length;
- out.writeShort(table_length);
- for (int i = 0; i < table_length; ++i) {
- out.writeShort(1); // for table length
- out.writeShort(p.lvarOffset[i]);
- out.writeShort(p.lvarLength[i]);
- out.writeShort(p.lvarIndex[i]);
- }
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- out.writeByte(p.parameter_index);
- break;
- // type parameters bounds
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- out.writeByte(p.parameter_index);
- out.writeByte(p.bound_index);
- break;
- // wildcards
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- write(p.wildcard_position, out);
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- out.writeByte(p.type_index);
- break;
- // throws
- case THROWS:
- out.writeByte(p.type_index);
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- out.writeShort(p.offset);
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- out.writeByte(p.parameter_index);
- break;
- // method type argument: wasn't specified
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- out.writeShort(p.offset);
- out.writeByte(p.type_index);
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- throw new AssertionError("unknown type: " + p);
- }
-
- // Append location data for generics/arrays.
- if (p.type.hasLocation()) {
- out.writeShort(p.location.size());
- for (int i : p.location)
- out.writeByte((byte)i);
- }
- }
}
}
--- a/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/classfile/ConstantPool.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -114,6 +114,54 @@
public static final int CONSTANT_Methodref = 10;
public static final int CONSTANT_InterfaceMethodref = 11;
public static final int CONSTANT_NameAndType = 12;
+ public static final int CONSTANT_MethodHandle = 15;
+ public static final int CONSTANT_MethodType = 16;
+ public static final int CONSTANT_InvokeDynamic = 18;
+
+ public static enum RefKind {
+ REF_getField(1, "getfield"),
+ REF_getStatic(2, "getstatic"),
+ REF_putField(3, "putfield"),
+ REF_putStatic(4, "putstatic"),
+ REF_invokeVirtual(5, "invokevirtual"),
+ REF_invokeStatic(6, "invokestatic"),
+ REF_invokeSpecial(7, "invokespecial"),
+ REF_newInvokeSpecial(8, "newinvokespecial"),
+ REF_invokeInterface(9, "invokeinterface");
+
+ public final int tag;
+ public final String name;
+
+ RefKind(int tag, String name) {
+ this.tag = tag;
+ this.name = name;
+ }
+
+ static RefKind getRefkind(int tag) {
+ switch(tag) {
+ case 1:
+ return REF_getField;
+ case 2:
+ return REF_getStatic;
+ case 3:
+ return REF_putField;
+ case 4:
+ return REF_putStatic;
+ case 5:
+ return REF_invokeVirtual;
+ case 6:
+ return REF_invokeStatic;
+ case 7:
+ return REF_invokeSpecial;
+ case 8:
+ return REF_newInvokeSpecial;
+ case 9:
+ return REF_invokeInterface;
+ default:
+ return null;
+ }
+ }
+ }
ConstantPool(ClassReader cr) throws IOException, InvalidEntry {
int count = cr.readUnsignedShort();
@@ -146,11 +194,23 @@
pool[i] = new CONSTANT_InterfaceMethodref_info(this, cr);
break;
+ case CONSTANT_InvokeDynamic:
+ pool[i] = new CONSTANT_InvokeDynamic_info(this, cr);
+ break;
+
case CONSTANT_Long:
pool[i] = new CONSTANT_Long_info(cr);
i++;
break;
+ case CONSTANT_MethodHandle:
+ pool[i] = new CONSTANT_MethodHandle_info(this, cr);
+ break;
+
+ case CONSTANT_MethodType:
+ pool[i] = new CONSTANT_MethodType_info(this, cr);
+ break;
+
case CONSTANT_Methodref:
pool[i] = new CONSTANT_Methodref_info(this, cr);
break;
@@ -279,9 +339,12 @@
R visitFloat(CONSTANT_Float_info info, P p);
R visitInteger(CONSTANT_Integer_info info, P p);
R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
+ R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p);
R visitLong(CONSTANT_Long_info info, P p);
R visitNameAndType(CONSTANT_NameAndType_info info, P p);
R visitMethodref(CONSTANT_Methodref_info info, P p);
+ R visitMethodHandle(CONSTANT_MethodHandle_info info, P p);
+ R visitMethodType(CONSTANT_MethodType_info info, P p);
R visitString(CONSTANT_String_info info, P p);
R visitUtf8(CONSTANT_Utf8_info info, P p);
}
@@ -548,6 +611,44 @@
}
}
+ public static class CONSTANT_InvokeDynamic_info extends CPInfo {
+ CONSTANT_InvokeDynamic_info(ConstantPool cp, ClassReader cr) throws IOException {
+ super(cp);
+ bootstrap_method_attr_index = cr.readUnsignedShort();
+ name_and_type_index = cr.readUnsignedShort();
+ }
+
+ public CONSTANT_InvokeDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) {
+ super(cp);
+ this.bootstrap_method_attr_index = bootstrap_method_index;
+ this.name_and_type_index = name_and_type_index;
+ }
+
+ public int getTag() {
+ return CONSTANT_InvokeDynamic;
+ }
+
+ public int byteLength() {
+ return 5;
+ }
+
+ @Override
+ public String toString() {
+ return "CONSTANT_InvokeDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]";
+ }
+
+ public <R, D> R accept(Visitor<R, D> visitor, D data) {
+ return visitor.visitInvokeDynamic(this, data);
+ }
+
+ public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
+ return cp.getNameAndTypeInfo(name_and_type_index);
+ }
+
+ public final int bootstrap_method_attr_index;
+ public final int name_and_type_index;
+ }
+
public static class CONSTANT_Long_info extends CPInfo {
CONSTANT_Long_info(ClassReader cr) throws IOException {
value = cr.readLong();
@@ -582,6 +683,87 @@
public final long value;
}
+ public static class CONSTANT_MethodHandle_info extends CPInfo {
+ CONSTANT_MethodHandle_info(ConstantPool cp, ClassReader cr) throws IOException {
+ super(cp);
+ reference_kind = RefKind.getRefkind(cr.readUnsignedByte());
+ reference_index = cr.readUnsignedShort();
+ }
+
+ public CONSTANT_MethodHandle_info(ConstantPool cp, RefKind ref_kind, int member_index) {
+ super(cp);
+ this.reference_kind = ref_kind;
+ this.reference_index = member_index;
+ }
+
+ public int getTag() {
+ return CONSTANT_MethodHandle;
+ }
+
+ public int byteLength() {
+ return 4;
+ }
+
+ @Override
+ public String toString() {
+ return "CONSTANT_MethodHandle_info[ref_kind: " + reference_kind + ", member_index: " + reference_index + "]";
+ }
+
+ public <R, D> R accept(Visitor<R, D> visitor, D data) {
+ return visitor.visitMethodHandle(this, data);
+ }
+
+ public CPRefInfo getCPRefInfo() throws ConstantPoolException {
+ int expected = CONSTANT_Methodref;
+ int actual = cp.get(reference_index).getTag();
+ // allow these tag types also:
+ switch (actual) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_InterfaceMethodref:
+ expected = actual;
+ }
+ return (CPRefInfo) cp.get(reference_index, expected);
+ }
+
+ public final RefKind reference_kind;
+ public final int reference_index;
+ }
+
+ public static class CONSTANT_MethodType_info extends CPInfo {
+ CONSTANT_MethodType_info(ConstantPool cp, ClassReader cr) throws IOException {
+ super(cp);
+ descriptor_index = cr.readUnsignedShort();
+ }
+
+ public CONSTANT_MethodType_info(ConstantPool cp, int signature_index) {
+ super(cp);
+ this.descriptor_index = signature_index;
+ }
+
+ public int getTag() {
+ return CONSTANT_MethodType;
+ }
+
+ public int byteLength() {
+ return 3;
+ }
+
+ @Override
+ public String toString() {
+ return "CONSTANT_MethodType_info[signature_index: " + descriptor_index + "]";
+ }
+
+ public <R, D> R accept(Visitor<R, D> visitor, D data) {
+ return visitor.visitMethodType(this, data);
+ }
+
+ public String getType() throws ConstantPoolException {
+ return cp.getUTF8Value(descriptor_index);
+ }
+
+ public final int descriptor_index;
+ }
+
public static class CONSTANT_Methodref_info extends CPRefInfo {
CONSTANT_Methodref_info(ConstantPool cp, ClassReader cr) throws IOException {
super(cp, cr, CONSTANT_Methodref);
@@ -729,5 +911,4 @@
public final String value;
}
-
}
--- a/langtools/src/share/classes/com/sun/tools/classfile/Dependencies.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/classfile/Dependencies.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -626,10 +626,26 @@
return visitRef(info, p);
}
+ public Void visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
+ return null;
+ }
+
public Void visitLong(CONSTANT_Long_info info, Void p) {
return null;
}
+ public Void visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
+ return null;
+ }
+
+ public Void visitMethodType(CONSTANT_MethodType_info info, Void p) {
+ return null;
+ }
+
+ public Void visitMethodref(CONSTANT_Methodref_info info, Void p) {
+ return visitRef(info, p);
+ }
+
public Void visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
try {
new Signature(info.type_index).getType(constant_pool).accept(this, null);
@@ -639,10 +655,6 @@
}
}
- public Void visitMethodref(CONSTANT_Methodref_info info, Void p) {
- return visitRef(info, p);
- }
-
public Void visitString(CONSTANT_String_info info, Void p) {
return null;
}
--- a/langtools/src/share/classes/com/sun/tools/classfile/ExtendedAnnotation.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,612 +0,0 @@
-/*
- * Copyright (c) 2009, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.classfile;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-
-import static com.sun.tools.classfile.ExtendedAnnotation.TargetAttribute.*;
-
-/**
- * See JSR 308 specification, section 4.1
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class ExtendedAnnotation {
- ExtendedAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
- annotation = new Annotation(cr);
- position = read_position(cr);
- }
-
- public ExtendedAnnotation(ConstantPool constant_pool,
- Annotation annotation, Position position) {
- this.annotation = annotation;
- this.position = position;
- }
-
- public int length() {
- int n = annotation.length();
- n += position_length(position);
- return n;
- }
-
- public final Annotation annotation;
- public final Position position;
-
- private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
- // Copied from ClassReader
- int tag = (byte)cr.readUnsignedByte(); // cast to introduce signedness
- if (!TargetType.isValidTargetTypeValue(tag))
- throw new Annotation.InvalidAnnotation("invalid type annotation target type value: " + tag);
-
- TargetType type = TargetType.fromTargetTypeValue(tag);
-
- Position position = new Position();
- position.type = type;
-
- switch (type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- position.offset = cr.readUnsignedShort();
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- int table_length = cr.readUnsignedShort();
- position.lvarOffset = new int[table_length];
- position.lvarLength = new int[table_length];
- position.lvarIndex = new int[table_length];
- for (int i = 0; i < table_length; ++i) {
- position.lvarOffset[i] = cr.readUnsignedShort();
- position.lvarLength[i] = cr.readUnsignedShort();
- position.lvarIndex[i] = cr.readUnsignedShort();
- }
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- position.parameter_index = cr.readUnsignedByte();
- break;
- // type parameter bounds
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- position.parameter_index = cr.readUnsignedByte();
- position.bound_index = cr.readUnsignedByte();
- break;
- // wildcards
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- position.wildcard_position = read_position(cr);
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- int in = cr.readUnsignedShort();
- if (in == 0xFFFF)
- in = -1;
- position.type_index = in;
- break;
- // throws
- case THROWS:
- position.type_index = cr.readUnsignedShort();
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- position.offset = cr.readUnsignedShort();
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- position.parameter_index = cr.readUnsignedByte();
- break;
- // method type argument: wasn't specified
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- position.offset = cr.readUnsignedShort();
- position.type_index = cr.readUnsignedByte();
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- throw new AssertionError("Cannot be here");
- }
-
- if (type.hasLocation()) {
- int len = cr.readUnsignedShort();
- List<Integer> loc = new ArrayList<Integer>(len);
- for (int i = 0; i < len; i++)
- loc.add(cr.readUnsignedByte());
- position.location = loc;
- }
- return position;
- }
-
- private static int position_length(Position pos) {
- int n = 0;
- n += 1; // target_type
- switch (pos.type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- n += 2;
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- n += 2; // table_length;
- int table_length = pos.lvarOffset.length;
- n += 2 * table_length; // offset
- n += 2 * table_length; // length;
- n += 2 * table_length; // index
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- n += 1; // parameter_index;
- break;
- // type parameter bounds
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- n += 1; // parameter_index
- n += 1; // bound_index
- break;
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- n += position_length(pos.wildcard_position);
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- n += 2; // type_index
- break;
- // throws
- case THROWS:
- n += 2; // type_index
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- n += 1; // offset
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- n += 1; // parameter_index
- break;
- // method type argument: wasn't specified
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- n += 2; // offset
- n += 1; // type index
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- }
-
- if (pos.type.hasLocation()) {
- n += 2; // length
- n += 1 * pos.location.size(); // actual array size
- }
-
- return n;
- }
-
- // Code duplicated from com.sun.tools.javac.code.TypeAnnotations.Position
- public static class Position {
-
- public TargetType type = TargetType.UNKNOWN;
-
- // For generic/array types.
- public List<Integer> location = new ArrayList<Integer>();
-
- // For typecasts, type tests, new (and locals, as start_pc).
- public int offset = -1;
-
- // For locals.
- public int[] lvarOffset = null;
- public int[] lvarLength = null;
- public int[] lvarIndex = null;
-
- // For type parameter bound
- public int bound_index = Integer.MIN_VALUE;
-
- // For type parameter and method parameter
- public int parameter_index = Integer.MIN_VALUE;
-
- // For class extends, implements, and throws classes
- public int type_index = Integer.MIN_VALUE;
-
- // For wildcards
- public Position wildcard_position = null;
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append('[');
- sb.append(type);
-
- switch (type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- sb.append(", offset = ");
- sb.append(offset);
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- sb.append(", {");
- for (int i = 0; i < lvarOffset.length; ++i) {
- if (i != 0) sb.append("; ");
- sb.append(", start_pc = ");
- sb.append(lvarOffset[i]);
- sb.append(", length = ");
- sb.append(lvarLength[i]);
- sb.append(", index = ");
- sb.append(lvarIndex[i]);
- }
- sb.append("}");
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- sb.append(", param_index = ");
- sb.append(parameter_index);
- break;
- // type parameters bound
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- sb.append(", param_index = ");
- sb.append(parameter_index);
- sb.append(", bound_index = ");
- sb.append(bound_index);
- break;
- // wildcard
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- sb.append(", wild_card = ");
- sb.append(wildcard_position);
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- sb.append(", type_index = ");
- sb.append(type_index);
- break;
- // throws
- case THROWS:
- sb.append(", type_index = ");
- sb.append(type_index);
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- sb.append(", offset = ");
- sb.append(offset);
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- sb.append(", param_index = ");
- sb.append(parameter_index);
- break;
- // method type argument: wasn't specified
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- sb.append(", offset = ");
- sb.append(offset);
- sb.append(", type_index = ");
- sb.append(type_index);
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- throw new AssertionError("unknown type: " + type);
- }
-
- // Append location data for generics/arrays.
- if (type.hasLocation()) {
- sb.append(", location = (");
- sb.append(location);
- sb.append(")");
- }
-
- sb.append(']');
- return sb.toString();
- }
- }
-
- // Code duplicated from com.sun.tools.javac.comp.TargetType
- public enum TargetType {
-
- /** For annotations on typecasts. */
- TYPECAST(0x00),
-
- /** For annotations on a type argument or nested array of a typecast. */
- TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation),
-
- /** For annotations on type tests. */
- INSTANCEOF(0x02),
-
- /** For annotations on a type argument or nested array of a type test. */
- INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation),
-
- /** For annotations on object creation expressions. */
- NEW(0x04),
-
- /**
- * For annotations on a type argument or nested array of an object creation
- * expression.
- */
- NEW_GENERIC_OR_ARRAY(0x05, HasLocation),
-
-
- /** For annotations on the method receiver. */
- METHOD_RECEIVER(0x06),
-
- // invalid location
- // METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation),
-
- /** For annotations on local variables. */
- LOCAL_VARIABLE(0x08),
-
- /** For annotations on a type argument or nested array of a local. */
- LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation),
-
- // already handled by regular annotations
- // METHOD_RETURN(0x0A),
-
- /**
- * For annotations on a type argument or nested array of a method return
- * type.
- */
- METHOD_RETURN_GENERIC_OR_ARRAY(0x0B, HasLocation),
-
- // already handled by regular annotations
- // METHOD_PARAMETER(0x0C),
-
- /** For annotations on a type argument or nested array of a method parameter. */
- METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation),
-
- // already handled by regular annotations
- // FIELD(0x0E),
-
- /** For annotations on a type argument or nested array of a field. */
- FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation),
-
- /** For annotations on a bound of a type parameter of a class. */
- CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter),
-
- /**
- * For annotations on a type argument or nested array of a bound of a type
- * parameter of a class.
- */
- CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x11, HasBound, HasLocation, HasParameter),
-
- /** For annotations on a bound of a type parameter of a method. */
- METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter),
-
- /**
- * For annotations on a type argument or nested array of a bound of a type
- * parameter of a method.
- */
- METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x13, HasBound, HasLocation, HasParameter),
-
- /** For annotations on the type of an "extends" or "implements" clause. */
- CLASS_EXTENDS(0x14),
-
- /** For annotations on the inner type of an "extends" or "implements" clause. */
- CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation),
-
- /** For annotations on a throws clause in a method declaration. */
- THROWS(0x16),
-
- // invalid location
- // THROWS_GENERIC_OR_ARRAY(0x17, HasLocation),
-
- /** For annotations in type arguments of object creation expressions. */
- NEW_TYPE_ARGUMENT(0x18),
- NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation),
-
- METHOD_TYPE_ARGUMENT(0x1A),
- METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation),
-
- WILDCARD_BOUND(0x1C, HasBound),
- WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation),
-
- CLASS_LITERAL(0x1E),
- CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation),
-
- METHOD_TYPE_PARAMETER(0x20, HasParameter),
-
- // invalid location
- // METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter),
-
- CLASS_TYPE_PARAMETER(0x22, HasParameter),
-
- // invalid location
- // CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter),
-
- /** For annotations with an unknown target. */
- UNKNOWN(-1);
-
- static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
-
- private final int targetTypeValue;
- private Set<TargetAttribute> flags;
-
- TargetType(int targetTypeValue, TargetAttribute... attrs) {
- if (targetTypeValue < Byte.MIN_VALUE
- || targetTypeValue > Byte.MAX_VALUE)
- throw new AssertionError("attribute type value needs to be a byte: " + targetTypeValue);
- this.targetTypeValue = (byte)targetTypeValue;
- this.flags = EnumSet.noneOf(TargetAttribute.class);
- for (TargetAttribute attr : attrs)
- this.flags.add(attr);
- }
-
- /**
- * Returns whether or not this TargetType represents an annotation whose
- * target is an inner type of a generic or array type.
- *
- * @return true if this TargetType represents an annotation on an inner
- * type, false otherwise
- */
- public boolean hasLocation() {
- return flags.contains(HasLocation);
- }
-
- public TargetType getGenericComplement() {
- if (hasLocation())
- return this;
- else
- return fromTargetTypeValue(targetTypeValue() + 1);
- }
-
- /**
- * Returns whether or not this TargetType represents an annotation whose
- * target has a parameter index.
- *
- * @return true if this TargetType has a parameter index,
- * false otherwise
- */
- public boolean hasParameter() {
- return flags.contains(HasParameter);
- }
-
- /**
- * Returns whether or not this TargetType represents an annotation whose
- * target is a type parameter bound.
- *
- * @return true if this TargetType represents an type parameter bound
- * annotation, false otherwise
- */
- public boolean hasBound() {
- return flags.contains(HasBound);
- }
-
- public int targetTypeValue() {
- return this.targetTypeValue;
- }
-
- private static TargetType[] targets = null;
-
- private static TargetType[] buildTargets() {
- TargetType[] targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
- TargetType[] alltargets = values();
- for (TargetType target : alltargets)
- if (target.targetTypeValue >= 0)
- targets[target.targetTypeValue] = target;
- for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i)
- if (targets[i] == null)
- targets[i] = UNKNOWN;
- return targets;
- }
-
- public static boolean isValidTargetTypeValue(int tag) {
- if (targets == null)
- targets = buildTargets();
-
- if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
- return true;
-
- return (tag >= 0 && tag < targets.length);
- }
-
- public static TargetType fromTargetTypeValue(int tag) {
- if (targets == null)
- targets = buildTargets();
-
- if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
- return UNKNOWN;
-
- if (tag < 0 || tag >= targets.length)
- throw new IllegalArgumentException("Unknown TargetType: " + tag);
- return targets[tag];
- }
- }
-
- static enum TargetAttribute {
- HasLocation, HasParameter, HasBound;
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeInvisibleTypeAnnotations_attribute.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.classfile;
-
-import java.io.IOException;
-
-/**
- * See JSR 308 specification, section 4.1
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class RuntimeInvisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute {
- RuntimeInvisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length)
- throws IOException, Annotation.InvalidAnnotation {
- super(cr, name_index, length);
- }
-
- public RuntimeInvisibleTypeAnnotations_attribute(ConstantPool cp, ExtendedAnnotation[] annotations)
- throws ConstantPoolException {
- this(cp.getUTF8Index(Attribute.RuntimeInvisibleTypeAnnotations), annotations);
- }
-
- public RuntimeInvisibleTypeAnnotations_attribute(int name_index, ExtendedAnnotation[] annotations) {
- super(name_index, annotations);
- }
-
- public <R, P> R accept(Visitor<R, P> visitor, P p) {
- return visitor.visitRuntimeInvisibleTypeAnnotations(this, p);
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeTypeAnnotations_attribute.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.classfile;
-
-import java.io.IOException;
-
-/**
- * See JSR 308 specification, section 4
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public abstract class RuntimeTypeAnnotations_attribute extends Attribute {
- protected RuntimeTypeAnnotations_attribute(ClassReader cr, int name_index, int length)
- throws IOException, Annotation.InvalidAnnotation {
- super(name_index, length);
- int num_annotations = cr.readUnsignedShort();
- annotations = new ExtendedAnnotation[num_annotations];
- for (int i = 0; i < annotations.length; i++)
- annotations[i] = new ExtendedAnnotation(cr);
- }
-
- protected RuntimeTypeAnnotations_attribute(int name_index, ExtendedAnnotation[] annotations) {
- super(name_index, length(annotations));
- this.annotations = annotations;
- }
-
- private static int length(ExtendedAnnotation[] annos) {
- int n = 2;
- for (ExtendedAnnotation anno: annos)
- n += anno.length();
- return n;
- }
-
- public final ExtendedAnnotation[] annotations;
-}
--- a/langtools/src/share/classes/com/sun/tools/classfile/RuntimeVisibleTypeAnnotations_attribute.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2007, 2008, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.classfile;
-
-import java.io.IOException;
-
-/**
- * See JSR 308 specification, section 4.1
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class RuntimeVisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute {
- RuntimeVisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length)
- throws IOException, Annotation.InvalidAnnotation {
- super(cr, name_index, length);
- }
-
- public RuntimeVisibleTypeAnnotations_attribute(ConstantPool cp, ExtendedAnnotation[] annotations)
- throws ConstantPoolException {
- this(cp.getUTF8Index(Attribute.RuntimeVisibleTypeAnnotations), annotations);
- }
-
- public RuntimeVisibleTypeAnnotations_attribute(int name_index, ExtendedAnnotation[] annotations) {
- super(name_index, annotations);
- }
-
- public <R, P> R accept(Visitor<R, P> visitor, P p) {
- return visitor.visitRuntimeVisibleTypeAnnotations(this, p);
- }
-}
--- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java Fri Feb 18 12:04:36 2011 -0800
@@ -755,22 +755,30 @@
if (!isInline() && !endsWithNewLine(contentBuilder))
contentBuilder.append(DocletConstants.NL);
String tagString = htmlTag.toString();
- contentBuilder.append("<" + tagString);
+ contentBuilder.append("<");
+ contentBuilder.append(tagString);
Iterator<HtmlAttr> iterator = attrs.keySet().iterator();
HtmlAttr key;
String value = "";
while (iterator.hasNext()) {
key = iterator.next();
value = attrs.get(key);
- contentBuilder.append(" " + key.toString());
- if (!value.isEmpty())
- contentBuilder.append("=\"" + value + "\"");
+ contentBuilder.append(" ");
+ contentBuilder.append(key.toString());
+ if (!value.isEmpty()) {
+ contentBuilder.append("=\"");
+ contentBuilder.append(value);
+ contentBuilder.append("\"");
+ }
}
contentBuilder.append(">");
for (Content c : content)
c.write(contentBuilder);
- if (htmlTag.endTagRequired())
- contentBuilder.append("</" + tagString + ">");
+ if (htmlTag.endTagRequired()) {
+ contentBuilder.append("</");
+ contentBuilder.append(tagString);
+ contentBuilder.append(">");
+ }
if (!isInline())
contentBuilder.append(DocletConstants.NL);
}
--- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Content.java Fri Feb 18 12:04:36 2011 -0800
@@ -99,8 +99,24 @@
* @param contentBuilder content to test for newline character at the end
* @return true if the content ends with newline.
*/
- public boolean endsWithNewLine(StringBuilder contentBuilder) {
- return ((contentBuilder.length() == 0) ||
- (contentBuilder.toString().endsWith(DocletConstants.NL)));
+ protected boolean endsWithNewLine(StringBuilder contentBuilder) {
+ int contentLength = contentBuilder.length();
+ if (contentLength == 0) {
+ return true;
+ }
+ int nlLength = DocletConstants.NL.length();
+ if (contentLength < nlLength) {
+ return false;
+ }
+ int contentIndex = contentLength - 1;
+ int nlIndex = nlLength - 1;
+ while (nlIndex >= 0) {
+ if (contentBuilder.charAt(contentIndex) != DocletConstants.NL.charAt(nlIndex)) {
+ return false;
+ }
+ contentIndex--;
+ nlIndex--;
+ }
+ return true;
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/Main.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/Main.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2006, 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
@@ -43,12 +43,6 @@
*/
public class Main {
- static {
- ClassLoader loader = Main.class.getClassLoader();
- if (loader != null)
- loader.setPackageAssertionStatus("com.sun.tools.javac", true);
- }
-
/** Unsupported command line interface.
* @param args The command line parameters.
*/
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -204,21 +204,6 @@
}
}
- public static class TypeCompound extends Compound {
- public TypeAnnotationPosition position;
- public TypeCompound(Compound compound,
- TypeAnnotationPosition position) {
- this(compound.type, compound.values, position);
- }
- public TypeCompound(Type type,
- List<Pair<MethodSymbol, Attribute>> values,
- TypeAnnotationPosition position) {
- super(type, values);
- this.position = position;
- }
-
- }
-
/** The value for an annotation element of an array type.
*/
public static class Array extends Attribute {
@@ -255,8 +240,7 @@
public VarSymbol value;
public Enum(Type type, VarSymbol value) {
super(type);
- assert value != null;
- this.value = value;
+ this.value = Assert.checkNonNull(value);
}
public void accept(Visitor v) { v.visitEnum(this); }
public String toString() {
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Scope.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -133,7 +133,7 @@
*/
private Scope(Scope next, Symbol owner, Entry[] table, ScopeCounter scopeCounter) {
this.next = next;
- assert emptyScope == null || owner != null;
+ Assert.check(emptyScope == null || owner != null);
this.owner = owner;
this.table = table;
this.hashMask = table.length - 1;
@@ -191,16 +191,16 @@
* with next.
*/
public Scope leave() {
- assert shared == 0;
+ Assert.check(shared == 0);
if (table != next.table) return next;
while (elems != null) {
int hash = getIndex(elems.sym.name);
Entry e = table[hash];
- assert e == elems : elems.sym;
+ Assert.check(e == elems, elems.sym);
table[hash] = elems.shadowed;
elems = elems.sibling;
}
- assert next.shared > 0;
+ Assert.check(next.shared > 0);
next.shared--;
next.nelems = nelems;
// System.out.println("====> leaving scope " + this.hashCode() + " owned by " + this.owner + " to " + next.hashCode());
@@ -211,12 +211,12 @@
/** Double size of hash table.
*/
private void dble() {
- assert shared == 0;
+ Assert.check(shared == 0);
Entry[] oldtable = table;
Entry[] newtable = new Entry[oldtable.length * 2];
for (Scope s = this; s != null; s = s.next) {
if (s.table == oldtable) {
- assert s == this || s.shared != 0;
+ Assert.check(s == this || s.shared != 0);
s.table = newtable;
s.hashMask = newtable.length - 1;
}
@@ -237,7 +237,7 @@
/** Enter symbol sym in this scope.
*/
public void enter(Symbol sym) {
- assert shared == 0;
+ Assert.check(shared == 0);
enter(sym, this);
}
@@ -251,7 +251,7 @@
* arguments are only used in import scopes.
*/
public void enter(Symbol sym, Scope s, Scope origin) {
- assert shared == 0;
+ Assert.check(shared == 0);
if (nelems * 3 >= hashMask * 2)
dble();
int hash = getIndex(sym.name);
@@ -274,7 +274,7 @@
* attribute tells us that the class isn't a package member.
*/
public void remove(Symbol sym) {
- assert shared == 0;
+ Assert.check(shared == 0);
Entry e = lookup(sym.name);
if (e.scope == null) return;
@@ -314,7 +314,7 @@
/** Enter symbol sym in this scope if not already there.
*/
public void enterIfAbsent(Symbol sym) {
- assert shared == 0;
+ Assert.check(shared == 0);
Entry e = lookup(sym.name);
while (e.scope == this && e.sym.kind != sym.kind) e = e.next();
if (e.scope != this) enter(sym);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 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
@@ -81,8 +81,7 @@
* method to make sure that the class symbol is loaded.
*/
public List<Attribute.Compound> getAnnotationMirrors() {
- assert attributes_field != null;
- return attributes_field;
+ return Assert.checkNonNull(attributes_field);
}
/** Fetch a particular annotation from a symbol. */
@@ -100,17 +99,6 @@
*/
public Type type;
- /** The type annotations targeted to a tree directly owned by this symbol
- */
- // type annotations are stored here for two purposes:
- // - convenient location to store annotations for generation after erasure
- // - a private interface for accessing type annotations parsed from
- // classfiles
- // the field is populated for the following declaration only
- // class, field, variable and type parameters
- //
- public List<Attribute.TypeCompound> typeAnnotations;
-
/** The owner of this symbol.
*/
public Symbol owner;
@@ -133,7 +121,6 @@
this.completer = null;
this.erasure_field = null;
this.attributes_field = List.nil();
- this.typeAnnotations = List.nil();
this.name = name;
}
@@ -608,7 +595,7 @@
}
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
- assert type.tag == TYPEVAR; // else override will be invoked
+ Assert.check(type.tag == TYPEVAR); // else override will be invoked
return v.visitTypeParameter(this, p);
}
@@ -682,8 +669,7 @@
if (attributes_field.isEmpty())
attributes_field = package_info.attributes_field;
}
- assert attributes_field != null;
- return attributes_field;
+ return Assert.checkNonNull(attributes_field);
}
/** A package "exists" if a type or package that exists has
@@ -780,8 +766,7 @@
public List<Attribute.Compound> getAnnotationMirrors() {
if (completer != null) complete();
- assert attributes_field != null;
- return attributes_field;
+ return Assert.checkNonNull(attributes_field);
}
public Type erasure(Types types) {
@@ -1032,7 +1017,7 @@
}
public void setData(Object data) {
- assert !(data instanceof Env<?>) : this;
+ Assert.check(!(data instanceof Env<?>), this);
this.data = data;
}
@@ -1064,7 +1049,7 @@
*/
public MethodSymbol(long flags, Name name, Type type, Symbol owner) {
super(MTH, flags, name, type, owner);
- assert owner.type.tag != TYPEVAR : owner + "." + name;
+ if (owner.type.tag == TYPEVAR) Assert.error(owner + "." + name);
}
/** Clone this symbol with new owner.
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Feb 18 12:04:36 2011 -0800
@@ -126,7 +126,6 @@
public final Type serializableType;
public final Type methodHandleType;
public final Type polymorphicSignatureType;
- public final Type invokeDynamicType;
public final Type throwableType;
public final Type errorType;
public final Type illegalArgumentExceptionType;
@@ -422,7 +421,6 @@
serializableType = enterClass("java.io.Serializable");
methodHandleType = enterClass("java.dyn.MethodHandle");
polymorphicSignatureType = enterClass("java.dyn.MethodHandle$PolymorphicSignature");
- invokeDynamicType = enterClass("java.dyn.InvokeDynamic");
errorType = enterClass("java.lang.Error");
illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
exceptionType = enterClass("java.lang.Exception");
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -138,7 +138,7 @@
*/
public Type constType(Object constValue) {
final Object value = constValue;
- assert tag <= BOOLEAN;
+ Assert.check(tag <= BOOLEAN);
return new Type(tag, tsym) {
@Override
public Object constValue() {
@@ -202,13 +202,13 @@
* The constant value of this type, converted to String
*/
public String stringValue() {
- assert constValue() != null;
+ Object cv = Assert.checkNonNull(constValue());
if (tag == BOOLEAN)
- return ((Integer) constValue()).intValue() == 0 ? "false" : "true";
+ return ((Integer) cv).intValue() == 0 ? "false" : "true";
else if (tag == CHAR)
- return String.valueOf((char) ((Integer) constValue()).intValue());
+ return String.valueOf((char) ((Integer) cv).intValue());
else
- return constValue().toString();
+ return cv.toString();
}
/**
@@ -365,6 +365,16 @@
return false;
}
+ public static List<Type> filter(List<Type> ts, Filter<Type> tf) {
+ ListBuffer<Type> buf = ListBuffer.lb();
+ for (Type t : ts) {
+ if (tf.accepts(t)) {
+ buf.append(t);
+ }
+ }
+ return buf.toList();
+ }
+
public boolean isSuperBound() { return false; }
public boolean isExtendsBound() { return false; }
public boolean isUnbound() { return false; }
@@ -428,9 +438,8 @@
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym) {
super(WILDCARD, tsym);
- assert(type != null);
+ this.type = Assert.checkNonNull(type);
this.kind = kind;
- this.type = type;
}
public WildcardType(WildcardType t, TypeVar bound) {
this(t.type, t.kind, t.tsym, bound);
@@ -1021,9 +1030,8 @@
Type lower,
WildcardType wildcard) {
super(name, owner, lower);
- assert lower != null;
+ this.lower = Assert.checkNonNull(lower);
this.bound = upper;
- this.lower = lower;
this.wildcard = wildcard;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,403 +0,0 @@
-/*
- * Copyright (c) 2009, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package com.sun.tools.javac.code;
-
-import javax.lang.model.element.ElementKind;
-
-import com.sun.tools.javac.code.Symbol.VarSymbol;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.TreeInfo;
-import com.sun.tools.javac.tree.TreeScanner;
-import com.sun.tools.javac.tree.JCTree.*;
-import com.sun.tools.javac.util.Context;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.ListBuffer;
-
-/**
- * Contains operations specific to processing type annotations
- */
-public class TypeAnnotations {
- private static final Context.Key<TypeAnnotations> key
- = new Context.Key<TypeAnnotations>();
-
- public static TypeAnnotations instance(Context context) {
- TypeAnnotations instance = context.get(key);
- if (instance == null)
- instance = new TypeAnnotations(context);
- return instance;
- }
-
- protected TypeAnnotations(Context context) {
- context.put(key, this);
- }
-
- public void taFillAndLift(JCClassDecl tree, boolean visitBodies) {
-//308 new TypeAnnotationPositions().scan(tree);
-//308 new TypeAnnotationLift().scan(tree);
- }
-
- private static class TypeAnnotationPositions extends TreeScanner {
-
- private ListBuffer<JCTree> frames = ListBuffer.lb();
- private void push(JCTree t) { frames = frames.prepend(t); }
- private JCTree pop() { return frames.next(); }
- private JCTree peek2() { return frames.toList().tail.head; }
-
- @Override
- public void scan(JCTree tree) {
- push(tree);
- super.scan(tree);
- pop();
- }
-
- private boolean inClass = false;
-
- @Override
- public void visitClassDef(JCClassDecl tree) {
- if (!inClass) {
- // Do not recurse into nested and inner classes since
- // TransTypes.visitClassDef makes an invocation for each class
- // separately.
- inClass = true;
- try {
- super.visitClassDef(tree);
- } finally {
- inClass = false;
- }
- }
- }
-
- private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame,
- List<JCTree> path, TypeAnnotationPosition p) {
- switch (frame.getKind()) {
- case TYPE_CAST:
- p.type = TargetType.TYPECAST;
- p.pos = frame.pos;
- return p;
-
- case INSTANCE_OF:
- p.type = TargetType.INSTANCEOF;
- p.pos = frame.pos;
- return p;
-
- case NEW_CLASS:
- p.type = TargetType.NEW;
- p.pos = frame.pos;
- return p;
-
- case NEW_ARRAY:
- p.type = TargetType.NEW;
- p.pos = frame.pos;
- return p;
-
- case ANNOTATION_TYPE:
- case CLASS:
- case ENUM:
- case INTERFACE:
- p.pos = frame.pos;
- if (((JCClassDecl)frame).extending == tree) {
- p.type = TargetType.CLASS_EXTENDS;
- p.type_index = -1;
- } else if (((JCClassDecl)frame).implementing.contains(tree)) {
- p.type = TargetType.CLASS_EXTENDS;
- p.type_index = ((JCClassDecl)frame).implementing.indexOf(tree);
- } else if (((JCClassDecl)frame).typarams.contains(tree)) {
- p.type = TargetType.CLASS_TYPE_PARAMETER;
- p.parameter_index = ((JCClassDecl)frame).typarams.indexOf(tree);
- } else
- throw new AssertionError();
- return p;
-
- case METHOD: {
- JCMethodDecl frameMethod = (JCMethodDecl)frame;
- p.pos = frame.pos;
- if (frameMethod.receiverAnnotations.contains(tree))
- p.type = TargetType.METHOD_RECEIVER;
- else if (frameMethod.thrown.contains(tree)) {
- p.type = TargetType.THROWS;
- p.type_index = frameMethod.thrown.indexOf(tree);
- } else if (((JCMethodDecl)frame).restype == tree) {
- p.type = TargetType.METHOD_RETURN_GENERIC_OR_ARRAY;
- } else if (frameMethod.typarams.contains(tree)) {
- p.type = TargetType.METHOD_TYPE_PARAMETER;
- p.parameter_index = frameMethod.typarams.indexOf(tree);
- } else
- throw new AssertionError();
- return p;
- }
- case MEMBER_SELECT: {
- JCFieldAccess fieldFrame = (JCFieldAccess)frame;
- if ("class".contentEquals(fieldFrame.name)) {
- p.type = TargetType.CLASS_LITERAL;
- p.pos = TreeInfo.innermostType(fieldFrame.selected).pos;
- } else
- throw new AssertionError();
- return p;
- }
- case PARAMETERIZED_TYPE: {
- TypeAnnotationPosition nextP;
- if (((JCTypeApply)frame).clazz == tree)
- nextP = p; // generic: RAW; noop
- else if (((JCTypeApply)frame).arguments.contains(tree))
- p.location = p.location.prepend(
- ((JCTypeApply)frame).arguments.indexOf(tree));
- else
- throw new AssertionError();
-
- List<JCTree> newPath = path.tail;
- return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
- }
-
- case ARRAY_TYPE: {
- p.location = p.location.prepend(0);
- List<JCTree> newPath = path.tail;
- return resolveFrame(newPath.head, newPath.tail.head, newPath, p);
- }
-
- case TYPE_PARAMETER:
- if (path.tail.tail.head.getTag() == JCTree.CLASSDEF) {
- JCClassDecl clazz = (JCClassDecl)path.tail.tail.head;
- p.type = TargetType.CLASS_TYPE_PARAMETER_BOUND;
- p.parameter_index = clazz.typarams.indexOf(path.tail.head);
- p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
- } else if (path.tail.tail.head.getTag() == JCTree.METHODDEF) {
- JCMethodDecl method = (JCMethodDecl)path.tail.tail.head;
- p.type = TargetType.METHOD_TYPE_PARAMETER_BOUND;
- p.parameter_index = method.typarams.indexOf(path.tail.head);
- p.bound_index = ((JCTypeParameter)frame).bounds.indexOf(tree);
- } else
- throw new AssertionError();
- p.pos = frame.pos;
- return p;
-
- case VARIABLE:
- VarSymbol v = ((JCVariableDecl)frame).sym;
- p.pos = frame.pos;
- switch (v.getKind()) {
- case LOCAL_VARIABLE:
- p.type = TargetType.LOCAL_VARIABLE; break;
- case FIELD:
- p.type = TargetType.FIELD_GENERIC_OR_ARRAY; break;
- case PARAMETER:
- p.type = TargetType.METHOD_PARAMETER_GENERIC_OR_ARRAY;
- p.parameter_index = methodParamIndex(path, frame);
- break;
- default: throw new AssertionError();
- }
- return p;
-
-//308 case ANNOTATED_TYPE: {
-//308 List<JCTree> newPath = path.tail;
-//308 return resolveFrame(newPath.head, newPath.tail.head,
-//308 newPath, p);
-//308 }
-
- case METHOD_INVOCATION: {
- JCMethodInvocation invocation = (JCMethodInvocation)frame;
- if (!invocation.typeargs.contains(tree))
- throw new AssertionError("{" + tree + "} is not an argument in the invocation: " + invocation);
- p.type = TargetType.METHOD_TYPE_ARGUMENT;
- p.pos = invocation.pos;
- p.type_index = invocation.typeargs.indexOf(tree);
- return p;
- }
-
- case EXTENDS_WILDCARD:
- case SUPER_WILDCARD: {
- p.type = TargetType.WILDCARD_BOUND;
- List<JCTree> newPath = path.tail;
-
- TypeAnnotationPosition wildcard =
- resolveFrame(newPath.head, newPath.tail.head, newPath,
- new TypeAnnotationPosition());
- if (!wildcard.location.isEmpty())
- wildcard.type = wildcard.type.getGenericComplement();
- p.wildcard_position = wildcard;
- p.pos = frame.pos;
- return p;
- }
- }
- return p;
- }
-
- private void setTypeAnnotationPos(List<JCTypeAnnotation> annotations, TypeAnnotationPosition position) {
- for (JCTypeAnnotation anno : annotations) {
- anno.annotation_position = position;
- anno.attribute_field.position = position;
- }
- }
-
- @Override
- public void visitNewArray(JCNewArray tree) {
- findPosition(tree, tree, tree.annotations);
- int dimAnnosCount = tree.dimAnnotations.size();
-
- // handle annotations associated with dimentions
- for (int i = 0; i < dimAnnosCount; ++i) {
- TypeAnnotationPosition p = new TypeAnnotationPosition();
- p.type = TargetType.NEW_GENERIC_OR_ARRAY;
- p.pos = tree.pos;
- p.location = p.location.append(i);
- setTypeAnnotationPos(tree.dimAnnotations.get(i), p);
- }
-
- // handle "free" annotations
- int i = dimAnnosCount == 0 ? 0 : dimAnnosCount - 1;
- JCExpression elemType = tree.elemtype;
- while (elemType != null) {
- if (elemType.getTag() == JCTree.ANNOTATED_TYPE) {
- JCAnnotatedType at = (JCAnnotatedType)elemType;
- TypeAnnotationPosition p = new TypeAnnotationPosition();
- p.type = TargetType.NEW_GENERIC_OR_ARRAY;
- p.pos = tree.pos;
- p.location = p.location.append(i);
- setTypeAnnotationPos(at.annotations, p);
- elemType = at.underlyingType;
- } else if (elemType.getTag() == JCTree.TYPEARRAY) {
- ++i;
- elemType = ((JCArrayTypeTree)elemType).elemtype;
- } else
- break;
- }
-
- // find annotations locations of initializer elements
- scan(tree.elems);
- }
-
- @Override
- public void visitAnnotatedType(JCAnnotatedType tree) {
- findPosition(tree, peek2(), tree.annotations);
- super.visitAnnotatedType(tree);
- }
-
- @Override
- public void visitMethodDef(JCMethodDecl tree) {
- TypeAnnotationPosition p = new TypeAnnotationPosition();
- p.type = TargetType.METHOD_RECEIVER;
- setTypeAnnotationPos(tree.receiverAnnotations, p);
- super.visitMethodDef(tree);
- }
- @Override
- public void visitTypeParameter(JCTypeParameter tree) {
- findPosition(tree, peek2(), tree.annotations);
- super.visitTypeParameter(tree);
- }
-
- void findPosition(JCTree tree, JCTree frame, List<JCTypeAnnotation> annotations) {
- if (!annotations.isEmpty()) {
- TypeAnnotationPosition p =
- resolveFrame(tree, frame, frames.toList(),
- new TypeAnnotationPosition());
- if (!p.location.isEmpty())
- p.type = p.type.getGenericComplement();
- setTypeAnnotationPos(annotations, p);
- }
- }
-
- private int methodParamIndex(List<JCTree> path, JCTree param) {
- List<JCTree> curr = path;
- if (curr.head != param)
- curr = path.tail;
- JCMethodDecl method = (JCMethodDecl)curr.tail.head;
- return method.params.indexOf(param);
- }
- }
-
- private static class TypeAnnotationLift extends TreeScanner {
- List<Attribute.TypeCompound> recordedTypeAnnotations = List.nil();
-
- boolean isInner = false;
- @Override
- public void visitClassDef(JCClassDecl tree) {
- if (isInner) {
- // tree is an inner class tree. stop now.
- // TransTypes.visitClassDef makes an invocation for each class
- // separately.
- return;
- }
- isInner = true;
- List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
- recordedTypeAnnotations = List.nil();
- try {
- super.visitClassDef(tree);
- } finally {
- tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
- recordedTypeAnnotations = prevTAs;
- }
- }
-
- @Override
- public void visitMethodDef(JCMethodDecl tree) {
- List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
- recordedTypeAnnotations = List.nil();
- try {
- super.visitMethodDef(tree);
- } finally {
- tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
- recordedTypeAnnotations = prevTAs;
- }
- }
-
- @Override
- public void visitVarDef(JCVariableDecl tree) {
- List<Attribute.TypeCompound> prevTAs = recordedTypeAnnotations;
- recordedTypeAnnotations = List.nil();
- ElementKind kind = tree.sym.getKind();
- if (kind == ElementKind.LOCAL_VARIABLE && tree.mods.annotations.nonEmpty()) {
- // need to lift the annotations
- TypeAnnotationPosition position = new TypeAnnotationPosition();
- position.pos = tree.pos;
- position.type = TargetType.LOCAL_VARIABLE;
- for (Attribute.Compound attribute : tree.sym.attributes_field) {
- Attribute.TypeCompound tc =
- new Attribute.TypeCompound(attribute.type, attribute.values, position);
- recordedTypeAnnotations = recordedTypeAnnotations.append(tc);
- }
- }
- try {
- super.visitVarDef(tree);
- } finally {
- if (kind.isField() || kind == ElementKind.LOCAL_VARIABLE)
- tree.sym.typeAnnotations = tree.sym.typeAnnotations.appendList(recordedTypeAnnotations);
- recordedTypeAnnotations = kind.isField() ? prevTAs : prevTAs.appendList(recordedTypeAnnotations);
- }
- }
-
- @Override
- public void visitApply(JCMethodInvocation tree) {
- scan(tree.meth);
- scan(tree.typeargs);
- scan(tree.args);
- }
-
- public void visitAnnotation(JCAnnotation tree) {
- if (tree instanceof JCTypeAnnotation)
- recordedTypeAnnotations = recordedTypeAnnotations.append(((JCTypeAnnotation)tree).attribute_field);
- super.visitAnnotation(tree);
- }
- }
-
-}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1061,8 +1061,9 @@
highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym);
}
if (highSub != null) {
- assert a.tsym == highSub.tsym && a.tsym == lowSub.tsym
- : a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym;
+ if (!(a.tsym == highSub.tsym && a.tsym == lowSub.tsym)) {
+ Assert.error(a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym);
+ }
if (!disjointTypes(aHigh.allparams(), highSub.allparams())
&& !disjointTypes(aHigh.allparams(), lowSub.allparams())
&& !disjointTypes(aLow.allparams(), highSub.allparams())
@@ -1703,9 +1704,9 @@
bt.supertype_field = bounds.head;
bt.interfaces_field = bounds.tail;
}
- assert bt.supertype_field.tsym.completer != null
- || !bt.supertype_field.isInterface()
- : bt.supertype_field;
+ Assert.check(bt.supertype_field.tsym.completer != null
+ || !bt.supertype_field.isInterface(),
+ bt.supertype_field);
return bt;
}
@@ -1834,7 +1835,7 @@
// t.interfaces_field is null after
// completion, we can assume that t is not the
// type of a class/interface declaration.
- assert t != t.tsym.type : t.toString();
+ Assert.check(t != t.tsym.type, t);
List<Type> actuals = t.allparams();
List<Type> formals = t.tsym.type.allparams();
if (t.hasErasedSupertypes()) {
@@ -2646,7 +2647,7 @@
act2 = act2.tail;
typarams = typarams.tail;
}
- assert(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
+ Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
return new ClassType(class1.getEnclosingType(), merged.toList(), class1.tsym);
}
@@ -2758,7 +2759,7 @@
// calculate lub(A, B)
while (ts.head.tag != CLASS && ts.head.tag != TYPEVAR)
ts = ts.tail;
- assert !ts.isEmpty();
+ Assert.check(!ts.isEmpty());
List<Type> cl = closure(ts.head);
for (Type t : ts.tail) {
if (t.tag == CLASS || t.tag == TYPEVAR)
@@ -3138,7 +3139,7 @@
boolean reverse = false;
Type target = to;
if ((to.tsym.flags() & INTERFACE) == 0) {
- assert (from.tsym.flags() & INTERFACE) != 0;
+ Assert.check((from.tsym.flags() & INTERFACE) != 0);
reverse = true;
to = from;
from = target;
@@ -3173,12 +3174,12 @@
boolean reverse = false;
Type target = to;
if ((to.tsym.flags() & INTERFACE) == 0) {
- assert (from.tsym.flags() & INTERFACE) != 0;
+ Assert.check((from.tsym.flags() & INTERFACE) != 0);
reverse = true;
to = from;
from = target;
}
- assert (from.tsym.flags() & FINAL) != 0;
+ Assert.check((from.tsym.flags() & FINAL) != 0);
Type t1 = asSuper(from, to.tsym);
if (t1 == null) return false;
Type t2 = to;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -563,7 +563,7 @@
if (bound != null && bound.tsym instanceof ClassSymbol) {
ClassSymbol c = (ClassSymbol)bound.tsym;
if ((c.flags_field & COMPOUND) != 0) {
- assert (c.flags_field & UNATTRIBUTED) != 0 : c;
+ Assert.check((c.flags_field & UNATTRIBUTED) != 0, c);
attribClass(typaram.pos(), c);
}
}
@@ -905,7 +905,10 @@
// or perhaps expr implements Iterable<T>?
Type base = types.asSuper(exprType, syms.iterableType.tsym);
if (base == null) {
- log.error(tree.expr.pos(), "foreach.not.applicable.to.type");
+ log.error(tree.expr.pos(),
+ "foreach.not.applicable.to.type",
+ exprType,
+ diags.fragment("type.req.array.or.iterable"));
elemtype = types.createErrorType(exprType);
} else {
List<Type> iterableParams = base.allparams();
@@ -970,7 +973,7 @@
if (enumSwitch) {
Symbol sym = enumConstant(c.pat, seltype);
if (sym == null) {
- log.error(c.pat.pos(), "enum.const.req");
+ log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
} else if (!labels.add(sym)) {
log.error(c.pos(), "duplicate.case.label");
}
@@ -1334,7 +1337,6 @@
// The types of the actual method type arguments.
List<Type> typeargtypes = null;
- boolean typeargtypesNonRefOK = false;
Name methName = TreeInfo.name(tree.meth);
@@ -1434,7 +1436,7 @@
localEnv.info.varArgs = false;
Type mtype = attribExpr(tree.meth, localEnv, mpt);
if (localEnv.info.varArgs)
- assert mtype.isErroneous() || tree.varargsElement != null;
+ Assert.check(mtype.isErroneous() || tree.varargsElement != null);
// Compute the result type.
Type restype = mtype.getReturnType();
@@ -1463,21 +1465,7 @@
restype.tsym);
}
- // Special case logic for JSR 292 types.
- if (rs.allowTransitionalJSR292 &&
- tree.meth.getTag() == JCTree.SELECT &&
- !typeargtypes.isEmpty()) {
- JCFieldAccess mfield = (JCFieldAccess) tree.meth;
- // MethodHandle.<T>invoke(abc) and InvokeDynamic.<T>foo(abc)
- // has type <T>, and T can be a primitive type.
- if (mfield.sym != null &&
- mfield.sym.isPolymorphicSignatureInstance())
- typeargtypesNonRefOK = true;
- }
-
- if (!(rs.allowTransitionalJSR292 && typeargtypesNonRefOK)) {
- chk.checkRefTypes(tree.typeargs, typeargtypes);
- }
+ chk.checkRefTypes(tree.typeargs, typeargtypes);
// Check that value of resulting type is admissible in the
// current context. Also, capture the return type
@@ -1667,7 +1655,7 @@
typeargtypes,
localEnv.info.varArgs);
if (localEnv.info.varArgs)
- assert tree.constructorType.isErroneous() || tree.varargsElement != null;
+ Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null);
}
if (cdef != null) {
@@ -1727,7 +1715,7 @@
Symbol sym = rs.resolveConstructor(
tree.pos(), localEnv, clazztype, argtypes,
typeargtypes, true, tree.varargsElement != null);
- assert sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous();
+ Assert.check(sym.kind < AMBIGUOUS || tree.constructor.type.isErroneous());
tree.constructor = sym;
if (tree.constructor.kind > ERRONEOUS) {
tree.constructorType = syms.errType;
@@ -2243,10 +2231,10 @@
// Determine the symbol represented by the selection.
env.info.varArgs = false;
- Symbol sym = selectSym(tree, site, env, pt, pkind);
+ Symbol sym = selectSym(tree, sitesym, site, env, pt, pkind);
if (sym.exists() && !isType(sym) && (pkind & (PCK | TYP)) != 0) {
site = capture(site);
- sym = selectSym(tree, site, env, pt, pkind);
+ sym = selectSym(tree, sitesym, site, env, pt, pkind);
}
boolean varArgs = env.info.varArgs;
tree.sym = sym;
@@ -2335,6 +2323,14 @@
* @param pkind The expected kind(s) of the Select expression.
*/
private Symbol selectSym(JCFieldAccess tree,
+ Type site,
+ Env<AttrContext> env,
+ Type pt,
+ int pkind) {
+ return selectSym(tree, site.tsym, site, env, pt, pkind);
+ }
+ private Symbol selectSym(JCFieldAccess tree,
+ Symbol location,
Type site,
Env<AttrContext> env,
Type pt,
@@ -2346,12 +2342,12 @@
case PACKAGE:
return rs.access(
rs.findIdentInPackage(env, site.tsym, name, pkind),
- pos, site, name, true);
+ pos, location, site, name, true);
case ARRAY:
case CLASS:
if (pt.tag == METHOD || pt.tag == FORALL) {
return rs.resolveQualifiedMethod(
- pos, env, site, name, pt.getParameterTypes(), pt.getTypeArguments());
+ pos, env, location, site, name, pt.getParameterTypes(), pt.getTypeArguments());
} else if (name == names._this || name == names._super) {
return rs.resolveSelf(pos, env, site.tsym, name);
} else if (name == names._class) {
@@ -2368,7 +2364,7 @@
// We are seeing a plain identifier as selector.
Symbol sym = rs.findIdentInType(env, site, name, pkind);
if ((pkind & ERRONEOUS) == 0)
- sym = rs.access(sym, pos, site, name, true);
+ sym = rs.access(sym, pos, location, site, name, true);
return sym;
}
case WILDCARD:
@@ -2376,12 +2372,12 @@
case TYPEVAR:
// Normally, site.getUpperBound() shouldn't be null.
// It should only happen during memberEnter/attribBase
- // when determining the super type which *must* be
+ // when determining the super type which *must* beac
// done before attributing the type variables. In
// other words, we are seeing this illegal program:
// class B<T> extends A<T.foo> {}
Symbol sym = (site.getUpperBound() != null)
- ? selectSym(tree, capture(site.getUpperBound()), env, pt, pkind)
+ ? selectSym(tree, location, capture(site.getUpperBound()), env, pt, pkind)
: null;
if (sym == null) {
log.error(pos, "type.var.cant.be.deref");
@@ -2390,7 +2386,7 @@
Symbol sym2 = (sym.flags() & Flags.PRIVATE) != 0 ?
rs.new AccessError(env, site, sym) :
sym;
- rs.access(sym2, pos, site, name, true);
+ rs.access(sym2, pos, location, site, name, true);
return sym;
}
case ERROR:
@@ -2961,7 +2957,7 @@
extending, implementing, List.<JCTree>nil());
ClassSymbol c = (ClassSymbol)a.getUpperBound().tsym;
- assert (c.flags() & COMPOUND) != 0;
+ Assert.check((c.flags() & COMPOUND) != 0);
cd.sym = c;
c.sourcefile = env.toplevel.sourcefile;
@@ -2989,10 +2985,6 @@
result = tree.type = syms.errType;
}
- public void visitAnnotatedType(JCAnnotatedType tree) {
- result = tree.type = attribType(tree.getUnderlyingType(), env);
- }
-
public void visitErroneous(JCErroneous tree) {
if (tree.errs != null)
for (JCTree err : tree.errs)
@@ -3097,7 +3089,7 @@
/** Finish the attribution of a class. */
private void attribClassBody(Env<AttrContext> env, ClassSymbol c) {
JCClassDecl tree = (JCClassDecl)env.tree;
- assert c == tree.sym;
+ Assert.check(c == tree.sym);
// Validate annotations
chk.validateAnnotations(tree.mods.annotations, c);
@@ -3138,12 +3130,9 @@
tree.type = c.type;
- boolean assertsEnabled = false;
- assert assertsEnabled = true;
- if (assertsEnabled) {
- for (List<JCTypeParameter> l = tree.typarams;
- l.nonEmpty(); l = l.tail)
- assert env.info.scope.lookup(l.head.name).scope != null;
+ for (List<JCTypeParameter> l = tree.typarams;
+ l.nonEmpty(); l = l.tail) {
+ Assert.checkNonNull(env.info.scope.lookup(l.head.name).scope);
}
// Check that a generic class doesn't extend Throwable
@@ -3167,7 +3156,7 @@
if (sym == null ||
sym.kind != VAR ||
((VarSymbol) sym).getConstValue() == null)
- log.error(l.head.pos(), "icls.cant.have.static.decl");
+ log.error(l.head.pos(), "icls.cant.have.static.decl", sym.location());
}
}
@@ -3184,9 +3173,6 @@
(c.flags() & ABSTRACT) == 0) {
checkSerialVersionUID(tree, c);
}
-
- // Check type annotations applicability rules
- validateTypeAnnotations(tree);
}
// where
/** check if a class is a subtype of Serializable, if that is available. */
@@ -3234,35 +3220,6 @@
return types.capture(type);
}
- private void validateTypeAnnotations(JCTree tree) {
- tree.accept(typeAnnotationsValidator);
- }
- //where
- private final JCTree.Visitor typeAnnotationsValidator =
- new TreeScanner() {
- public void visitAnnotation(JCAnnotation tree) {
- if (tree instanceof JCTypeAnnotation) {
- chk.validateTypeAnnotation((JCTypeAnnotation)tree, false);
- }
- super.visitAnnotation(tree);
- }
- public void visitTypeParameter(JCTypeParameter tree) {
- chk.validateTypeAnnotations(tree.annotations, true);
- // don't call super. skip type annotations
- scan(tree.bounds);
- }
- public void visitMethodDef(JCMethodDecl tree) {
- // need to check static methods
- if ((tree.sym.flags() & Flags.STATIC) != 0) {
- for (JCTypeAnnotation a : tree.receiverAnnotations) {
- if (chk.isTypeAnnotation(a, false))
- log.error(a.pos(), "annotation.type.not.applicable");
- }
- }
- super.visitMethodDef(tree);
- }
- };
-
// <editor-fold desc="post-attribution visitor">
/**
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -506,43 +506,18 @@
* @param a The type that should be bounded by bs.
* @param bs The bound.
*/
- private void checkExtends(DiagnosticPosition pos, Type a, TypeVar bs) {
+ private boolean checkExtends(Type a, TypeVar bs) {
if (a.isUnbound()) {
- return;
+ return true;
} else if (a.tag != WILDCARD) {
a = types.upperBound(a);
- for (List<Type> l = types.getBounds(bs); l.nonEmpty(); l = l.tail) {
- if (!types.isSubtype(a, l.head)) {
- log.error(pos, "not.within.bounds", a);
- return;
- }
- }
+ return types.isSubtype(a, bs.bound);
} else if (a.isExtendsBound()) {
- if (!types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings))
- log.error(pos, "not.within.bounds", a);
+ return types.isCastable(bs.getUpperBound(), types.upperBound(a), Warner.noWarnings);
} else if (a.isSuperBound()) {
- if (types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound()))
- log.error(pos, "not.within.bounds", a);
+ return !types.notSoftSubtype(types.lowerBound(a), bs.getUpperBound());
}
- }
-
- /** Check that a type is within some bounds.
- *
- * Used in TypeApply to verify that, e.g., X in V<X> is a valid
- * type argument.
- * @param pos Position to be used for error reporting.
- * @param a The type that should be bounded by bs.
- * @param bs The bound.
- */
- private void checkCapture(JCTypeApply tree) {
- List<JCExpression> args = tree.getTypeArguments();
- for (Type arg : types.capture(tree.type).getTypeArguments()) {
- if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
- log.error(args.head.pos, "not.within.bounds", args.head.type);
- break;
- }
- args = args.tail;
- }
+ return true;
}
/** Check that type is different from 'void'.
@@ -775,6 +750,79 @@
}
}
+ /**
+ * Check that type 't' is a valid instantiation of a generic class
+ * (see JLS 4.5)
+ *
+ * @param t class type to be checked
+ * @return true if 't' is well-formed
+ */
+ public boolean checkValidGenericType(Type t) {
+ return firstIncompatibleTypeArg(t) == null;
+ }
+ //WHERE
+ private Type firstIncompatibleTypeArg(Type type) {
+ List<Type> formals = type.tsym.type.allparams();
+ List<Type> actuals = type.allparams();
+ List<Type> args = type.getTypeArguments();
+ List<Type> forms = type.tsym.type.getTypeArguments();
+ ListBuffer<Type> tvars_buf = new ListBuffer<Type>();
+
+ // For matching pairs of actual argument types `a' and
+ // formal type parameters with declared bound `b' ...
+ while (args.nonEmpty() && forms.nonEmpty()) {
+ // exact type arguments needs to know their
+ // bounds (for upper and lower bound
+ // calculations). So we create new TypeVars with
+ // bounds substed with actuals.
+ tvars_buf.append(types.substBound(((TypeVar)forms.head),
+ formals,
+ actuals));
+ args = args.tail;
+ forms = forms.tail;
+ }
+
+ args = type.getTypeArguments();
+ List<Type> tvars_cap = types.substBounds(formals,
+ formals,
+ types.capture(type).allparams());
+ while (args.nonEmpty() && tvars_cap.nonEmpty()) {
+ // Let the actual arguments know their bound
+ args.head.withTypeVar((TypeVar)tvars_cap.head);
+ args = args.tail;
+ tvars_cap = tvars_cap.tail;
+ }
+
+ args = type.getTypeArguments();
+ List<Type> tvars = tvars_buf.toList();
+
+ while (args.nonEmpty() && tvars.nonEmpty()) {
+ Type actual = types.subst(args.head,
+ type.tsym.type.getTypeArguments(),
+ tvars_buf.toList());
+ if (!checkExtends(actual, (TypeVar)tvars.head) &&
+ !tvars.head.getUpperBound().isErroneous()) {
+ return args.head;
+ }
+ args = args.tail;
+ tvars = tvars.tail;
+ }
+
+ args = type.getTypeArguments();
+ tvars = tvars_buf.toList();
+
+ for (Type arg : types.capture(type).getTypeArguments()) {
+ if (arg.tag == TYPEVAR &&
+ arg.getUpperBound().isErroneous() &&
+ !tvars.head.getUpperBound().isErroneous()) {
+ return args.head;
+ }
+ tvars = tvars.tail;
+ }
+
+ return null;
+ }
+
/** Check that given modifiers are legal for given symbol and
* return modifiers together with any implicit modififiers for that symbol.
* Warning: we can't use flags() here since this method
@@ -987,11 +1035,20 @@
@Override
public void visitTypeApply(JCTypeApply tree) {
if (tree.type.tag == CLASS) {
- List<Type> formals = tree.type.tsym.type.allparams();
- List<Type> actuals = tree.type.allparams();
List<JCExpression> args = tree.arguments;
List<Type> forms = tree.type.tsym.type.getTypeArguments();
- ListBuffer<Type> tvars_buf = new ListBuffer<Type>();
+
+ Type incompatibleArg = firstIncompatibleTypeArg(tree.type);
+ if (incompatibleArg != null) {
+ for (JCTree arg : tree.arguments) {
+ if (arg.type == incompatibleArg) {
+ log.error(arg, "not.within.bounds", incompatibleArg, forms.head);
+ }
+ forms = forms.tail;
+ }
+ }
+
+ forms = tree.type.tsym.type.getTypeArguments();
boolean is_java_lang_Class = tree.type.tsym.flatName() == names.java_lang_Class;
@@ -1001,46 +1058,10 @@
validateTree(args.head,
!(isOuter && is_java_lang_Class),
false);
-
- // exact type arguments needs to know their
- // bounds (for upper and lower bound
- // calculations). So we create new TypeVars with
- // bounds substed with actuals.
- tvars_buf.append(types.substBound(((TypeVar)forms.head),
- formals,
- actuals));
-
args = args.tail;
forms = forms.tail;
}
- args = tree.arguments;
- List<Type> tvars_cap = types.substBounds(formals,
- formals,
- types.capture(tree.type).allparams());
- while (args.nonEmpty() && tvars_cap.nonEmpty()) {
- // Let the actual arguments know their bound
- args.head.type.withTypeVar((TypeVar)tvars_cap.head);
- args = args.tail;
- tvars_cap = tvars_cap.tail;
- }
-
- args = tree.arguments;
- List<Type> tvars = tvars_buf.toList();
-
- while (args.nonEmpty() && tvars.nonEmpty()) {
- Type actual = types.subst(args.head.type,
- tree.type.tsym.type.getTypeArguments(),
- tvars_buf.toList());
- checkExtends(args.head.pos(),
- actual,
- (TypeVar)tvars.head);
- args = args.tail;
- tvars = tvars.tail;
- }
-
- checkCapture(tree);
-
// Check that this type is either fully parameterized, or
// not parameterized at all.
if (tree.type.getEnclosingType().isRaw())
@@ -1086,11 +1107,6 @@
}
}
- @Override
- public void visitAnnotatedType(JCAnnotatedType tree) {
- tree.underlyingType.accept(this);
- }
-
/** Default visitor method: do nothing.
*/
@Override
@@ -2239,14 +2255,6 @@
validateAnnotation(a, s);
}
- /** Check the type annotations
- */
- public void validateTypeAnnotations(List<JCTypeAnnotation> annotations, boolean isTypeParameter) {
- if (skipAnnotations) return;
- for (JCTypeAnnotation a : annotations)
- validateTypeAnnotation(a, isTypeParameter);
- }
-
/** Check an annotation of a symbol.
*/
public void validateAnnotation(JCAnnotation a, Symbol s) {
@@ -2261,15 +2269,6 @@
}
}
- public void validateTypeAnnotation(JCTypeAnnotation a, boolean isTypeParameter) {
- if (a.type == null)
- throw new AssertionError("annotation tree hasn't been attributed yet: " + a);
- validateAnnotationTree(a);
-
- if (!isTypeAnnotation(a, isTypeParameter))
- log.error(a.pos(), "annotation.type.not.applicable");
- }
-
/** Is s a method symbol that overrides a method in a superclass? */
boolean isOverrider(Symbol s) {
if (s.kind != MTH || s.isStatic())
@@ -2288,25 +2287,6 @@
return false;
}
- /** Is the annotation applicable to type annotations */
- boolean isTypeAnnotation(JCTypeAnnotation a, boolean isTypeParameter) {
- Attribute.Compound atTarget =
- a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
- if (atTarget == null) return true;
- Attribute atValue = atTarget.member(names.value);
- if (!(atValue instanceof Attribute.Array)) return true; // error recovery
- Attribute.Array arr = (Attribute.Array) atValue;
- for (Attribute app : arr.values) {
- if (!(app instanceof Attribute.Enum)) return true; // recovery
- Attribute.Enum e = (Attribute.Enum) app;
- if (!isTypeParameter && e.value.name == names.TYPE_USE)
- return true;
- else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER)
- return true;
- }
- return false;
- }
-
/** Is the annotation applicable to the symbol? */
boolean annotationApplicable(JCAnnotation a, Symbol s) {
Attribute.Compound atTarget =
@@ -2438,7 +2418,7 @@
*/
void checkNonCyclicElements(JCClassDecl tree) {
if ((tree.sym.flags_field & ANNOTATION) == 0) return;
- assert (tree.sym.flags_field & LOCKED) == 0;
+ Assert.check((tree.sym.flags_field & LOCKED) == 0);
try {
tree.sym.flags_field |= LOCKED;
for (JCTree def : tree.defs) {
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -37,7 +37,6 @@
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Flags.*;
@@ -709,7 +708,7 @@
lint = lint.augment(tree.sym.attributes_field);
- assert pendingExits.isEmpty();
+ Assert.check(pendingExits.isEmpty());
try {
boolean isInitialConstructor =
@@ -747,7 +746,7 @@
PendingExit exit = exits.head;
exits = exits.tail;
if (exit.thrown == null) {
- assert exit.tree.getTag() == JCTree.RETURN;
+ Assert.check(exit.tree.getTag() == JCTree.RETURN);
if (isInitialConstructor) {
inits = exit.inits;
for (int i = firstadr; i < nextadr; i++)
@@ -1350,11 +1349,6 @@
}
}
- public void visitAnnotatedType(JCAnnotatedType tree) {
- // annotations don't get scanned
- tree.underlyingType.accept(this);
- }
-
public void visitIdent(JCIdent tree) {
if (tree.sym.kind == VAR) {
checkInit(tree.pos(), (VarSymbol)tree.sym);
@@ -1373,7 +1367,6 @@
if (!tree.type.isErroneous()
&& lint.isEnabled(Lint.LintCategory.CAST)
&& types.isSameType(tree.expr.type, tree.clazz.type)
- && !(ignoreAnnotatedCasts && containsTypeAnnotation(tree.clazz))
&& !is292targetTypeCast(tree)) {
log.warning(Lint.LintCategory.CAST,
tree.pos(), "redundant.cast", tree.expr.type);
@@ -1382,8 +1375,9 @@
//where
private boolean is292targetTypeCast(JCTypeCast tree) {
boolean is292targetTypeCast = false;
- if (tree.expr.getTag() == JCTree.APPLY) {
- JCMethodInvocation apply = (JCMethodInvocation)tree.expr;
+ JCExpression expr = TreeInfo.skipParens(tree.expr);
+ if (expr.getTag() == JCTree.APPLY) {
+ JCMethodInvocation apply = (JCMethodInvocation)expr;
Symbol sym = TreeInfo.symbol(apply.meth);
is292targetTypeCast = sym != null &&
sym.kind == MTH &&
@@ -1397,23 +1391,6 @@
}
/**************************************************************************
- * utility methods for ignoring type-annotated casts lint checking
- *************************************************************************/
- private static final boolean ignoreAnnotatedCasts = true;
- private static class AnnotationFinder extends TreeScanner {
- public boolean foundTypeAnno = false;
- public void visitAnnotation(JCAnnotation tree) {
- foundTypeAnno = foundTypeAnno || (tree instanceof JCTypeAnnotation);
- }
- }
-
- private boolean containsTypeAnnotation(JCTree e) {
- AnnotationFinder finder = new AnnotationFinder();
- finder.scan(e);
- return finder.foundTypeAnno;
- }
-
-/**************************************************************************
* main method
*************************************************************************/
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Feb 18 12:04:36 2011 -0800
@@ -27,6 +27,7 @@
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
+import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.*;
@@ -204,19 +205,20 @@
* Throw a NoInstanceException if this not possible.
*/
void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
+ List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
if (that.inst == null) {
- if (that.hibounds.isEmpty())
+ if (hibounds.isEmpty())
that.inst = syms.objectType;
- else if (that.hibounds.tail.isEmpty())
- that.inst = that.hibounds.head;
+ else if (hibounds.tail.isEmpty())
+ that.inst = hibounds.head;
else
- that.inst = types.glb(that.hibounds);
+ that.inst = types.glb(hibounds);
}
if (that.inst == null ||
that.inst.isErroneous())
throw ambiguousNoInstanceException
.setMessage("no.unique.maximal.instance.exists",
- that.qtype, that.hibounds);
+ that.qtype, hibounds);
}
//where
private boolean isSubClass(Type t, final List<Type> ts) {
@@ -240,37 +242,46 @@
return true;
}
+ private Filter<Type> errorFilter = new Filter<Type>() {
+ @Override
+ public boolean accepts(Type t) {
+ return !t.isErroneous();
+ }
+ };
+
/** Instantiate undetermined type variable to the lub of all its lower bounds.
* Throw a NoInstanceException if this not possible.
*/
void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
+ List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
if (that.inst == null) {
- if (that.lobounds.isEmpty())
+ if (lobounds.isEmpty())
that.inst = syms.botType;
- else if (that.lobounds.tail.isEmpty())
- that.inst = that.lobounds.head.isPrimitive() ? syms.errType : that.lobounds.head;
+ else if (lobounds.tail.isEmpty())
+ that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
else {
- that.inst = types.lub(that.lobounds);
+ that.inst = types.lub(lobounds);
}
if (that.inst == null || that.inst.tag == ERROR)
throw ambiguousNoInstanceException
.setMessage("no.unique.minimal.instance.exists",
- that.qtype, that.lobounds);
+ that.qtype, lobounds);
// VGJ: sort of inlined maximizeInst() below. Adding
// bounds can cause lobounds that are above hibounds.
- if (that.hibounds.isEmpty())
+ List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
+ if (hibounds.isEmpty())
return;
Type hb = null;
- if (that.hibounds.tail.isEmpty())
- hb = that.hibounds.head;
- else for (List<Type> bs = that.hibounds;
+ if (hibounds.tail.isEmpty())
+ hb = hibounds.head;
+ else for (List<Type> bs = hibounds;
bs.nonEmpty() && hb == null;
bs = bs.tail) {
- if (isSubClass(bs.head, that.hibounds))
+ if (isSubClass(bs.head, hibounds))
hb = types.fromUnknownFun.apply(bs.head);
}
if (hb == null ||
- !types.isSubtypeUnchecked(hb, that.hibounds, warn) ||
+ !types.isSubtypeUnchecked(hb, hibounds, warn) ||
!types.isSubtypeUnchecked(that.inst, hb, warn))
throw ambiguousNoInstanceException;
}
@@ -396,7 +407,9 @@
// for varargs arguments as well
if (useVarargs) {
- Type elemType = types.elemtype(varargsFormal);
+ //note: if applicability check is triggered by most specific test,
+ //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
+ Type elemType = types.elemtypeOrType(varargsFormal);
Type elemUndet = types.subst(elemType, tvars, undetvars);
while (actuals.nonEmpty()) {
Type actual = actuals.head.baseType();
@@ -527,7 +540,8 @@
for (List<Type> tvs = tvars, args = arguments;
tvs.nonEmpty();
tvs = tvs.tail, args = args.tail) {
- if (args.head instanceof UndetVar) continue;
+ if (args.head instanceof UndetVar ||
+ tvars.head.getUpperBound().isErroneous()) continue;
List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
if (!types.isSubtypeUnchecked(args.head, bounds, warn))
throw invalidInstanceException
@@ -538,43 +552,39 @@
/**
* Compute a synthetic method type corresponding to the requested polymorphic
- * method signature. If no explicit return type is supplied, a provisional
- * return type is computed (just Object in case of non-transitional 292)
+ * method signature. The target return type is computed from the immediately
+ * enclosing scope surrounding the polymorphic-signature call.
*/
Type instantiatePolymorphicSignatureInstance(Env<AttrContext> env, Type site,
Name name,
MethodSymbol spMethod, // sig. poly. method or null if none
- List<Type> argtypes,
- List<Type> typeargtypes) {
+ List<Type> argtypes) {
final Type restype;
- if (rs.allowTransitionalJSR292 && typeargtypes.nonEmpty()) {
- restype = typeargtypes.head;
- } else {
- //The return type for a polymorphic signature call is computed from
- //the enclosing tree E, as follows: if E is a cast, then use the
- //target type of the cast expression as a return type; if E is an
- //expression statement, the return type is 'void' - otherwise the
- //return type is simply 'Object'. A correctness check ensures that
- //env.next refers to the lexically enclosing environment in which
- //the polymorphic signature call environment is nested.
+
+ //The return type for a polymorphic signature call is computed from
+ //the enclosing tree E, as follows: if E is a cast, then use the
+ //target type of the cast expression as a return type; if E is an
+ //expression statement, the return type is 'void' - otherwise the
+ //return type is simply 'Object'. A correctness check ensures that
+ //env.next refers to the lexically enclosing environment in which
+ //the polymorphic signature call environment is nested.
- switch (env.next.tree.getTag()) {
- case JCTree.TYPECAST:
- JCTypeCast castTree = (JCTypeCast)env.next.tree;
- restype = (castTree.expr == env.tree) ?
- castTree.clazz.type :
- syms.objectType;
- break;
- case JCTree.EXEC:
- JCTree.JCExpressionStatement execTree =
- (JCTree.JCExpressionStatement)env.next.tree;
- restype = (execTree.expr == env.tree) ?
- syms.voidType :
- syms.objectType;
- break;
- default:
- restype = syms.objectType;
- }
+ switch (env.next.tree.getTag()) {
+ case JCTree.TYPECAST:
+ JCTypeCast castTree = (JCTypeCast)env.next.tree;
+ restype = (TreeInfo.skipParens(castTree.expr) == env.tree) ?
+ castTree.clazz.type :
+ syms.objectType;
+ break;
+ case JCTree.EXEC:
+ JCTree.JCExpressionStatement execTree =
+ (JCTree.JCExpressionStatement)env.next.tree;
+ restype = (TreeInfo.skipParens(execTree.expr) == env.tree) ?
+ syms.voidType :
+ syms.objectType;
+ break;
+ default:
+ restype = syms.objectType;
}
List<Type> paramtypes = Type.map(argtypes, implicitArgType);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -1057,7 +1057,7 @@
}
// Otherwise replace the variable by its proxy.
sym = proxies.lookup(proxyName(sym.name)).sym;
- assert sym != null && (sym.flags_field & FINAL) != 0;
+ Assert.check(sym != null && (sym.flags_field & FINAL) != 0);
tree = make.at(tree.pos).Ident(sym);
}
JCExpression base = (tree.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree).selected : null;
@@ -1208,7 +1208,7 @@
*/
void makeAccessible(Symbol sym) {
JCClassDecl cdef = classDef(sym.owner.enclClass());
- assert cdef != null : "class def not found: " + sym + " in " + sym.owner;
+ if (cdef == null) Assert.error("class def not found: " + sym + " in " + sym.owner);
if (sym.name == names.init) {
cdef.defs = cdef.defs.prepend(
accessConstructorDef(cdef.pos, sym, accessConstrs.get(sym)));
@@ -1458,7 +1458,7 @@
expr = make.Ident(var.sym).setType(resource.type);
stats.add(var);
} else {
- assert resource instanceof JCExpression;
+ Assert.check(resource instanceof JCExpression);
VarSymbol syntheticTwrVar =
new VarSymbol(SYNTHETIC | FINAL,
makeSyntheticName(names.fromString("twrVar" +
@@ -1552,7 +1552,7 @@
List<VarSymbol> ots = outerThisStack;
if (ots.isEmpty()) {
log.error(pos, "no.encl.instance.of.type.in.scope", c);
- assert false;
+ Assert.error();
return makeNull();
}
VarSymbol ot = ots.head;
@@ -1565,14 +1565,14 @@
log.error(pos,
"no.encl.instance.of.type.in.scope",
c);
- assert false; // should have been caught in Attr
+ Assert.error(); // should have been caught in Attr
return tree;
}
ot = ots.head;
} while (ot.owner != otc);
if (otc.owner.kind != PCK && !otc.hasOuterInstance()) {
chk.earlyRefError(pos, c);
- assert false; // should have been caught in Attr
+ Assert.error(); // should have been caught in Attr
return makeNull();
}
tree = access(make.at(pos).Select(tree, ot));
@@ -1610,7 +1610,7 @@
List<VarSymbol> ots = outerThisStack;
if (ots.isEmpty()) {
log.error(pos, "no.encl.instance.of.type.in.scope", c);
- assert false;
+ Assert.error();
return makeNull();
}
VarSymbol ot = ots.head;
@@ -1623,7 +1623,7 @@
log.error(pos,
"no.encl.instance.of.type.in.scope",
c);
- assert false;
+ Assert.error();
return tree;
}
ot = ots.head;
@@ -1640,9 +1640,9 @@
JCStatement initField(int pos, Name name) {
Scope.Entry e = proxies.lookup(name);
Symbol rhs = e.sym;
- assert rhs.owner.kind == MTH;
+ Assert.check(rhs.owner.kind == MTH);
Symbol lhs = e.next().sym;
- assert rhs.owner.owner == lhs.owner;
+ Assert.check(rhs.owner.owner == lhs.owner);
make.at(pos);
return
make.Exec(
@@ -1655,9 +1655,9 @@
*/
JCStatement initOuterThis(int pos) {
VarSymbol rhs = outerThisStack.head;
- assert rhs.owner.kind == MTH;
+ Assert.check(rhs.owner.kind == MTH);
VarSymbol lhs = outerThisStack.tail.head;
- assert rhs.owner.owner == lhs.owner;
+ Assert.check(rhs.owner.owner == lhs.owner);
make.at(pos);
return
make.Exec(
@@ -1856,7 +1856,7 @@
// where
/** Create an attributed tree of the form left.name(). */
private JCMethodInvocation makeCall(JCExpression left, Name name, List<JCExpression> args) {
- assert left.type != null;
+ Assert.checkNonNull(left.type);
Symbol funcsym = lookupMethod(make_pos, name, left.type,
TreeInfo.types(args));
return make.App(make.Select(left, funcsym), args);
@@ -2399,7 +2399,7 @@
names.valueOf,
tree.sym.type,
List.of(syms.stringType));
- assert (valueOfSym.flags() & STATIC) != 0;
+ Assert.check((valueOfSym.flags() & STATIC) != 0);
VarSymbol nameArgSym = valueOfSym.params.head;
JCIdent nameVal = make.Ident(nameArgSym);
JCStatement enum_ValueOf =
@@ -2585,11 +2585,6 @@
result = tree;
}
- public void visitAnnotatedType(JCAnnotatedType tree) {
- tree.underlyingType = translate(tree.underlyingType);
- result = tree.underlyingType;
- }
-
public void visitTypeCast(JCTypeCast tree) {
tree.clazz = translate(tree.clazz);
if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())
@@ -3421,7 +3416,7 @@
if (expression != null) { // expression for a "default" case is null
String labelExpr = (String) expression.type.constValue();
Integer mapping = caseLabelToPosition.put(labelExpr, casePosition);
- assert mapping == null;
+ Assert.checkNull(mapping);
int hashCode = labelExpr.hashCode();
Set<String> stringSet = hashToString.get(hashCode);
@@ -3431,7 +3426,7 @@
hashToString.put(hashCode, stringSet);
} else {
boolean added = stringSet.add(labelExpr);
- assert added;
+ Assert.check(added);
}
}
casePosition++;
@@ -3483,7 +3478,7 @@
for(Map.Entry<Integer, Set<String>> entry : hashToString.entrySet()) {
int hashCode = entry.getKey();
Set<String> stringsWithHashCode = entry.getValue();
- assert stringsWithHashCode.size() >= 1;
+ Assert.check(stringsWithHashCode.size() >= 1);
JCStatement elsepart = null;
for(String caseLabel : stringsWithHashCode ) {
@@ -3697,8 +3692,7 @@
cdef.type,
List.<Type>nil());
- assert(ordinalSym != null);
- assert(ordinalSym instanceof MethodSymbol);
+ Assert.check(ordinalSym instanceof MethodSymbol);
JCStatement ret = make.Return(make.Ident(ordinalSymbol));
cdef.defs = cdef.defs.append(make.MethodDef((MethodSymbol)ordinalSym,
@@ -3714,8 +3708,7 @@
cdef.type,
List.<Type>nil());
- assert(nameSym != null);
- assert(nameSym instanceof MethodSymbol);
+ Assert.check(nameSym instanceof MethodSymbol);
JCStatement ret = make.Return(make.Ident(nameSymbol));
@@ -3766,8 +3759,7 @@
cdef.type,
List.of(cdef.sym.type));
- assert(compareToSym != null);
- assert(compareToSym instanceof MethodSymbol);
+ Assert.check(compareToSym instanceof MethodSymbol);
JCMethodDecl compareToDecl = (JCMethodDecl) TreeInfo.declarationFor(compareToSym, cdef);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -581,8 +581,7 @@
JCVariableDecl lastParam = null;
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
JCVariableDecl param = lastParam = l.head;
- assert param.sym != null;
- params.append(param.sym);
+ params.append(Assert.checkNonNull(param.sym));
}
m.params = params.toList();
@@ -699,7 +698,7 @@
*********************************************************************/
Type attribImportType(JCTree tree, Env<AttrContext> env) {
- assert completionEnabled;
+ Assert.check(completionEnabled);
try {
// To prevent deep recursion, suppress completion of some
// types.
@@ -725,7 +724,7 @@
return "annotate " + annotations + " onto " + s + " in " + s.owner;
}
public void enterAnnotation() {
- assert s.kind == PCK || s.attributes_field == null;
+ Assert.check(s.kind == PCK || s.attributes_field == null);
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
try {
if (s.attributes_field != null &&
@@ -782,8 +781,8 @@
types.isSameType(c.type, syms.polymorphicSignatureType)) {
if (!target.hasMethodHandles()) {
// Somebody is compiling JDK7 source code to a JDK6 target.
- // Make it a strict warning, since it is unlikely but important.
- log.strictWarning(env.tree.pos(),
+ // Make it an error, since it is unlikely but important.
+ log.error(env.tree.pos(),
"wrong.target.for.polymorphic.signature.definition",
target.name);
}
@@ -836,7 +835,7 @@
// Suppress some (recursive) MemberEnter invocations
if (!completionEnabled) {
// Re-install same completer for next time around and return.
- assert (sym.flags() & Flags.COMPOUND) == 0;
+ Assert.check((sym.flags() & Flags.COMPOUND) == 0);
sym.completer = this;
return;
}
@@ -928,10 +927,6 @@
if (hasDeprecatedAnnotation(tree.mods.annotations))
c.flags_field |= DEPRECATED;
annotateLater(tree.mods.annotations, baseEnv, c);
- // class type parameters use baseEnv but everything uses env
- for (JCTypeParameter tp : tree.typarams)
- tp.accept(new TypeAnnotate(baseEnv));
- tree.accept(new TypeAnnotate(env));
chk.checkNonCyclicDecl(tree);
@@ -989,7 +984,7 @@
c.owner.kind == PCK && c.owner != syms.unnamedPackage &&
reader.packageExists(c.fullname))
{
- log.error(tree.pos, "clash.with.pkg.of.same.name", c);
+ log.error(tree.pos, "clash.with.pkg.of.same.name", Kinds.kindName(sym), c);
}
} catch (CompletionFailure ex) {
@@ -1014,86 +1009,6 @@
}
}
- // A sub-phase that "compiles" annotations in annotated types.
- private class TypeAnnotate extends TreeScanner {
- private Env<AttrContext> env;
- public TypeAnnotate(Env<AttrContext> env) { this.env = env; }
-
- private void enterTypeAnnotations(List<JCTypeAnnotation> annotations) {
- Set<TypeSymbol> annotated = new HashSet<TypeSymbol>();
- if (!skipAnnotations)
- for (List<JCTypeAnnotation> al = annotations; al.nonEmpty(); al = al.tail) {
- JCTypeAnnotation a = al.head;
- Attribute.Compound c = annotate.enterAnnotation(a,
- syms.annotationType,
- env);
- if (c == null) continue;
- Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, a.annotation_position);
- a.attribute_field = tc;
- // Note: @Deprecated has no effect on local variables and parameters
- if (!annotated.add(a.type.tsym))
- log.error(a.pos, "duplicate.annotation");
- }
- }
-
- // each class (including enclosed inner classes) should be visited
- // separately through MemberEnter.complete(Symbol)
- // this flag is used to prevent from visiting inner classes.
- private boolean isEnclosingClass = false;
- @Override
- public void visitClassDef(final JCClassDecl tree) {
- if (isEnclosingClass)
- return;
- isEnclosingClass = true;
- scan(tree.mods);
- // type parameter need to be visited with a separate env
- // scan(tree.typarams);
- scan(tree.extending);
- scan(tree.implementing);
- scan(tree.defs);
- }
-
- private void annotate(final JCTree tree, final List<JCTypeAnnotation> annotations) {
- annotate.later(new Annotate.Annotator() {
- public String toString() {
- return "annotate " + annotations + " onto " + tree;
- }
- public void enterAnnotation() {
- JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
- try {
- enterTypeAnnotations(annotations);
- } finally {
- log.useSource(prev);
- }
- }
- });
- }
-
- @Override
- public void visitAnnotatedType(final JCAnnotatedType tree) {
- annotate(tree, tree.annotations);
- super.visitAnnotatedType(tree);
- }
- @Override
- public void visitTypeParameter(final JCTypeParameter tree) {
- annotate(tree, tree.annotations);
- super.visitTypeParameter(tree);
- }
- @Override
- public void visitNewArray(final JCNewArray tree) {
- annotate(tree, tree.annotations);
- for (List<JCTypeAnnotation> dimAnnos : tree.dimAnnotations)
- annotate(tree, dimAnnos);
- super.visitNewArray(tree);
- }
- @Override
- public void visitMethodDef(JCMethodDecl tree) {
- annotate(tree, tree.receiverAnnotations);
- super.visitMethodDef(tree);
- }
- }
-
-
private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) {
Scope baseScope = new Scope.ClassScope(tree.sym, scopeCounter);
//import already entered local classes into base scope
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -70,8 +70,6 @@
public final boolean boxingEnabled; // = source.allowBoxing();
public final boolean varargsEnabled; // = source.allowVarargs();
public final boolean allowMethodHandles;
- public final boolean allowInvokeDynamic;
- public final boolean allowTransitionalJSR292;
private final boolean debugResolve;
Scope polymorphicSignatureScope;
@@ -111,13 +109,8 @@
varargsEnabled = source.allowVarargs();
Options options = Options.instance(context);
debugResolve = options.isSet("debugresolve");
- allowTransitionalJSR292 = options.isSet("allowTransitionalJSR292");
Target target = Target.instance(context);
- allowMethodHandles = allowTransitionalJSR292 ||
- target.hasMethodHandles();
- allowInvokeDynamic = (allowTransitionalJSR292 ||
- target.hasInvokedynamic()) &&
- options.isSet("invokedynamic");
+ allowMethodHandles = target.hasMethodHandles();
polymorphicSignatureScope = new Scope(syms.noSymbol);
inapplicableMethodException = new InapplicableMethodException(diags);
@@ -336,8 +329,7 @@
boolean useVarargs,
Warner warn)
throws Infer.InferenceException {
- boolean polymorphicSignature = (m.isPolymorphicSignatureGeneric() && allowMethodHandles) ||
- isTransitionalDynamicCallSite(site, m);
+ boolean polymorphicSignature = m.isPolymorphicSignatureGeneric() && allowMethodHandles;
if (useVarargs && (m.flags() & VARARGS) == 0)
throw inapplicableMethodException.setMessage(null);
Type mt = types.memberType(site, m);
@@ -346,10 +338,7 @@
// need to inferred.
List<Type> tvars = env.info.tvars;
if (typeargtypes == null) typeargtypes = List.nil();
- if (allowTransitionalJSR292 && polymorphicSignature && typeargtypes.nonEmpty()) {
- //transitional 292 call sites might have wrong number of targs
- }
- else if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
+ if (mt.tag != FORALL && typeargtypes.nonEmpty()) {
// This is not a polymorphic method, but typeargs are supplied
// which is fine, see JLS3 15.12.2.1
} else if (mt.tag == FORALL && typeargtypes.nonEmpty()) {
@@ -387,7 +376,7 @@
if (instNeeded)
return polymorphicSignature ?
- infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes, typeargtypes) :
+ infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes) :
infer.instantiateMethod(env,
tvars,
(MethodType)mt,
@@ -402,14 +391,6 @@
return mt;
}
- boolean isTransitionalDynamicCallSite(Type site, Symbol sym) {
- return allowTransitionalJSR292 && // old logic that doesn't use annotations
- !sym.isPolymorphicSignatureInstance() &&
- ((allowMethodHandles && site == syms.methodHandleType && // invokeExact, invokeGeneric, invoke
- (sym.name == names.invoke && sym.isPolymorphicSignatureGeneric())) ||
- (site == syms.invokeDynamicType && allowInvokeDynamic)); // InvokeDynamic.XYZ
- }
-
/** Same but returns null instead throwing a NoInstanceException
*/
Type instantiate(Env<AttrContext> env,
@@ -679,7 +660,7 @@
boolean operator) {
if (sym.kind == ERR) return bestSoFar;
if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar;
- assert sym.kind < AMBIGUOUS;
+ Assert.check(sym.kind < AMBIGUOUS);
try {
rawInstantiate(env, site, sym, argtypes, typeargtypes,
allowBoxing, useVarargs, Warner.noWarnings);
@@ -1255,6 +1236,7 @@
*/
Symbol access(Symbol sym,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
boolean qualified,
@@ -1265,23 +1247,46 @@
if (!site.isErroneous() &&
!Type.isErroneous(argtypes) &&
(typeargtypes==null || !Type.isErroneous(typeargtypes)))
- logResolveError(errSym, pos, site, name, argtypes, typeargtypes);
+ logResolveError(errSym, pos, location, site, name, argtypes, typeargtypes);
sym = errSym.access(name, qualified ? site.tsym : syms.noSymbol);
}
return sym;
}
- /** Same as above, but without type arguments and arguments.
+ /** Same as original access(), but without location.
+ */
+ Symbol access(Symbol sym,
+ DiagnosticPosition pos,
+ Type site,
+ Name name,
+ boolean qualified,
+ List<Type> argtypes,
+ List<Type> typeargtypes) {
+ return access(sym, pos, site.tsym, site, name, qualified, argtypes, typeargtypes);
+ }
+
+ /** Same as original access(), but without type arguments and arguments.
+ */
+ Symbol access(Symbol sym,
+ DiagnosticPosition pos,
+ Symbol location,
+ Type site,
+ Name name,
+ boolean qualified) {
+ if (sym.kind >= AMBIGUOUS)
+ return access(sym, pos, location, site, name, qualified, List.<Type>nil(), null);
+ else
+ return sym;
+ }
+
+ /** Same as original access(), but without location, type arguments and arguments.
*/
Symbol access(Symbol sym,
DiagnosticPosition pos,
Type site,
Name name,
boolean qualified) {
- if (sym.kind >= AMBIGUOUS)
- return access(sym, pos, site, name, qualified, List.<Type>nil(), null);
- else
- return sym;
+ return access(sym, pos, site.tsym, site, name, qualified);
}
/** Check that sym is not an abstract method.
@@ -1399,6 +1404,11 @@
Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
Type site, Name name, List<Type> argtypes,
List<Type> typeargtypes) {
+ return resolveQualifiedMethod(pos, env, site.tsym, site, name, argtypes, typeargtypes);
+ }
+ Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env,
+ Symbol location, Type site, Name name, List<Type> argtypes,
+ List<Type> typeargtypes) {
Symbol sym = startResolution();
List<MethodResolutionPhase> steps = methodResolutionSteps;
while (steps.nonEmpty() &&
@@ -1412,26 +1422,25 @@
steps = steps.tail;
}
if (sym.kind >= AMBIGUOUS) {
- if (site.tsym.isPolymorphicSignatureGeneric() ||
- isTransitionalDynamicCallSite(site, sym)) {
+ if (site.tsym.isPolymorphicSignatureGeneric()) {
//polymorphic receiver - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
- site, name, null, argtypes, typeargtypes);
+ site, name, null, argtypes);
}
else {
//if nothing is found return the 'first' error
MethodResolutionPhase errPhase =
firstErroneousResolutionPhase();
sym = access(methodResolutionCache.get(errPhase),
- pos, site, name, true, argtypes, typeargtypes);
+ pos, location, site, name, true, argtypes, typeargtypes);
env.info.varArgs = errPhase.isVarargsRequired;
}
} else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) {
//non-instantiated polymorphic signature - synthesize new method symbol
env.info.varArgs = false;
sym = findPolymorphicSignatureInstance(env,
- site, name, (MethodSymbol)sym, argtypes, typeargtypes);
+ site, name, (MethodSymbol)sym, argtypes);
}
return sym;
}
@@ -1449,15 +1458,9 @@
Symbol findPolymorphicSignatureInstance(Env<AttrContext> env, Type site,
Name name,
MethodSymbol spMethod, // sig. poly. method or null if none
- List<Type> argtypes,
- List<Type> typeargtypes) {
- if (typeargtypes.nonEmpty() && (site.tsym.isPolymorphicSignatureGeneric() ||
- (spMethod != null && spMethod.isPolymorphicSignatureGeneric()))) {
- log.warning(env.tree.pos(), "type.parameter.on.polymorphic.signature");
- }
-
+ List<Type> argtypes) {
Type mtype = infer.instantiatePolymorphicSignatureInstance(env,
- site, name, spMethod, argtypes, typeargtypes);
+ site, name, spMethod, argtypes);
long flags = ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE |
(spMethod != null ?
spMethod.flags() & Flags.AccessFlags :
@@ -1497,7 +1500,7 @@
List<Type> argtypes,
List<Type> typeargtypes) {
Symbol sym = resolveQualifiedMethod(
- pos, env, site, name, argtypes, typeargtypes);
+ pos, env, site.tsym, site, name, argtypes, typeargtypes);
if (sym.kind == MTH) return (MethodSymbol)sym;
else throw new FatalError(
diags.fragment("fatal.err.cant.locate.meth",
@@ -1572,11 +1575,13 @@
null;
Symbol errSym = new ResolveError(WRONG_MTH, "diamond error") {
@Override
- JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
+ JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
+ Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
String key = details == null ?
"cant.apply.diamond" :
"cant.apply.diamond.1";
- return diags.create(dkind, log.currentSource(), pos, key, diags.fragment("diamond", site.tsym), details);
+ return diags.create(dkind, log.currentSource(), pos, key,
+ diags.fragment("diamond", site.tsym), details);
}
};
MethodResolutionPhase errPhase = firstErroneousResolutionPhase();
@@ -1755,17 +1760,18 @@
public void logAccessError(Env<AttrContext> env, JCTree tree, Type type) {
AccessError error = new AccessError(env, type.getEnclosingType(), type.tsym);
- logResolveError(error, tree.pos(), type.getEnclosingType(), null, null, null);
+ logResolveError(error, tree.pos(), type.getEnclosingType().tsym, type.getEnclosingType(), null, null, null);
}
//where
private void logResolveError(ResolveError error,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
JCDiagnostic d = error.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
- pos, site, name, argtypes, typeargtypes);
+ pos, location, site, name, argtypes, typeargtypes);
if (d != null) {
d.setFlag(DiagnosticFlag.RESOLVE_ERROR);
log.report(d);
@@ -1835,6 +1841,7 @@
*/
abstract JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
@@ -1900,6 +1907,7 @@
@Override
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
@@ -1910,16 +1918,23 @@
return null;
if (isOperator(name)) {
+ boolean isUnaryOp = argtypes.size() == 1;
+ String key = argtypes.size() == 1 ?
+ "operator.cant.be.applied" :
+ "operator.cant.be.applied.1";
+ Type first = argtypes.head;
+ Type second = !isUnaryOp ? argtypes.tail.head : null;
return diags.create(dkind, log.currentSource(), pos,
- "operator.cant.be.applied", name, argtypes);
+ key, name, first, second);
}
boolean hasLocation = false;
- if (!site.tsym.name.isEmpty()) {
- if (site.tsym.kind == PCK && !site.tsym.exists()) {
+ if (!location.name.isEmpty()) {
+ if (location.kind == PCK && !site.tsym.exists()) {
return diags.create(dkind, log.currentSource(), pos,
- "doesnt.exist", site.tsym);
+ "doesnt.exist", location);
}
- hasLocation = true;
+ hasLocation = !location.name.equals(names._this) &&
+ !location.name.equals(names._super);
}
boolean isConstructor = kind == ABSENT_MTH &&
name == names.table.names.init;
@@ -1930,7 +1945,7 @@
return diags.create(dkind, log.currentSource(), pos,
errKey, kindname, idname, //symbol kindname, name
typeargtypes, argtypes, //type parameters and arguments (if any)
- typeKindName(site), site); //location kindname, type
+ getLocationDiag(location)); //location kindname, type
}
else {
return diags.create(dkind, log.currentSource(), pos,
@@ -1951,6 +1966,16 @@
}
return key + suffix;
}
+ private JCDiagnostic getLocationDiag(Symbol location) {
+ boolean isVar = location.kind == VAR;
+ String key = isVar ?
+ "location.1" :
+ "location";
+ return diags.fragment(key,
+ kindName(location),
+ location,
+ isVar ? location.type : null);
+ }
}
/**
@@ -1991,6 +2016,7 @@
@Override
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
@@ -2042,6 +2068,7 @@
@Override
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
@@ -2057,7 +2084,7 @@
return new JCDiagnostic.MultilineDiagnostic(err, candidateDetails(site));
} else {
return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind, pos,
- site, name, argtypes, typeargtypes);
+ location, site, name, argtypes, typeargtypes);
}
}
@@ -2157,6 +2184,7 @@
@Override
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
@@ -2166,7 +2194,7 @@
if (sym.name == names.init && sym.owner != site.tsym) {
return new SymbolNotFoundError(ABSENT_MTH).getDiagnostic(dkind,
- pos, site, name, argtypes, typeargtypes);
+ pos, location, site, name, argtypes, typeargtypes);
}
else if ((sym.flags() & PUBLIC) != 0
|| (env != null && this.site != null
@@ -2201,6 +2229,7 @@
@Override
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
@@ -2231,6 +2260,7 @@
@Override
JCDiagnostic getDiagnostic(JCDiagnostic.DiagnosticType dkind,
DiagnosticPosition pos,
+ Symbol location,
Type site,
Name name,
List<Type> argtypes,
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -69,7 +69,6 @@
private boolean allowEnums;
private Types types;
private final Resolve resolve;
- private final TypeAnnotations typeAnnotations;
/**
* Flag to indicate whether or not to generate bridge methods.
@@ -91,7 +90,6 @@
types = Types.instance(context);
make = TreeMaker.instance(context);
resolve = Resolve.instance(context);
- typeAnnotations = TypeAnnotations.instance(context);
}
/** A hashtable mapping bridge methods to the methods they override after
@@ -182,7 +180,7 @@
parameters = parameters.tail;
}
Type parameter = parameters.head;
- assert varargsElement != null || args.length() == 1;
+ Assert.check(varargsElement != null || args.length() == 1);
if (varargsElement != null) {
while (args.nonEmpty()) {
args.head = translate(args.head, varargsElement);
@@ -445,14 +443,12 @@
}
public void visitClassDef(JCClassDecl tree) {
- typeAnnotations.taFillAndLift(tree, true);
translateClass(tree.sym);
result = tree;
}
JCMethodDecl currentMethod = null;
public void visitMethodDef(JCMethodDecl tree) {
- tree.sym.typeAnnotations = tree.sym.typeAnnotations;
JCMethodDecl previousMethod = currentMethod;
try {
currentMethod = tree;
@@ -598,7 +594,7 @@
if (tree.varargsElement != null)
tree.varargsElement = types.erasure(tree.varargsElement);
else
- assert tree.args.length() == argtypes.length();
+ Assert.check(tree.args.length() == argtypes.length());
tree.args = translateArgs(tree.args, argtypes, tree.varargsElement);
// Insert casts of method invocation results as needed.
--- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -472,7 +472,7 @@
*/
protected Archive openArchive(File zipFileName) throws IOException {
File origZipFileName = zipFileName;
- if (!ignoreSymbolFile && paths.isBootClassPathRtJar(zipFileName)) {
+ if (!ignoreSymbolFile && paths.isDefaultBootClassPathRtJar(zipFileName)) {
File file = zipFileName.getParentFile().getParentFile(); // ${java.home}
if (new File(file.getName()).equals(new File("jre")))
file = file.getParentFile();
--- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -112,7 +112,7 @@
* rt.jar as found on the default bootclass path. If the user specified a
* bootclasspath, null is used.
*/
- private File bootClassPathRtJar = null;
+ private File defaultBootClassPathRtJar = null;
/**
* Is bootclasspath the default?
@@ -143,8 +143,10 @@
// no defaults for other paths
p = null;
} else {
- if (location == PLATFORM_CLASS_PATH)
+ if (location == PLATFORM_CLASS_PATH) {
+ defaultBootClassPathRtJar = null;
isDefaultBootClassPath = false;
+ }
p = new Path();
for (File f: path)
p.addFile(f, warn); // TODO: is use of warn appropriate?
@@ -185,8 +187,8 @@
: Collections.unmodifiableCollection(p);
}
- boolean isBootClassPathRtJar(File file) {
- return file.equals(bootClassPathRtJar);
+ boolean isDefaultBootClassPathRtJar(File file) {
+ return file.equals(defaultBootClassPathRtJar);
}
/**
@@ -355,7 +357,7 @@
}
private Path computeBootClassPath() {
- bootClassPathRtJar = null;
+ defaultBootClassPathRtJar = null;
Path path = new Path();
String bootclasspathOpt = options.get(BOOTCLASSPATH);
@@ -380,7 +382,7 @@
File rt_jar = new File("rt.jar");
for (File file : getPathEntries(files)) {
if (new File(file.getName()).equals(rt_jar))
- bootClassPathRtJar = file;
+ defaultBootClassPathRtJar = file;
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/file/ZipFileIndexArchive.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2009, 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
@@ -42,6 +42,7 @@
import com.sun.tools.javac.file.JavacFileManager.Archive;
import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
import com.sun.tools.javac.file.RelativePath.RelativeFile;
+import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.List;
/**
@@ -146,7 +147,7 @@
@Override
public InputStream openInputStream() throws IOException {
if (inputStream == null) {
- assert entry != null; // see constructor
+ Assert.checkNonNull(entry); // see constructor
inputStream = new ByteArrayInputStream(zfIndex.read(entry));
}
return inputStream;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/CRTable.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -101,7 +101,7 @@
continue;
SourceRange pos = positions.get(entry.tree);
- assert pos != null : "CRT: tree source positions are undefined";
+ Assert.checkNonNull(pos, "CRT: tree source positions are undefined");
if ((pos.startPos == Position.NOPOS) || (pos.endPos == Position.NOPOS))
continue;
@@ -517,7 +517,7 @@
}
public void visitTree(JCTree tree) {
- assert false;
+ Assert.error();
}
/** The start position of given tree.
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassFile.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, 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
@@ -80,6 +80,9 @@
public final static int CONSTANT_Methodref = 10;
public final static int CONSTANT_InterfaceMethodref = 11;
public final static int CONSTANT_NameandType = 12;
+ public final static int CONSTANT_MethodHandle = 15;
+ public final static int CONSTANT_MethodType = 16;
+ public final static int CONSTANT_InvokeDynamic = 18;
public final static int MAX_PARAMETERS = 0xff;
public final static int MAX_DIMENSIONS = 0xff;
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -207,10 +207,6 @@
/** The minor version number of the class file being read. */
int minorVersion;
- /** Switch: debug output for JSR 308-related operations.
- */
- boolean debugJSR308;
-
/** A table to hold the constant pool indices for method parameter
* names, as given in LocalVariableTable attributes.
*/
@@ -246,9 +242,9 @@
if (classes != null) return;
if (definitive) {
- assert packages == null || packages == syms.packages;
+ Assert.check(packages == null || packages == syms.packages);
packages = syms.packages;
- assert classes == null || classes == syms.classes;
+ Assert.check(classes == null || classes == syms.classes);
classes = syms.classes;
} else {
packages = new HashMap<Name, PackageSymbol>();
@@ -297,7 +293,6 @@
: null;
typevars = new Scope(syms.noSymbol);
- debugJSR308 = options.isSet("TA:reader");
lintClassfile = Lint.instance(context).isEnabled(LintCategory.CLASSFILE);
@@ -439,14 +434,19 @@
}
case CONSTANT_Class:
case CONSTANT_String:
+ case CONSTANT_MethodType:
bp = bp + 2;
break;
+ case CONSTANT_MethodHandle:
+ bp = bp + 3;
+ break;
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameandType:
case CONSTANT_Integer:
case CONSTANT_Float:
+ case CONSTANT_InvokeDynamic:
bp = bp + 4;
break;
case CONSTANT_Long:
@@ -515,6 +515,15 @@
case CONSTANT_Double:
poolObj[i] = new Double(getDouble(index + 1));
break;
+ case CONSTANT_MethodHandle:
+ skipBytes(4);
+ break;
+ case CONSTANT_MethodType:
+ skipBytes(3);
+ break;
+ case CONSTANT_InvokeDynamic:
+ skipBytes(5);
+ break;
default:
throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
}
@@ -535,7 +544,7 @@
int index = poolIdx[i];
int len = getChar(index + 1);
int start = index + 3;
- assert buf[start] == '[' || buf[start + len - 1] != ';';
+ Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
// by the above assertion, the following test can be
// simplified to (buf[start] == '[')
return (buf[start] == '[' || buf[start + len - 1] == ';')
@@ -1046,7 +1055,7 @@
readingClassAttr = true;
try {
ClassType ct1 = (ClassType)c.type;
- assert c == currentOwner;
+ Assert.check(c == currentOwner);
ct1.typarams_field = readTypeParams(nextChar());
ct1.supertype_field = sigToType();
ListBuffer<Type> is = new ListBuffer<Type>();
@@ -1128,20 +1137,6 @@
}
},
- // v51 attributes
- new AttributeReader(names.RuntimeVisibleTypeAnnotations, V51, CLASS_OR_MEMBER_ATTRIBUTE) {
- void read(Symbol sym, int attrLen) {
- attachTypeAnnotations(sym);
- }
- },
-
- new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V51, CLASS_OR_MEMBER_ATTRIBUTE) {
- void read(Symbol sym, int attrLen) {
- attachTypeAnnotations(sym);
- }
- },
-
-
// The following attributes for a Code attribute are not currently handled
// StackMapTable
// SourceDebugExtension
@@ -1351,17 +1346,6 @@
}
}
- void attachTypeAnnotations(final Symbol sym) {
- int numAttributes = nextChar();
- if (numAttributes != 0) {
- ListBuffer<TypeAnnotationProxy> proxies =
- ListBuffer.lb();
- for (int i = 0; i < numAttributes; i++)
- proxies.append(readTypeAnnotation());
- annotate.later(new TypeAnnotationCompleter(sym, proxies.toList()));
- }
- }
-
/** Attach the default value for an annotation element.
*/
void attachAnnotationDefault(final Symbol sym) {
@@ -1398,121 +1382,6 @@
return new CompoundAnnotationProxy(t, pairs.toList());
}
- TypeAnnotationProxy readTypeAnnotation() {
- CompoundAnnotationProxy proxy = readCompoundAnnotation();
- TypeAnnotationPosition position = readPosition();
-
- if (debugJSR308)
- System.out.println("TA: reading: " + proxy + " @ " + position
- + " in " + log.currentSourceFile());
-
- return new TypeAnnotationProxy(proxy, position);
- }
-
- TypeAnnotationPosition readPosition() {
- byte tag = nextByte();
-
- if (!TargetType.isValidTargetTypeValue(tag))
- throw this.badClassFile("bad.type.annotation.value", tag);
-
- TypeAnnotationPosition position = new TypeAnnotationPosition();
- TargetType type = TargetType.fromTargetTypeValue(tag);
-
- position.type = type;
-
- switch (type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- position.offset = nextChar();
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- int table_length = nextChar();
- position.lvarOffset = new int[table_length];
- position.lvarLength = new int[table_length];
- position.lvarIndex = new int[table_length];
-
- for (int i = 0; i < table_length; ++i) {
- position.lvarOffset[i] = nextChar();
- position.lvarLength[i] = nextChar();
- position.lvarIndex[i] = nextChar();
- }
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- position.parameter_index = nextByte();
- break;
- // type parameter bounds
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- position.parameter_index = nextByte();
- position.bound_index = nextByte();
- break;
- // wildcard
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- position.wildcard_position = readPosition();
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- position.type_index = nextChar();
- break;
- // throws
- case THROWS:
- position.type_index = nextChar();
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- position.offset = nextChar();
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- position.parameter_index = nextByte();
- break;
- // method type argument: wasn't specified
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- position.offset = nextChar();
- position.type_index = nextByte();
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- throw new AssertionError("unknown type: " + position);
- }
-
- if (type.hasLocation()) {
- int len = nextChar();
- ListBuffer<Integer> loc = ListBuffer.lb();
- for (int i = 0; i < len; i++)
- loc = loc.append((int)nextByte());
- position.location = loc.toList();
- }
-
- return position;
- }
Attribute readAttributeValue() {
char c = (char) buf[bp++];
switch (c) {
@@ -1825,45 +1694,6 @@
}
}
- class TypeAnnotationCompleter extends AnnotationCompleter {
-
- List<TypeAnnotationProxy> proxies;
-
- TypeAnnotationCompleter(Symbol sym,
- List<TypeAnnotationProxy> proxies) {
- super(sym, List.<CompoundAnnotationProxy>nil());
- this.proxies = proxies;
- }
-
- List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
- ListBuffer<Attribute.TypeCompound> buf = ListBuffer.lb();
- for (TypeAnnotationProxy proxy: proxies) {
- Attribute.Compound compound = deproxyCompound(proxy.compound);
- Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
- buf.add(typeCompound);
- }
- return buf.toList();
- }
-
- @Override
- public void enterAnnotation() {
- JavaFileObject previousClassFile = currentClassFile;
- try {
- currentClassFile = classFile;
- List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
- if (debugJSR308)
- System.out.println("TA: reading: adding " + newList
- + " to symbol " + sym + " in " + log.currentSourceFile());
- sym.typeAnnotations = ((sym.typeAnnotations == null)
- ? newList
- : newList.prependList(sym.typeAnnotations));
-
- } finally {
- currentClassFile = previousClassFile;
- }
- }
- }
-
/************************************************************************
* Reading Symbols
@@ -2005,6 +1835,13 @@
sym.savedParameterNames = paramNames.reverse();
}
+ /**
+ * skip n bytes
+ */
+ void skipBytes(int n) {
+ bp = bp + n;
+ }
+
/** Skip a field or method
*/
void skipMember() {
@@ -2092,9 +1929,9 @@
if (ct.interfaces_field == null)
ct.interfaces_field = is.reverse();
- if (fieldCount != nextChar()) assert false;
+ Assert.check(fieldCount == nextChar());
for (int i = 0; i < fieldCount; i++) enterMember(c, readField());
- if (methodCount != nextChar()) assert false;
+ Assert.check(methodCount == nextChar());
for (int i = 0; i < methodCount; i++) enterMember(c, readMethod());
typevars = typevars.leave();
@@ -2203,7 +2040,7 @@
public ClassSymbol defineClass(Name name, Symbol owner) {
ClassSymbol c = new ClassSymbol(0, name, owner);
if (owner.kind == PCK)
- assert classes.get(c.flatname) == null : c;
+ Assert.checkNull(classes.get(c.flatname), c);
c.completer = this;
return c;
}
@@ -2343,9 +2180,9 @@
if (classfile != null) {
JavaFileObject previousClassFile = currentClassFile;
try {
- assert !filling :
- "Filling " + classfile.toUri() +
- " during " + previousClassFile;
+ if (filling) {
+ Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
+ }
currentClassFile = classfile;
if (verbose) {
printVerbose("loading", currentClassFile.toString());
@@ -2491,7 +2328,7 @@
public PackageSymbol enterPackage(Name fullname) {
PackageSymbol p = packages.get(fullname);
if (p == null) {
- assert !fullname.isEmpty() : "rootPackage missing!";
+ Assert.check(!fullname.isEmpty(), "rootPackage missing!");
p = new PackageSymbol(
Convert.shortName(fullname),
enterPackage(Convert.packagePart(fullname)));
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -65,10 +65,6 @@
private final Options options;
- /** Switch: debugging output for JSR 308-related operations.
- */
- private boolean debugJSR308;
-
/** Switch: verbose output.
*/
private boolean verbose;
@@ -180,7 +176,6 @@
types = Types.instance(context);
fileManager = context.get(JavaFileManager.class);
- debugJSR308 = options.isSet("TA:writer");
verbose = options.isSet(VERBOSE);
scramble = options.isSet("-scramble");
scrambleAll = options.isSet("-scrambleAll");
@@ -224,11 +219,14 @@
/** Return flags as a string, separated by " ".
*/
public static String flagNames(long flags) {
- StringBuffer sbuf = new StringBuffer();
+ StringBuilder sbuf = new StringBuilder();
int i = 0;
long f = flags & StandardFlags;
while (f != 0) {
- if ((f & 1) != 0) sbuf.append(" " + flagName[i]);
+ if ((f & 1) != 0) {
+ sbuf.append(" ");
+ sbuf.append(flagName[i]);
+ }
f = f >> 1;
i++;
}
@@ -381,7 +379,7 @@
? types.erasure(outer)
: outer);
sigbuf.appendByte('.');
- assert c.flatname.startsWith(c.owner.enclClass().flatname);
+ Assert.check(c.flatname.startsWith(c.owner.enclClass().flatname));
sigbuf.appendName(rawOuter
? c.flatname.subName(c.owner.enclClass().flatname.getByteLength()+1,c.flatname.getByteLength())
: c.name);
@@ -421,7 +419,7 @@
/** Return signature of given type
*/
Name typeSig(Type type) {
- assert sigbuf.length == 0;
+ Assert.check(sigbuf.length == 0);
//- System.out.println(" ? " + type);
assembleSig(type);
Name n = sigbuf.toName(names);
@@ -471,7 +469,7 @@
int i = 1;
while (i < pool.pp) {
Object value = pool.pool[i];
- assert value != null;
+ Assert.checkNonNull(value);
if (value instanceof Pool.Method)
value = ((Pool.Method)value).m;
else if (value instanceof Pool.Variable)
@@ -534,7 +532,7 @@
poolbuf.appendByte(CONSTANT_Class);
poolbuf.appendChar(pool.put(xClassName(type)));
} else {
- assert false : "writePool " + value;
+ Assert.error("writePool " + value);
}
i++;
}
@@ -677,7 +675,6 @@
acount++;
}
acount += writeJavaAnnotations(sym.getAnnotationMirrors());
- acount += writeTypeAnnotations(sym.typeAnnotations);
return acount;
}
@@ -772,46 +769,6 @@
return attrCount;
}
- int writeTypeAnnotations(List<Attribute.TypeCompound> typeAnnos) {
- if (typeAnnos.isEmpty()) return 0;
-
- ListBuffer<Attribute.TypeCompound> visibles = ListBuffer.lb();
- ListBuffer<Attribute.TypeCompound> invisibles = ListBuffer.lb();
-
- for (Attribute.TypeCompound tc : typeAnnos) {
- if (tc.position.type == TargetType.UNKNOWN
- || !tc.position.emitToClassfile())
- continue;
- switch (types.getRetention(tc)) {
- case SOURCE: break;
- case CLASS: invisibles.append(tc); break;
- case RUNTIME: visibles.append(tc); break;
- default: ;// /* fail soft */ throw new AssertionError(vis);
- }
- }
-
- int attrCount = 0;
- if (visibles.length() != 0) {
- int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations);
- databuf.appendChar(visibles.length());
- for (Attribute.TypeCompound p : visibles)
- writeTypeAnnotation(p);
- endAttr(attrIndex);
- attrCount++;
- }
-
- if (invisibles.length() != 0) {
- int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations);
- databuf.appendChar(invisibles.length());
- for (Attribute.TypeCompound p : invisibles)
- writeTypeAnnotation(p);
- endAttr(attrIndex);
- attrCount++;
- }
-
- return attrCount;
- }
-
/** A visitor to write an attribute including its leading
* single-character marker.
*/
@@ -844,7 +801,7 @@
databuf.appendByte('Z');
break;
case CLASS:
- assert value instanceof String;
+ Assert.check(value instanceof String);
databuf.appendByte('s');
value = names.fromString(value.toString()); // CONSTANT_Utf8
break;
@@ -888,104 +845,6 @@
p.snd.accept(awriter);
}
}
-
- void writeTypeAnnotation(Attribute.TypeCompound c) {
- if (debugJSR308)
- System.out.println("TA: writing " + c + " at " + c.position
- + " in " + log.currentSourceFile());
- writeCompoundAttribute(c);
- writePosition(c.position);
- }
-
- void writePosition(TypeAnnotationPosition p) {
- databuf.appendByte(p.type.targetTypeValue());
- switch (p.type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- databuf.appendChar(p.offset);
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- databuf.appendChar(p.lvarOffset.length); // for table length
- for (int i = 0; i < p.lvarOffset.length; ++i) {
- databuf.appendChar(p.lvarOffset[i]);
- databuf.appendChar(p.lvarLength[i]);
- databuf.appendChar(p.lvarIndex[i]);
- }
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- databuf.appendByte(p.parameter_index);
- break;
- // type parameters bounds
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- databuf.appendByte(p.parameter_index);
- databuf.appendByte(p.bound_index);
- break;
- // wildcards
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- writePosition(p.wildcard_position);
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- databuf.appendChar(p.type_index);
- break;
- // throws
- case THROWS:
- databuf.appendChar(p.type_index);
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- databuf.appendChar(p.offset);
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- databuf.appendByte(p.parameter_index);
- break;
- // method type argument: wasn't specified
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- databuf.appendChar(p.offset);
- databuf.appendByte(p.type_index);
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- throw new AssertionError("unknown position: " + p);
- }
-
- // Append location data for generics/arrays.
- if (p.type.hasLocation()) {
- databuf.appendChar(p.location.size());
- for (int i : p.location)
- databuf.appendByte((byte)i);
- }
- }
-
/**********************************************************************
* Writing Objects
**********************************************************************/
@@ -1159,11 +1018,11 @@
Code.LocalVar var = code.varBuffer[i];
// write variable info
- assert var.start_pc >= 0;
- assert var.start_pc <= code.cp;
+ Assert.check(var.start_pc >= 0
+ && var.start_pc <= code.cp);
databuf.appendChar(var.start_pc);
- assert var.length >= 0;
- assert (var.start_pc + var.length) <= code.cp;
+ Assert.check(var.length >= 0
+ && (var.start_pc + var.length) <= code.cp);
databuf.appendChar(var.length);
VarSymbol sym = var.sym;
databuf.appendChar(pool.put(sym.name));
@@ -1195,7 +1054,7 @@
databuf.appendChar(pool.put(typeSig(sym.type)));
databuf.appendChar(var.reg);
}
- assert count == nGenericVars;
+ Assert.check(count == nGenericVars);
endAttr(alenIdx);
acount++;
}
@@ -1266,7 +1125,7 @@
}
break;
case JSR202: {
- assert code.stackMapBuffer == null;
+ Assert.checkNull(code.stackMapBuffer);
for (int i=0; i<nframes; i++) {
if (debugstackmap) System.out.print(" " + i + ":");
StackMapTableFrame frame = code.stackMapTableBuffer[i];
@@ -1606,7 +1465,7 @@
*/
public void writeClassFile(OutputStream out, ClassSymbol c)
throws IOException, PoolOverflow, StringOverflow {
- assert (c.flags() & COMPOUND) == 0;
+ Assert.check((c.flags() & COMPOUND) == 0);
databuf.reset();
poolbuf.reset();
sigbuf.reset();
@@ -1643,7 +1502,7 @@
case MTH: if ((e.sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
break;
case TYP: enterInner((ClassSymbol)e.sym); break;
- default : assert false;
+ default : Assert.error();
}
}
databuf.appendChar(fieldsCount);
@@ -1659,7 +1518,7 @@
for (List<Type> l = interfaces; !sigReq && l.nonEmpty(); l = l.tail)
sigReq = l.head.allparams().length() != 0;
if (sigReq) {
- assert source.allowGenerics();
+ Assert.check(source.allowGenerics());
int alenIdx = writeAttr(names.Signature);
if (typarams.length() != 0) assembleParamsSig(typarams);
assembleSig(supertype);
@@ -1698,7 +1557,6 @@
acount += writeFlagAttrs(c.flags());
acount += writeJavaAnnotations(c.getAnnotationMirrors());
- acount += writeTypeAnnotations(c.typeAnnotations);
acount += writeEnclosingMethodAttribute(c);
poolbuf.appendInt(JAVA_MAGIC);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -372,7 +372,7 @@
}
void postop() {
- assert alive || state.stacksize == 0;
+ Assert.check(alive || state.stacksize == 0);
}
/** Emit a multinewarray instruction.
@@ -583,7 +583,7 @@
case areturn:
case ireturn:
case freturn:
- assert state.nlocks == 0;
+ Assert.check(state.nlocks == 0);
state.pop(1);
markDead();
break;
@@ -604,7 +604,7 @@
break;
case lreturn:
case dreturn:
- assert state.nlocks == 0;
+ Assert.check(state.nlocks == 0);
state.pop(2);
markDead();
break;
@@ -612,7 +612,7 @@
state.push(state.stack[state.stacksize-1]);
break;
case return_:
- assert state.nlocks == 0;
+ Assert.check(state.nlocks == 0);
markDead();
break;
case arraylength:
@@ -1147,7 +1147,7 @@
int pc = curPc();
alive = true;
this.state = state.dup();
- assert state.stacksize <= max_stack;
+ Assert.check(state.stacksize <= max_stack);
if (debugCode) System.err.println("entry point " + state);
pendingStackMap = needStackMap;
return pc;
@@ -1160,7 +1160,7 @@
int pc = curPc();
alive = true;
this.state = state.dup();
- assert state.stacksize <= max_stack;
+ Assert.check(state.stacksize <= max_stack);
this.state.push(pushed);
if (debugCode) System.err.println("entry point " + state);
pendingStackMap = needStackMap;
@@ -1289,7 +1289,7 @@
}
frame.locals = new Type[localCount];
for (int i=0, j=0; i<localsSize; i++, j++) {
- assert(j < localCount);
+ Assert.check(j < localCount);
frame.locals[j] = locals[i];
if (width(locals[i]) > 1) i++;
}
@@ -1435,8 +1435,8 @@
boolean changed = false;
State newState = state;
for (; chain != null; chain = chain.next) {
- assert state != chain.state;
- assert target > chain.pc || state.stacksize == 0;
+ Assert.check(state != chain.state
+ && (target > chain.pc || state.stacksize == 0));
if (target >= cp) {
target = cp;
} else if (get1(target) == goto_) {
@@ -1464,9 +1464,9 @@
fatcode = true;
else
put2(chain.pc + 1, target - chain.pc);
- assert !alive ||
+ Assert.check(!alive ||
chain.state.stacksize == newState.stacksize &&
- chain.state.nlocks == newState.nlocks;
+ chain.state.nlocks == newState.nlocks);
}
fixedPc = true;
if (cp == target) {
@@ -1481,7 +1481,7 @@
}
}
}
- assert !changed || state != newState;
+ Assert.check(!changed || state != newState);
if (state != newState) {
setDefined(newState.defined);
state = newState;
@@ -1492,11 +1492,11 @@
/** Resolve chain to point to current code pointer.
*/
public void resolve(Chain chain) {
- assert
+ Assert.check(
!alive ||
chain==null ||
state.stacksize == chain.state.stacksize &&
- state.nlocks == chain.state.nlocks;
+ state.nlocks == chain.state.nlocks);
pendingJumps = mergeChains(chain, pendingJumps);
}
@@ -1514,9 +1514,9 @@
// recursive merge sort
if (chain2 == null) return chain1;
if (chain1 == null) return chain2;
- assert
+ Assert.check(
chain1.state.stacksize == chain2.state.stacksize &&
- chain1.state.nlocks == chain2.state.nlocks;
+ chain1.state.nlocks == chain2.state.nlocks);
if (chain1.pc < chain2.pc)
return new Chain(
chain2.pc,
@@ -1631,7 +1631,7 @@
void unlock(int register) {
nlocks--;
- assert locks[nlocks] == register;
+ Assert.check(locks[nlocks] == register);
locks[nlocks] = -1;
}
@@ -1673,7 +1673,7 @@
stacksize--;
Type result = stack[stacksize];
stack[stacksize] = null;
- assert result != null && width(result) == 1;
+ Assert.check(result != null && width(result) == 1);
return result;
}
@@ -1686,8 +1686,8 @@
stacksize -= 2;
Type result = stack[stacksize];
stack[stacksize] = null;
- assert stack[stacksize+1] == null;
- assert result != null && width(result) == 2;
+ Assert.check(stack[stacksize+1] == null
+ && result != null && width(result) == 2);
return result;
}
@@ -1712,8 +1712,8 @@
case ARRAY:
int width = width(t);
Type old = stack[stacksize-width];
- assert types.isSubtype(types.erasure(old),
- types.erasure(t));
+ Assert.check(types.isSubtype(types.erasure(old),
+ types.erasure(t)));
stack[stacksize-width] = t;
break;
default:
@@ -1739,8 +1739,8 @@
State join(State other) {
defined = defined.andSet(other.defined);
- assert stacksize == other.stacksize;
- assert nlocks == other.nlocks;
+ Assert.check(stacksize == other.stacksize
+ && nlocks == other.nlocks);
for (int i=0; i<stacksize; ) {
Type t = stack[i];
Type tother = other.stack[i];
@@ -1751,7 +1751,7 @@
error();
int w = width(result);
stack[i] = result;
- if (w == 2) assert stack[i+1] == null;
+ if (w == 2) Assert.checkNull(stack[i+1]);
i += w;
}
return this;
@@ -1847,7 +1847,7 @@
System.arraycopy(lvar, 0, new_lvar, 0, lvar.length);
lvar = new_lvar;
}
- assert lvar[adr] == null;
+ Assert.checkNull(lvar[adr]);
if (pendingJumps != null) resolvePending();
lvar[adr] = new LocalVar(v);
state.defined.excl(adr);
@@ -1912,29 +1912,12 @@
if (length < Character.MAX_VALUE) {
v.length = length;
putVar(v);
- fillLocalVarPosition(v);
}
}
}
state.defined.excl(adr);
}
- private void fillLocalVarPosition(LocalVar lv) {
- if (lv == null || lv.sym == null
- || lv.sym.typeAnnotations == null)
- return;
- for (Attribute.TypeCompound ta : lv.sym.typeAnnotations) {
- TypeAnnotationPosition p = ta.position;
- while (p != null) {
- p.lvarOffset = new int[] { (int)lv.start_pc };
- p.lvarLength = new int[] { (int)lv.length };
- p.lvarIndex = new int[] { (int)lv.reg };
- p.isValidOffset = true;
- p = p.wildcard_position;
- }
- }
- }
-
/** Put a live variable range into the buffer to be output to the
* class file.
*/
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -500,7 +500,7 @@
}
break;
default:
- assert false;
+ Assert.error();
}
}
// Insert any instance initializers into all constructors.
@@ -857,7 +857,7 @@
pts = pts.tail;
}
// require lists be of same length
- assert pts.isEmpty();
+ Assert.check(pts.isEmpty());
}
/* ************************************************************************
@@ -1111,7 +1111,7 @@
public void visitSwitch(JCSwitch tree) {
int limit = code.nextreg;
- assert tree.selector.type.tag != CLASS;
+ Assert.check(tree.selector.type.tag != CLASS);
int startpcCrt = genCrt ? code.curPc() : 0;
Item sel = genExpr(tree.selector, syms.intType);
List<JCCase> cases = tree.cases;
@@ -1148,7 +1148,7 @@
if (hi < val) hi = val;
nlabels++;
} else {
- assert defaultIndex == -1;
+ Assert.check(defaultIndex == -1);
defaultIndex = i;
}
l = l.tail;
@@ -1290,7 +1290,7 @@
syncEnv.info.finalize = new GenFinalizer() {
void gen() {
genLast();
- assert syncEnv.info.gaps.length() % 2 == 0;
+ Assert.check(syncEnv.info.gaps.length() % 2 == 0);
syncEnv.info.gaps.append(code.curPc());
}
void genLast() {
@@ -1329,10 +1329,10 @@
tryEnv.info.cont,
jsrState);
}
- assert tryEnv.info.gaps.length() % 2 == 0;
+ Assert.check(tryEnv.info.gaps.length() % 2 == 0);
tryEnv.info.gaps.append(code.curPc());
} else {
- assert tryEnv.info.gaps.length() % 2 == 0;
+ Assert.check(tryEnv.info.gaps.length() % 2 == 0);
tryEnv.info.gaps.append(code.curPc());
genLast();
}
@@ -1640,14 +1640,14 @@
public void visitBreak(JCBreak tree) {
Env<GenContext> targetEnv = unwind(tree.target, env);
- assert code.state.stacksize == 0;
+ Assert.check(code.state.stacksize == 0);
targetEnv.info.addExit(code.branch(goto_));
endFinalizerGaps(env, targetEnv);
}
public void visitContinue(JCContinue tree) {
Env<GenContext> targetEnv = unwind(tree.target, env);
- assert code.state.stacksize == 0;
+ Assert.check(code.state.stacksize == 0);
targetEnv.info.addCont(code.branch(goto_));
endFinalizerGaps(env, targetEnv);
}
@@ -1682,7 +1682,6 @@
*************************************************************************/
public void visitApply(JCMethodInvocation tree) {
- setTypeAnnotationPositions(tree.pos);
// Generate code for method.
Item m = genExpr(tree.meth, methodType);
// Generate code for all arguments, where the expected types are
@@ -1718,48 +1717,10 @@
result = items.makeStackItem(pt);
}
- private void setTypeAnnotationPositions(int treePos) {
- MethodSymbol meth = code.meth;
-
- for (Attribute.TypeCompound ta : meth.typeAnnotations) {
- if (ta.position.pos == treePos) {
- ta.position.offset = code.cp;
- ta.position.lvarOffset = new int[] { code.cp };
- ta.position.isValidOffset = true;
- }
- }
-
- if (code.meth.getKind() != ElementKind.CONSTRUCTOR
- && code.meth.getKind() != ElementKind.STATIC_INIT)
- return;
-
- for (Attribute.TypeCompound ta : meth.owner.typeAnnotations) {
- if (ta.position.pos == treePos) {
- ta.position.offset = code.cp;
- ta.position.lvarOffset = new int[] { code.cp };
- ta.position.isValidOffset = true;
- }
- }
-
- ClassSymbol clazz = meth.enclClass();
- for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
- if (!s.getKind().isField())
- continue;
- for (Attribute.TypeCompound ta : s.typeAnnotations) {
- if (ta.position.pos == treePos) {
- ta.position.offset = code.cp;
- ta.position.lvarOffset = new int[] { code.cp };
- ta.position.isValidOffset = true;
- }
- }
- }
- }
-
public void visitNewClass(JCNewClass tree) {
// Enclosing instances or anonymous classes should have been eliminated
// by now.
- assert tree.encl == null && tree.def == null;
- setTypeAnnotationPositions(tree.pos);
+ Assert.check(tree.encl == null && tree.def == null);
code.emitop2(new_, makeRef(tree.pos(), tree.type));
code.emitop0(dup);
@@ -1774,7 +1735,6 @@
}
public void visitNewArray(JCNewArray tree) {
- setTypeAnnotationPositions(tree.pos);
if (tree.elems != null) {
Type elemtype = types.elemtype(tree.type);
@@ -1942,7 +1902,7 @@
genNullCheck(tree.pos());
break;
default:
- assert false;
+ Assert.error();
}
}
}
@@ -2017,7 +1977,7 @@
items.makeMemberItem(getStringBufferAppend(tree, t), false).invoke();
}
Symbol getStringBufferAppend(JCTree tree, Type t) {
- assert t.constValue() == null;
+ Assert.checkNull(t.constValue());
Symbol method = stringBufferAppend.get(t);
if (method == null) {
method = rs.resolveInternalMethod(tree.pos(),
@@ -2104,7 +2064,6 @@
}
public void visitTypeCast(JCTypeCast tree) {
- setTypeAnnotationPositions(tree.pos);
result = genExpr(tree.expr, tree.clazz.type).load();
// Additional code is only needed if we cast to a reference type
// which is not statically a supertype of the expression's type.
@@ -2121,8 +2080,6 @@
}
public void visitTypeTest(JCInstanceOf tree) {
- setTypeAnnotationPositions(tree.pos);
-
genExpr(tree.expr, tree.expr.type).load();
code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type));
result = items.makeStackItem(syms.booleanType);
@@ -2163,16 +2120,10 @@
Symbol sym = tree.sym;
if (tree.name == names._class) {
- assert target.hasClassLiterals();
- setTypeAnnotationPositions(tree.pos);
+ Assert.check(target.hasClassLiterals());
code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type));
result = items.makeStackItem(pt);
return;
- } else if (tree.name == names.TYPE) {
- // Set the annotation positions for primitive class literals
- // (e.g. int.class) which have been converted to TYPE field
- // access on the corresponding boxed type (e.g. Integer.TYPE).
- setTypeAnnotationPositions(tree.pos);
}
Symbol ssym = TreeInfo.symbol(tree.selected);
@@ -2202,9 +2153,6 @@
}
result = items.
makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
- } else if (allowInvokedynamic && sym.kind == MTH && ssym == syms.invokeDynamicType.tsym) {
- base.drop();
- result = items.makeDynamicItem(sym);
} else {
if (!accessSuper)
sym = binaryQualifier(sym, tree.selected.type);
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java Fri Feb 18 12:04:36 2011 -0800
@@ -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,11 +26,11 @@
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.*;
-
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.jvm.Code.*;
import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.util.Assert;
import static com.sun.tools.javac.jvm.ByteCodes.*;
@@ -139,13 +139,6 @@
return new StaticItem(member);
}
- /** Make an item representing a dynamically invoked method.
- * @param member The represented symbol.
- */
- Item makeDynamicItem(Symbol member) {
- return new DynamicItem(member);
- }
-
/** Make an item representing an instance variable or method.
* @param member The represented symbol.
* @param nonvirtual Is the reference not virtual? (true for constructors
@@ -387,7 +380,7 @@
LocalItem(Type type, int reg) {
super(Code.typecode(type));
- assert reg >= 0;
+ Assert.check(reg >= 0);
this.type = type;
this.reg = reg;
}
@@ -464,38 +457,6 @@
}
}
- /** An item representing a dynamic call site.
- */
- class DynamicItem extends StaticItem {
- DynamicItem(Symbol member) {
- super(member);
- assert member.owner == syms.invokeDynamicType.tsym;
- }
-
- Item load() {
- assert false;
- return null;
- }
-
- void store() {
- assert false;
- }
-
- Item invoke() {
- // assert target.hasNativeInvokeDynamic();
- MethodType mtype = (MethodType)member.erasure(types);
- int rescode = Code.typecode(mtype.restype);
- ClassFile.NameAndType descr = new ClassFile.NameAndType(member.name, mtype);
- code.emitInvokedynamic(pool.put(descr), mtype);
- return stackItem[rescode];
- }
-
- public String toString() {
- return "dynamic(" + member + ")";
- }
- }
-
-
/** An item representing an instance variable or method.
*/
class MemberItem extends Item {
@@ -620,7 +581,7 @@
ldc();
break;
default:
- assert false;
+ Assert.error();
}
return stackItem[typecode];
}
@@ -716,7 +677,7 @@
}
void stash(int toscode) {
- assert false;
+ Assert.error();
}
int width() {
@@ -784,7 +745,7 @@
}
void stash(int toscode) {
- assert false;
+ Assert.error();
}
CondItem mkCond() {
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -848,7 +848,7 @@
break;
default:
- assert false: "unknown compile policy";
+ Assert.error("unknown compile policy");
}
} catch (Abort ex) {
if (devVerbose)
@@ -1066,7 +1066,7 @@
classSymbols = classSymbols.prepend((ClassSymbol)sym);
continue;
}
- assert sym.kind == Kinds.PCK;
+ Assert.check(sym.kind == Kinds.PCK);
log.warning("proc.package.does.not.exist", nameStr);
pckSymbols = pckSymbols.prepend((PackageSymbol)sym);
} catch (CompletionFailure e) {
@@ -1086,8 +1086,8 @@
if (c != this)
annotationProcessingOccurred = c.annotationProcessingOccurred = true;
// doProcessing will have handled deferred diagnostics
- assert c.log.deferDiagnostics == false;
- assert c.log.deferredDiagnostics.size() == 0;
+ Assert.check(c.log.deferDiagnostics == false
+ && c.log.deferredDiagnostics.size() == 0);
return c;
} finally {
procEnvImpl.close();
@@ -1324,7 +1324,7 @@
return;
List<JCTree> pdef = lower.translateTopLevelClass(env, env.tree, localMake);
if (pdef.head != null) {
- assert pdef.tail.isEmpty();
+ Assert.check(pdef.tail.isEmpty());
results.add(new Pair<Env<AttrContext>, JCClassDecl>(env, (JCClassDecl)pdef.head));
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Fri Feb 18 12:04:36 2011 -0800
@@ -284,13 +284,6 @@
}
}
- // phase this out with JSR 292 PFD
- if ("no".equals(options.get("allowTransitionalJSR292"))) {
- options.put("allowTransitionalJSR292", null);
- } else if (target.hasInvokedynamic() && options.isUnset("allowTransitionalJSR292")) {
- options.put("allowTransitionalJSR292", "allowTransitionalJSR292");
- }
-
// handle this here so it works even if no other options given
String showClass = options.get("showClass");
if (showClass != null) {
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -547,7 +547,7 @@
null);
break;
default:
- assert false;
+ Assert.error();
}
if (t == errorTree)
t = F.at(pos).Erroneous();
@@ -724,7 +724,7 @@
topOpPos = posStack[top];
}
}
- assert top == 0;
+ Assert.check(top == 0);
t = odStack[0];
if (t.getTag() == JCTree.PLUS) {
@@ -2168,8 +2168,11 @@
JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
int pos = S.pos();
Name name = ident();
- if ((mods.flags & Flags.VARARGS) == 0)
- type = bracketsOpt(type);
+ if ((mods.flags & Flags.VARARGS) != 0 &&
+ S.token() == LBRACKET) {
+ log.error(S.pos(), "varargs.and.old.array.syntax");
+ }
+ type = bracketsOpt(type);
return toP(F.at(pos).VarDef(mods, name, type, null));
}
@@ -2569,6 +2572,12 @@
} else {
pos = S.pos();
List<JCTypeParameter> typarams = typeParametersOpt();
+ // if there are type parameters but no modifiers, save the start
+ // position of the method in the modifiers.
+ if (typarams.nonEmpty() && mods.pos == Position.NOPOS) {
+ mods.pos = pos;
+ storeEnd(mods, pos);
+ }
Name name = S.name();
pos = S.pos();
JCExpression type;
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -445,7 +445,7 @@
*/
private void scanHexFractionAndSuffix(boolean seendigit) {
this.radix = 16;
- assert ch == '.';
+ Assert.check(ch == '.');
putChar(ch);
scanChar();
skipIllegalUnderscores();
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -49,7 +49,6 @@
import javax.tools.JavaFileObject;
import javax.tools.DiagnosticListener;
-//308 import com.sun.source.util.AbstractTypeProcessor;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTaskImpl;
@@ -66,6 +65,7 @@
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.Abort;
+import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Convert;
import com.sun.tools.javac.util.FatalError;
@@ -712,7 +712,6 @@
}
if (matchedNames.size() > 0 || ps.contributed) {
-//308 foundTypeProcessors = foundTypeProcessors || (ps.processor instanceof AbstractTypeProcessor);
boolean processingResult = callProcessor(ps.processor, typeElements, renv);
ps.contributed = true;
ps.removeSupportedOptions(unmatchedProcessorOptions);
@@ -1048,17 +1047,17 @@
Context next = new Context();
Options options = Options.instance(context);
- assert options != null;
+ Assert.checkNonNull(options);
next.put(Options.optionsKey, options);
PrintWriter out = context.get(Log.outKey);
- assert out != null;
+ Assert.checkNonNull(out);
next.put(Log.outKey, out);
final boolean shareNames = true;
if (shareNames) {
Names names = Names.instance(context);
- assert names != null;
+ Assert.checkNonNull(names);
next.put(Names.namesKey, names);
}
@@ -1071,18 +1070,18 @@
next.put(TaskListener.class, tl);
JavaFileManager jfm = context.get(JavaFileManager.class);
- assert jfm != null;
+ Assert.checkNonNull(jfm);
next.put(JavaFileManager.class, jfm);
if (jfm instanceof JavacFileManager) {
((JavacFileManager)jfm).setContext(next);
}
Names names = Names.instance(context);
- assert names != null;
+ Assert.checkNonNull(names);
next.put(Names.namesKey, names);
Keywords keywords = Keywords.instance(context);
- assert(keywords != null);
+ Assert.checkNonNull(keywords);
next.put(Keywords.keywordsKey, keywords);
JavaCompiler oldCompiler = JavaCompiler.instance(context);
@@ -1241,7 +1240,7 @@
for (JCTree node : unit.defs) {
if (node.getTag() == JCTree.CLASSDEF) {
ClassSymbol sym = ((JCClassDecl) node).sym;
- assert sym != null;
+ Assert.checkNonNull(sym);
classes = classes.prepend(sym);
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -112,11 +112,9 @@
compiler.err.catch.without.try=\
''catch'' without ''try''
compiler.err.clash.with.pkg.of.same.name=\
- {0} clashes with package of same name
+ {0} {1} clashes with package of same name
compiler.err.const.expr.req=\
constant expression required
-compiler.err.enum.const.req=\
- unqualified enumeration constant name required
compiler.err.cont.outside.loop=\
continue outside of loop
compiler.err.cyclic.inheritance=\
@@ -128,9 +126,7 @@
compiler.err.no.superclass=\
{0} has no superclass
-compiler.warn.type.parameter.on.polymorphic.signature=\
- change obsolete notation for MethodHandle invocations from x.<T>invoke(y) to (T)x.invoke(y)
-compiler.warn.wrong.target.for.polymorphic.signature.definition=\
+compiler.err.wrong.target.for.polymorphic.signature.definition=\
MethodHandle API building requires -target 7 runtimes or better; current is -target {0}
compiler.err.concrete.inheritance.conflict=\
@@ -186,7 +182,9 @@
compiler.err.finally.without.try=\
''finally'' without ''try''
compiler.err.foreach.not.applicable.to.type=\
- foreach not applicable to expression type
+ for-each not applicable to expression type\n\
+ required: {1}\n\
+ found: {0}
compiler.err.fp.number.too.large=\
floating point number too large
compiler.err.fp.number.too.small=\
@@ -198,7 +196,8 @@
a generic class may not extend java.lang.Throwable
compiler.err.icls.cant.have.static.decl=\
- inner classes cannot have static declarations
+ Illegal static declaration in inner class {0}\n\
+ modifier \''static\'' is only allowed in constant variable declarations
compiler.err.illegal.char=\
illegal character: \\{0}
compiler.err.illegal.char.for.encoding=\
@@ -240,7 +239,7 @@
compiler.err.improperly.formed.type.param.missing=\
improperly formed type, some parameters are missing
compiler.err.improperly.formed.type.inner.raw.param=\
- improperly formed type, type parameters given on a raw type
+ improperly formed type, type arguments given on a raw type
compiler.err.incomparable.types=\
incomparable types: {0} and {1}
compiler.err.int.number.too.large=\
@@ -267,6 +266,8 @@
hexadecimal numbers must contain at least one hexadecimal digit
compiler.err.invalid.meth.decl.ret.type.req=\
invalid method declaration; return type required
+compiler.err.varargs.and.old.array.syntax=\
+ legacy array notation not allowed on variable-arity parameter
compiler.err.label.already.in.use=\
label {0} already in use
@@ -356,7 +357,11 @@
not an enclosing class: {0}
compiler.err.operator.cant.be.applied=\
- operator {0} cannot be applied to {1}
+ bad operand type {1} for unary operator ''{0}''
+compiler.err.operator.cant.be.applied.1=\
+ bad operand types for binary operator ''{0}''\n\
+ first type: {1}\n\
+ second type: {2}
compiler.err.pkg.annotations.sb.in.package-info.java=\
package annotations should be in file package-info.java
@@ -483,9 +488,10 @@
compiler.err.undef.label=\
undefined label: {0}
compiler.err.undetermined.type=\
- type parameters of {0} cannot be determined
+ cannot infer type arguments for {0}
compiler.err.undetermined.type.1=\
- type parameters of {0} cannot be determined; {1}
+ cannot infer type arguments for {0};\n\
+ reason: {1}
compiler.err.invalid.inferred.types=\
invalid inferred types for {0}; {1}
compiler.err.cant.apply.diamond=\
@@ -865,7 +871,7 @@
compiler.warn.raw.class.use=\
found raw type: {0}\n\
- missing type parameters for generic class {1}
+ missing type arguments for generic class {1}
compiler.warn.diamond.redundant.args=\
redundant type arguments in new expression (use diamond operator instead).
@@ -971,8 +977,6 @@
bad constant pool tag: {0} at {1}
compiler.misc.bad.signature=\
bad signature: {0}
-compiler.misc.bad.type.annotation.value=\
- bad type annotation target type value: {0}
compiler.misc.class.file.wrong.class=\
class file contains wrong class: {0}
compiler.misc.class.file.not.found=\
@@ -995,10 +999,7 @@
#####
compiler.err.not.within.bounds=\
- type parameter {0} is not within its bound
-
-compiler.err.not.within.bounds.explain=\
- type parameter {0} is not within its bound; {1}
+ type argument {0} is not within bounds of type-variable {1}
## The following are all possible strings for the second argument ({1}) of the
## above string.
@@ -1065,6 +1066,8 @@
class
compiler.misc.type.req.class.array=\
class or array
+compiler.misc.type.req.array.or.iterable=\
+ array or java.lang.Iterable
compiler.misc.type.req.ref=\
reference
compiler.misc.type.req.exact=\
@@ -1148,22 +1151,31 @@
symbol: {0} <{2}>{1}({3})
## arguments from {0} to {3} have the same meaning as above
-## The fifth argument {4} is the location "kindname" (e.g. 'constructor', 'field', etc.)
-## The sixth argument {5} is the location type
+## The fifth argument {4} is a location subdiagnostic (see below)
compiler.err.cant.resolve.location=\
cannot find symbol\n\
symbol: {0} {1}\n\
- location: {4} {5}
+ location: {4}
compiler.err.cant.resolve.location.args=\
cannot find symbol\n\
symbol: {0} {1}({3})\n\
- location: {4} {5}
+ location: {4}
compiler.err.cant.resolve.location.args.params=\
cannot find symbol\n\
symbol: {0} <{2}>{1}({3})\n\
- location: {4} {5}
+ location: {4}
+
+##a location subdiagnostic is composed as follows:
+## The first argument {0} is the location "kindname" (e.g. 'constructor', 'field', etc.)
+## The second argument {1} is the location name
+## The third argument {2} is the location type (only when {1} is a variable name)
+
+compiler.misc.location=\
+ {0} {1}
+compiler.misc.location.1=\
+ {0} {1} of type {2}
## The following are all possible string for "kindname".
## They should be called whatever the JLS calls them after it been translated
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -640,7 +640,6 @@
public JCExpression restype;
public List<JCTypeParameter> typarams;
public List<JCVariableDecl> params;
- public List<JCTypeAnnotation> receiverAnnotations;
public List<JCExpression> thrown;
public JCBlock body;
public JCExpression defaultValue; // for annotation types
@@ -650,7 +649,6 @@
JCExpression restype,
List<JCTypeParameter> typarams,
List<JCVariableDecl> params,
- List<JCTypeAnnotation> receiver,
List<JCExpression> thrown,
JCBlock body,
JCExpression defaultValue,
@@ -661,7 +659,6 @@
this.restype = restype;
this.typarams = typarams;
this.params = params;
- this.receiverAnnotations = (receiver != null ? receiver : List.<JCTypeAnnotation>nil());
this.thrown = thrown;
this.body = body;
this.defaultValue = defaultValue;
@@ -680,7 +677,6 @@
public List<JCVariableDecl> getParameters() {
return params;
}
- public List<JCTypeAnnotation> getReceiverAnnotations() { return receiverAnnotations; }
public List<JCExpression> getThrows() {
return thrown;
}
@@ -1402,8 +1398,6 @@
public static class JCNewArray extends JCExpression implements NewArrayTree {
public JCExpression elemtype;
public List<JCExpression> dims;
- public List<JCTypeAnnotation> annotations;
- public List<List<JCTypeAnnotation>> dimAnnotations;
public List<JCExpression> elems;
protected JCNewArray(JCExpression elemtype,
List<JCExpression> dims,
@@ -1411,8 +1405,6 @@
{
this.elemtype = elemtype;
this.dims = dims;
- this.annotations = List.nil();
- this.dimAnnotations = List.nil();
this.elems = elems;
}
@Override
@@ -1923,11 +1915,9 @@
public static class JCTypeParameter extends JCTree implements TypeParameterTree {
public Name name;
public List<JCExpression> bounds;
- public List<JCTypeAnnotation> annotations;
- protected JCTypeParameter(Name name, List<JCExpression> bounds, List<JCTypeAnnotation> annotations) {
+ protected JCTypeParameter(Name name, List<JCExpression> bounds) {
this.name = name;
this.bounds = bounds;
- this.annotations = annotations;
}
@Override
public void accept(Visitor v) { v.visitTypeParameter(this); }
@@ -1937,9 +1927,6 @@
public List<JCExpression> getBounds() {
return bounds;
}
- public List<JCTypeAnnotation> getAnnotations() {
- return annotations;
- }
@Override
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitTypeParameter(this, d);
@@ -2030,16 +2017,6 @@
}
}
- public static class JCTypeAnnotation extends JCAnnotation {
- public TypeAnnotationPosition annotation_position;
- public Attribute.TypeCompound attribute_field;
-
- protected JCTypeAnnotation(JCTree annotationType, List<JCExpression> args) {
- super(annotationType, args);
- this.annotation_position = new TypeAnnotationPosition();
- }
- }
-
public static class JCModifiers extends JCTree implements com.sun.source.tree.ModifiersTree {
public long flags;
public List<JCAnnotation> annotations;
@@ -2067,40 +2044,6 @@
}
}
- public static class JCAnnotatedType extends JCExpression
-//308 implements com.sun.source.tree.AnnotatedTypeTree
- {
- public List<JCTypeAnnotation> annotations;
- public JCExpression underlyingType;
- protected JCAnnotatedType(List<JCTypeAnnotation> annotations, JCExpression underlyingType) {
- throw new UnsupportedOperationException();
-//308 this.annotations = annotations;
-//308 this.underlyingType = underlyingType;
- }
- @Override
- public void accept(Visitor v) { v.visitAnnotatedType(this); }
-
- public Kind getKind() {
- throw new UnsupportedOperationException();
-//308 return Kind.ANNOTATED_TYPE;
- }
- public List<JCTypeAnnotation> getAnnotations() {
- return annotations;
- }
- public JCExpression getUnderlyingType() {
- return underlyingType;
- }
- @Override
- public <R,D> R accept(TreeVisitor<R,D> v, D d) {
- throw new UnsupportedOperationException();
-//308 return v.visitAnnotatedType(this, d);
- }
- @Override
- public int getTag() {
- return ANNOTATED_TYPE;
- }
- }
-
public static class JCErroneous extends JCExpression
implements com.sun.source.tree.ErroneousTree {
public List<? extends JCTree> errs;
@@ -2168,7 +2111,6 @@
JCExpression restype,
List<JCTypeParameter> typarams,
List<JCVariableDecl> params,
- List<JCTypeAnnotation> receiver,
List<JCExpression> thrown,
JCBlock body,
JCExpression defaultValue);
@@ -2290,11 +2232,10 @@
public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); }
public void visitAnnotation(JCAnnotation that) { visitTree(that); }
public void visitModifiers(JCModifiers that) { visitTree(that); }
- public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); }
public void visitErroneous(JCErroneous that) { visitTree(that); }
public void visitLetExpr(LetExpr that) { visitTree(that); }
- public void visitTree(JCTree that) { assert false; }
+ public void visitTree(JCTree that) { Assert.error(); }
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/Pretty.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -224,15 +224,6 @@
}
}
- public void printTypeAnnotations(List<JCTypeAnnotation> trees) throws IOException {
- if (trees.nonEmpty())
- print(" ");
- for (List<JCTypeAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
- printExpr(l.head);
- print(" ");
- }
- }
-
/** Print documentation comment, if it exists
* @param tree The tree for which a documentation comment should be printed.
*/
@@ -890,33 +881,21 @@
try {
if (tree.elemtype != null) {
print("new ");
- printTypeAnnotations(tree.annotations);
JCTree elem = tree.elemtype;
- printBaseElementType(elem);
- boolean isElemAnnoType = elem instanceof JCAnnotatedType;
- int i = 0;
- List<List<JCTypeAnnotation>> da = tree.dimAnnotations;
+ if (elem.getTag() == JCTree.TYPEARRAY)
+ printBaseElementType((JCArrayTypeTree) elem);
+ else
+ printExpr(elem);
for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
- if (da.size() > i) {
- printTypeAnnotations(da.get(i));
- }
print("[");
- i++;
printExpr(l.head);
print("]");
}
- if (tree.elems != null) {
- if (isElemAnnoType) {
- printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations);
- }
- print("[]");
- }
- if (isElemAnnoType)
- elem = ((JCAnnotatedType)elem).underlyingType;
if (elem instanceof JCArrayTypeTree)
printBrackets((JCArrayTypeTree) elem);
}
if (tree.elems != null) {
+ if (tree.elemtype != null) print("[]");
print("{");
printExprs(tree.elems);
print("}");
@@ -1173,11 +1152,6 @@
JCTree elem;
while (true) {
elem = tree.elemtype;
- if (elem.getTag() == JCTree.ANNOTATED_TYPE) {
- JCAnnotatedType atype = (JCAnnotatedType) elem;
- printTypeAnnotations(atype.annotations);
- elem = atype.underlyingType;
- }
print("[]");
if (elem.getTag() != JCTree.TYPEARRAY) break;
tree = (JCArrayTypeTree) elem;
@@ -1272,15 +1246,6 @@
}
}
- public void visitAnnotatedType(JCAnnotatedType tree) {
- try {
- printTypeAnnotations(tree.annotations);
- printExpr(tree.underlyingType);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
public void visitTree(JCTree tree) {
try {
print("(UNKNOWN: " + tree + ")");
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2010, 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
@@ -71,13 +71,6 @@
return lb.toList();
}
-//308 public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) {
-//308 JCAnnotatedType t = (JCAnnotatedType) node;
-//308 List<JCTypeAnnotation> annotations = copy(t.annotations, p);
-//308 JCExpression underlyingType = copy(t.underlyingType, p);
-//308 return M.at(t.pos).AnnotatedType(annotations, underlyingType);
-//308 }
-
public JCTree visitAnnotation(AnnotationTree node, P p) {
JCAnnotation t = (JCAnnotation) node;
JCTree annotationType = copy(t.annotationType, p);
@@ -240,11 +233,10 @@
JCExpression restype = copy(t.restype, p);
List<JCTypeParameter> typarams = copy(t.typarams, p);
List<JCVariableDecl> params = copy(t.params, p);
- List<JCTypeAnnotation> receiver = copy(t.receiverAnnotations, p);
List<JCExpression> thrown = copy(t.thrown, p);
JCBlock body = copy(t.body, p);
JCExpression defaultValue = copy(t.defaultValue, p);
- return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, receiver, thrown, body, defaultValue);
+ return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, thrown, body, defaultValue);
}
public JCTree visitMethodInvocation(MethodInvocationTree node, P p) {
@@ -372,9 +364,8 @@
public JCTree visitTypeParameter(TypeParameterTree node, P p) {
JCTypeParameter t = (JCTypeParameter) node;
- List<JCTypeAnnotation> annos = copy(t.annotations, p);
List<JCExpression> bounds = copy(t.bounds, p);
- return M.at(t.pos).TypeParameter(t.name, bounds, annos);
+ return M.at(t.pos).TypeParameter(t.name, bounds);
}
public JCTree visitInstanceOf(InstanceOfTree node, P p) {
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -311,12 +311,6 @@
case(JCTree.POSTINC):
case(JCTree.POSTDEC):
return getStartPos(((JCUnary) tree).arg);
- case(JCTree.ANNOTATED_TYPE): {
- JCAnnotatedType node = (JCAnnotatedType) tree;
- if (node.annotations.nonEmpty())
- return getStartPos(node.annotations.head);
- return getStartPos(node.underlyingType);
- }
case(JCTree.NEWCLASS): {
JCNewClass node = (JCNewClass)tree;
if (node.encl != null)
@@ -420,8 +414,6 @@
return getEndPos(((JCUnary) tree).arg, endPositions);
case(JCTree.WHILELOOP):
return getEndPos(((JCWhileLoop) tree).body, endPositions);
- case(JCTree.ANNOTATED_TYPE):
- return getEndPos(((JCAnnotatedType) tree).underlyingType, endPositions);
case(JCTree.ERRONEOUS): {
JCErroneous node = (JCErroneous)tree;
if (node.errs != null && node.errs.nonEmpty())
@@ -453,7 +445,7 @@
public static int finalizerPos(JCTree tree) {
if (tree.getTag() == JCTree.TRY) {
JCTry t = (JCTry) tree;
- assert t.finalizer != null;
+ Assert.checkNonNull(t.finalizer);
return firstStatPos(t.finalizer);
} else if (tree.getTag() == JCTree.SYNCHRONIZED) {
return endPos(((JCSynchronized) tree).body);
@@ -909,8 +901,6 @@
*/
public static JCExpression typeIn(JCExpression tree) {
switch (tree.getTag()) {
- case JCTree.ANNOTATED_TYPE:
- return ((JCAnnotatedType)tree).underlyingType;
case JCTree.IDENT: /* simple names */
case JCTree.TYPEIDENT: /* primitive name */
case JCTree.SELECT: /* qualified name */
@@ -930,8 +920,6 @@
return innermostType(((JCArrayTypeTree)type).elemtype);
case JCTree.WILDCARD:
return innermostType(((JCWildcard)type).inner);
- case JCTree.ANNOTATED_TYPE:
- return innermostType(((JCAnnotatedType)type).underlyingType);
default:
return type;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -122,15 +122,15 @@
public JCCompilationUnit TopLevel(List<JCAnnotation> packageAnnotations,
JCExpression pid,
List<JCTree> defs) {
- assert packageAnnotations != null;
+ Assert.checkNonNull(packageAnnotations);
for (JCTree node : defs)
- assert node instanceof JCClassDecl
+ Assert.check(node instanceof JCClassDecl
|| node instanceof JCImport
|| node instanceof JCSkip
|| node instanceof JCErroneous
|| (node instanceof JCExpressionStatement
- && ((JCExpressionStatement)node).expr instanceof JCErroneous)
- : node.getClass().getSimpleName();
+ && ((JCExpressionStatement)node).expr instanceof JCErroneous),
+ node.getClass().getSimpleName());
JCCompilationUnit tree = new JCCompilationUnit(packageAnnotations, pid, defs,
null, null, null, null);
tree.pos = pos;
@@ -169,27 +169,11 @@
List<JCExpression> thrown,
JCBlock body,
JCExpression defaultValue) {
- return MethodDef(
- mods, name, restype, typarams, params,
- null, thrown, body, defaultValue);
- }
-
- public JCMethodDecl MethodDef(JCModifiers mods,
- Name name,
- JCExpression restype,
- List<JCTypeParameter> typarams,
- List<JCVariableDecl> params,
- List<JCTypeAnnotation> receiver,
- List<JCExpression> thrown,
- JCBlock body,
- JCExpression defaultValue)
- {
JCMethodDecl tree = new JCMethodDecl(mods,
name,
restype,
typarams,
params,
- receiver,
thrown,
body,
defaultValue,
@@ -458,11 +442,7 @@
}
public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
- return TypeParameter(name, bounds, List.<JCTypeAnnotation>nil());
- }
-
- public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds, List<JCTypeAnnotation> annos) {
- JCTypeParameter tree = new JCTypeParameter(name, bounds, annos);
+ JCTypeParameter tree = new JCTypeParameter(name, bounds);
tree.pos = pos;
return tree;
}
@@ -485,12 +465,6 @@
return tree;
}
- public JCTypeAnnotation TypeAnnotation(JCTree annotationType, List<JCExpression> args) {
- JCTypeAnnotation tree = new JCTypeAnnotation(annotationType, args);
- tree.pos = pos;
- return tree;
- }
-
public JCModifiers Modifiers(long flags, List<JCAnnotation> annotations) {
JCModifiers tree = new JCModifiers(flags, annotations);
boolean noFlags = (flags & (Flags.ModifierFlags | Flags.ANNOTATION)) == 0;
@@ -502,12 +476,6 @@
return Modifiers(flags, List.<JCAnnotation>nil());
}
- public JCAnnotatedType AnnotatedType(List<JCTypeAnnotation> annotations, JCExpression underlyingType) {
- JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType);
- tree.pos = pos;
- return tree;
- }
-
public JCErroneous Erroneous() {
return Erroneous(List.<JCTree>nil());
}
@@ -679,19 +647,14 @@
}
return tp.setType(t);
}
-//where
- private JCExpression Selectors(JCExpression base, Symbol sym, Symbol limit) {
- if (sym == limit) return base;
- else return Select(Selectors(base, sym.owner, limit), sym);
- }
/** Create a list of trees representing given list of types.
*/
public List<JCExpression> Types(List<Type> ts) {
- ListBuffer<JCExpression> types = new ListBuffer<JCExpression>();
+ ListBuffer<JCExpression> lb = new ListBuffer<JCExpression>();
for (List<Type> l = ts; l.nonEmpty(); l = l.tail)
- types.append(Type(l.head));
- return types.toList();
+ lb.append(Type(l.head));
+ return lb.toList();
}
/** Create a variable definition from a variable symbol and an initializer
@@ -821,7 +784,6 @@
Type(mtype.getReturnType()),
TypeParams(mtype.getTypeArguments()),
Params(mtype.getParameterTypes(), m),
- null,
Types(mtype.getThrownTypes()),
body,
null,
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -85,7 +85,6 @@
scan(tree.restype);
scan(tree.typarams);
scan(tree.params);
- scan(tree.receiverAnnotations);
scan(tree.thrown);
scan(tree.defaultValue);
scan(tree.body);
@@ -208,11 +207,8 @@
}
public void visitNewArray(JCNewArray tree) {
- scan(tree.annotations);
scan(tree.elemtype);
scan(tree.dims);
- for (List<JCTypeAnnotation> annos : tree.dimAnnotations)
- scan(annos);
scan(tree.elems);
}
@@ -281,7 +277,6 @@
}
public void visitTypeParameter(JCTypeParameter tree) {
- scan(tree.annotations);
scan(tree.bounds);
}
@@ -305,11 +300,6 @@
scan(tree.args);
}
- public void visitAnnotatedType(JCAnnotatedType tree) {
- scan(tree.annotations);
- scan(tree.underlyingType);
- }
-
public void visitErroneous(JCErroneous tree) {
}
@@ -319,6 +309,6 @@
}
public void visitTree(JCTree tree) {
- assert false;
+ Assert.error();
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -283,11 +283,6 @@
}
public void visitNewArray(JCNewArray tree) {
- tree.annotations = translate(tree.annotations);
- List<List<JCTypeAnnotation>> dimAnnos = List.nil();
- for (List<JCTypeAnnotation> origDimAnnos : tree.dimAnnotations)
- dimAnnos = dimAnnos.append(translate(origDimAnnos));
- tree.dimAnnotations = dimAnnos;
tree.elemtype = translate(tree.elemtype);
tree.dims = translate(tree.dims);
tree.elems = translate(tree.elems);
@@ -374,7 +369,6 @@
}
public void visitTypeParameter(JCTypeParameter tree) {
- tree.annotations = translate(tree.annotations);
tree.bounds = translate(tree.bounds);
result = tree;
}
@@ -412,12 +406,6 @@
result = tree;
}
- public void visitAnnotatedType(JCAnnotatedType tree) {
- tree.annotations = translate(tree.annotations);
- tree.underlyingType = translate(tree.underlyingType);
- result = tree;
- }
-
public void visitTree(JCTree tree) {
throw new AssertionError(tree);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -117,7 +117,7 @@
protected abstract String formatDiagnostic(JCDiagnostic d, Locale locale);
public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) {
- assert (d.getPosition() != Position.NOPOS);
+ Assert.check(d.getPosition() != Position.NOPOS);
return String.valueOf(getPosition(d, pk));
}
//where
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Assert.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,138 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.tools.javac.util;
+
+
+/**
+ * Simple facility for unconditional assertions.
+ * The methods in this class are described in terms of equivalent assert
+ * statements, assuming that assertions have been enabled.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class Assert {
+ /** Equivalent to
+ * assert cond;
+ */
+ public static void check(boolean cond) {
+ if (!cond)
+ error();
+ }
+
+ /** Equivalent to
+ * assert (o == null);
+ */
+ public static void checkNull(Object o) {
+ if (o != null)
+ error();
+ }
+
+ /** Equivalent to
+ * assert (t != null); return t;
+ */
+ public static <T> T checkNonNull(T t) {
+ if (t == null)
+ error();
+ return t;
+ }
+
+ /** Equivalent to
+ * assert cond : value;
+ */
+ public static void check(boolean cond, int value) {
+ if (!cond)
+ error(String.valueOf(value));
+ }
+
+ /** Equivalent to
+ * assert cond : value;
+ */
+ public static void check(boolean cond, long value) {
+ if (!cond)
+ error(String.valueOf(value));
+ }
+
+ /** Equivalent to
+ * assert cond : value;
+ */
+ public static void check(boolean cond, Object value) {
+ if (!cond)
+ error(String.valueOf(value));
+ }
+
+ /** Equivalent to
+ * assert cond : value;
+ */
+ public static void check(boolean cond, String msg) {
+ if (!cond)
+ error(msg);
+ }
+
+ /** Equivalent to
+ * assert (o == null) : value;
+ */
+ public static void checkNull(Object o, Object value) {
+ if (o != null)
+ error(String.valueOf(value));
+ }
+
+ /** Equivalent to
+ * assert (o == null) : value;
+ */
+ public static void checkNull(Object o, String msg) {
+ if (o != null)
+ error(msg);
+ }
+
+ /** Equivalent to
+ * assert (o != null) : value;
+ */
+ public static <T> T checkNonNull(T t, String msg) {
+ if (t == null)
+ error(msg);
+ return t;
+ }
+
+ /** Equivalent to
+ * assert false;
+ */
+ public static void error() {
+ throw new AssertionError();
+ }
+
+ /** Equivalent to
+ * assert false : msg;
+ */
+ public static void error(String msg) {
+ throw new AssertionError(msg);
+ }
+
+ /** Prevent instantiation. */
+ private Assert() { }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -85,7 +85,7 @@
/** Include x in this set.
*/
public void incl(int x) {
- assert x >= 0;
+ Assert.check(x >= 0);
sizeTo((x >>> wordshift) + 1);
bits[x >>> wordshift] = bits[x >>> wordshift] |
(1 << (x & wordmask));
@@ -113,7 +113,7 @@
/** Exclude x from this set.
*/
public void excl(int x) {
- assert x >= 0;
+ Assert.check(x >= 0);
sizeTo((x >>> wordshift) + 1);
bits[x >>> wordshift] = bits[x >>> wordshift] &
~(1 << (x & wordmask));
@@ -169,7 +169,7 @@
* Delight" by Henry S. Warren Jr. (figure 5-13)
*/
private static int trailingZeroBits(int x) {
- assert wordlen == 32;
+ Assert.check(wordlen == 32);
if (x == 0) return 32;
int n = 1;
if ((x & 0xffff) == 0) { n += 16; x >>>= 16; }
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Context.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Context.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -145,7 +145,7 @@
o = fac.make();
if (o instanceof Factory<?>)
throw new AssertionError("T extends Context.Factory");
- assert ht.get(key) == o;
+ Assert.check(ht.get(key) == o);
}
/* The following cast can't fail unless there was
--- a/langtools/src/share/classes/com/sun/tools/javac/util/List.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/List.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -184,7 +184,7 @@
// return this.prependList(xs.tail).prepend(xs.head);
List<A> result = this;
List<A> rev = xs.reverse();
- assert rev != xs;
+ Assert.check(rev != xs);
// since xs.reverse() returned a new list, we can reuse the
// individual List objects, instead of allocating new ones.
while (rev.nonEmpty()) {
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Names.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Names.java Fri Feb 18 12:04:36 2011 -0800
@@ -74,7 +74,6 @@
public final Name serialVersionUID;
public final Name java_lang_Enum;
public final Name java_dyn_MethodHandle;
- public final Name java_dyn_InvokeDynamic;
public final Name package_info;
public final Name ConstantValue;
public final Name LineNumberTable;
@@ -115,7 +114,6 @@
public final Name value;
public final Name getMessage;
public final Name getClass;
- public final Name invoke; //allowTransitionalJSR292 only
public final Name TYPE;
public final Name TYPE_USE;
public final Name TYPE_PARAMETER;
@@ -186,7 +184,6 @@
java_io_Serializable = fromString("java.io.Serializable");
java_lang_Enum = fromString("java.lang.Enum");
java_dyn_MethodHandle = fromString("java.dyn.MethodHandle");
- java_dyn_InvokeDynamic = fromString("java.dyn.InvokeDynamic");
package_info = fromString("package-info");
serialVersionUID = fromString("serialVersionUID");
ConstantValue = fromString("ConstantValue");
@@ -230,7 +227,6 @@
value = fromString("value");
getMessage = fromString("getMessage");
getClass = fromString("getClass");
- invoke = fromString("invoke"); //allowTransitionalJSR292 only
TYPE = fromString("TYPE");
TYPE_USE = fromString("TYPE_USE");
--- a/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/UnsharedNameTable.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2008, 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
@@ -107,7 +107,7 @@
hashes[h] = firstTableEntry = element.next;
}
else {
- assert previousNonNullTableEntry != null : "previousNonNullTableEntry cannot be null here.";
+ Assert.checkNonNull(previousNonNullTableEntry, "previousNonNullTableEntry cannot be null here.");
previousNonNullTableEntry.next = element.next;
}
}
@@ -133,7 +133,7 @@
hashes[h] = newEntry;
}
else {
- assert previousNonNullTableEntry.next == null : "previousNonNullTableEntry.next must be null.";
+ Assert.checkNull(previousNonNullTableEntry.next, "previousNonNullTableEntry.next must be null.");
previousNonNullTableEntry.next = newEntry;
}
--- a/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javap/AnnotationWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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,7 +26,6 @@
package com.sun.tools.javap;
import com.sun.tools.classfile.Annotation;
-import com.sun.tools.classfile.ExtendedAnnotation;
import com.sun.tools.classfile.Annotation.Annotation_element_value;
import com.sun.tools.classfile.Annotation.Array_element_value;
import com.sun.tools.classfile.Annotation.Class_element_value;
@@ -77,129 +76,6 @@
print(")");
}
- public void write(ExtendedAnnotation annot) {
- write(annot, true, false);
- }
-
- public void write(ExtendedAnnotation annot, boolean showOffsets, boolean resolveIndices) {
- write(annot.annotation, resolveIndices);
- print(": ");
- write(annot.position, showOffsets);
- }
-
- public void write(ExtendedAnnotation.Position pos, boolean showOffsets) {
- print(pos.type);
-
- switch (pos.type) {
- // type case
- case TYPECAST:
- case TYPECAST_GENERIC_OR_ARRAY:
- // object creation
- case INSTANCEOF:
- case INSTANCEOF_GENERIC_OR_ARRAY:
- // new expression
- case NEW:
- case NEW_GENERIC_OR_ARRAY:
- case NEW_TYPE_ARGUMENT:
- case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- if (showOffsets) {
- print(", offset=");
- print(pos.offset);
- }
- break;
- // local variable
- case LOCAL_VARIABLE:
- case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
- print(", {");
- for (int i = 0; i < pos.lvarOffset.length; ++i) {
- if (i != 0) print("; ");
- if (showOffsets) {
- print(", start_pc=");
- print(pos.lvarOffset[i]);
- }
- print(", length=");
- print(pos.lvarLength[i]);
- print(", index=");
- print(pos.lvarIndex[i]);
- }
- print("}");
- break;
- // method receiver
- case METHOD_RECEIVER:
- // Do nothing
- break;
- // type parameters
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- print(", param_index=");
- print(pos.parameter_index);
- break;
- // type parameters bound
- case CLASS_TYPE_PARAMETER_BOUND:
- case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- case METHOD_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
- print(", param_index=");
- print(pos.parameter_index);
- print(", bound_index=");
- print(pos.bound_index);
- break;
- // wildcard
- case WILDCARD_BOUND:
- case WILDCARD_BOUND_GENERIC_OR_ARRAY:
- print(", wild_card=");
- print(pos.wildcard_position);
- break;
- // Class extends and implements clauses
- case CLASS_EXTENDS:
- case CLASS_EXTENDS_GENERIC_OR_ARRAY:
- print(", type_index=");
- print(pos.type_index);
- break;
- // throws
- case THROWS:
- print(", type_index=");
- print(pos.type_index);
- break;
- case CLASS_LITERAL:
- case CLASS_LITERAL_GENERIC_OR_ARRAY:
- if (showOffsets) {
- print(", offset=");
- print(pos.offset);
- }
- break;
- // method parameter: not specified
- case METHOD_PARAMETER_GENERIC_OR_ARRAY:
- print(", param_index=");
- print(pos.parameter_index);
- break;
- // method type argument: wasn't specified
- case METHOD_TYPE_ARGUMENT:
- case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
- if (showOffsets) {
- print(", offset=");
- print(pos.offset);
- }
- print(", type_index=");
- print(pos.type_index);
- break;
- // We don't need to worry abut these
- case METHOD_RETURN_GENERIC_OR_ARRAY:
- case FIELD_GENERIC_OR_ARRAY:
- break;
- case UNKNOWN:
- break;
- default:
- throw new AssertionError("unknown type: " + pos.type);
- }
-
- // Append location data for generics/arrays.
- if (pos.type.hasLocation()) {
- print(", location=");
- print(pos.location);
- }
- }
-
public void write(Annotation.element_value_pair pair) {
write(pair, false);
}
--- a/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javap/AttributeWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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,6 +31,7 @@
import com.sun.tools.classfile.AnnotationDefault_attribute;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.Attributes;
+import com.sun.tools.classfile.BootstrapMethods_attribute;
import com.sun.tools.classfile.CharacterRangeTable_attribute;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.CompilationID_attribute;
@@ -47,10 +48,8 @@
import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
-import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
-import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.Signature_attribute;
import com.sun.tools.classfile.SourceDebugExtension_attribute;
import com.sun.tools.classfile.SourceFile_attribute;
@@ -153,6 +152,25 @@
return null;
}
+ public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) {
+ println(Attribute.BootstrapMethods + ":");
+ for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) {
+ BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i];
+ indent(+1);
+ print(i + ": #" + bsm.bootstrap_method_ref + " ");
+ println(constantWriter.stringValue(bsm.bootstrap_method_ref));
+ indent(+1);
+ println("Method arguments:");
+ indent(+1);
+ for (int j = 0; j < bsm.bootstrap_arguments.length; j++) {
+ print("#" + bsm.bootstrap_arguments[j] + " ");
+ println(constantWriter.stringValue(bsm.bootstrap_arguments[j]));
+ }
+ indent(-3);
+ }
+ return null;
+ }
+
public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) {
println("CharacterRangeTable:");
indent(+1);
@@ -392,30 +410,6 @@
return null;
}
- public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) {
- println("RuntimeVisibleTypeAnnotations:");
- indent(+1);
- for (int i = 0; i < attr.annotations.length; i++) {
- print(i + ": ");
- annotationWriter.write(attr.annotations[i]);
- println();
- }
- indent(-1);
- return null;
- }
-
- public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) {
- println("RuntimeInvisibleTypeAnnotations:");
- indent(+1);
- for (int i = 0; i < attr.annotations.length; i++) {
- print(i + ": ");
- annotationWriter.write(attr.annotations[i]);
- println();
- }
- indent(-1);
- return null;
- }
-
public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
println("RuntimeVisibleParameterAnnotations:");
indent(+1);
--- a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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 @@
stackMapWriter = StackMapWriter.instance(context);
localVariableTableWriter = LocalVariableTableWriter.instance(context);
localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
- typeAnnotationWriter = TypeAnnotationWriter.instance(context);
options = Options.instance(context);
}
@@ -266,11 +265,6 @@
detailWriters.add(tryBlockWriter);
}
- if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) {
- typeAnnotationWriter.reset(attr);
- detailWriters.add(typeAnnotationWriter);
- }
-
return detailWriters;
}
@@ -279,7 +273,6 @@
private ConstantWriter constantWriter;
private LocalVariableTableWriter localVariableTableWriter;
private LocalVariableTypeTableWriter localVariableTypeTableWriter;
- private TypeAnnotationWriter typeAnnotationWriter;
private SourceWriter sourceWriter;
private StackMapWriter stackMapWriter;
private TryBlockWriter tryBlockWriter;
--- a/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javap/ConstantWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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,6 +97,13 @@
return 1;
}
+ public Integer visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
+ print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index);
+ tab();
+ println("// " + stringValue(info));
+ return 1;
+ }
+
public Integer visitLong(CONSTANT_Long_info info, Void p) {
println(stringValue(info));
return 2;
@@ -116,6 +123,20 @@
return 1;
}
+ public Integer visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
+ print("#" + info.reference_kind.tag + ":#" + info.reference_index);
+ tab();
+ println("// " + stringValue(info));
+ return 1;
+ }
+
+ public Integer visitMethodType(CONSTANT_MethodType_info info, Void p) {
+ print("#" + info.descriptor_index);
+ tab();
+ println("// " + stringValue(info));
+ return 1;
+ }
+
public Integer visitString(CONSTANT_String_info info, Void p) {
print("#" + info.string_index);
tab();
@@ -201,14 +222,20 @@
return "String";
case CONSTANT_Fieldref:
return "Field";
+ case CONSTANT_MethodHandle:
+ return "MethodHandle";
+ case CONSTANT_MethodType:
+ return "MethodType";
case CONSTANT_Methodref:
return "Method";
case CONSTANT_InterfaceMethodref:
return "InterfaceMethod";
+ case CONSTANT_InvokeDynamic:
+ return "InvokeDynamic";
case CONSTANT_NameAndType:
return "NameAndType";
default:
- return "(unknown tag)";
+ return "(unknown tag " + tag + ")";
}
}
@@ -264,6 +291,15 @@
return visitRef(info, p);
}
+ public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, Void p) {
+ try {
+ String callee = stringValue(info.getNameAndTypeInfo());
+ return "#" + info.bootstrap_method_attr_index + ":" + callee;
+ } catch (ConstantPoolException e) {
+ return report(e);
+ }
+ }
+
public String visitLong(CONSTANT_Long_info info, Void p) {
return info.value + "l";
}
@@ -288,6 +324,22 @@
}
}
+ public String visitMethodHandle(CONSTANT_MethodHandle_info info, Void p) {
+ try {
+ return info.reference_kind.name + " " + stringValue(info.getCPRefInfo());
+ } catch (ConstantPoolException e) {
+ return report(e);
+ }
+ }
+
+ public String visitMethodType(CONSTANT_MethodType_info info, Void p) {
+ try {
+ return info.getType();
+ } catch (ConstantPoolException e) {
+ return report(e);
+ }
+ }
+
public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
return visitRef(info, p);
}
@@ -347,7 +399,6 @@
}
}
-
/* If name is a valid binary name, return it; otherwise quote it. */
private static String checkName(String name) {
if (name == null)
--- a/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javap/InstructionDetailWriter.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -42,13 +42,13 @@
LOCAL_VAR_TYPES("localVariableTypes"),
SOURCE("source"),
STACKMAPS("stackMaps"),
- TRY_BLOCKS("tryBlocks"),
- TYPE_ANNOS("typeAnnotations");
+ TRY_BLOCKS("tryBlocks");
Kind(String option) {
this.option = option;
}
final String option;
}
+
InstructionDetailWriter(Context context) {
super(context);
}
--- a/langtools/src/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2009, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package com.sun.tools.javap;
-
-import com.sun.tools.classfile.Attribute;
-import com.sun.tools.classfile.Code_attribute;
-import com.sun.tools.classfile.ExtendedAnnotation;
-import com.sun.tools.classfile.ExtendedAnnotation.Position;
-import com.sun.tools.classfile.Instruction;
-import com.sun.tools.classfile.Method;
-import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
-import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute;
-import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Annotate instructions with details about type annotations.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class TypeAnnotationWriter extends InstructionDetailWriter {
- public enum NoteKind { VISIBLE, INVISIBLE };
- public static class Note {
- Note(NoteKind kind, ExtendedAnnotation anno) {
- this.kind = kind;
- this.anno = anno;
- }
- public final NoteKind kind;
- public final ExtendedAnnotation anno;
- }
-
- static TypeAnnotationWriter instance(Context context) {
- TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class);
- if (instance == null)
- instance = new TypeAnnotationWriter(context);
- return instance;
- }
-
- protected TypeAnnotationWriter(Context context) {
- super(context);
- context.put(TypeAnnotationWriter.class, this);
- annotationWriter = AnnotationWriter.instance(context);
- classWriter = ClassWriter.instance(context);
- }
-
- public void reset(Code_attribute attr) {
- Method m = classWriter.getMethod();
- pcMap = new HashMap<Integer, List<Note>>();
- check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations));
- check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations));
- }
-
- private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) {
- if (attr == null)
- return;
-
- for (ExtendedAnnotation anno: attr.annotations) {
- Position p = anno.position;
- Note note = null;
- if (p.offset != -1)
- addNote(p.offset, note = new Note(kind, anno));
- if (p.lvarOffset != null) {
- for (int i = 0; i < p.lvarOffset.length; i++) {
- if (note == null)
- note = new Note(kind, anno);
- addNote(p.lvarOffset[i], note);
- }
- }
- }
- }
-
- private void addNote(int pc, Note note) {
- List<Note> list = pcMap.get(pc);
- if (list == null)
- pcMap.put(pc, list = new ArrayList<Note>());
- list.add(note);
- }
-
- @Override
- void writeDetails(Instruction instr) {
- String indent = space(2); // get from Options?
- int pc = instr.getPC();
- List<Note> notes = pcMap.get(pc);
- if (notes != null) {
- for (Note n: notes) {
- print(indent);
- print("@");
- annotationWriter.write(n.anno, false, true);
- print(", ");
- println(n.kind.toString().toLowerCase());
- }
- }
- }
-
- private AnnotationWriter annotationWriter;
- private ClassWriter classWriter;
- private Map<Integer, List<Note>> pcMap;
-}
--- a/langtools/src/share/classes/javax/tools/JavaCompiler.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/javax/tools/JavaCompiler.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, 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
@@ -137,9 +137,9 @@
* StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
* compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits).call();
*
- * for (Diagnostic diagnostic : diagnostics.getDiagnostics())
- * System.out.format("Error on line %d in %d%n",
- * diagnostic.getLineNumber()
+ * for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics())
+ * System.out.format("Error on line %d in %s%n",
+ * diagnostic.getLineNumber(),
* diagnostic.getSource().toUri());
*
* fileManager.close();</pre>
--- a/langtools/src/share/classes/javax/tools/ToolProvider.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/src/share/classes/javax/tools/ToolProvider.java Fri Feb 18 12:04:36 2011 -0800
@@ -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
@@ -172,7 +172,7 @@
{
// try loading class directly, in case tool is on the bootclasspath
try {
- return enableAsserts(Class.forName(toolClassName, false, null));
+ return Class.forName(toolClassName, false, null);
} catch (ClassNotFoundException e) {
trace(FINE, e);
@@ -194,27 +194,10 @@
trace(FINE, urls[0].toString());
cl = URLClassLoader.newInstance(urls);
- cl.setPackageAssertionStatus("com.sun.tools.javac", true);
refToolClassLoader = new WeakReference<ClassLoader>(cl);
}
return Class.forName(toolClassName, false, cl);
}
-
}
-
- private static Class<?> enableAsserts(Class<?> cls) {
- try {
- ClassLoader loader = cls.getClassLoader();
- if (loader != null)
- loader.setPackageAssertionStatus("com.sun.tools.javac", true);
- else
- trace(FINE, "loader == null");
- } catch (SecurityException ex) {
- trace(FINE, ex);
- }
- return cls;
- }
-
-
}
--- a/langtools/test/tools/javac/6304921/T6304921.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6304921/T6304921.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,7 +1,7 @@
T6304921.java:29:34: compiler.warn.raw.class.use: java.util.ArrayList, java.util.ArrayList<E>
T6304921.java:29:30: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.ArrayList, java.util.List<java.lang.Integer>
- compiler.err.warnings.and.werror
-T6304921.java:35:15: compiler.err.cant.resolve.location: kindname.variable, orr, , , kindname.class, java.lang.System
-T6304921.java:38:20: compiler.err.operator.cant.be.applied: +, int,boolean
+T6304921.java:35:15: compiler.err.cant.resolve.location: kindname.variable, orr, , , (compiler.misc.location: kindname.class, java.lang.System, null)
+T6304921.java:38:20: compiler.err.operator.cant.be.applied.1: +, int, boolean
3 errors
2 warnings
--- a/langtools/test/tools/javac/6330920/T6330920.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6330920/T6330920.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,2 +1,2 @@
-T6330920.java:11:22: compiler.err.cant.resolve.location: kindname.class, T6330920Missing, , , kindname.class, T6330920
+T6330920.java:11:22: compiler.err.cant.resolve.location: kindname.class, T6330920Missing, , , (compiler.misc.location: kindname.class, T6330920, null)
1 error
--- a/langtools/test/tools/javac/6717241/T6717241a.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6717241/T6717241a.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,4 +1,4 @@
-T6717241a.java:13:21: compiler.err.cant.resolve: kindname.variable, v, ,
-T6717241a.java:15:10: compiler.err.cant.resolve.args: kindname.method, m1, , int,java.lang.String
-T6717241a.java:17:10: compiler.err.cant.resolve.args.params: kindname.method, m2, java.lang.Integer,java.lang.Double, int,java.lang.String
+T6717241a.java:13:21: compiler.err.cant.resolve.location: kindname.variable, v, , , (compiler.misc.location.1: kindname.variable, x, X)
+T6717241a.java:15:10: compiler.err.cant.resolve.location.args: kindname.method, m1, , int,java.lang.String, (compiler.misc.location.1: kindname.variable, x, X)
+T6717241a.java:17:10: compiler.err.cant.resolve.location.args.params: kindname.method, m2, java.lang.Integer,java.lang.Double, int,java.lang.String, (compiler.misc.location.1: kindname.variable, x, X)
3 errors
--- a/langtools/test/tools/javac/6717241/T6717241b.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6717241/T6717241b.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,4 +1,4 @@
-T6717241b.java:12:20: compiler.err.cant.resolve.location: kindname.variable, v, , , kindname.class, T6717241b
-T6717241b.java:14:9: compiler.err.cant.resolve.location.args: kindname.method, m1, , int,java.lang.String, kindname.class, T6717241b
-T6717241b.java:16:18: compiler.err.cant.resolve.location.args.params: kindname.method, m2, java.lang.Integer,java.lang.Double, int,java.lang.String, kindname.class, T6717241b
+T6717241b.java:12:20: compiler.err.cant.resolve.location: kindname.variable, v, , , (compiler.misc.location: kindname.class, T6717241b, null)
+T6717241b.java:14:9: compiler.err.cant.resolve.location.args: kindname.method, m1, , int,java.lang.String, (compiler.misc.location: kindname.class, T6717241b, null)
+T6717241b.java:16:18: compiler.err.cant.resolve.location.args.params: kindname.method, m2, java.lang.Integer,java.lang.Double, int,java.lang.String, (compiler.misc.location: kindname.class, T6717241b, null)
3 errors
--- a/langtools/test/tools/javac/6857948/T6857948.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6857948/T6857948.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
-T6857948.java:16:32: compiler.err.cant.resolve.location.args: kindname.method, nosuchfunction, , , kindname.class, Test
+T6857948.java:16:32: compiler.err.cant.resolve.location.args: kindname.method, nosuchfunction, , , (compiler.misc.location: kindname.class, Test, null)
T6857948.java:16:50: compiler.err.cant.apply.symbol.1: kindname.constructor, Foo, java.lang.String, compiler.misc.no.args, kindname.class, Foo, (compiler.misc.arg.length.mismatch)
2 errors
--- a/langtools/test/tools/javac/6863465/T6863465c.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6863465/T6863465c.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
-T6863465c.java:13:47: compiler.err.cant.resolve.location: kindname.class, d, , , kindname.class, T6863465c.z
+T6863465c.java:13:47: compiler.err.cant.resolve.location: kindname.class, d, , , (compiler.misc.location: kindname.class, T6863465c.z, null)
T6863465c.java:11:12: compiler.err.cyclic.inheritance: T6863465c.z
2 errors
--- a/langtools/test/tools/javac/6863465/T6863465d.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/6863465/T6863465d.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
-T6863465d.java:13:47: compiler.err.cant.resolve.location: kindname.class, w, , , kindname.class, T6863465d.c
+T6863465d.java:13:47: compiler.err.cant.resolve.location: kindname.class, w, , , (compiler.misc.location: kindname.class, T6863465d.c, null)
T6863465d.java:11:12: compiler.err.cyclic.inheritance: T6863465d.c
2 errors
--- a/langtools/test/tools/javac/InnerNamedConstant_2.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/InnerNamedConstant_2.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
-InnerNamedConstant_2.java:22:20: compiler.err.icls.cant.have.static.decl
-InnerNamedConstant_2.java:23:29: compiler.err.icls.cant.have.static.decl
+InnerNamedConstant_2.java:22:20: compiler.err.icls.cant.have.static.decl: InnerNamedConstant_2.Inner2
+InnerNamedConstant_2.java:23:29: compiler.err.icls.cant.have.static.decl: InnerNamedConstant_2.Inner2
InnerNamedConstant_2.java:25:13: compiler.err.cant.assign.val.to.final.var: z
-InnerNamedConstant_2.java:34:26: compiler.err.icls.cant.have.static.decl
+InnerNamedConstant_2.java:34:26: compiler.err.icls.cant.have.static.decl: InnerNamedConstant_2.Inner3
4 errors
--- a/langtools/test/tools/javac/T6247324.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/T6247324.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,2 +1,2 @@
-T6247324.java:18:6: compiler.err.cant.resolve.location: kindname.class, Seetharam, , , kindname.class, Pair<X,Y>
+T6247324.java:18:6: compiler.err.cant.resolve.location: kindname.class, Seetharam, , , (compiler.misc.location: kindname.class, Pair, null)
1 error
--- a/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/TryWithResources/ResourceOutsideTry.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
-ResourceOutsideTry.java:14:13: compiler.err.cant.resolve.location: kindname.variable, c, , , kindname.class, ResourceOutsideTry
-ResourceOutsideTry.java:16:13: compiler.err.cant.resolve.location: kindname.variable, c, , , kindname.class, ResourceOutsideTry
+ResourceOutsideTry.java:14:13: compiler.err.cant.resolve.location: kindname.variable, c, , , (compiler.misc.location: kindname.class, ResourceOutsideTry, null)
+ResourceOutsideTry.java:16:13: compiler.err.cant.resolve.location: kindname.variable, c, , , (compiler.misc.location: kindname.class, ResourceOutsideTry, null)
2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/api/T6419926.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,51 @@
+/*
+ * 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 6419926
+ * @summary JSR 199: FileObject.toUri() generates URI without schema (Solaris)
+ */
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import javax.tools.*;
+
+public class T6419926 {
+ public static void main(String[] argv) throws Exception {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager mgr = compiler.getStandardFileManager( new DiagnosticCollector<JavaFileObject>(), null, null);
+ System.out.println( new File( new File(".").toURI() ).getAbsolutePath() );
+ mgr.setLocation(StandardLocation.CLASS_OUTPUT,
+ Collections.singleton(new File(".")));
+
+ FileObject fo = mgr.getFileForOutput(StandardLocation.CLASS_OUTPUT,
+ "", "file.to.delete", null);
+ URI uri = fo.toUri();
+ System.out.println( uri );
+
+ if (!"file".equals(uri.getScheme()))
+ throw new Exception("unexpected scheme for uri: " + uri.getScheme());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/api/T6430241.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,237 @@
+ /*
+ * 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 6430241
+ * @summary Hard to disable symbol file feature through API
+ */
+
+ import java.io.*;
+ import java.util.*;
+ import javax.tools.*;
+
+ import com.sun.source.util.JavacTask;
+ import com.sun.tools.javac.api.JavacTool;
+
+ public class T6430241 {
+ public static void main(String... args) throws Exception {
+ new T6430241().run();
+ }
+
+ void run() throws Exception {
+ setup();
+ testCommandLine();
+ testSimpleAPI();
+ testTaskAPI();
+
+ if (errors > 0)
+ throw new Exception(errors + " errors found");
+ }
+
+ void setup() throws Exception {
+ classesDir = new File("classes");
+ classesDir.mkdirs();
+
+ emptyDir = new File("empty");
+ emptyDir.mkdirs();
+
+ bootClassPath = System.getProperty("sun.boot.class.path");
+
+ File srcDir = new File("src");
+ String test = "import sun.misc.Unsafe; class Test { }";
+ testFile = writeFile(srcDir, "Test.java", test);
+ }
+
+ //----- tests for command line invocation
+
+ void testCommandLine() throws Exception {
+ testCommandLine(true);
+ testCommandLine(true, "-Xbootclasspath/p:" + emptyDir);
+ testCommandLine(false, "-Xbootclasspath:" + bootClassPath);
+ testCommandLine(true, "-Xbootclasspath/a:" + emptyDir);
+ testCommandLine(false, "-XDignore.symbol.file");
+ System.err.println();
+ }
+
+ void testCommandLine(boolean expectWarnings, String... opts) throws Exception {
+ System.err.println("test command line: " + Arrays.asList(opts));
+
+ String[] args = initArgs(opts);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ int rc = com.sun.tools.javac.Main.compile(args, pw);
+ String out = showOutput(sw.toString());
+
+ checkCompilationOK(rc);
+ checkOutput(out, expectWarnings);
+ }
+
+ //----- tests for simple API invocation
+
+ void testSimpleAPI() {
+ testSimpleAPI(true);
+ testSimpleAPI(true, "-Xbootclasspath/p:" + emptyDir);
+ testSimpleAPI(false, "-Xbootclasspath:" + bootClassPath);
+ testSimpleAPI(true, "-Xbootclasspath/a:" + emptyDir);
+ testSimpleAPI(false, "-XDignore.symbol.file");
+ System.err.println();
+ }
+
+ void testSimpleAPI(boolean expectWarnings, String... opts) {
+ System.err.println("test simple API: " + Arrays.asList(opts));
+
+ String[] args = initArgs(opts);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+
+ JavacTool tool = JavacTool.create();
+ int rc = tool.run(null, null, ps, args);
+
+ String out = showOutput(baos.toString());
+
+ checkCompilationOK(rc);
+ checkOutput(out, expectWarnings);
+ }
+
+ //----- tests for CompilationTask API invocation
+
+ void testTaskAPI() throws Exception {
+ List<File> bcp = new ArrayList<File>();
+ for (String f: bootClassPath.split(File.pathSeparator)) {
+ if (!f.isEmpty())
+ bcp.add(new File(f));
+ }
+
+ testTaskAPI(true, null);
+ testTaskAPI(false, bcp);
+ System.err.println();
+ }
+
+ void testTaskAPI(boolean expectWarnings, Iterable<? extends File> pcp) throws Exception {
+ System.err.println("test task API: " + pcp);
+
+ JavacTool tool = JavacTool.create();
+ StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+
+ if (pcp != null)
+ fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, pcp);
+
+ Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(testFile);
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ JavacTask task = tool.getTask(pw, fm, null, null, null, files);
+ boolean ok = task.call();
+ String out = showOutput(sw.toString());
+
+ checkCompilationOK(ok);
+ checkOutput(out, expectWarnings);
+ }
+
+ //----- utility methods
+
+ /**
+ * Create a file with given content.
+ */
+ File writeFile(File dir, String path, String content) throws IOException {
+ File f = new File(dir, path);
+ f.getParentFile().mkdirs();
+ FileWriter out = new FileWriter(f);
+ try {
+ out.write(content);
+ } finally {
+ out.close();
+ }
+ return f;
+ }
+
+ /**
+ * Initialize args for compilation with given opts.
+ * @return opts -d classesDir testFile
+ */
+ String[] initArgs(String[] opts) {
+ List<String> args = new ArrayList<String>();
+ args.addAll(Arrays.asList(opts));
+ args.add("-d");
+ args.add(classesDir.getPath());
+ args.add(testFile.getPath());
+ return args.toArray(new String[args.size()]);
+ }
+
+ /**
+ * Show output from compilation if non empty.
+ */
+ String showOutput(String out) {
+ if (!out.isEmpty())
+ System.err.println(out);
+ return out;
+ }
+
+ /**
+ * Verify compilation succeeeded.
+ */
+ void checkCompilationOK(boolean ok) {
+ if (!ok)
+ error("compilation failed");
+ }
+
+ /**
+ * Verify compilation succeeeded.
+ */
+ void checkCompilationOK(int rc) {
+ if (rc != 0)
+ error("compilation failed, rc: " + rc);
+ }
+
+ /**
+ * Check whether output contains warnings if and only if warnings
+ * are expected.
+ */
+ void checkOutput(String out, boolean expectWarnings) {
+ boolean foundWarnings = out.contains("warning");
+ if (foundWarnings) {
+ if (!expectWarnings)
+ error("unexpected warnings found");
+ } else {
+ if (expectWarnings)
+ error("expected warnings not found");
+ }
+ }
+
+ /**
+ * Report an error.
+ */
+ void error(String msg) {
+ System.err.println("error: " + msg);
+ errors++;
+ }
+
+ String bootClassPath;
+ File classesDir;
+ File emptyDir;
+ File testFile;
+ int errors;
+ }
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Fri Feb 18 12:04:36 2011 -0800
@@ -24,7 +24,6 @@
compiler.err.no.encl.instance.of.type.in.scope # cannot occur; always followed by assert false;
compiler.err.no.match.entry # UNUSED?
compiler.err.not.annotation.type # cannot occur given preceding checkType
-compiler.err.not.within.bounds.explain # UNUSED?
compiler.err.prob.found.req.1 # Check: DEAD, in unused method
compiler.err.proc.bad.config.file # JavacProcessingEnvironment
compiler.err.proc.cant.access # completion failure
@@ -43,6 +42,7 @@
compiler.err.unexpected.type
compiler.err.unknown.enum.constant # in bad class file
compiler.err.unsupported.cross.fp.lit # Scanner: host system dependent
+compiler.err.wrong.target.for.polymorphic.signature.definition # Transitional 292
compiler.misc.assignment.from.super-bound
compiler.misc.assignment.to.extends-bound
compiler.misc.bad.class.file.header # bad class file
@@ -52,7 +52,6 @@
compiler.misc.bad.enclosing.method # bad class file
compiler.misc.bad.runtime.invisible.param.annotations # bad class file
compiler.misc.bad.signature # bad class file
-compiler.misc.bad.type.annotation.value
compiler.misc.base.membership # UNUSED
compiler.misc.ccf.found.later.version
compiler.misc.ccf.unrecognized.attribute
@@ -113,4 +112,3 @@
compiler.warn.unchecked.assign # DEAD, replaced by compiler.misc.unchecked.assign
compiler.warn.unchecked.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type
compiler.warn.unexpected.archive.file # Paths: zip file with unknown extn
-compiler.warn.wrong.target.for.polymorphic.signature.definition # Transitional 292
--- a/langtools/test/tools/javac/diags/examples/CantResolve.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/CantResolve.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,9 +23,8 @@
// key: compiler.err.cant.resolve
-class CantResolve<T extends Object & java.io.Serializable> {
- T t;
- void m() {
- Object o = t.v;
- }
+class CantResolve {
+ Object o = new Object() {
+ int i = f;
+ };
}
--- a/langtools/test/tools/javac/diags/examples/CantResolveArgsParams.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/CantResolveArgsParams.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,9 +23,8 @@
// key: compiler.err.cant.resolve.args.params
-class CantResolveArgsParams<T extends Object & java.io.Serializable> {
- T t;
- void m() {
- t.<Integer,Double>m2(1, "");
- }
+class CantResolveArgsParams {
+ Object o = new Object() {
+ { this.<Integer,Double>m2(1, ""); }
+ };
}
--- a/langtools/test/tools/javac/diags/examples/CantResolveLocation.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/CantResolveLocation.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -22,6 +22,7 @@
*/
// key: compiler.err.cant.resolve.location
+// key: compiler.misc.location
class CantResolveLocation {
Unknown y;
--- a/langtools/test/tools/javac/diags/examples/CantResolveLocationArgs.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/CantResolveLocationArgs.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -22,6 +22,7 @@
*/
// key: compiler.err.cant.resolve.location.args
+// key: compiler.misc.location
class X {
void m() {
--- a/langtools/test/tools/javac/diags/examples/CantResolveLocationArgsParams.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/CantResolveLocationArgsParams.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -22,6 +22,7 @@
*/
// key: compiler.err.cant.resolve.location.args.params
+// key: compiler.misc.location
import java.util.*;
--- a/langtools/test/tools/javac/diags/examples/EnumConstRequired.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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.err.enum.const.req
-
-class EnumConstRequired {
- enum E { A, B, C };
-
- void m(E e) {
- switch (e) {
- case e:
- System.err.println("It's me!");
- }
- }
-}
--- a/langtools/test/tools/javac/diags/examples/ForeachNotApplicable.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/ForeachNotApplicable.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -22,6 +22,7 @@
*/
// key: compiler.err.foreach.not.applicable.to.type
+// key: compiler.misc.type.req.array.or.iterable
class ForeachNotApplicable {
void m(String arg) {
--- a/langtools/test/tools/javac/diags/examples/KindnameClass.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/KindnameClass.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,6 +23,7 @@
// key: compiler.misc.kindname.class
// key: compiler.err.cant.resolve.location
+// key: compiler.misc.location
// key: compiler.misc.count.error
// run: backdoor
--- a/langtools/test/tools/javac/diags/examples/KindnameMethod.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/KindnameMethod.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -24,6 +24,7 @@
// key: compiler.misc.kindname.method
// key: compiler.misc.kindname.class
// key: compiler.err.cant.resolve.location.args
+// key: compiler.misc.location
// key: compiler.misc.count.error
// run: backdoor
--- a/langtools/test/tools/javac/diags/examples/KindnameVariable.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/KindnameVariable.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -24,6 +24,7 @@
// key: compiler.misc.kindname.variable
// key: compiler.misc.kindname.class
// key: compiler.err.cant.resolve.location
+// key: compiler.misc.location
// key: compiler.misc.count.error
// run: backdoor
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/Location.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,29 @@
+/*
+ * 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.err.cant.resolve.location
+// key: compiler.misc.location
+
+class Location {
+ { Object o = v; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/Location1.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,30 @@
+/*
+ * 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.err.cant.resolve.location
+// key: compiler.misc.location.1
+
+class Location1 {
+ Object o = null;
+ { Object o2 = o.v; }
+}
--- a/langtools/test/tools/javac/diags/examples/OperatorCantBeApplied.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/OperatorCantBeApplied.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -24,5 +24,6 @@
// key: compiler.err.operator.cant.be.applied
class OperatorCantBeApplied {
- String s = ("a" - "b");
+ String s = null;
+ { s++; }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/OperatorCantBeApplied1.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,28 @@
+/*
+ * 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.err.operator.cant.be.applied.1
+
+class OperatorCantBeApplied1 {
+ String s = ("a" - "b");
+}
--- a/langtools/test/tools/javac/diags/examples/StaticImportOnlyClassesAndInterfaces/StaticImportOnlyClassesAndInterfaces.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/diags/examples/StaticImportOnlyClassesAndInterfaces/StaticImportOnlyClassesAndInterfaces.java Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -23,6 +23,7 @@
// key: compiler.err.static.imp.only.classes.and.interfaces
// key: compiler.err.cant.resolve.location
+// key: compiler.misc.location
import static p.Other.array.length;
--- a/langtools/test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +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.warn.type.parameter.on.polymorphic.signature
-// key: compiler.err.unreported.exception.need.to.catch.or.throw
-
-import java.dyn.MethodHandle;
-
-class TypeParameterOnPolymorphicSignature {
- void test(MethodHandle mh) {
- mh.<void>invokeExact("",123);
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VarargsAndOldArraySyntax.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,28 @@
+/*
+ * 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.err.varargs.and.old.array.syntax
+
+class VarargsAndOldArraySyntax {
+ void m1 (Integer... i[]) { }
+}
--- a/langtools/test/tools/javac/failover/FailOver01.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/failover/FailOver01.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
FailOver01.java:10:22: compiler.err.expected: ';'
-FailOver01.java:10:16: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, Test
+FailOver01.java:10:16: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, Test, null)
2 errors
--- a/langtools/test/tools/javac/failover/FailOver02.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/failover/FailOver02.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
FailOver02.java:10:1: compiler.err.does.not.override.abstract: Test, close(), java.lang.AutoCloseable
-FailOver02.java:12:9: compiler.err.cant.resolve.location.args: kindname.method, close, , , kindname.class, Test
+FailOver02.java:12:9: compiler.err.cant.resolve.location.args: kindname.method, close, , , (compiler.misc.location: kindname.class, Test, null)
2 errors
--- a/langtools/test/tools/javac/failover/FailOver04.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/failover/FailOver04.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,2 +1,2 @@
-FailOver04.java:11:10: compiler.err.cant.resolve.location: kindname.class, Unknown, , , kindname.class, Test
+FailOver04.java:11:10: compiler.err.cant.resolve.location: kindname.class, Unknown, , , (compiler.misc.location: kindname.class, Test, null)
1 error
--- a/langtools/test/tools/javac/generics/6711619/T6711619a.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/6711619/T6711619a.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,5 +1,5 @@
-T6711619a.java:40:14: compiler.err.cant.resolve.args: kindname.method, a, ,
-T6711619a.java:41:14: compiler.err.cant.resolve.args: kindname.method, b, ,
+T6711619a.java:40:14: compiler.err.cant.resolve.location.args: kindname.method, a, , , (compiler.misc.location.1: kindname.variable, t, T)
+T6711619a.java:41:14: compiler.err.cant.resolve.location.args: kindname.method, b, , , (compiler.misc.location.1: kindname.variable, t, T)
T6711619a.java:46:19: compiler.err.report.access: a, private, T6711619a.A
T6711619a.java:47:19: compiler.err.report.access: b, private, T6711619a.B
T6711619a.java:48:19: compiler.err.report.access: a, private, T6711619a.A
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg01.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg01.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,29 +1,29 @@
-Neg01.java:18:15: compiler.err.not.within.bounds: java.lang.String
+Neg01.java:18:15: compiler.err.not.within.bounds: java.lang.String, X
Neg01.java:18:28: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:19:15: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg01.java:19:15: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg01.java:19:38: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
Neg01.java:20:23: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:21:15: compiler.err.not.within.bounds: ? super java.lang.String
+Neg01.java:21:15: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg01.java:21:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:23:15: compiler.err.not.within.bounds: java.lang.String
+Neg01.java:23:15: compiler.err.not.within.bounds: java.lang.String, X
Neg01.java:23:28: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:24:15: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg01.java:24:15: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg01.java:24:38: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
Neg01.java:25:23: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:26:15: compiler.err.not.within.bounds: ? super java.lang.String
+Neg01.java:26:15: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg01.java:26:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:28:15: compiler.err.not.within.bounds: java.lang.String
+Neg01.java:28:15: compiler.err.not.within.bounds: java.lang.String, X
Neg01.java:28:28: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:29:15: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg01.java:29:15: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg01.java:29:39: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
Neg01.java:30:24: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:31:9: compiler.err.cant.resolve.location: kindname.class, Foo, , , kindname.class, Neg01<X>
+Neg01.java:31:9: compiler.err.cant.resolve.location: kindname.class, Foo, , , (compiler.misc.location: kindname.class, Neg01, null)
Neg01.java:31:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:33:15: compiler.err.not.within.bounds: java.lang.String
+Neg01.java:33:15: compiler.err.not.within.bounds: java.lang.String, X
Neg01.java:33:29: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:34:15: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg01.java:34:15: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg01.java:34:39: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
Neg01.java:35:24: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
-Neg01.java:36:15: compiler.err.not.within.bounds: ? super java.lang.String
+Neg01.java:36:15: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg01.java:36:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg01), null
28 errors
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg02.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg02.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,57 +1,57 @@
-Neg02.java:19:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:19:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:19:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:20:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:21:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:22:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:24:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:24:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:24:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:25:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:26:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:27:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:29:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:29:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:29:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:30:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:31:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:32:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:34:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:34:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:34:27: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:35:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:36:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:37:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:41:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:41:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:41:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:42:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:43:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:44:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:46:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:46:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:46:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:47:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:48:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:49:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:51:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:51:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:51:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:52:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:53:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:54:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:56:13: compiler.err.not.within.bounds: java.lang.String
+Neg02.java:56:13: compiler.err.not.within.bounds: java.lang.String, X
Neg02.java:56:27: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg02.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String, X
Neg02.java:57:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
Neg02.java:58:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
-Neg02.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg02.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String, X
Neg02.java:59:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg02.Foo), null
56 errors
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg03.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg03.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,85 +1,85 @@
-Neg03.java:19:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:19:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:19:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:20:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:21:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:22:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:24:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:24:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:24:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:25:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:26:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:27:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:29:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:29:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:29:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:30:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:31:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:32:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:34:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:34:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:34:27: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:35:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:36:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:37:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:41:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:41:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:41:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:42:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:43:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:44:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:46:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:46:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:46:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:47:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:48:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:49:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:51:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:51:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:51:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:52:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:53:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:54:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:56:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:56:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:56:27: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:57:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:58:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:59:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:63:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:63:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:63:28: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:64:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:64:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:64:38: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:65:23: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:66:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:66:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:66:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:68:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:68:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:68:28: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:69:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:69:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:69:38: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:70:23: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:71:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:71:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:71:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:73:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:73:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:73:28: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:74:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:74:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:74:39: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:75:24: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:76:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:76:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:76:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:78:13: compiler.err.not.within.bounds: java.lang.String
+Neg03.java:78:13: compiler.err.not.within.bounds: java.lang.String, V
Neg03.java:78:29: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:79:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg03.java:79:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg03.java:79:39: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
Neg03.java:80:24: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
-Neg03.java:81:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg03.java:81:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg03.java:81:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Neg03.Foo), null
84 errors
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg04.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg04.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,29 +1,29 @@
-Neg04.java:18:13: compiler.err.not.within.bounds: java.lang.String
+Neg04.java:18:13: compiler.err.not.within.bounds: java.lang.String, V
Neg04.java:18:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:19:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg04.java:19:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg04.java:19:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
Neg04.java:20:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:21:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg04.java:21:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg04.java:21:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:23:13: compiler.err.not.within.bounds: java.lang.String
+Neg04.java:23:13: compiler.err.not.within.bounds: java.lang.String, V
Neg04.java:23:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:24:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg04.java:24:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg04.java:24:36: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
Neg04.java:25:21: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:26:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg04.java:26:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg04.java:26:34: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:28:13: compiler.err.not.within.bounds: java.lang.String
+Neg04.java:28:13: compiler.err.not.within.bounds: java.lang.String, V
Neg04.java:28:26: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:29:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg04.java:29:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg04.java:29:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
Neg04.java:30:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:31:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg04.java:31:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg04.java:31:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:33:13: compiler.err.not.within.bounds: java.lang.String
+Neg04.java:33:13: compiler.err.not.within.bounds: java.lang.String, V
Neg04.java:33:27: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:34:13: compiler.err.not.within.bounds: ? extends java.lang.String
+Neg04.java:34:13: compiler.err.not.within.bounds: ? extends java.lang.String, V
Neg04.java:34:37: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
Neg04.java:35:22: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
-Neg04.java:36:13: compiler.err.not.within.bounds: ? super java.lang.String
+Neg04.java:36:13: compiler.err.not.within.bounds: ? super java.lang.String, V
Neg04.java:36:35: compiler.err.cant.apply.diamond: (compiler.misc.diamond: Foo), null
28 errors
--- a/langtools/test/tools/javac/generics/diamond/neg/Neg11.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/diamond/neg/Neg11.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,3 +1,3 @@
-Neg11.java:15:25: compiler.err.cant.resolve.location: kindname.class, UndeclaredName, , , kindname.class, Neg11
-Neg11.java:16:25: compiler.err.cant.resolve.location: kindname.class, UndeclaredName, , , kindname.class, Neg11
+Neg11.java:15:25: compiler.err.cant.resolve.location: kindname.class, UndeclaredName, , , (compiler.misc.location: kindname.class, Neg11, null)
+Neg11.java:16:25: compiler.err.cant.resolve.location: kindname.class, UndeclaredName, , , (compiler.misc.location: kindname.class, Neg11, null)
2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/6943278/T6943278.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,12 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 6943278
+ * @summary spurious error message for inference and type-variable with erroneous bound
+ * @compile/fail/ref=T6943278.out -XDrawDiagnostics -Xlint:unchecked T6943278.java
+ */
+class T6943278<X extends Number & NonExistentInterface> {
+ <X> T6943278<X> m() { return null;}
+ <X extends Number & NonExistentInterface> T6943278<X> m(X x) { return null;}
+ T6943278<?> f1 = m();
+ T6943278<?> f2 = m("");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/6943278/T6943278.out Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,3 @@
+T6943278.java:7:35: compiler.err.cant.resolve: kindname.class, NonExistentInterface, ,
+T6943278.java:9:25: compiler.err.cant.resolve.location: kindname.class, NonExistentInterface, , , (compiler.misc.location: kindname.class, T6943278, null)
+2 errors
--- a/langtools/test/tools/javac/generics/typevars/5060485/Compatibility.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/typevars/5060485/Compatibility.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,2 +1,2 @@
-Compatibility.java:36:35: compiler.err.not.within.bounds: Test.Y
+Compatibility.java:36:35: compiler.err.not.within.bounds: Test.Y, T
1 error
--- a/langtools/test/tools/javac/generics/typevars/5060485/Compatibility02.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/generics/typevars/5060485/Compatibility02.out Fri Feb 18 12:04:36 2011 -0800
@@ -1,2 +1,2 @@
-Compatibility.java:36:35: compiler.err.not.within.bounds: Test.Y
+Compatibility.java:36:35: compiler.err.not.within.bounds: Test.Y, T
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/typevars/6968793/T6968793.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,11 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6968793
+ * @summary javac generates spourious diagnostics for ill-formed type-variable bounds
+ * @author mcimadamore
+ * @compile/fail/ref=T6968793.out -XDrawDiagnostics T6968793.java
+ */
+
+class T6968793<X extends Number, Y extends X, Z extends Object & Comparable<Y>> {
+ T6968793<Object, Object, Object> o;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/typevars/6968793/T6968793.out Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,4 @@
+T6968793.java:10:14: compiler.err.not.within.bounds: java.lang.Object, X
+T6968793.java:10:22: compiler.err.not.within.bounds: java.lang.Object, Y
+T6968793.java:10:30: compiler.err.not.within.bounds: java.lang.Object, Z
+3 errors
--- a/langtools/test/tools/javac/meth/InvokeDynTrans.out Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-InvokeDynTrans.java:55:39: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeDynTrans.java:57:34: compiler.warn.type.parameter.on.polymorphic.signature
-- compiler.err.warnings.and.werror
-1 error
-2 warnings
--- a/langtools/test/tools/javac/meth/InvokeMHTrans.java Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/* Copyright (c) 2008, 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 6754038 6979327
- * @summary Generate call sites for method handle
- * @author jrose
- *
- * @compile/fail/ref=InvokeMHTrans.out -Werror -XDrawDiagnostics -source 7 -target 7 InvokeMHTrans.java
- */
-
-/*
- * Standalone testing:
- * <code>
- * $ cd $MY_REPO_DIR/langtools
- * $ (cd make; make)
- * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeMH.java
- * $ javap -c -classpath dist meth.InvokeMH
- * </code>
- */
-
-package meth;
-
-import java.dyn.MethodHandle;
-
-public class InvokeMHTrans {
- void test(MethodHandle mh_SiO,
- MethodHandle mh_vS,
- MethodHandle mh_vi,
- MethodHandle mh_vv) throws Throwable {
- Object o; String s; int i; // for return type testing
-
- // next five must have sig = (String,int)Object
- mh_SiO.invokeExact("world", 123);
- mh_SiO.invokeExact("mundus", 456);
- Object k = "kosmos";
- mh_SiO.invokeExact((String)k, 789);
- o = mh_SiO.invokeExact((String)null, 000);
- o = mh_SiO.<Object>invokeExact("arda", -123);
-
- // sig = ()String
- s = mh_vS.<String>invokeExact();
-
- // sig = ()int
- i = mh_vi.<int>invokeExact();
- o = mh_vi.<int>invokeExact();
- //s = mh_vi.<int>invokeExact(); //BAD
- mh_vi.<int>invokeExact();
-
- // sig = ()void
- //o = mh_vv.<void>invokeExact(); //BAD
- mh_vv.<void>invokeExact();
- }
-
- void testGen(MethodHandle mh_SiO,
- MethodHandle mh_vS,
- MethodHandle mh_vi,
- MethodHandle mh_vv) throws Throwable {
- Object o; String s; int i; // for return type testing
-
- // next five must have sig = (*,*)*
- mh_SiO.invokeGeneric((Object)"world", (Object)123);
- mh_SiO.<void>invokeGeneric((Object)"mundus", (Object)456);
- Object k = "kosmos";
- mh_SiO.invokeGeneric(k, 789);
- o = mh_SiO.invokeGeneric(null, 000);
- o = mh_SiO.<Object>invokeGeneric("arda", -123);
-
- // sig = ()String
- o = mh_vS.invokeGeneric();
-
- // sig = ()int
- i = mh_vi.<int>invokeGeneric();
- o = mh_vi.invokeGeneric();
- //s = mh_vi.<int>invokeGeneric(); //BAD
- mh_vi.<void>invokeGeneric();
-
- // sig = ()void
- //o = mh_vv.<void>invokeGeneric(); //BAD
- o = mh_vv.invokeGeneric();
- }
-}
--- a/langtools/test/tools/javac/meth/InvokeMHTrans.out Fri Feb 18 11:15:40 2011 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-InvokeMHTrans.java:59:39: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:62:38: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:65:35: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:66:35: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:68:31: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:72:32: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:83:35: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:87:41: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:93:37: compiler.warn.type.parameter.on.polymorphic.signature
-InvokeMHTrans.java:96:34: compiler.warn.type.parameter.on.polymorphic.signature
-- compiler.err.warnings.and.werror
-1 error
-10 warnings
--- a/langtools/test/tools/javac/meth/TestCP.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/meth/TestCP.java Fri Feb 18 12:04:36 2011 -0800
@@ -42,13 +42,15 @@
static class TestClass {
void test(MethodHandle mh) throws Throwable {
- Number n = mh.<Number>invokeExact("daddy",1,'n');
+ Number n = (Number)mh.invokeExact("daddy",1,'n');
n = (Number)mh.invokeExact("bunny",1,'d');
+ n = (Number)(mh.invokeExact("foo",1,'d'));
+ n = (Number)((mh.invokeExact("bar",1,'d')));
}
}
static final String PS_TYPE = "(Ljava/lang/String;IC)Ljava/lang/Number;";
- static final int PS_CALLS_COUNT = 2;
+ static final int PS_CALLS_COUNT = 4;
static final String SUBTEST_NAME = TestClass.class.getName() + ".class";
static final String TEST_METHOD_NAME = "test";
--- a/langtools/test/tools/javac/meth/XlintWarn.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/meth/XlintWarn.java Fri Feb 18 12:04:36 2011 -0800
@@ -35,6 +35,19 @@
class XlintWarn {
void test(MethodHandle mh) throws Throwable {
int i1 = (int)mh.invokeExact();
- int i2 = (int)mh.invokeVarargs();
+ int i2 = (int)mh.invokeGeneric();
+ int i3 = (int)mh.invokeWithArguments();
+ }
+
+ void test2(MethodHandle mh) throws Throwable {
+ int i1 = (int)(mh.invokeExact());
+ int i2 = (int)(mh.invokeGeneric());
+ int i3 = (int)(mh.invokeWithArguments());
+ }
+
+ void test3(MethodHandle mh) throws Throwable {
+ int i1 = (int)((mh.invokeExact()));
+ int i2 = (int)((mh.invokeGeneric()));
+ int i3 = (int)((mh.invokeWithArguments()));
}
}
--- a/langtools/test/tools/javac/policy/test1/byfile.ABD.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/policy/test1/byfile.ABD.out Fri Feb 18 12:04:36 2011 -0800
@@ -12,6 +12,6 @@
[generate code A2]
[attribute B]
[attribute B1]
-B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, B1
+B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, B1, null)
[attribute B2]
1 error
--- a/langtools/test/tools/javac/policy/test1/bytodo.ABD.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/policy/test1/bytodo.ABD.out Fri Feb 18 12:04:36 2011 -0800
@@ -15,7 +15,7 @@
[desugar B]
[generate code B]
[attribute B1]
-B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, B1
+B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, B1, null)
[attribute B2]
[attribute D]
[attribute D1]
--- a/langtools/test/tools/javac/policy/test1/simple.ABD.out Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/policy/test1/simple.ABD.out Fri Feb 18 12:04:36 2011 -0800
@@ -3,7 +3,7 @@
[attribute A2]
[attribute B]
[attribute B1]
-B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, B1
+B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , (compiler.misc.location: kindname.class, B1, null)
[attribute B2]
[attribute D]
[attribute D1]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/tree/T6993305.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,124 @@
+/*
+ * 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 6993305
+ * @summary starting position of a method without modifiers and with type parameters is incorrect
+ */
+
+import java.io.File;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.SourcePositions;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTool;
+import java.io.IOException;
+
+/*
+ * Test verifies the starting position of all methods by computing the start position
+ * of each method as the first non-white character on the first line containing
+ * (" " + methodName + "("), and then comparing this value against the reported
+ * value in the SourcePositions table.
+ */
+public class T6993305 {
+ <T> void test1(T t) { } // this is the primary case to be tested
+ public <T> void test2(T t) { }
+ @Deprecated <T> void test3(T t) { }
+
+ public static void main(String... args) throws Exception {
+ new T6993305().run();
+ }
+
+ void run() throws Exception {
+ File testSrc = new File(System.getProperty("test.src"));
+
+ JavacTool tool = JavacTool.create();
+ StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
+
+ File f = new File(testSrc, T6993305.class.getSimpleName() + ".java");
+ Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjects(f);
+ JavacTask task = tool.getTask(null, fm, null, null, null, fos);
+ Iterable<? extends CompilationUnitTree> cus = task.parse();
+
+ TestScanner s = new TestScanner();
+ s.scan(cus, task);
+
+ if (errors > 0)
+ throw new Exception(errors + " errors occurred");
+ }
+
+ void error(String msg) {
+ System.err.println("Error: " + msg);
+ errors++;
+ }
+
+ int errors;
+
+ class TestScanner extends TreeScanner<Void, JavacTask> {
+ CompilationUnitTree cu;
+ SourcePositions sourcePositions;
+ String source;
+
+ void show(String label, int pos) {
+ System.err.println(label + ": " +
+ source.substring(pos, Math.min(source.length(), pos + 10)));
+ }
+
+ @Override public Void visitCompilationUnit(CompilationUnitTree tree, JavacTask task) {
+ cu = tree;
+ Trees trees = Trees.instance(task);
+ sourcePositions = trees.getSourcePositions();
+ try {
+ source = String.valueOf(tree.getSourceFile().getCharContent(true));
+ } catch (IOException e) {
+ throw new Error(e);
+ }
+ return super.visitCompilationUnit(tree, task);
+ }
+
+ // this is the core of the test
+ @Override public Void visitMethod(MethodTree tree, JavacTask task) {
+ String name = String.valueOf(tree.getName());
+ int pos = source.indexOf(" " + name + "(");
+ while (source.charAt(pos - 1) != '\n') pos--;
+ while (source.charAt(pos) == ' ') pos++;
+ int expectedStart = pos;
+ int reportedStart = (int) sourcePositions.getStartPosition(cu, tree);
+ System.err.println("Method " + name
+ + " expectedStart:" + expectedStart
+ + " reportedStart:" + reportedStart);
+ if (expectedStart != reportedStart) {
+ error("Unexpected value for " + name);
+ show("expected", expectedStart);
+ show("reported", reportedStart);
+ }
+ return super.visitMethod(tree, task);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/GenericTypeWellFormednessTest.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,261 @@
+/*
+ * 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 7007432 7006109
+ * @summary Test generic types well-formedness
+ * @author mcimadamore
+ * @library .
+ * @run main GenericTypeWellFormednessTest
+ */
+
+import com.sun.tools.javac.code.BoundKind;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.*;
+import java.lang.reflect.Array;
+
+/**
+ * Check parameterized type well-formedness. This test executes a number of checks
+ * in order to establish as to whether an instantiation of a generic type conforms
+ * to the generic class' declared bounds.
+ */
+public class GenericTypeWellFormednessTest extends TypeHarness {
+
+ static int executedCount = 0;
+ static int ignoredCount = 0;
+
+ InstantiableType[] rows;
+ Type[] columns;
+
+ static class InstantiableType {
+ protected Type type;
+
+ public InstantiableType(Type type) {
+ this.type = type;
+ }
+
+ Type inst(Type clazz) {
+ return type;
+ }
+ }
+
+ enum Result {
+ /* generic type is well-formed w.r.t. declared bounds */
+ OK(true),
+ /* generic type is not well-formed w.r.t. declared bounds */
+ FAIL(false),
+ /* generic type is not well-formed w.r.t. declared bounds according to the JLS 3rd,
+ * but javac allows it (spec for generic type well-formedness is overly restrictive)
+ * See regression test test/tools/generics/wildcards/T5097548.java
+ */
+ IGNORE(false);
+
+ boolean value;
+
+ Result(boolean value) {
+ this.value = value;
+ }
+ }
+
+ static final Result T = Result.OK;
+ static final Result F = Result.FAIL;
+ static final Result I = Result.IGNORE;
+
+ /*is a type in 'rows' a valid instantiation for the generic class in 'col' ? */
+ Result[][] isValidInstantiation = {
+ //Foo<X>, Foo<X ext Object>, Foo<X ext Number>, Foo<X ext Foo<X>>, Foo<X ext Foo<+X>>, Foo<X ext Foo<-X>>, Foo<X ext Foo<?>>
+ /*Foo<Object>*/ { T , T , F , F , F , F , F },
+ /*Foo<Number>*/ { T , T , T , F , F , F , F },
+ /*Foo<Integer>*/ { T , T , T , F , F , F , F },
+ /*Foo<Double>*/ { T , T , T , F , F , F , F },
+ /*Foo<String>*/ { T , T , F , F , F , F , F },
+ /*Foo<X1>*/ { T , T , F , F , F , F , F },
+ /*Foo<X2>*/ { T , T , T , F , F , F , F },
+ /*Foo<X3>*/ { T , T , T , F , F , F , F },
+ /*Foo<X4>*/ { T , T , T , F , F , F , F },
+ /*Foo<X5>*/ { T , T , F , F , F , F , F },
+ /*Foo<X6>*/ { T , T , F , T , T , T , T },
+ /*Foo<+Object>*/ { T , T , I , I , I , I , I },
+ /*Foo<+Number>*/ { T , T , T , F , F , F , F },
+ /*Foo<+Integer>*/{ T , T , T , F , F , F , F },
+ /*Foo<+Double>*/ { T , T , T , F , F , F , F },
+ /*Foo<+String>*/ { T , T , F , F , F , F , F },
+ /*Foo<+X1>*/ { T , T , F , F , F , F , F },
+ /*Foo<+X2>*/ { T , T , T , F , F , F , F },
+ /*Foo<+X3>*/ { T , T , T , F , F , F , F },
+ /*Foo<+X4>*/ { T , T , T , F , F , F , F },
+ /*Foo<+X5>*/ { T , T , F , F , F , F , F },
+ /*Foo<+X6>*/ { T , T , F , T , T , I , T },
+ /*Foo<-Object>*/ { T , T , F , F , F , F , F },
+ /*Foo<-Number>*/ { T , T , T , F , F , F , F },
+ /*Foo<-Integer>*/{ T , T , T , F , F , F , F },
+ /*Foo<-Double>*/ { T , T , T , F , F , F , F },
+ /*Foo<-String>*/ { T , T , F , F , F , F , F },
+ /*Foo<-X1>*/ { T , T , I , I , I , I , I },
+ /*Foo<-X2>*/ { T , T , I , F , F , F , F },
+ /*Foo<-X3>*/ { T , T , I , F , F , F , F },
+ /*Foo<-X4>*/ { T , T , I , F , F , F , F },
+ /*Foo<-X5>*/ { T , T , I , F , F , F , F },
+ /*Foo<-X6>*/ { T , T , F , T , I , I , T },
+ /*Foo<?>*/ { T , T , T , T , T , T , T }};
+
+ GenericTypeWellFormednessTest() {
+ InstantiableType[] basicTypes = {
+ new InstantiableType(predef.objectType),
+ new InstantiableType(NumberType()),
+ new InstantiableType(box(predef.intType)),
+ new InstantiableType(box(predef.doubleType)),
+ new InstantiableType(predef.stringType) };
+
+ InstantiableType[] typeVars = new InstantiableType[basicTypes.length + 1];
+ for (int i = 0 ; i < basicTypes.length ; i++) {
+ typeVars[i] = new InstantiableType(fac.TypeVariable(basicTypes[i].type));
+ }
+ typeVars[typeVars.length - 1] = new InstantiableType(null) {
+ Type inst(Type clazz) {
+ TypeVar tvar = fac.TypeVariable();
+ tvar.bound = subst(clazz, Mapping(clazz.getTypeArguments().head, tvar));
+ return tvar;
+ }
+ };
+
+ InstantiableType[] typeArgs = join(InstantiableType.class, basicTypes, typeVars);
+
+ InstantiableType[] invariantTypes = new InstantiableType[typeArgs.length];
+ for (int i = 0 ; i < typeArgs.length ; i++) {
+ final InstantiableType type1 = typeArgs[i];
+ invariantTypes[i] = new InstantiableType(typeArgs[i].type) {
+ Type inst(Type clazz) {
+ return subst(clazz, Mapping(clazz.getTypeArguments().head, type1.inst(clazz)));
+ }
+ };
+ }
+
+ InstantiableType[] covariantTypes = new InstantiableType[typeArgs.length];
+ for (int i = 0 ; i < typeArgs.length ; i++) {
+ final InstantiableType type1 = typeArgs[i];
+ covariantTypes[i] = new InstantiableType(null) {
+ Type inst(Type clazz) {
+ Type t = fac.Wildcard(BoundKind.EXTENDS, type1.inst(clazz));
+ return subst(clazz, Mapping(clazz.getTypeArguments().head, t));
+ }
+ };
+ }
+
+ InstantiableType[] contravariantTypes = new InstantiableType[typeArgs.length];
+ for (int i = 0 ; i < typeArgs.length ; i++) {
+ final InstantiableType type1 = typeArgs[i];
+ contravariantTypes[i] = new InstantiableType(null) {
+ Type inst(Type clazz) {
+ Type t = fac.Wildcard(BoundKind.SUPER, type1.inst(clazz));
+ return subst(clazz, Mapping(clazz.getTypeArguments().head, t));
+ }
+ };
+ }
+
+ InstantiableType[] bivariantTypes = {
+ new InstantiableType(fac.Wildcard(BoundKind.UNBOUND, predef.objectType)) {
+ Type inst(Type clazz) {
+ return subst(clazz, Mapping(clazz.getTypeArguments().head, type));
+ }
+ }
+ };
+
+ rows = join(InstantiableType.class, invariantTypes, covariantTypes, contravariantTypes, bivariantTypes);
+
+ Type tv1 = fac.TypeVariable();
+ Type decl1 = fac.Class(tv1);
+
+ Type tv2 = fac.TypeVariable(predef.objectType);
+ Type decl2 = fac.Class(tv2);
+
+ Type tv3 = fac.TypeVariable(NumberType());
+ Type decl3 = fac.Class(tv3);
+
+ TypeVar tv4 = fac.TypeVariable();
+ Type decl4 = fac.Class(tv4);
+ tv4.bound = decl4;
+ tv4.tsym.name = predef.exceptionType.tsym.name;
+
+ TypeVar tv5 = fac.TypeVariable();
+ Type decl5 = fac.Class(tv5);
+ tv5.bound = subst(decl5, Mapping(tv5, fac.Wildcard(BoundKind.EXTENDS, tv5)));
+
+ TypeVar tv6 = fac.TypeVariable();
+ Type decl6 = fac.Class(tv6);
+ tv6.bound = subst(decl6, Mapping(tv6, fac.Wildcard(BoundKind.SUPER, tv6)));
+
+ TypeVar tv7 = fac.TypeVariable();
+ Type decl7 = fac.Class(tv7);
+ tv7.bound = subst(decl7, Mapping(tv7, fac.Wildcard(BoundKind.UNBOUND, predef.objectType)));
+
+ columns = new Type[] {
+ decl1, decl2, decl3, decl4, decl5, decl6, decl7
+ };
+ }
+
+ void test() {
+ for (int i = 0; i < rows.length ; i++) {
+ for (int j = 0; j < columns.length ; j++) {
+ Type decl = columns[j];
+ Type inst = rows[i].inst(decl);
+ if (isValidInstantiation[i][j] != Result.IGNORE) {
+ executedCount++;
+ assertValidGenericType(inst, isValidInstantiation[i][j].value);
+ } else {
+ ignoredCount++;
+ }
+ }
+ }
+ }
+
+ Type NumberType() {
+ Symbol s = box(predef.intType).tsym;
+ s.complete();
+ return ((ClassType)s.type).supertype_field;
+ }
+
+ @SuppressWarnings("unchecked")
+ <T> T[] join(Class<T> type, T[]... args) {
+ int totalLength = 0;
+ for (T[] arr : args) {
+ totalLength += arr.length;
+ }
+ T[] new_arr = (T[])Array.newInstance(type, totalLength);
+ int idx = 0;
+ for (T[] arr : args) {
+ System.arraycopy(arr, 0, new_arr, idx, arr.length);
+ idx += arr.length;
+ }
+ return new_arr;
+ }
+
+ public static void main(String[] args) {
+ new GenericTypeWellFormednessTest().test();
+ System.out.println("Executed checks : " + executedCount);
+ System.out.println("Ignored checks : " + ignoredCount);
+ }
+}
--- a/langtools/test/tools/javac/types/TypeHarness.java Fri Feb 18 11:15:40 2011 -0800
+++ b/langtools/test/tools/javac/types/TypeHarness.java Fri Feb 18 12:04:36 2011 -0800
@@ -29,6 +29,7 @@
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
@@ -68,6 +69,7 @@
public class TypeHarness {
protected Types types;
+ protected Check chk;
protected Symtab predef;
protected Names names;
protected Factory fac;
@@ -76,6 +78,7 @@
Context ctx = new Context();
JavacFileManager.preRegister(ctx);
types = Types.instance(ctx);
+ chk = Check.instance(ctx);
predef = Symtab.instance(ctx);
names = Names.instance(ctx);
fac = new Factory();
@@ -157,6 +160,21 @@
error(s + msg + t);
}
}
+
+ /** assert that generic type 't' is well-formed */
+ public void assertValidGenericType(Type t) {
+ assertValidGenericType(t, true);
+ }
+
+ /** assert that 's' is/is not assignable to 't' */
+ public void assertValidGenericType(Type t, boolean expected) {
+ if (chk.checkValidGenericType(t) != expected) {
+ String msg = expected ?
+ " is not a valid generic type" :
+ " is a valid generic type";
+ error(t + msg + " " + t.tsym.type);
+ }
+ }
// </editor-fold>
private void error(String msg) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6569633/T6569633.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6569633
+ * @author mcimadamore
+ * @summary Varargs: parser error when varargs element type is an array
+ * @compile/fail/ref=T6569633.out -XDrawDiagnostics T6569633.java
+ */
+
+class T6569633 {
+ void m1 (Integer... i[]) { }
+ void m2 (Integer[]... i) { }
+ void m3 (Integer[]... i[]) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6569633/T6569633.out Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,3 @@
+T6569633.java:10:27: compiler.err.varargs.and.old.array.syntax
+T6569633.java:12:29: compiler.err.varargs.and.old.array.syntax
+2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/T7013865.java Fri Feb 18 12:04:36 2011 -0800
@@ -0,0 +1,36 @@
+/*
+ * 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 7013865
+ * @summary varargs: javac crashes during overload resolution with generic varargs
+ * @compile T7013865.java
+ */
+
+class T7013865 {
+ public <X extends Number> void m(X... args) { }
+ public void m(Object... args) { }
+
+ { m(null, null); }
+}
--- a/make/Defs-internal.gmk Fri Feb 18 11:15:40 2011 -0800
+++ b/make/Defs-internal.gmk Fri Feb 18 12:04:36 2011 -0800
@@ -147,7 +147,7 @@
endif
-# Do we build the source and openjdk binary plug bundles?
+# Do we build the source bundles?
BUNDLE_RULES = $(JDK_TOPDIR)/make/closed/bundles.gmk
ifeq ($(SKIP_BUNDLES_BUILD), true)
BUNDLE_RULES_AVAILABLE := false
@@ -171,7 +171,6 @@
ifndef SKIP_COMPARE_IMAGES
SKIP_COMPARE_IMAGES = true
endif
- SKIP_OPENJDK_BUILD = true
else
# Various non-OPENJDK reasons to NOT build the deploy repository
@@ -187,21 +186,11 @@
endif
endif
- ifndef SKIP_OPENJDK_BUILD
- #SKIP_OPENJDK_BUILD = false
- # Until 6675289 is resolved, or this feature is removed.
- SKIP_OPENJDK_BUILD = true
- endif
endif
ifndef SKIP_PRODUCT_BUILD
SKIP_PRODUCT_BUILD = false
endif
-# Solaris 64 bit builds are not complete enough to ever do this
-ifeq ($(PLATFORM)$(ARCH_DATA_MODEL),solaris64)
- SKIP_OPENJDK_BUILD = true
-endif
-
# Many reasons why we would want to skip the comparison to previous jdk
ifndef SKIP_COMPARE_IMAGES
ifeq ($(BUILD_JDK), false)
--- a/test/Makefile Fri Feb 18 11:15:40 2011 -0800
+++ b/test/Makefile Fri Feb 18 12:04:36 2011 -0800
@@ -79,7 +79,7 @@
# Test targets
$(LANGTOOLS_TEST_LIST):
@$(NO_STOPPING)$(call SUBDIR_TEST, $(LANGTOOLS_DIR), $(subst langtools_,,$@))
-$(JDK_TEST_LIST):
+$(JDK_TEST_LIST) $(JDK_TEST_LIST2):
@$(NO_STOPPING)$(call SUBDIR_TEST, $(JDK_DIR), $@)
clean: