diff --git a/.hgtags b/.hgtags
index 39ca1fe7089..abf4dd939ca 100644
--- a/.hgtags
+++ b/.hgtags
@@ -374,3 +374,4 @@ d53037a90c441cb528dc41c30827985de0e67c62 jdk-9+123
e8373543a3f0f60589b7d72b1f9b172721124caf jdk-9+129
e613affb88d178dc7c589f1679db113d589bddb4 jdk-9+130
4d2a15091124488080d65848b704e25599b2aaeb jdk-9+131
+2e83d21d78cd9c1d52e6cd2599e9c8aa36ea1f52 jdk-9+132
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 9c7560ce460..2ab754ea198 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -374,3 +374,4 @@ b30ae794d974d7dd3eb4e84203f70021823fa6c6 jdk-9+128
f5902d3841b82cac6e7716a20c24e8e916fb14a8 jdk-9+129
d94d54a3192fea79234c3ac55cd0b4052d45e954 jdk-9+130
8728756c2f70a79a90188f4019cfd6b9a275765c jdk-9+131
+a24702d4d5ab0015a5c553ed57f66fce7d85155e jdk-9+132
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index e4d41e81b43..c591a79d327 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -251,8 +251,6 @@ SUPPORT_HEADLESS:=@SUPPORT_HEADLESS@
# Legacy support
USE_NEW_HOTSPOT_BUILD:=@USE_NEW_HOTSPOT_BUILD@
-MACOSX_UNIVERSAL=@MACOSX_UNIVERSAL@
-
# JDK_OUTPUTDIR specifies where a working jvm is built.
# You can run $(JDK_OUTPUTDIR)/bin/java
# Though the layout of the contents of $(JDK_OUTPUTDIR) is not
diff --git a/corba/.hgtags b/corba/.hgtags
index 1e46a9e1c46..2ba88ee0421 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -374,3 +374,4 @@ c7f5ba08fcd4b8416e62c21229f9a07c95498919 jdk-9+126
c3e83ccab3bb1733ae903d681879a33f85ed465c jdk-9+129
77f9692d5976ae155773dd3e07533616bb95bae1 jdk-9+130
f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131
+1ab4b9399c4cba584f66c1c088188f2f565fbf9c jdk-9+132
diff --git a/corba/src/java.corba/share/classes/module-info.java b/corba/src/java.corba/share/classes/module-info.java
index 644e19c6f80..8c21cc30ca0 100644
--- a/corba/src/java.corba/share/classes/module-info.java
+++ b/corba/src/java.corba/share/classes/module-info.java
@@ -23,6 +23,9 @@
* questions.
*/
+/**
+ * Defines the Java binding of the OMG CORBA APIs, and the RMI-IIOP API.
+ */
module java.corba {
requires public java.desktop;
requires public java.rmi;
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index ada9a1ad431..dd85a0e3b2b 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -534,3 +534,4 @@ adc8c84b7cf8c540d920182f78a2bc982366432a jdk-9+126
e96b34b76d863ed1fa04e0eeb3f297ac17b490fd jdk-9+129
7d54c7056328b6a2bf4877458b8f4d8cd870f93b jdk-9+130
943bf73b49c33c2d7cbd796f6a4ae3c7a00ae932 jdk-9+131
+713951c08aa26813375175c2ab6cc99ff2a56903 jdk-9+132
diff --git a/hotspot/make/Dist.gmk b/hotspot/make/Dist.gmk
index bfe3daf2062..710de55960c 100644
--- a/hotspot/make/Dist.gmk
+++ b/hotspot/make/Dist.gmk
@@ -45,15 +45,6 @@ else
LIB_SUBDIR := lib$(OPENJDK_TARGET_CPU_LIBDIR)
endif
-################################################################################
-# Functions to setup copying of files for variants
-
-# Support macro for SetupDistLibFile
-define macosx_universalize
- $(MKDIR) -p $(@D)
- $(LIPO) -create -output $@ $<
-endef
-
################################################################################
# Setup make rules to copy a native library and associated data.
#
@@ -74,16 +65,9 @@ define SetupDistLibFileBody
$1_LIB_NAME := $(LIBRARY_PREFIX)$$($1_NAME)
$1_TARGET_DIR := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$$($1_VARIANT_TARGET_DIR)
- ifeq ($(OPENJDK_TARGET_OS), macosx)
- # We must use the 'universalize' macro to run lipo on shared libraries, at
- # least until JDK-8069540 is fixed.
- $1_MACRO := macosx_universalize
- endif
-
# Copy the the native library.
$$(eval $$(call SetupCopyFiles, $1_COPY_LIB, \
DEST := $$($1_TARGET_DIR), \
- MACRO := $$($1_MACRO), \
FILES := $$(wildcard \
$$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX)), \
))
diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk
index efb108ad9f0..ce4a0319909 100644
--- a/hotspot/make/test/JtregNative.gmk
+++ b/hotspot/make/test/JtregNative.gmk
@@ -50,7 +50,6 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \
$(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
$(HOTSPOT_TOPDIR)/test/compiler/calls \
- $(HOTSPOT_TOPDIR)/test/compiler/native \
$(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \
$(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \
$(HOTSPOT_TOPDIR)/test/compiler/jvmci/jdk.vm.ci.code.test \
diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
index 42c61b9a33f..473c4bc67eb 100644
--- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp
@@ -110,17 +110,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
// Entry frame checks
if (is_entry_frame()) {
// an entry frame must have a valid fp.
-
- if (!fp_safe) return false;
-
- // Validate the JavaCallWrapper an entry frame must have
-
- address jcw = (address)entry_frame_call_wrapper();
-
- bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > fp);
-
- return jcw_safe;
-
+ return fp_safe && is_entry_frame_valid(thread);
}
intptr_t* sender_sp = NULL;
@@ -210,15 +200,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
}
// construct the potential sender
-
frame sender(sender_sp, sender_unextended_sp, saved_fp, sender_pc);
-
- // Validate the JavaCallWrapper an entry frame must have
- address jcw = (address)sender.entry_frame_call_wrapper();
-
- bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp());
-
- return jcw_safe;
+ return sender.is_entry_frame_valid(thread);
}
CompiledMethod* nm = sender_blob->as_compiled_method_or_null();
diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp
index ab6aeeeeabf..f1664a2b6df 100644
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp
@@ -225,19 +225,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
// Entry frame checks
if (is_entry_frame()) {
// an entry frame must have a valid fp.
-
- if (!fp_safe) {
- return false;
- }
-
- // Validate the JavaCallWrapper an entry frame must have
-
- address jcw = (address)entry_frame_call_wrapper();
-
- bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > _FP);
-
- return jcw_safe;
-
+ return fp_safe && is_entry_frame_valid(thread);
}
intptr_t* younger_sp = sp();
@@ -290,14 +278,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
return false;
}
- if( sender.is_entry_frame()) {
- // Validate the JavaCallWrapper an entry frame must have
-
- address jcw = (address)sender.entry_frame_call_wrapper();
-
- bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > sender_fp);
-
- return jcw_safe;
+ if (sender.is_entry_frame()) {
+ return sender.is_entry_frame_valid(thread);
}
// If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size
@@ -357,12 +339,6 @@ void frame::init(intptr_t* sp, address pc, CodeBlob* cb) {
_cb = CodeCache::find_blob(_pc);
}
_deopt_state = unknown;
-#ifdef ASSERT
- if ( _cb != NULL && _cb->is_compiled()) {
- // Without a valid unextended_sp() we can't convert the pc to "original"
- assert(!((CompiledMethod*)_cb)->is_deopt_pc(_pc), "invariant broken");
- }
-#endif // ASSERT
}
frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) {
@@ -534,6 +510,7 @@ frame frame::sender(RegisterMap* map) const {
void frame::patch_pc(Thread* thread, address pc) {
+ vmassert(_deopt_state != unknown, "frame is unpatchable");
if(thread == Thread::current()) {
StubRoutines::Sparc::flush_callers_register_windows_func()();
}
diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp
index ae8628c05d2..1db4b424cf5 100644
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp
@@ -108,17 +108,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
// Entry frame checks
if (is_entry_frame()) {
// an entry frame must have a valid fp.
-
- if (!fp_safe) return false;
-
- // Validate the JavaCallWrapper an entry frame must have
-
- address jcw = (address)entry_frame_call_wrapper();
-
- bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > fp);
-
- return jcw_safe;
-
+ return fp_safe && is_entry_frame_valid(thread);
}
intptr_t* sender_sp = NULL;
@@ -209,15 +199,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
}
// construct the potential sender
-
frame sender(sender_sp, sender_unextended_sp, saved_fp, sender_pc);
-
- // Validate the JavaCallWrapper an entry frame must have
- address jcw = (address)sender.entry_frame_call_wrapper();
-
- bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp());
-
- return jcw_safe;
+ return sender.is_entry_frame_valid(thread);
}
CompiledMethod* nm = sender_blob->as_compiled_method_or_null();
diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
index 15cf1f751a7..f3ae96f05a1 100644
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp
@@ -1071,6 +1071,9 @@ void InterpreterMacroAssembler::remove_activation(
NOT_LP64(get_thread(rthread);)
+ cmpl(Address(rthread, JavaThread::stack_guard_state_offset()), JavaThread::stack_guard_enabled);
+ jcc(Assembler::equal, no_reserved_zone_enabling);
+
cmpptr(rbx, Address(rthread, JavaThread::reserved_stack_activation_offset()));
jcc(Assembler::lessEqual, no_reserved_zone_enabling);
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java
index 8513c109bb6..3d4c2db9362 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/SALauncher.java
@@ -255,7 +255,8 @@ public class SALauncher {
}
buildAttachArgs(newArgs, pid, exe, core, false);
- JStack.main(newArgs.toArray(new String[newArgs.size()]));
+ JStack jstack = new JStack(false, false);
+ jstack.runWithArgs(newArgs.toArray(new String[newArgs.size()]));
}
private static void runJMAP(String[] oldArgs) {
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/BreakpointInfo.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/BreakpointInfo.java
index 207810dd99b..7519520d7da 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/BreakpointInfo.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/BreakpointInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodCounters.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodCounters.java
index ce6ba6c8f37..5f74240ff4b 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodCounters.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodCounters.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
index 5937f7f19a2..49849f9240c 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java
@@ -46,7 +46,6 @@ public class PPC64Frame extends Frame {
private static final int SENDER_SP_OFFSET = 0;
// Interpreter frames
- private static final int INTERPRETER_FRAME_MIRROR_OFFSET = -3; // for native calls only
private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -4;
private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
private static final int INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET -1;
@@ -55,7 +54,8 @@ public class PPC64Frame extends Frame {
private static final int INTERPRETER_FRAME_CACHE_OFFSET =INTERPRETER_FRAME_BCX_OFFSET - 1;
private static final int INTERPRETER_FRAME_MONITORS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
private static final int INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_MONITORS_OFFSET - 1;
- private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
+ private static final int INTERPRETER_FRAME_MIRROR_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
+ private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_MIRROR_OFFSET - 1;
private static final int INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; // FIXME: probably wrong, but unused anyway
private static final int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
private static final int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
index bbb1dfa7e44..afa4660691f 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java
@@ -714,11 +714,7 @@ public class SPARCFrame extends Frame {
/** 2 words, also used to save float regs across calls to C */
public static final int INTERPRETER_FRAME_D_SCRATCH_FP_OFFSET = -2;
public static final int INTERPRETER_FRAME_L_SCRATCH_FP_OFFSET = -4;
- /** For native calls only */
- public static final int INTERPRETER_FRAME_PADDING_OFFSET = -5;
- /** For native calls only */
- public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -6;
- /** Should be same as above, and should be zero mod 8 */
+ public static final int INTERPRETER_FRAME_MIRROR_OFFSET = -5;
public static final int INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET = -6;
public static final int INTERPRETER_FRAME_VM_LOCAL_WORDS = -INTERPRETER_FRAME_VM_LOCALS_FP_OFFSET;
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
index 51e2b6e8089..65488fe96c6 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java
@@ -48,10 +48,10 @@ public class X86Frame extends Frame {
private static final int SENDER_SP_OFFSET = 2;
// Interpreter frames
- private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only
private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
+ private static int INTERPRETER_FRAME_MIRROR_OFFSET;
private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only
private static int INTERPRETER_FRAME_CACHE_OFFSET;
private static int INTERPRETER_FRAME_LOCALS_OFFSET;
@@ -74,7 +74,8 @@ public class X86Frame extends Frame {
}
private static synchronized void initialize(TypeDataBase db) {
- INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
+ INTERPRETER_FRAME_MIRROR_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
+ INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_MIRROR_OFFSET - 1;
INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java
index 1a8afe111eb..9cb559bf31c 100644
--- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java
+++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ObjectReader.java
@@ -26,6 +26,7 @@ package sun.jvm.hotspot.utilities;
import java.lang.reflect.Modifier;
import java.util.*;
+import java.util.stream.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
@@ -204,15 +205,29 @@ public class ObjectReader {
}
}
- protected Object getHashtable(Instance oop, boolean isProperties) {
+ private void setPropertiesEntry(java.util.Properties p, Oop oop) {
+ InstanceKlass ik = (InstanceKlass)oop.getKlass();
+ OopField keyField = (OopField)ik.findField("key", "Ljava/lang/Object;");
+ OopField valueField = (OopField)ik.findField("val", "Ljava/lang/Object;");
+
+ try {
+ p.setProperty((String)readObject(keyField.getValue(oop)),
+ (String)readObject(valueField.getValue(oop)));
+ } catch (ClassNotFoundException ce) {
+ if (DEBUG) {
+ debugPrintStackTrace(ce);
+ }
+ }
+ }
+
+ protected Object getHashtable(Instance oop) {
InstanceKlass k = (InstanceKlass)oop.getKlass();
OopField tableField = (OopField)k.findField("table", "[Ljava/util/Hashtable$Entry;");
if (tableField == null) {
debugPrintln("Could not find field of [Ljava/util/Hashtable$Entry;");
return null;
}
- java.util.Hashtable table = (isProperties) ? new java.util.Properties()
- : new java.util.Hashtable();
+ java.util.Hashtable table = new java.util.Hashtable();
ObjArray kvs = (ObjArray)tableField.getValue(oop);
long size = kvs.getLength();
debugPrintln("Hashtable$Entry Size = " + size);
@@ -225,6 +240,39 @@ public class ObjectReader {
return table;
}
+ private Properties getProperties(Instance oop) {
+ InstanceKlass k = (InstanceKlass)oop.getKlass();
+ OopField mapField = (OopField)k.findField("map", "Ljava/util/concurrent/ConcurrentHashMap;");
+ if (mapField == null) {
+ debugPrintln("Could not find field of Ljava/util/concurrent/ConcurrentHashMap");
+ return null;
+ }
+
+ Instance mapObj = (Instance)mapField.getValue(oop);
+ if (mapObj == null) {
+ debugPrintln("Could not get map field from java.util.Properties");
+ return null;
+ }
+
+ InstanceKlass mk = (InstanceKlass)mapObj.getKlass();
+ OopField tableField = (OopField)mk.findField("table", "[Ljava/util/concurrent/ConcurrentHashMap$Node;");
+ if (tableField == null) {
+ debugPrintln("Could not find field of [Ljava/util/concurrent/ConcurrentHashMap$Node");
+ return null;
+ }
+
+ java.util.Properties props = new java.util.Properties();
+ ObjArray kvs = (ObjArray)tableField.getValue(mapObj);
+ long size = kvs.getLength();
+ debugPrintln("ConcurrentHashMap$Node Size = " + size);
+ LongStream.range(0, size)
+ .mapToObj(kvs::getObjAt)
+ .filter(o -> o != null)
+ .forEach(o -> setPropertiesEntry(props, o));
+
+ return props;
+ }
+
public Object readInstance(Instance oop) throws ClassNotFoundException {
Object result = getFromObjTable(oop);
if (result == null) {
@@ -240,11 +288,11 @@ public class ObjectReader {
}
if (kls.getName().equals(javaUtilHashtable())) {
- return getHashtable(oop, false);
+ return getHashtable(oop);
}
if (kls.getName().equals(javaUtilProperties())) {
- return getHashtable(oop, true);
+ return getProperties(oop);
}
Class clz = readClass(kls);
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
index 72f9d18caa3..c96da48e6fc 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java
@@ -265,9 +265,10 @@ final class CompilerToVM {
native HotSpotResolvedObjectTypeImpl resolveTypeInPool(HotSpotConstantPool constantPool, int cpi) throws LinkageError;
/**
- * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index {@code cpi} in
- * {@code constantPool}. For some opcodes, checks are performed that require the {@code method}
- * that contains {@code opcode} to be specified. The values returned in {@code info} are:
+ * Looks up and attempts to resolve the {@code JVM_CONSTANT_Field} entry for at index
+ * {@code cpi} in {@code constantPool}. For some opcodes, checks are performed that require the
+ * {@code method} that contains {@code opcode} to be specified. The values returned in
+ * {@code info} are:
*
*
* [(int) flags, // only valid if field is resolved
@@ -556,20 +557,18 @@ final class CompilerToVM {
native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(Object base, long displacement);
/**
- * Read a HotSpot ConstantPool* value from the memory location described by {@code base} plus
- * {@code displacement} and return the {@link HotSpotConstantPool} wrapping it. This method does
- * no checking that the memory location actually contains a valid pointer and may crash the VM
- * if an invalid location is provided. If the {@code base} is null then {@code displacement} is
- * used by itself. If {@code base} is a {@link HotSpotResolvedJavaMethodImpl},
- * {@link HotSpotConstantPool} or {@link HotSpotResolvedObjectTypeImpl} then the metaspace
- * pointer is fetched from that object and added to {@code displacement}. Any other non-null
- * object type causes an {@link IllegalArgumentException} to be thrown.
+ * Gets the {@code ConstantPool*} associated with {@code object} and returns a
+ * {@link HotSpotConstantPool} wrapping it.
*
- * @param base an object to read from or null
- * @param displacement
- * @return null or the resolved method for this location
+ * @param object a {@link HotSpotResolvedJavaMethodImpl} or
+ * {@link HotSpotResolvedObjectTypeImpl} object
+ * @return a {@link HotSpotConstantPool} wrapping the {@code ConstantPool*} associated with
+ * {@code object}
+ * @throws NullPointerException if {@code object == null}
+ * @throws IllegalArgumentException if {@code object} is neither a
+ * {@link HotSpotResolvedJavaMethodImpl} nor a {@link HotSpotResolvedObjectTypeImpl}
*/
- native HotSpotConstantPool getConstantPool(Object base, long displacement);
+ native HotSpotConstantPool getConstantPool(Object object);
/**
* Read a HotSpot Klass* value from the memory location described by {@code base} plus
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
index b861b2cec99..196616c4d61 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java
@@ -121,7 +121,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
if (metaspaceConstantPool == holder.getConstantPool().getMetaspaceConstantPool()) {
this.constantPool = holder.getConstantPool();
} else {
- this.constantPool = compilerToVM().getConstantPool(null, constMethod + config.constMethodConstantsOffset);
+ this.constantPool = compilerToVM().getConstantPool(this);
}
final int nameIndex = UNSAFE.getChar(constMethod + config.constMethodNameIndexOffset);
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
index 636c26c2c6c..b2ff5b32491 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java
@@ -445,7 +445,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
* operating on the latest one and that HotSpotResolvedJavaMethodImpls will be able to
* use the shared copy instead of creating their own instance.
*/
- constantPool = compilerToVM().getConstantPool(this, config().instanceKlassConstantsOffset);
+ constantPool = compilerToVM().getConstantPool(this);
}
return constantPool;
}
diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index 42aa1a635a9..dffad2b7f3f 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -2686,7 +2686,8 @@ void os::hint_no_preempt() {}
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
-// Note that the SR_lock plays no role in this suspend/resume protocol.
+// Note that the SR_lock plays no role in this suspend/resume protocol,
+// but is checked for NULL in SR_handler as a thread termination indicator.
//
static void resume_clear_context(OSThread *osthread) {
@@ -2718,10 +2719,23 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
// after sigsuspend.
int old_errno = errno;
- Thread* thread = Thread::current();
- OSThread* osthread = thread->osthread();
+ Thread* thread = Thread::current_or_null_safe();
+ assert(thread != NULL, "Missing current thread in SR_handler");
+
+ // On some systems we have seen signal delivery get "stuck" until the signal
+ // mask is changed as part of thread termination. Check that the current thread
+ // has not already terminated (via SR_lock()) - else the following assertion
+ // will fail because the thread is no longer a JavaThread as the ~JavaThread
+ // destructor has completed.
+
+ if (thread->SR_lock() == NULL) {
+ return;
+ }
+
assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+ OSThread* osthread = thread->osthread();
+
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
suspend_save_context(osthread, siginfo, context);
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index 738144baf3b..a40175df89c 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -2716,7 +2716,8 @@ void os::hint_no_preempt() {}
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
-// Note that the SR_lock plays no role in this suspend/resume protocol.
+// Note that the SR_lock plays no role in this suspend/resume protocol,
+// but is checked for NULL in SR_handler as a thread termination indicator.
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@@ -2746,10 +2747,23 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
// after sigsuspend.
int old_errno = errno;
- Thread* thread = Thread::current();
- OSThread* osthread = thread->osthread();
+ Thread* thread = Thread::current_or_null_safe();
+ assert(thread != NULL, "Missing current thread in SR_handler");
+
+ // On some systems we have seen signal delivery get "stuck" until the signal
+ // mask is changed as part of thread termination. Check that the current thread
+ // has not already terminated (via SR_lock()) - else the following assertion
+ // will fail because the thread is no longer a JavaThread as the ~JavaThread
+ // destructor has completed.
+
+ if (thread->SR_lock() == NULL) {
+ return;
+ }
+
assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+ OSThread* osthread = thread->osthread();
+
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
suspend_save_context(osthread, siginfo, context);
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index b8c1a72ae4a..5f4f1174c9d 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -3971,7 +3971,8 @@ void os::hint_no_preempt() {}
// - sets target osthread state to continue
// - sends signal to end the sigsuspend loop in the SR_handler
//
-// Note that the SR_lock plays no role in this suspend/resume protocol.
+// Note that the SR_lock plays no role in this suspend/resume protocol,
+// but is checked for NULL in SR_handler as a thread termination indicator.
static void resume_clear_context(OSThread *osthread) {
osthread->set_ucontext(NULL);
@@ -4004,9 +4005,21 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
Thread* thread = Thread::current_or_null_safe();
assert(thread != NULL, "Missing current thread in SR_handler");
- OSThread* osthread = thread->osthread();
+
+ // On some systems we have seen signal delivery get "stuck" until the signal
+ // mask is changed as part of thread termination. Check that the current thread
+ // has not already terminated (via SR_lock()) - else the following assertion
+ // will fail because the thread is no longer a JavaThread as the ~JavaThread
+ // destructor has completed.
+
+ if (thread->SR_lock() == NULL) {
+ return;
+ }
+
assert(thread->is_VM_thread() || thread->is_Java_thread(), "Must be VMThread or JavaThread");
+ OSThread* osthread = thread->osthread();
+
os::SuspendResume::State current = osthread->sr.state();
if (current == os::SuspendResume::SR_SUSPEND_REQUEST) {
suspend_save_context(osthread, siginfo, context);
diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp
index 6ed034c3bf5..2b7407dc985 100644
--- a/hotspot/src/os/posix/vm/os_posix.cpp
+++ b/hotspot/src/os/posix/vm/os_posix.cpp
@@ -93,10 +93,6 @@ void os::check_dump_limit(char* buffer, size_t bufferSize) {
}
int os::get_native_stack(address* stack, int frames, int toSkip) {
-#ifdef _NMT_NOINLINE_
- toSkip++;
-#endif
-
int frame_idx = 0;
int num_of_frames; // number of frames captured
frame fr = os::current_frame();
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index bd85cf01e61..5dfdab012d6 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -318,9 +318,6 @@ extern "C" void breakpoint() {
// only supported on Windows XP or later.
//
int os::get_native_stack(address* stack, int frames, int toSkip) {
-#ifdef _NMT_NOINLINE_
- toSkip++;
-#endif
int captured = RtlCaptureStackBackTrace(toSkip + 1, frames, (PVOID*)stack, NULL);
for (int index = captured; index < frames; index ++) {
stack[index] = NULL;
diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
index 5f7d479726c..0bdbc7c3aaa 100644
--- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
+++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
@@ -417,7 +417,15 @@ intptr_t* _get_previous_fp() {
#else
register intptr_t **ebp __asm__ (SPELL_REG_FP);
#endif
- return (intptr_t*) *ebp; // we want what it points to.
+ // ebp is for this frame (_get_previous_fp). We want the ebp for the
+ // caller of os::current_frame*(), so go up two frames. However, for
+ // optimized builds, _get_previous_fp() will be inlined, so only go
+ // up 1 frame in that case.
+#ifdef _NMT_NOINLINE_
+ return **(intptr_t***)ebp;
+#else
+ return *ebp;
+#endif
}
diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp
index 0003988860c..554dfa42286 100644
--- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp
+++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp
@@ -238,6 +238,28 @@ JVM_handle_linux_signal(int sig,
}
}
+ // Make the signal handler transaction-aware by checking the existence of a
+ // second (transactional) context with MSR TS bits active. If the signal is
+ // caught during a transaction, then just return to the HTM abort handler.
+ // Please refer to Linux kernel document powerpc/transactional_memory.txt,
+ // section "Signals".
+ if (uc && uc->uc_link) {
+ ucontext_t* second_uc = uc->uc_link;
+
+ // MSR TS bits are 29 and 30 (Power ISA, v2.07B, Book III-S, pp. 857-858,
+ // 3.2.1 "Machine State Register"), however note that ISA notation for bit
+ // numbering is MSB 0, so for normal bit numbering (LSB 0) they come to be
+ // bits 33 and 34. It's not related to endianness, just a notation matter.
+ if (second_uc->uc_mcontext.regs->msr & 0x600000000) {
+ if (TraceTraps) {
+ tty->print_cr("caught signal in transaction, "
+ "ignoring to jump to abort handler");
+ }
+ // Return control to the HTM abort handler.
+ return true;
+ }
+ }
+
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (os::Linux::signal_handlers_are_installed) {
diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
index 06a8a6eb5f1..6eeb1280c82 100644
--- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
+++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
@@ -235,7 +235,15 @@ intptr_t* _get_previous_fp() {
#else
register intptr_t **ebp __asm__ (SPELL_REG_FP);
#endif
- return (intptr_t*) *ebp; // we want what it points to.
+ // ebp is for this frame (_get_previous_fp). We want the ebp for the
+ // caller of os::current_frame*(), so go up two frames. However, for
+ // optimized builds, _get_previous_fp() will be inlined, so only go
+ // up 1 frame in that case.
+#ifdef _NMT_NOINLINE_
+ return **(intptr_t***)ebp;
+#else
+ return *ebp;
+#endif
}
diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
index 328ac2ebc7a..7713550f374 100644
--- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
+++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
@@ -292,15 +292,19 @@ extern "C" intptr_t *_get_current_fp(); // in .il file
frame os::current_frame() {
intptr_t* fp = _get_current_fp(); // it's inlined so want current fp
+ // fp is for os::current_frame. We want the fp for our caller.
frame myframe((intptr_t*)os::current_stack_pointer(),
(intptr_t*)fp,
CAST_FROM_FN_PTR(address, os::current_frame));
- if (os::is_first_C_frame(&myframe)) {
+ frame caller_frame = os::get_sender_for_C_frame(&myframe);
+
+ if (os::is_first_C_frame(&caller_frame)) {
// stack is not walkable
frame ret; // This will be a null useless frame
return ret;
} else {
- return os::get_sender_for_C_frame(&myframe);
+ // return frame for our caller's caller
+ return os::get_sender_for_C_frame(&caller_frame);
}
}
diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp
index efb1b3b0851..f3df7d386d6 100644
--- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp
+++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp
@@ -496,7 +496,15 @@ intptr_t* _get_previous_fp() {
__asm {
mov frameptr, ebp
};
+ // ebp (frameptr) is for this frame (_get_previous_fp). We want the ebp for the
+ // caller of os::current_frame*(), so go up two frames. However, for
+ // optimized builds, _get_previous_fp() will be inlined, so only go
+ // up 1 frame in that case.
+#ifdef _NMT_NOINLINE_
+ return **(intptr_t***)frameptr;
+#else
return *frameptr;
+#endif
}
#endif // !AMD64
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp
index fc1774d1941..09ddbf40b92 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp
@@ -126,13 +126,17 @@ bool ClassLoaderData::claim() {
// ClassLoaderData, no other non-GC thread has knowledge of the anonymous class while
// it is being defined, therefore _keep_alive is not volatile or atomic.
void ClassLoaderData::inc_keep_alive() {
- assert(_keep_alive >= 0, "Invalid keep alive count");
- _keep_alive++;
+ if (is_anonymous()) {
+ assert(_keep_alive >= 0, "Invalid keep alive increment count");
+ _keep_alive++;
+ }
}
void ClassLoaderData::dec_keep_alive() {
- assert(_keep_alive > 0, "Invalid keep alive count");
- _keep_alive--;
+ if (is_anonymous()) {
+ assert(_keep_alive > 0, "Invalid keep alive decrement count");
+ _keep_alive--;
+ }
}
void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
@@ -1173,7 +1177,7 @@ void ClassLoaderData::print_value_on(outputStream* out) const {
if (class_loader() == NULL) {
out->print("NULL class_loader");
} else {
- out->print("class loader " INTPTR_FORMAT, p2i(this));
+ out->print("class loader " INTPTR_FORMAT " ", p2i(this));
class_loader()->print_value_on(out);
}
}
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index 602097935cc..e1798d349ad 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -176,9 +176,9 @@ class ClassLoaderData : public CHeapObj {
Mutex* _metaspace_lock; // Locks the metaspace for allocations and setup.
bool _unloading; // true if this class loader goes away
bool _is_anonymous; // if this CLD is for an anonymous class
- int _keep_alive; // if this CLD is kept alive without a keep_alive_object().
- // Currently used solely for anonymous classes.
- // _keep_alive does not need to be volatile or
+ s2 _keep_alive; // if this CLD is kept alive without a keep_alive_object().
+ // Used for anonymous classes and the boot class
+ // loader. _keep_alive does not need to be volatile or
// atomic since there is one unique CLD per anonymous class.
volatile int _claimed; // true if claimed, for example during GC traces.
// To avoid applying oop closure more than once.
@@ -289,6 +289,8 @@ class ClassLoaderData : public CHeapObj {
return _unloading;
}
+ // Used to refcount an anonymous class's CLD in order to
+ // indicate their aliveness without a keep_alive_object().
void inc_keep_alive();
void dec_keep_alive();
diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp
index 8bcef277d2a..d33df4eda1b 100644
--- a/hotspot/src/share/vm/code/dependencies.cpp
+++ b/hotspot/src/share/vm/code/dependencies.cpp
@@ -1082,12 +1082,11 @@ class ClassHierarchyWalker {
if (!(m->is_public() || m->is_protected()))
// The override story is complex when packages get involved.
return true; // Must punt the assertion to true.
- Klass* k = ctxk;
- Method* lm = k->lookup_method(m->name(), m->signature());
- if (lm == NULL && k->is_instance_klass()) {
+ Method* lm = ctxk->lookup_method(m->name(), m->signature());
+ if (lm == NULL && ctxk->is_instance_klass()) {
// It might be an interface method
- lm = InstanceKlass::cast(k)->lookup_method_in_ordered_interfaces(m->name(),
- m->signature());
+ lm = InstanceKlass::cast(ctxk)->lookup_method_in_ordered_interfaces(m->name(),
+ m->signature());
}
if (lm == m)
// Method m is inherited into ctxk.
@@ -1101,11 +1100,19 @@ class ClassHierarchyWalker {
// Static methods don't override non-static so punt
return true;
}
- if ( !Dependencies::is_concrete_method(lm, k)
- && !Dependencies::is_concrete_method(m, ctxk)
- && lm->method_holder()->is_subtype_of(m->method_holder()))
- // Method m is overridden by lm, but both are non-concrete.
- return true;
+ if (!Dependencies::is_concrete_method(lm, ctxk) &&
+ !Dependencies::is_concrete_method(m, ctxk)) {
+ // They are both non-concrete
+ if (lm->method_holder()->is_subtype_of(m->method_holder())) {
+ // Method m is overridden by lm, but both are non-concrete.
+ return true;
+ }
+ if (lm->method_holder()->is_interface() && m->method_holder()->is_interface() &&
+ ctxk->is_subtype_of(m->method_holder()) && ctxk->is_subtype_of(lm->method_holder())) {
+ // Interface method defined in multiple super interfaces
+ return true;
+ }
+ }
}
ResourceMark rm;
tty->print_cr("Dependency method not found in the associated context:");
diff --git a/hotspot/src/share/vm/gc/g1/g1Analytics.cpp b/hotspot/src/share/vm/gc/g1/g1Analytics.cpp
index c43b4169e49..8214a4bfa55 100644
--- a/hotspot/src/share/vm/gc/g1/g1Analytics.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1Analytics.cpp
@@ -316,10 +316,14 @@ size_t G1Analytics::predict_pending_cards() const {
return get_new_size_prediction(_pending_cards_seq);
}
-double G1Analytics::last_known_gc_end_time_sec() const {
+double G1Analytics::oldest_known_gc_end_time_sec() const {
return _recent_prev_end_times_for_all_gcs_sec->oldest();
}
+double G1Analytics::last_known_gc_end_time_sec() const {
+ return _recent_prev_end_times_for_all_gcs_sec->last();
+}
+
void G1Analytics::update_recent_gc_times(double end_time_sec,
double pause_time_ms) {
_recent_gc_times_ms->add(pause_time_ms);
diff --git a/hotspot/src/share/vm/gc/g1/g1Analytics.hpp b/hotspot/src/share/vm/gc/g1/g1Analytics.hpp
index a22d0dd72bd..3f9a37a98e7 100644
--- a/hotspot/src/share/vm/gc/g1/g1Analytics.hpp
+++ b/hotspot/src/share/vm/gc/g1/g1Analytics.hpp
@@ -155,6 +155,7 @@ public:
void update_recent_gc_times(double end_time_sec, double elapsed_ms);
void compute_pause_time_ratio(double interval_ms, double pause_time_ms);
+ double oldest_known_gc_end_time_sec() const;
double last_known_gc_end_time_sec() const;
};
diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
index d84e1000763..a267098ed86 100644
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
@@ -28,6 +28,7 @@
#include "classfile/symbolTable.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
+#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/bufferingOopClosure.hpp"
#include "gc/g1/concurrentG1Refine.hpp"
#include "gc/g1/concurrentG1RefineThread.hpp"
@@ -2473,8 +2474,19 @@ size_t G1CollectedHeap::max_capacity() const {
}
jlong G1CollectedHeap::millis_since_last_gc() {
- // assert(false, "NYI");
- return 0;
+ jlong now = os::elapsed_counter() / NANOSECS_PER_MILLISEC;
+ const G1Analytics* analytics = _g1_policy->analytics();
+ double last = analytics->last_known_gc_end_time_sec();
+ jlong ret_val = now - (last * 1000);
+ if (ret_val < 0) {
+ // See the notes in GenCollectedHeap::millis_since_last_gc()
+ // for more information about the implementation.
+ log_warning(gc)("Detected clock going backwards. "
+ "Milliseconds since last GC would be " JLONG_FORMAT
+ ". returning zero instead.", ret_val);
+ return 0;
+ }
+ return ret_val;
}
void G1CollectedHeap::prepare_for_verify() {
diff --git a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp
index 454f73bc0c6..dfef9538ba7 100644
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp
@@ -604,7 +604,7 @@ void G1DefaultPolicy::record_collection_pause_end(double pause_time_ms, size_t c
_analytics->report_alloc_rate_ms(alloc_rate_ms);
double interval_ms =
- (end_time_sec - _analytics->last_known_gc_end_time_sec()) * 1000.0;
+ (end_time_sec - _analytics->oldest_known_gc_end_time_sec()) * 1000.0;
_analytics->update_recent_gc_times(end_time_sec, pause_time_ms);
_analytics->compute_pause_time_ratio(interval_ms, pause_time_ms);
}
diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
index 049b675bd51..c1a28350047 100644
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp
@@ -1256,21 +1256,21 @@ class GenTimeOfLastGCClosure: public GenCollectedHeap::GenClosure {
};
jlong GenCollectedHeap::millis_since_last_gc() {
- // We need a monotonically non-decreasing time in ms but
- // os::javaTimeMillis() does not guarantee monotonicity.
+ // javaTimeNanos() is guaranteed to be monotonically non-decreasing
+ // provided the underlying platform provides such a time source
+ // (and it is bug free). So we still have to guard against getting
+ // back a time later than 'now'.
jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
GenTimeOfLastGCClosure tolgc_cl(now);
// iterate over generations getting the oldest
// time that a generation was collected
generation_iterate(&tolgc_cl, false);
- // javaTimeNanos() is guaranteed to be monotonically non-decreasing
- // provided the underlying platform provides such a time source
- // (and it is bug free). So we still have to guard against getting
- // back a time later than 'now'.
jlong retVal = now - tolgc_cl.time();
if (retVal < 0) {
- NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);)
+ log_warning(gc)("Detected clock going backwards. "
+ "Milliseconds since last GC would be " JLONG_FORMAT
+ ". returning zero instead.", retVal);
return 0;
}
return retVal;
diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
index 36837cda7f4..edc47626853 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
@@ -461,31 +461,26 @@ C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv *, jobject, jobject base, jl
return JNIHandles::make_local(THREAD, result);
}
-C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject base, jlong offset))
+C2V_VMENTRY(jobject, getConstantPool, (JNIEnv *, jobject, jobject object_handle))
constantPoolHandle cp;
- oop base_object = JNIHandles::resolve(base);
- jlong base_address = 0;
- if (base_object != NULL) {
- if (base_object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
- base_address = HotSpotResolvedJavaMethodImpl::metaspaceMethod(base_object);
- } else if (base_object->is_a(SystemDictionary::HotSpotConstantPool_klass())) {
- base_address = HotSpotConstantPool::metaspaceConstantPool(base_object);
- } else if (base_object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
- base_address = (jlong) CompilerToVM::asKlass(base_object);
- } else {
- THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
- err_msg("Unexpected type: %s", base_object->klass()->external_name()));
- }
+ oop object = JNIHandles::resolve(object_handle);
+ if (object == NULL) {
+ THROW_0(vmSymbols::java_lang_NullPointerException());
}
- cp = *((ConstantPool**) (intptr_t) (base_address + offset));
- if (!cp.is_null()) {
- JavaValue method_result(T_OBJECT);
- JavaCallArguments args;
- args.push_long((jlong) (address) cp());
- JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
- return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
+ if (object->is_a(SystemDictionary::HotSpotResolvedJavaMethodImpl_klass())) {
+ cp = CompilerToVM::asMethod(object)->constMethod()->constants();
+ } else if (object->is_a(SystemDictionary::HotSpotResolvedObjectTypeImpl_klass())) {
+ cp = InstanceKlass::cast(CompilerToVM::asKlass(object))->constants();
+ } else {
+ THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+ err_msg("Unexpected type: %s", object->klass()->external_name()));
}
- return NULL;
+ assert(!cp.is_null(), "npe");
+ JavaValue method_result(T_OBJECT);
+ JavaCallArguments args;
+ args.push_long((jlong) (address) cp());
+ JavaCalls::call_static(&method_result, SystemDictionary::HotSpotConstantPool_klass(), vmSymbols::fromMetaspace_name(), vmSymbols::constantPool_fromMetaspace_signature(), &args, CHECK_NULL);
+ return JNIHandles::make_local(THREAD, (oop)method_result.get_jobject());
}
C2V_VMENTRY(jobject, getResolvedJavaType, (JNIEnv *, jobject, jobject base, jlong offset, jboolean compressed))
@@ -1522,7 +1517,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getMaxCallTargetOffset", CC "(J)J", FN_PTR(getMaxCallTargetOffset)},
{CC "getResolvedJavaMethodAtSlot", CC "(" CLASS "I)" HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethodAtSlot)},
{CC "getResolvedJavaMethod", CC "(Ljava/lang/Object;J)" HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethod)},
- {CC "getConstantPool", CC "(Ljava/lang/Object;J)" HS_CONSTANT_POOL, FN_PTR(getConstantPool)},
+ {CC "getConstantPool", CC "(Ljava/lang/Object;)" HS_CONSTANT_POOL, FN_PTR(getConstantPool)},
{CC "getResolvedJavaType", CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS, FN_PTR(getResolvedJavaType)},
{CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)},
{CC "installCode", CC "(" TARGET_DESCRIPTION HS_COMPILED_CODE INSTALLED_CODE HS_SPECULATION_LOG ")I", FN_PTR(installCode)},
diff --git a/hotspot/src/share/vm/logging/logTagSet.hpp b/hotspot/src/share/vm/logging/logTagSet.hpp
index 0b238b32b52..a40ed5175bc 100644
--- a/hotspot/src/share/vm/logging/logTagSet.hpp
+++ b/hotspot/src/share/vm/logging/logTagSet.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/hotspot/src/share/vm/oops/methodCounters.hpp b/hotspot/src/share/vm/oops/methodCounters.hpp
index 2a06ab6eb2e..351cbff76b9 100644
--- a/hotspot/src/share/vm/oops/methodCounters.hpp
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/hotspot/src/share/vm/opto/arraycopynode.cpp b/hotspot/src/share/vm/opto/arraycopynode.cpp
index 08334b22597..f73f09165fb 100644
--- a/hotspot/src/share/vm/opto/arraycopynode.cpp
+++ b/hotspot/src/share/vm/opto/arraycopynode.cpp
@@ -630,6 +630,12 @@ bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase) {
}
bool ArrayCopyNode::may_modify_helper(const TypeOopPtr *t_oop, Node* n, PhaseTransform *phase, ArrayCopyNode*& ac) {
+ if (n->Opcode() == Op_StoreCM ||
+ n->Opcode() == Op_StoreB) {
+ // Ignore card mark stores
+ n = n->in(MemNode::Memory);
+ }
+
if (n->is_Proj()) {
n = n->in(0);
if (n->is_Call() && n->as_Call()->may_modify(t_oop, phase)) {
@@ -657,9 +663,6 @@ bool ArrayCopyNode::may_modify(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTra
}
}
}
- } else if (n->Opcode() == Op_StoreCM) {
- // Ignore card mark stores
- return may_modify_helper(t_oop, n->in(MemNode::Memory), phase, ac);
}
}
diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp
index 594ffd2e70a..47606b6a599 100644
--- a/hotspot/src/share/vm/opto/cfgnode.cpp
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp
@@ -1703,29 +1703,51 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
if (uncasted) {
- // Add a cast node between the phi to be removed and its unique input.
+ // Add cast nodes between the phi to be removed and its unique input.
// Wait until after parsing for the type information to propagate from the casts.
assert(can_reshape, "Invalid during parsing");
const Type* phi_type = bottom_type();
assert(phi_type->isa_int() || phi_type->isa_ptr(), "bad phi type");
- int opcode;
- // Determine the type of cast to be added.
+ // Add casts to carry the control dependency of the Phi that is
+ // going away
+ Node* cast = NULL;
if (phi_type->isa_int()) {
- opcode = Op_CastII;
+ cast = ConstraintCastNode::make_cast(Op_CastII, r, uin, phi_type, true);
} else {
const Type* uin_type = phase->type(uin);
- if ((phi_type->join(TypePtr::NOTNULL) == uin_type->join(TypePtr::NOTNULL)) ||
- (!phi_type->isa_oopptr() && !uin_type->isa_oopptr())) {
- opcode = Op_CastPP;
+ if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) {
+ cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, true);
} else {
- opcode = Op_CheckCastPP;
+ // Use a CastPP for a cast to not null and a CheckCastPP for
+ // a cast to a new klass (and both if both null-ness and
+ // klass change).
+
+ // If the type of phi is not null but the type of uin may be
+ // null, uin's type must be casted to not null
+ if (phi_type->join(TypePtr::NOTNULL) == phi_type->remove_speculative() &&
+ uin_type->join(TypePtr::NOTNULL) != uin_type->remove_speculative()) {
+ cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, TypePtr::NOTNULL, true);
+ }
+
+ // If the type of phi and uin, both casted to not null,
+ // differ the klass of uin must be (check)cast'ed to match
+ // that of phi
+ if (phi_type->join_speculative(TypePtr::NOTNULL) != uin_type->join_speculative(TypePtr::NOTNULL)) {
+ Node* n = uin;
+ if (cast != NULL) {
+ cast = phase->transform(cast);
+ n = cast;
+ }
+ cast = ConstraintCastNode::make_cast(Op_CheckCastPP, r, n, phi_type, true);
+ }
+ if (cast == NULL) {
+ cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, true);
+ }
}
}
- // Add a cast to carry the control dependency of the Phi that is
- // going away
- Node* cast = ConstraintCastNode::make_cast(opcode, r, uin, phi_type, true);
+ assert(cast != NULL, "cast should be set");
cast = phase->transform(cast);
- // set all inputs to the new cast so the Phi is removed by Identity
+ // set all inputs to the new cast(s) so the Phi is removed by Identity
PhaseIterGVN* igvn = phase->is_IterGVN();
for (uint i = 1; i < req(); i++) {
set_req_X(i, cast, igvn);
diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp
index e129fbafc41..d7721ec5f55 100644
--- a/hotspot/src/share/vm/prims/unsafe.cpp
+++ b/hotspot/src/share/vm/prims/unsafe.cpp
@@ -861,6 +861,13 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
}
const Klass* host_klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(host_class));
+
+ // Make sure it's the real host class, not another anonymous class.
+ while (host_klass != NULL && host_klass->is_instance_klass() &&
+ InstanceKlass::cast(host_klass)->is_anonymous()) {
+ host_klass = InstanceKlass::cast(host_klass)->host_klass();
+ }
+
// Primitive types have NULL Klass* fields in their java.lang.Class instances.
if (host_klass == NULL) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp
index 6a6389da9ff..6228453f6cc 100644
--- a/hotspot/src/share/vm/prims/whitebox.cpp
+++ b/hotspot/src/share/vm/prims/whitebox.cpp
@@ -679,7 +679,7 @@ WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobje
WB_END
WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject method, jobject compilation_context, jint compLevel))
- if (compLevel < CompLevel_none || compLevel > CompLevel_highest_tier) {
+ if (compLevel < CompLevel_none || compLevel > MIN2((CompLevel) TieredStopAtLevel, CompLevel_highest_tier)) {
return false; // Intrinsic is not available on a non-existent compilation level.
}
jmethodID method_id, compilation_context_id;
@@ -689,6 +689,7 @@ WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject metho
DirectiveSet* directive;
AbstractCompiler* comp = CompileBroker::compiler((int)compLevel);
+ assert(comp != NULL, "compiler not available");
if (compilation_context != NULL) {
compilation_context_id = reflected_method_to_jmid(thread, env, compilation_context);
CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
@@ -698,7 +699,7 @@ WB_ENTRY(jboolean, WB_IsIntrinsicAvailable(JNIEnv* env, jobject o, jobject metho
// Calling with NULL matches default directive
directive = DirectivesStack::getDefaultDirective(comp);
}
- bool result = CompileBroker::compiler(compLevel)->is_intrinsic_available(mh, directive);
+ bool result = comp->is_intrinsic_available(mh, directive);
DirectivesStack::release(directive);
return result;
WB_END
diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
index fc1ea544cce..9b8e3e6a394 100644
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
@@ -55,7 +55,8 @@ void AdvancedThresholdPolicy::initialize() {
// Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n
int log_cpu = log2_intptr(os::active_processor_count());
int loglog_cpu = log2_intptr(MAX2(log_cpu, 1));
- count = MAX2(log_cpu * loglog_cpu, 1) * 3 / 2;
+ count = MAX2(log_cpu * loglog_cpu * 3 / 2, 2);
+ FLAG_SET_ERGO(intx, CICompilerCount, count);
}
#else
// On 32-bit systems, the number of compiler threads is limited to 3.
@@ -67,12 +68,18 @@ void AdvancedThresholdPolicy::initialize() {
/// available to the VM and thus cause the VM to crash.
if (FLAG_IS_DEFAULT(CICompilerCount)) {
count = 3;
+ FLAG_SET_ERGO(intx, CICompilerCount, count);
}
#endif
- set_c1_count(MAX2(count / 3, 1));
- set_c2_count(MAX2(count - c1_count(), 1));
- FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count());
+ if (TieredStopAtLevel < CompLevel_full_optimization) {
+ // No C2 compiler thread required
+ set_c1_count(count);
+ } else {
+ set_c1_count(MAX2(count / 3, 1));
+ set_c2_count(MAX2(count - c1_count(), 1));
+ }
+ assert(count == c1_count() + c2_count(), "inconsistent compiler thread count");
// Some inlining tuning
#ifdef X86
diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp
index 82f5ead336d..129a08850db 100644
--- a/hotspot/src/share/vm/runtime/frame.cpp
+++ b/hotspot/src/share/vm/runtime/frame.cpp
@@ -225,6 +225,19 @@ JavaCallWrapper* frame::entry_frame_call_wrapper_if_safe(JavaThread* thread) con
return NULL;
}
+bool frame::is_entry_frame_valid(JavaThread* thread) const {
+ // Validate the JavaCallWrapper an entry frame must have
+ address jcw = (address)entry_frame_call_wrapper();
+ bool jcw_safe = (jcw < thread->stack_base()) && (jcw > (address)fp()); // less than stack base
+ if (!jcw_safe) {
+ return false;
+ }
+
+ // Validate sp saved in the java frame anchor
+ JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor();
+ return (jfa->last_Java_sp() > sp());
+}
+
bool frame::should_be_deoptimized() const {
if (_deopt_state == is_deoptimized ||
!is_compiled_frame() ) return false;
diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp
index d3974d713b2..1a122da60c5 100644
--- a/hotspot/src/share/vm/runtime/frame.hpp
+++ b/hotspot/src/share/vm/runtime/frame.hpp
@@ -166,6 +166,8 @@ class frame VALUE_OBJ_CLASS_SPEC {
frame sender_for_interpreter_frame(RegisterMap* map) const;
frame sender_for_native_frame(RegisterMap* map) const;
+ bool is_entry_frame_valid(JavaThread* thread) const;
+
// All frames:
// A low-level interface for vframes:
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 930c51acc17..89314669efd 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -2411,7 +2411,7 @@ public:
product(intx, CICompilerCount, CI_COMPILER_COUNT, \
"Number of compiler threads to run") \
range(0, max_jint) \
- constraint(CICompilerCountConstraintFunc, AtParse) \
+ constraint(CICompilerCountConstraintFunc, AfterErgo) \
\
product(intx, CompilationPolicyChoice, 0, \
"which compilation policy (0-3)") \
diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp
index 867c831a165..7b2753e516f 100644
--- a/hotspot/src/share/vm/runtime/reflection.cpp
+++ b/hotspot/src/share/vm/runtime/reflection.cpp
@@ -660,11 +660,13 @@ bool Reflection::verify_field_access(const Klass* current_class,
}
const Klass* host_class = current_class;
- while (host_class->is_instance_klass() &&
- InstanceKlass::cast(host_class)->is_anonymous()) {
- const Klass* next_host_class = InstanceKlass::cast(host_class)->host_klass();
- if (next_host_class == NULL) break;
- host_class = next_host_class;
+ if (host_class->is_instance_klass() &&
+ InstanceKlass::cast(host_class)->is_anonymous()) {
+ host_class = InstanceKlass::cast(host_class)->host_klass();
+ assert(host_class != NULL, "Anonymous class has null host class");
+ assert(!(host_class->is_instance_klass() &&
+ InstanceKlass::cast(host_class)->is_anonymous()),
+ "host_class should not be anonymous");
}
if (host_class == field_class) {
return true;
diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
index e38c69279a9..4f532121fc8 100644
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
@@ -147,12 +147,18 @@ void SimpleThresholdPolicy::initialize() {
// performed on 32-bit systems because it can lead to exhaustion
// of the virtual memory address space available to the JVM.
if (CICompilerCountPerCPU) {
- count = MAX2(log2_intptr(os::active_processor_count()), 1) * 3 / 2;
+ count = MAX2(log2_intptr(os::active_processor_count()) * 3 / 2, 2);
+ FLAG_SET_ERGO(intx, CICompilerCount, count);
}
#endif
- set_c1_count(MAX2(count / 3, 1));
- set_c2_count(MAX2(count - c1_count(), 1));
- FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count());
+ if (TieredStopAtLevel < CompLevel_full_optimization) {
+ // No C2 compiler thread required
+ set_c1_count(count);
+ } else {
+ set_c1_count(MAX2(count / 3, 1));
+ set_c2_count(MAX2(count - c1_count(), 1));
+ }
+ assert(count == c1_count() + c2_count(), "inconsistent compiler thread count");
}
void SimpleThresholdPolicy::set_carry_if_necessary(InvocationCounter *counter) {
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
index 26c7e870d07..c87de622492 100644
--- a/hotspot/src/share/vm/runtime/thread.cpp
+++ b/hotspot/src/share/vm/runtime/thread.cpp
@@ -374,11 +374,14 @@ Thread::~Thread() {
delete handle_area();
delete metadata_handles();
+ // SR_handler uses this as a termination indicator -
+ // needs to happen before os::free_thread()
+ delete _SR_lock;
+ _SR_lock = NULL;
+
// osthread() can be NULL, if creation of thread failed.
if (osthread() != NULL) os::free_thread(osthread());
- delete _SR_lock;
-
// clear Thread::current if thread is deleting itself.
// Needed to ensure JNI correctly detects non-attached threads.
if (this == Thread::current()) {
diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp
index a0687534eb3..34b48c3cf80 100644
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp
@@ -2643,7 +2643,7 @@ typedef CompactHashtable SymbolCompactHashTable;
/* DEFAULT_CACHE_LINE_SIZE (globalDefinitions.hpp) */ \
/***************************************************/ \
\
- declare_constant(DEFAULT_CACHE_LINE_SIZE) \
+ declare_preprocessor_constant("DEFAULT_CACHE_LINE_SIZE", DEFAULT_CACHE_LINE_SIZE) \
\
declare_constant(Deoptimization::Unpack_deopt) \
declare_constant(Deoptimization::Unpack_exception) \
diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.cpp b/hotspot/src/share/vm/utilities/nativeCallStack.cpp
index 940b3c8840e..b606f9e9c00 100644
--- a/hotspot/src/share/vm/utilities/nativeCallStack.cpp
+++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,6 +33,19 @@ NativeCallStack::NativeCallStack(int toSkip, bool fillStack) :
_hash_value(0) {
if (fillStack) {
+ // We need to skip the NativeCallStack::NativeCallStack frame if a tail call is NOT used
+ // to call os::get_native_stack. A tail call is used if _NMT_NOINLINE_ is not defined
+ // (which means this is not a slowdebug build), and we are on 64-bit (except Windows).
+ // This is not necessarily a rule, but what has been obvserved to date.
+#define TAIL_CALL (!defined(_NMT_NOINLINE_) && !defined(WINDOWS) && defined(_LP64))
+#if !TAIL_CALL
+ toSkip++;
+#if (defined(_NMT_NOINLINE_) && defined(BSD) && defined(_LP64))
+ // Mac OS X slowdebug builds have this odd behavior where NativeCallStack::NativeCallStack
+ // appears as two frames, so we need to skip an extra frame.
+ toSkip++;
+#endif
+#endif
os::get_native_stack(_stack, NMT_TrackingStackDepth, toSkip);
} else {
for (int index = 0; index < NMT_TrackingStackDepth; index ++) {
diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile
index 2f2f810f37b..07f12c40801 100644
--- a/hotspot/test/Makefile
+++ b/hotspot/test/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -226,6 +226,9 @@ BUNDLE_UP_AND_EXIT = \
( \
jtregExitCode=$$? && \
_summary="$(SUMMARY_TXT)"; \
+ if [ $${jtregExitCode} = 1 ] ; then \
+ jtregExitCode=0; \
+ fi; \
$(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \
$(ECHO) "$${jtregExitCode}" > $(EXITCODE); \
if [ -r "$${_summary}" ] ; then \
diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups
index e1bdec26de5..c87769b91e1 100644
--- a/hotspot/test/TEST.groups
+++ b/hotspot/test/TEST.groups
@@ -167,7 +167,7 @@ needs_compact3 = \
gc/survivorAlignment \
runtime/InternalApi/ThreadCpuTimesDeadlock.java \
runtime/NMT/JcmdSummaryDiff.java \
- runtime/RedefineTests/RedefineAnnotations.java
+ runtime/RedefineTests/RedefineAnnotations.java \
serviceability/sa/jmap-hashcode/Test8028623.java \
serviceability/threads/TestFalseDeadLock.java \
compiler/codecache/jmx \
@@ -282,7 +282,7 @@ hotspot_fast_compiler_1 = \
-compiler/c2/Test6905845.java \
-compiler/c2/cr6340864 \
-compiler/c2/cr6589834 \
- -compiler/c2/cr8004867
+ -compiler/c2/cr8004867 \
-compiler/c2/stemmer \
-compiler/c2/Test6792161.java \
-compiler/c2/Test6603011.java \
diff --git a/hotspot/test/compiler/arguments/CheckCICompilerCount.java b/hotspot/test/compiler/arguments/CheckCICompilerCount.java
index 1c361cfdf42..14bbdaa3dc5 100644
--- a/hotspot/test/compiler/arguments/CheckCICompilerCount.java
+++ b/hotspot/test/compiler/arguments/CheckCICompilerCount.java
@@ -23,8 +23,7 @@
/*
* @test CheckCheckCICompilerCount
- * @bug 8130858
- * @bug 8132525
+ * @bug 8130858 8132525 8162881
* @summary Check that correct range of values for CICompilerCount are allowed depending on whether tiered is enabled or not
* @library /testlibrary /
* @modules java.base/jdk.internal.misc
@@ -53,6 +52,13 @@ public class CheckCICompilerCount {
"-XX:CICompilerCount=1",
"-version"
},
+ {
+ "-server",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-XX:-TieredCompilation",
+ "-version"
+ },
{
"-client",
"-XX:-TieredCompilation",
@@ -66,30 +72,31 @@ public class CheckCICompilerCount {
"-XX:+PrintFlagsFinal",
"-XX:CICompilerCount=1",
"-version"
+ },
+ {
+ "-client",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-XX:-TieredCompilation",
+ "-version"
}
};
- private static final String[][] NON_TIERED_EXPECTED_OUTPUTS = {
- {
+ private static final String[] NON_TIERED_EXPECTED_OUTPUTS = {
"CICompilerCount (0) must be at least 1",
- "Improperly specified VM option 'CICompilerCount=0'"
- },
- {
- "intx CICompilerCount = 1 {product} {command line}"
- },
- {
+ "intx CICompilerCount = 1 {product} {command line}",
+ "intx CICompilerCount = 1 {product} {command line}",
"CICompilerCount (0) must be at least 1",
- "Improperly specified VM option 'CICompilerCount=0'"
- },
- {
+ "intx CICompilerCount = 1 {product} {command line}",
"intx CICompilerCount = 1 {product} {command line}"
- }
};
private static final int[] NON_TIERED_EXIT = {
1,
0,
+ 0,
1,
+ 0,
0
};
@@ -101,6 +108,22 @@ public class CheckCICompilerCount {
"-XX:CICompilerCount=1",
"-version"
},
+ {
+ "-server",
+ "-XX:+TieredCompilation",
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-version"
+ },
+ {
+ "-server",
+ "-XX:+TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-XX:TieredStopAtLevel=1",
+ "-version"
+ },
{
"-server",
"-XX:+TieredCompilation",
@@ -115,6 +138,22 @@ public class CheckCICompilerCount {
"-XX:CICompilerCount=1",
"-version"
},
+ {
+ "-client",
+ "-XX:+TieredCompilation",
+ "-XX:TieredStopAtLevel=1",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-version"
+ },
+ {
+ "-client",
+ "-XX:+TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CICompilerCount=1",
+ "-XX:TieredStopAtLevel=1",
+ "-version"
+ },
{
"-client",
"-XX:+TieredCompilation",
@@ -124,31 +163,29 @@ public class CheckCICompilerCount {
}
};
- private static final String[][] TIERED_EXPECTED_OUTPUTS = {
- {
+ private static final String[] TIERED_EXPECTED_OUTPUTS = {
"CICompilerCount (1) must be at least 2",
- "Improperly specified VM option 'CICompilerCount=1'"
- },
- {
- "intx CICompilerCount = 2 {product} {command line, ergonomic}"
- },
- {
+ "intx CICompilerCount = 1 {product} {command line}",
+ "intx CICompilerCount = 1 {product} {command line}",
+ "intx CICompilerCount = 2 {product} {command line}",
"CICompilerCount (1) must be at least 2",
- "Improperly specified VM option 'CICompilerCount=1'"
- },
- {
- "intx CICompilerCount = 2 {product} {command line, ergonomic}"
- }
+ "intx CICompilerCount = 1 {product} {command line}",
+ "intx CICompilerCount = 1 {product} {command line}",
+ "intx CICompilerCount = 2 {product} {command line}",
};
private static final int[] TIERED_EXIT = {
1,
0,
+ 0,
+ 0,
1,
+ 0,
+ 0,
0
};
- private static void verifyValidOption(String[] arguments, String[] expected_outputs, int exit, boolean tiered) throws Exception {
+ private static void verifyValidOption(String[] arguments, String expected_output, int exit, boolean tiered) throws Exception {
ProcessBuilder pb;
OutputAnalyzer out;
@@ -157,9 +194,7 @@ public class CheckCICompilerCount {
try {
out.shouldHaveExitValue(exit);
- for (String expected_output : expected_outputs) {
- out.shouldContain(expected_output);
- }
+ out.shouldContain(expected_output);
} catch (RuntimeException e) {
// Check if tiered compilation is available in this JVM
// Version. Throw exception only if it is available.
diff --git a/hotspot/test/compiler/arraycopy/TestEliminatedArrayCopyDeopt.java b/hotspot/test/compiler/arraycopy/TestEliminatedArrayCopyDeopt.java
index 80f81c64c9d..85be6c5d428 100644
--- a/hotspot/test/compiler/arraycopy/TestEliminatedArrayCopyDeopt.java
+++ b/hotspot/test/compiler/arraycopy/TestEliminatedArrayCopyDeopt.java
@@ -25,7 +25,6 @@
* @test
* @bug 8130847 8156760
* @summary Eliminated instance/array written to by an array copy variant must be correctly initialized when reallocated at a deopt
- * @ignore 8136818
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
* compiler.arraycopy.TestEliminatedArrayCopyDeopt
* @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement
diff --git a/hotspot/test/compiler/c2/Test6792161.java b/hotspot/test/compiler/c2/Test6792161.java
index fa4aaddcdfd..c2b22412681 100644
--- a/hotspot/test/compiler/c2/Test6792161.java
+++ b/hotspot/test/compiler/c2/Test6792161.java
@@ -27,7 +27,7 @@
* @bug 6792161
* @summary assert("No dead instructions after post-alloc")
*
- * @run main/othervm/timeout=600 -Xcomp -XX:MaxInlineSize=120 compiler.c2.Test6792161
+ * @run main/othervm/timeout=600 -Xcomp -XX:-TieredCompilation -XX:MaxInlineSize=120 compiler.c2.Test6792161
*/
package compiler.c2;
diff --git a/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java b/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java
index ea17ba28bdb..e96dc4713d9 100644
--- a/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java
+++ b/hotspot/test/compiler/codecache/jmx/InitialAndMaxUsageTest.java
@@ -36,6 +36,11 @@
* -XX:CompileCommand=compileonly,null::* -XX:-UseLargePages
* -XX:+SegmentedCodeCache
* compiler.codecache.jmx.InitialAndMaxUsageTest
+ * @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
+ * -XX:-MethodFlushing -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:CompileCommand=compileonly,null::* -XX:-UseLargePages
+ * -XX:-SegmentedCodeCache
+ * compiler.codecache.jmx.InitialAndMaxUsageTest
*/
package compiler.codecache.jmx;
@@ -70,10 +75,16 @@ public class InitialAndMaxUsageTest {
}
}
- private void fillWithSize(long size, List blobs) {
+ private void fillWithSize(long size, List blobs, MemoryPoolMXBean bean) {
long blob;
- while ((blob = CodeCacheUtils.WB.allocateCodeBlob(size, btype.id))
- != 0L) {
+ /* Don't fill too much to have space for adapters. So, stop after crossing 95% and
+ don't allocate in case we'll cross 97% on next allocation. We can hit situation
+ like 94% -> (1 allocation) -> 100% otherwise. So, check if
+ is less than 97%, then allocate in case it is, then, stop
+ further allocations with given size in case more than 95% */
+ while (((double) bean.getUsage().getUsed() + size <= (CACHE_USAGE_COEF + 0.02d) * maxSize)
+ && (blob = CodeCacheUtils.WB.allocateCodeBlob(size, btype.id)) != 0L
+ && ((double) bean.getUsage().getUsed() <= CACHE_USAGE_COEF * maxSize)) {
blobs.add(blob);
}
}
@@ -90,13 +101,13 @@ public class InitialAndMaxUsageTest {
Asserts.assertEQ(initialUsage, 0L, "Unexpected initial usage");
}
ArrayList blobs = new ArrayList<>();
- long minAllocationUnit = Math.max(0, CodeCacheUtils.MIN_ALLOCATION - headerSize);
+ long minAllocationUnit = Math.max(1, CodeCacheUtils.MIN_ALLOCATION - headerSize);
/* now filling code cache with large-sized allocation first, since
lots of small allocations takes too much time, so, just a small
optimization */
try {
for (int coef = 1000000; coef > 0; coef /= 10) {
- fillWithSize(coef * minAllocationUnit, blobs);
+ fillWithSize(coef * minAllocationUnit, blobs, bean);
}
Asserts.assertGT((double) bean.getUsage().getUsed(),
CACHE_USAGE_COEF * maxSize, String.format("Unable to fill "
diff --git a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java
index 86b22cd5fec..e173fc8a6c7 100644
--- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java
+++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java
@@ -31,11 +31,11 @@
* @build compiler.codecache.jmx.ThresholdNotificationsTest
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:+WhiteBoxAPI -XX:-MethodFlushing -XX:CompileCommand=compileonly,null::*
* -XX:+SegmentedCodeCache
* compiler.codecache.jmx.ThresholdNotificationsTest
- * @run main/othervm -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -Xbootclasspath/a:. -XX:-UseCodeCacheFlushing
* -XX:+WhiteBoxAPI -XX:-MethodFlushing -XX:CompileCommand=compileonly,null::*
* -XX:-SegmentedCodeCache
* compiler.codecache.jmx.ThresholdNotificationsTest
@@ -63,7 +63,9 @@ public class ThresholdNotificationsTest implements NotificationListener {
public static void main(String[] args) {
for (BlobType bt : BlobType.getAvailable()) {
- new ThresholdNotificationsTest(bt).runTest();
+ if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+ new ThresholdNotificationsTest(bt).runTest();
+ }
}
}
diff --git a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java
index baa2ebe351b..154a096a277 100644
--- a/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdExceededTest.java
@@ -63,7 +63,9 @@ public class UsageThresholdExceededTest {
public static void main(String[] args) {
int iterationsCount = Integer.getInteger("jdk.test.lib.iterations", 1);
for (BlobType btype : BlobType.getAvailable()) {
- new UsageThresholdExceededTest(btype, iterationsCount).runTest();
+ if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
+ new UsageThresholdExceededTest(btype, iterationsCount).runTest();
+ }
}
}
diff --git a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java
index 2f628229cf1..f432f8a1e70 100644
--- a/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java
+++ b/hotspot/test/compiler/codecache/jmx/UsageThresholdIncreasedTest.java
@@ -29,9 +29,9 @@
* @modules java.base/jdk.internal.misc
* java.management
*
+ * @build compiler.codecache.jmx.UsageThresholdIncreasedTest
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @build compiler.codecache.jmx.UsageThresholdIncreasedTest
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -XX:-MethodFlushing
* -XX:CompileCommand=compileonly,null::*
diff --git a/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java b/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java
index f1b8fd26890..761cbfd4842 100644
--- a/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java
+++ b/hotspot/test/compiler/codecache/stress/RandomAllocationTest.java
@@ -24,6 +24,7 @@
/*
* @test RandomAllocationTest
+ * @key stress
* @summary stressing code cache by allocating randomly sized "dummy" code blobs
* @library /testlibrary /test/lib /
* @modules java.base/jdk.internal.misc
diff --git a/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java b/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java
index c6e455d4986..4cd43a154e7 100644
--- a/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java
+++ b/hotspot/test/compiler/codecache/stress/UnexpectedDeoptimizationTest.java
@@ -24,6 +24,7 @@
/*
* @test UnexpectedDeoptimizationTest
+ * @key stress
* @summary stressing code cache by forcing unexpected deoptimizations
* @library /testlibrary /test/lib /
* @modules java.base/jdk.internal.misc
diff --git a/hotspot/test/compiler/codegen/aes/TestAESMain.java b/hotspot/test/compiler/codegen/aes/TestAESMain.java
index 679cd880e53..36353ca45f3 100644
--- a/hotspot/test/compiler/codegen/aes/TestAESMain.java
+++ b/hotspot/test/compiler/codegen/aes/TestAESMain.java
@@ -25,6 +25,7 @@
/**
* @test
* @bug 7184394
+ * @key stress
* @summary add intrinsics to use AES instructions
* @library /testlibrary /
* @modules java.base/jdk.internal.misc
diff --git a/hotspot/test/compiler/floatingpoint/ModNaN.java b/hotspot/test/compiler/floatingpoint/ModNaN.java
index a1bdcdcdd61..30bc0285781 100644
--- a/hotspot/test/compiler/floatingpoint/ModNaN.java
+++ b/hotspot/test/compiler/floatingpoint/ModNaN.java
@@ -26,7 +26,6 @@
* @bug 8015396
* @summary double a%b returns NaN for some (a,b) (|a| < inf, |b|>0) (on Core i7 980X)
*
- * @ignore 8145543
* @run main compiler.floatingpoint.ModNaN
*/
diff --git a/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java
index dd55d5496c9..ddc5bd04f8a 100644
--- a/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java
+++ b/hotspot/test/compiler/intrinsics/IntrinsicAvailableTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* 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,7 +114,7 @@ public class IntrinsicAvailableTest extends CompilerWhiteBoxTest {
public void test() throws Exception {
Executable intrinsicMethod = testCase.getExecutable();
- if (Platform.isServer()) {
+ if (Platform.isServer() && (TIERED_STOP_AT_LEVEL == COMP_LEVEL_FULL_OPTIMIZATION)) {
if (TIERED_COMPILATION) {
checkIntrinsicForCompilationLevel(intrinsicMethod, COMP_LEVEL_SIMPLE);
}
diff --git a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
index 7cbe3cb6088..53cf827602f 100644
--- a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
+++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
@@ -59,9 +59,9 @@ public class IntrinsicDisabledTest {
private static final int COMP_LEVEL_FULL_OPTIMIZATION = 4;
/* Determine if tiered compilation is enabled. */
- private static boolean isTieredCompilationEnabled() {
- return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation")));
- }
+ private static final boolean TIERED_COMPILATION = wb.getBooleanVMFlag("TieredCompilation");
+
+ private static final int TIERED_STOP_AT_LEVEL = wb.getIntxVMFlag("TieredStopAtLevel").intValue();
/* This test uses several methods from jdk.internal.misc.Unsafe. The method
* getMethod() returns a different Executable for each different
@@ -202,8 +202,8 @@ public class IntrinsicDisabledTest {
}
public static void main(String args[]) {
- if (Platform.isServer()) {
- if (isTieredCompilationEnabled()) {
+ if (Platform.isServer() && (TIERED_STOP_AT_LEVEL == COMP_LEVEL_FULL_OPTIMIZATION)) {
+ if (TIERED_COMPILATION) {
test(COMP_LEVEL_SIMPLE);
}
test(COMP_LEVEL_FULL_OPTIMIZATION);
diff --git a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
index f2b40928602..2985ed89a94 100644
--- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
+++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
@@ -273,8 +273,8 @@ public class CompilerToVMHelper {
return CTVM.getResolvedJavaMethod(base, displacement);
}
- public static HotSpotConstantPool getConstantPool(Object base, long displacement) {
- return CTVM.getConstantPool(base, displacement);
+ public static HotSpotConstantPool getConstantPool(Object object) {
+ return CTVM.getConstantPool(object);
}
public static HotSpotResolvedObjectType getResolvedJavaType(Object base,
diff --git a/hotspot/test/compiler/jvmci/common/testcases/DuplicateSimpleSingleImplementerInterface.java b/hotspot/test/compiler/jvmci/common/testcases/DuplicateSimpleSingleImplementerInterface.java
new file mode 100644
index 00000000000..03f18e92a70
--- /dev/null
+++ b/hotspot/test/compiler/jvmci/common/testcases/DuplicateSimpleSingleImplementerInterface.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface DuplicateSimpleSingleImplementerInterface {
+ void interfaceMethod();
+}
diff --git a/hotspot/test/compiler/jvmci/common/testcases/MultipleSuperImplementers.java b/hotspot/test/compiler/jvmci/common/testcases/MultipleSuperImplementers.java
new file mode 100644
index 00000000000..d7f297e6101
--- /dev/null
+++ b/hotspot/test/compiler/jvmci/common/testcases/MultipleSuperImplementers.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public abstract class MultipleSuperImplementers implements DuplicateSimpleSingleImplementerInterface, SimpleSingleImplementerInterface {
+ public void finalize() {
+ }
+}
diff --git a/hotspot/test/compiler/jvmci/common/testcases/SimpleSingleImplementerInterface.java b/hotspot/test/compiler/jvmci/common/testcases/SimpleSingleImplementerInterface.java
new file mode 100644
index 00000000000..4f03bbb761c
--- /dev/null
+++ b/hotspot/test/compiler/jvmci/common/testcases/SimpleSingleImplementerInterface.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package compiler.jvmci.common.testcases;
+
+public interface SimpleSingleImplementerInterface {
+ void interfaceMethod();
+}
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java
index 3c818d9f2d5..5eccc6d1164 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java
@@ -32,6 +32,8 @@
* java.base/jdk.internal.org.objectweb.asm.tree
* jdk.vm.ci/jdk.vm.ci.hotspot
* jdk.vm.ci/jdk.vm.ci.code
+ * jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.runtime
* @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
* @build compiler.jvmci.compilerToVM.FindUniqueConcreteMethodTest
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
@@ -41,7 +43,10 @@
package compiler.jvmci.compilerToVM;
import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.DuplicateSimpleSingleImplementerInterface;
+import compiler.jvmci.common.testcases.SimpleSingleImplementerInterface;
import compiler.jvmci.common.testcases.MultipleImplementer1;
+import compiler.jvmci.common.testcases.MultipleSuperImplementers;
import compiler.jvmci.common.testcases.SingleImplementer;
import compiler.jvmci.common.testcases.SingleImplementerInterface;
import compiler.jvmci.common.testcases.SingleSubclass;
@@ -96,6 +101,11 @@ public class FindUniqueConcreteMethodTest {
// static method
result.add(new TestCase(false, SingleSubclass.class,
SingleSubclass.class, "staticMethod"));
+ // interface method
+ result.add(new TestCase(false, MultipleSuperImplementers.class,
+ DuplicateSimpleSingleImplementerInterface.class, "interfaceMethod", false));
+ result.add(new TestCase(false, MultipleSuperImplementers.class,
+ SimpleSingleImplementerInterface.class, "interfaceMethod", false));
return result;
}
@@ -103,7 +113,7 @@ public class FindUniqueConcreteMethodTest {
System.out.println(tcase);
Method method = tcase.holder.getDeclaredMethod(tcase.methodName);
HotSpotResolvedJavaMethod testMethod = CTVMUtilities
- .getResolvedMethod(tcase.receiver, method);
+ .getResolvedMethod(tcase.methodFromReceiver ? tcase.receiver : tcase.holder, method);
HotSpotResolvedObjectType resolvedType = CompilerToVMHelper
.lookupType(Utils.toJVMTypeSignature(tcase.receiver), getClass(),
/* resolve = */ true);
@@ -118,20 +128,25 @@ public class FindUniqueConcreteMethodTest {
public final Class> holder;
public final String methodName;
public final boolean isPositive;
+ public final boolean methodFromReceiver;
public TestCase(boolean isPositive, Class> clazz, Class> holder,
- String methodName) {
+ String methodName, boolean methodFromReceiver) {
this.receiver = clazz;
this.methodName = methodName;
this.isPositive = isPositive;
this.holder = holder;
+ this.methodFromReceiver = methodFromReceiver;
+ }
+
+ public TestCase(boolean isPositive, Class> clazz, Class> holder, String methodName) {
+ this(isPositive, clazz, holder, methodName, true);
}
@Override
public String toString() {
- return String.format("CASE: receiver=%s, holder=%s, method=%s,"
- + " isPositive=%s", receiver.getName(),
- holder.getName(), methodName, isPositive);
+ return String.format("CASE: receiver=%s, holder=%s, method=%s, isPositive=%s, methodFromReceiver=%s",
+ receiver.getName(), holder.getName(), methodName, isPositive, methodFromReceiver);
}
}
}
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
index ceb35fe6378..097d42e5235 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java
@@ -29,187 +29,76 @@
* @library /testlibrary /test/lib /
* @library ../common/patches
* @modules java.base/jdk.internal.misc
- * @modules jdk.vm.ci/jdk.vm.ci.hotspot
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ java.base/jdk.internal.org.objectweb.asm.tree
+ jdk.vm.ci/jdk.vm.ci.hotspot
* jdk.vm.ci/jdk.vm.ci.meta
+ * jdk.vm.ci/jdk.vm.ci.code
*
* @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
- * @build jdk.vm.ci/jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject
* @build compiler.jvmci.compilerToVM.GetConstantPoolTest
- * @build sun.hotspot.WhiteBox
- * @run driver ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:.
- * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
+ * -XX:+UnlockDiagnosticVMOptions
* -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
* compiler.jvmci.compilerToVM.GetConstantPoolTest
*/
package compiler.jvmci.compilerToVM;
-import jdk.internal.misc.Unsafe;
import jdk.test.lib.Utils;
+import compiler.jvmci.common.CTVMUtilities;
+import compiler.jvmci.common.testcases.TestCase;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
import jdk.vm.ci.meta.ConstantPool;
-import sun.hotspot.WhiteBox;
import java.lang.reflect.Field;
+import java.lang.reflect.Executable;
/**
* Tests for jdk.vm.ci.hotspot.CompilerToVM::getConstantPool method
*/
public class GetConstantPoolTest {
- private static enum TestCase {
- NULL_BASE {
- @Override
- ConstantPool getConstantPool() {
- return CompilerToVMHelper.getConstantPool(null,
- getPtrToCpAddress());
- }
- },
- JAVA_METHOD_BASE {
- @Override
- ConstantPool getConstantPool() {
- HotSpotResolvedJavaMethod methodInstance
- = CompilerToVMHelper.getResolvedJavaMethodAtSlot(
- TEST_CLASS, 0);
- Field field;
- try {
- // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod
- field = methodInstance.getClass()
- .getDeclaredField("metaspaceMethod");
- field.setAccessible(true);
- field.set(methodInstance, getPtrToCpAddress());
- } catch (ReflectiveOperationException e) {
- throw new Error("TESTBUG : " + e, e);
- }
- return CompilerToVMHelper.getConstantPool(methodInstance, 0L);
- }
- },
- CONSTANT_POOL_BASE {
- @Override
- ConstantPool getConstantPool() {
- ConstantPool cpInst;
- try {
- cpInst = CompilerToVMHelper.getConstantPool(null,
- getPtrToCpAddress());
- Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
- .getDeclaredField("metaspaceConstantPool");
- field.setAccessible(true);
- field.set(cpInst, getPtrToCpAddress());
- } catch (ReflectiveOperationException e) {
- throw new Error("TESTBUG : " + e.getMessage(), e);
- }
- return CompilerToVMHelper.getConstantPool(cpInst, 0L);
- }
- },
- CONSTANT_POOL_BASE_IN_TWO {
- @Override
- ConstantPool getConstantPool() {
- long ptr = getPtrToCpAddress();
- ConstantPool cpInst;
- try {
- cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
- Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
- .getDeclaredField("metaspaceConstantPool");
- field.setAccessible(true);
- field.set(cpInst, ptr / 2L);
- } catch (ReflectiveOperationException e) {
- throw new Error("TESTBUG : " + e.getMessage(), e);
- }
- return CompilerToVMHelper.getConstantPool(cpInst,
- ptr - ptr / 2L);
- }
- },
- CONSTANT_POOL_BASE_ZERO {
- @Override
- ConstantPool getConstantPool() {
- long ptr = getPtrToCpAddress();
- ConstantPool cpInst;
- try {
- cpInst = CompilerToVMHelper.getConstantPool(null, ptr);
- Field field = CompilerToVMHelper.HotSpotConstantPoolClass()
- .getDeclaredField("metaspaceConstantPool");
- field.setAccessible(true);
- field.set(cpInst, 0L);
- } catch (ReflectiveOperationException e) {
- throw new Error("TESTBUG : " + e.getMessage(), e);
- }
- return CompilerToVMHelper.getConstantPool(cpInst, ptr);
- }
- },
- ;
- abstract ConstantPool getConstantPool();
+ public static void testMethod(Executable executable) {
+ test(CTVMUtilities.getResolvedMethod(executable));
}
- private static final WhiteBox WB = WhiteBox.getWhiteBox();
- private static final Unsafe UNSAFE = Utils.getUnsafe();
+ public static void testClass(Class cls) {
+ HotSpotResolvedObjectType type = CompilerToVMHelper
+ .lookupType(Utils.toJVMTypeSignature(cls),
+ GetConstantPoolTest.class, /* resolve = */ true);
+ test(type);
+ }
- private static final Class TEST_CLASS = GetConstantPoolTest.class;
- private static final long CP_ADDRESS
- = WB.getConstantPool(GetConstantPoolTest.class);
-
- public void test(TestCase testCase) {
- System.out.println(testCase.name());
- ConstantPool cp = testCase.getConstantPool();
- String cpStringRep = cp.toString();
- String cpClassSimpleName
- = CompilerToVMHelper.HotSpotConstantPoolClass().getSimpleName();
- if (!cpStringRep.contains(cpClassSimpleName)
- || !cpStringRep.contains(TEST_CLASS.getName())) {
- String msg = String.format("%s : "
- + " Constant pool is not valid."
- + " String representation should contain \"%s\" and \"%s\"",
- testCase.name(), cpClassSimpleName,
- TEST_CLASS.getName());
- throw new AssertionError(msg);
- }
+ private static void test(Object object) {
+ ConstantPool cp = CompilerToVMHelper.getConstantPool(object);
+ System.out.println(object + " -> " + cp);
}
public static void main(String[] args) {
- GetConstantPoolTest test = new GetConstantPoolTest();
- for (TestCase testCase : TestCase.values()) {
- test.test(testCase);
- }
- testObjectBase();
- testMetaspaceWrapperBase();
+ TestCase.getAllClasses().forEach(GetConstantPoolTest::testClass);
+ TestCase.getAllExecutables().forEach(GetConstantPoolTest::testMethod);
+ testNull();
+ testObject();
}
- private static void testObjectBase() {
+ private static void testNull() {
try {
- Object cp = CompilerToVMHelper.getConstantPool(new Object(), 0L);
- throw new AssertionError("Test OBJECT_BASE."
+ Object cp = CompilerToVMHelper.getConstantPool(null);
+ throw new AssertionError("Test OBJECT."
+ + " Expected IllegalArgumentException has not been caught");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+ private static void testObject() {
+ try {
+ Object cp = CompilerToVMHelper.getConstantPool(new Object());
+ throw new AssertionError("Test OBJECT."
+ " Expected IllegalArgumentException has not been caught");
} catch (IllegalArgumentException iae) {
// expected
}
}
- private static void testMetaspaceWrapperBase() {
- try {
- Object cp = CompilerToVMHelper.getConstantPool(
- new PublicMetaspaceWrapperObject() {
- @Override
- public long getMetaspacePointer() {
- return getPtrToCpAddress();
- }
- }, 0L);
- throw new AssertionError("Test METASPACE_WRAPPER_BASE."
- + " Expected IllegalArgumentException has not been caught");
- } catch (IllegalArgumentException iae) {
- // expected
- }
- }
-
- private static long getPtrToCpAddress() {
- Field field;
- try {
- field = TEST_CLASS.getDeclaredField("CP_ADDRESS");
- } catch (NoSuchFieldException nsfe) {
- throw new Error("TESTBUG : cannot find field \"CP_ADDRESS\" : "
- + nsfe.getMessage(), nsfe);
- }
- Object base = UNSAFE.staticFieldBase(field);
- return WB.getObjectAddress(base) + UNSAFE.staticFieldOffset(field);
- }
}
diff --git a/hotspot/test/compiler/runtime/cr8015436/Driver8015436.java b/hotspot/test/compiler/runtime/cr8015436/Driver8015436.java
new file mode 100644
index 00000000000..79c4eb8971a
--- /dev/null
+++ b/hotspot/test/compiler/runtime/cr8015436/Driver8015436.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+package compiler.runtime.cr8015436;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class Driver8015436 {
+ public static void main(String args[]) {
+ OutputAnalyzer oa;
+ try {
+ oa = ProcessTools.executeProcess(ProcessTools.createJavaProcessBuilder(
+ /* add test vm options */ true, Test8015436.class.getName()));
+ } catch (Exception ex) {
+ throw new Error("TESTBUG: exception while running child process: " + ex, ex);
+ }
+ oa.shouldHaveExitValue(0);
+ oa.shouldContain(Test8015436.SOME_MTD_INVOKED);
+ oa.shouldContain(Test8015436.DEFAULT_MTD_INVOKED_DIRECTLY);
+ oa.shouldContain(Test8015436.DEFAULT_MTD_INVOKED_MH);
+ }
+}
diff --git a/hotspot/test/compiler/runtime/cr8015436/Test8015436.java b/hotspot/test/compiler/runtime/cr8015436/Test8015436.java
index 8c70624f32a..256f352b87e 100644
--- a/hotspot/test/compiler/runtime/cr8015436/Test8015436.java
+++ b/hotspot/test/compiler/runtime/cr8015436/Test8015436.java
@@ -25,8 +25,12 @@
* @test
* @bug 8015436
* @summary the IK _initial_method_idnum value must be adjusted if overpass methods are added
+ * @library /test/lib/share/classes /
+ * @modules java.base/jdk.internal.misc
+ * @build compiler.runtime.cr8015436.Test8015436
+ * compiler.runtime.cr8015436.Driver8015436
*
- * @run main compiler.runtime.cr8015436.Test8015436
+ * @run driver compiler.runtime.cr8015436.Driver8015436
*/
/*
@@ -45,20 +49,24 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
public class Test8015436 implements InterfaceWithDefaultMethod {
+ public static final String SOME_MTD_INVOKED = "someMethod() invoked";
+ public static final String DEFAULT_MTD_INVOKED_DIRECTLY = "defaultMethod() invoked directly";
+ public static final String DEFAULT_MTD_INVOKED_MH = "defaultMethod() invoked via a MethodHandle";
+
@Override
public void someMethod() {
- System.out.println("someMethod() invoked");
+ System.out.println(SOME_MTD_INVOKED);
}
public static void main(String[] args) throws Throwable {
Test8015436 testObj = new Test8015436();
testObj.someMethod();
- testObj.defaultMethod("invoked directly");
+ testObj.defaultMethod(DEFAULT_MTD_INVOKED_DIRECTLY);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType mt = MethodType.methodType(void.class, String.class);
MethodHandle mh = lookup.findVirtual(Test8015436.class, "defaultMethod", mt);
- mh.invokeExact(testObj, "invoked via a MethodHandle");
+ mh.invokeExact(testObj, DEFAULT_MTD_INVOKED_MH);
}
}
@@ -66,7 +74,7 @@ interface InterfaceWithDefaultMethod {
public void someMethod();
default public void defaultMethod(String str){
- System.out.println("defaultMethod() " + str);
+ System.out.println(str);
}
}
/*
diff --git a/hotspot/test/gc/g1/ihop/TestIHOPErgo.java b/hotspot/test/gc/g1/ihop/TestIHOPErgo.java
index f187d629842..d70c926e298 100644
--- a/hotspot/test/gc/g1/ihop/TestIHOPErgo.java
+++ b/hotspot/test/gc/g1/ihop/TestIHOPErgo.java
@@ -24,6 +24,7 @@
/*
* @test TestIHOPErgo
* @bug 8148397
+ * @key stress
* @summary Test checks that behavior of Adaptive and Static IHOP at concurrent cycle initiation
* @requires vm.gc.G1
* @requires !vm.flightRecorder
diff --git a/hotspot/test/runtime/NMT/CheckForProperDetailStackTrace.java b/hotspot/test/runtime/NMT/CheckForProperDetailStackTrace.java
new file mode 100644
index 00000000000..7936a9b7253
--- /dev/null
+++ b/hotspot/test/runtime/NMT/CheckForProperDetailStackTrace.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+ /*
+ * @test
+ * @key nmt
+ * @summary Running with NMT detail should produce expected stack traces.
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ */
+
+import jdk.test.lib.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CheckForProperDetailStackTrace {
+ /* The stack trace we look for by default. Note that :: has been replaced by .*
+ to make sure it maches even if the symbol is not unmangled. */
+ public static String stackTraceDefault =
+ ".*ModuleEntryTable.*new_entry.*\n" +
+ ".*ModuleEntryTable.*locked_create_entry_or_null.*\n" +
+ ".*Modules.*define_module.*\n" +
+ ".*JVM_DefineModule.*\n";
+
+ /* The stack trace we look for on Solaris and Windows slowdebug builds. For some
+ reason ALWAYSINLINE for AllocateHeap is ignored, so it appears in the stack strace. */
+ public static String stackTraceAllocateHeap =
+ ".*AllocateHeap.*\n" +
+ ".*ModuleEntryTable.*new_entry.*\n" +
+ ".*ModuleEntryTable.*locked_create_entry_or_null.*\n" +
+ ".*Modules.*define_module.*\n";
+
+ /* A symbol that should always be present in NMT detail output. */
+ private static String expectedSymbol =
+ "locked_create_entry_or_null";
+
+ private static final String jdkDebug = System.getProperty("jdk.debug");
+ private static boolean isSlowDebugBuild() {
+ return (jdkDebug.toLowerCase().equals("slowdebug"));
+ }
+
+ public static void main(String args[]) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:NativeMemoryTracking=detail",
+ "-XX:+PrintNMTStatistics",
+ "-version");
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+ output.shouldHaveExitValue(0);
+
+ // We should never see either of these frames because they are supposed to be skipped. */
+ output.shouldNotContain("NativeCallStack::NativeCallStack");
+ output.shouldNotContain("os::get_native_stack");
+
+ // AllocateHeap shouldn't be in the output because it is suppose to always be inlined.
+ // We check for that here, but allow it for Windows and Solaris slowdebug builds because
+ // the compiler ends up not inlining AllocateHeap.
+ Boolean okToHaveAllocateHeap =
+ isSlowDebugBuild() && (Platform.isSolaris() || Platform.isWindows());
+ if (!okToHaveAllocateHeap) {
+ output.shouldNotContain("AllocateHeap");
+ }
+
+ // See if we have any stack trace symbols in the output
+ boolean hasSymbols =
+ output.getStdout().contains(expectedSymbol) || output.getStderr().contains(expectedSymbol);
+ if (!hasSymbols) {
+ // It's ok for ARM not to have symbols, because it does not support NMT detail
+ // when targeting thumb2. It's also ok for Windows not to have symbols, because
+ // they are only available if the symbols file is included with the build.
+ if (Platform.isWindows() || Platform.isARM()) {
+ return; // we are done
+ }
+ output.reportDiagnosticSummary();
+ throw new RuntimeException("Expected symbol missing missing from output: " + expectedSymbol);
+ }
+
+ /* Make sure the expected NMT detail stack trace is found. */
+ String expectedStackTrace =
+ (okToHaveAllocateHeap ? stackTraceAllocateHeap : stackTraceDefault);
+ if (!stackTraceMatches(expectedStackTrace, output)) {
+ output.reportDiagnosticSummary();
+ throw new RuntimeException("Expected stack trace missing missing from output: " + expectedStackTrace);
+ }
+ }
+
+ public static boolean stackTraceMatches(String stackTrace, OutputAnalyzer output) {
+ Matcher stdoutMatcher = Pattern.compile(stackTrace, Pattern.MULTILINE).matcher(output.getStdout());
+ Matcher stderrMatcher = Pattern.compile(stackTrace, Pattern.MULTILINE).matcher(output.getStderr());
+ return (stdoutMatcher.find() || stderrMatcher.find());
+ }
+}
diff --git a/hotspot/test/runtime/StackGuardPages/exeinvoke.c b/hotspot/test/runtime/StackGuardPages/exeinvoke.c
index fa2a06e9869..da77e42ba7b 100644
--- a/hotspot/test/runtime/StackGuardPages/exeinvoke.c
+++ b/hotspot/test/runtime/StackGuardPages/exeinvoke.c
@@ -242,7 +242,7 @@ int main (int argc, const char** argv) {
CLASS_PATH_OPT, javaclasspath);
options[0].optionString = "-Xint";
- options[1].optionString = "-Xss328k";
+ options[1].optionString = "-Xss1M";
options[2].optionString = javaclasspathopt;
vm_args.version = JNI_VERSION_1_2;
diff --git a/hotspot/test/runtime/Unsafe/NestedUnsafe.java b/hotspot/test/runtime/Unsafe/NestedUnsafe.java
new file mode 100644
index 00000000000..f009d6dddd4
--- /dev/null
+++ b/hotspot/test/runtime/Unsafe/NestedUnsafe.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @summary Creates an anonymous class inside of an anonymous class.
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * java.management
+ * @run main NestedUnsafe
+ */
+
+import java.security.ProtectionDomain;
+import java.io.InputStream;
+import java.lang.*;
+import jdk.test.lib.*;
+import jdk.internal.misc.Unsafe;
+import static jdk.test.lib.Asserts.*;
+
+// package p;
+
+public class NestedUnsafe {
+ // The String concatenation should create the nested anonymous class.
+ static byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass",
+ "public class TestClass { " +
+ " public static void concat(String one, String two) throws Throwable { " +
+ " System.out.println(one + two);" +
+ " } } ");
+
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+
+ Class klass = unsafe.defineAnonymousClass(NestedUnsafe.class, klassbuf, new Object[0]);
+ unsafe.ensureClassInitialized(klass);
+ Class[] cArgs = new Class[2];
+ cArgs[0] = String.class;
+ cArgs[1] = String.class;
+ try {
+ klass.getMethod("concat", cArgs).invoke(null, "AA", "BB");
+ } catch (Throwable ex) {
+ throw new RuntimeException("Exception: " + ex.toString());
+ }
+
+ // The anonymous class calls defineAnonymousClass creating a nested anonymous class.
+ byte klassbuf2[] = InMemoryJavaCompiler.compile("TestClass2",
+ "import jdk.internal.misc.Unsafe; " +
+ "public class TestClass2 { " +
+ " public static void doit() throws Throwable { " +
+ " Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe(); " +
+ " Class klass2 = unsafe.defineAnonymousClass(TestClass2.class, NestedUnsafe.klassbuf, new Object[0]); " +
+ " unsafe.ensureClassInitialized(klass2); " +
+ " Class[] dArgs = new Class[2]; " +
+ " dArgs[0] = String.class; " +
+ " dArgs[1] = String.class; " +
+ " try { " +
+ " klass2.getMethod(\"concat\", dArgs).invoke(null, \"CC\", \"DD\"); " +
+ " } catch (Throwable ex) { " +
+ " throw new RuntimeException(\"Exception: \" + ex.toString()); " +
+ " } " +
+ "} } ",
+ "-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED");
+ Class klass2 = unsafe.defineAnonymousClass(NestedUnsafe.class, klassbuf2, new Object[0]);
+ try {
+ klass2.getMethod("doit").invoke(null);
+ } catch (Throwable ex) {
+ throw new RuntimeException("Exception: " + ex.toString());
+ }
+ }
+}
diff --git a/hotspot/test/serviceability/sa/sadebugd/SADebugDTest.java b/hotspot/test/serviceability/sa/sadebugd/SADebugDTest.java
new file mode 100644
index 00000000000..a9cf6e53119
--- /dev/null
+++ b/hotspot/test/serviceability/sa/sadebugd/SADebugDTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
+ * @summary Checks that the jshdb debugd utility sucessfully starts
+ * and tries to attach to a running process
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib/share/classes
+ *
+ * @ignore 8163805
+ * @run main/othervm SADebugDTest
+ */
+import java.io.File;
+import java.util.concurrent.CountDownLatch;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.Reader;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
+import static jdk.test.lib.Asserts.assertTrue;
+import static jdk.test.lib.Platform.shouldSAAttach;
+import static jdk.test.lib.process.ProcessTools.startProcess;
+
+public class SADebugDTest {
+
+ private static final String GOLDEN = "Attaching to process ID %d and starting RMI services, please wait...";
+
+ private static final String JAVA_HOME = (System.getProperty("test.jdk") != null)
+ ? System.getProperty("test.jdk") : System.getProperty("java.home");
+
+ private static final String JAVA_BIN_DIR
+ = JAVA_HOME + File.separator + "bin" + File.separator;
+
+ private static final String JHSDB = JAVA_BIN_DIR + "jhsdb";
+
+ public static void main(String[] args) throws Exception {
+
+ if (!shouldSAAttach()) {
+ log("Not possible to attach the SA. Skipping the test");
+ return;
+ }
+
+ long ourPid = ProcessHandle.current().getPid();
+
+ // The string we are expecting in the debugd ouput
+ String golden = String.format(GOLDEN, ourPid);
+
+ // We are going to run 'jhsdb debugd '
+ // The startProcess will block untl the 'golden' string appears in either process' stdout or stderr
+ // In case of timeout startProcess kills the debugd process
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(JHSDB, "debugd", String.valueOf(ourPid));
+ Process debugd = startProcess("debugd", pb, null, (line) -> line.trim().contains(golden), 0, TimeUnit.SECONDS);
+
+ // If we are here, this means we have received the golden line and the test has passed
+ // The debugd remains running, we have to kill it
+ debugd.destroy();
+
+ }
+
+ private static void log(String string) {
+ System.out.println(string);
+ }
+
+}
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index bfe5860fa48..380d39ea6ab 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -374,3 +374,4 @@ bdc3c0b737efbf899709eb3121ce760dcfb51151 jdk-9+127
74241304e87b0d463391a8ecab40979b5af86dc2 jdk-9+129
e66cdc2de6b02443911d386fc9217b0d824d0686 jdk-9+130
874082a9b565a7092a40bfa934a6e3e3c3455a60 jdk-9+131
+907445d85e680ea410fe2c83c0ec64b5508e4f3e jdk-9+132
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java
index 1a85fc3ba9b..5ef374f3fae 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources.java
@@ -17,9 +17,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: XSLTErrorResources.java,v 1.2.4.1 2005/09/13 09:55:37 pvedula Exp $
- */
package com.sun.org.apache.xalan.internal.res;
import java.util.ListResourceBundle;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java
index cf83580147f..52f944101dc 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java
@@ -17,9 +17,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: ErrorMessages.java,v 1.2.4.1 2005/09/15 09:59:41 pvedula Exp $
- */
package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java
index e1fd9e38df3..fe98ae968c0 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/ErrorMessages.java
@@ -17,9 +17,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: ErrorMessages.java,v 1.2.4.1 2005/09/14 05:06:42 pvedula Exp $
- */
package com.sun.org.apache.xalan.internal.xsltc.runtime;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AbortException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AbortException.java
new file mode 100644
index 00000000000..3e178dd8d71
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/AbortException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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.org.apache.xerces.internal.dom;
+
+public class AbortException extends RuntimeException {
+
+ private static final long serialVersionUID = 2608302175475740417L;
+
+ /**
+ * Constructor AbortException
+ */
+ public AbortException() { super(null, null, false, false); }
+}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java
index 1e4fc39be62..c2f33916772 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/dom/DOMNormalizer.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.io.StringReader;
import java.util.Vector;
+import com.sun.org.apache.xerces.internal.dom.AbortException;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar;
@@ -157,11 +158,6 @@ public class DOMNormalizer implements XMLDocumentHandler {
// attribute value normalization
final XMLString fNormalizedValue = new XMLString(new char[16], 0, 0);
- /**
- * If the user stops the process, this exception will be thrown.
- */
- public static final RuntimeException abort = new RuntimeException();
-
//DTD validator
private XMLDTDValidator fDTDValidator;
@@ -242,11 +238,8 @@ public class DOMNormalizer implements XMLDocumentHandler {
XMLGrammarDescription.XML_SCHEMA, fValidationHandler);
fValidationHandler = null;
}
- }
- catch (RuntimeException e) {
- if( e==abort )
- return; // processing aborted by the user
- throw e; // otherwise re-throw.
+ } catch (AbortException e) {
+ return;
}
}
@@ -1371,10 +1364,10 @@ public class DOMNormalizer implements XMLDocumentHandler {
error.fRelatedData = locator.fRelatedNode;
if(!errorHandler.handleError(error))
- throw abort;
+ throw new AbortException();
}
if( severity==DOMError.SEVERITY_FATAL_ERROR )
- throw abort;
+ throw new AbortException();
}
protected final void updateQName (Node node, QName qname){
@@ -2043,5 +2036,4 @@ public class DOMNormalizer implements XMLDocumentHandler {
return null;
}
-
} // DOMNormalizer class
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties
index 9d6841b5fb1..1bd94b8a314 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages.properties
@@ -2,8 +2,6 @@
# DOM implementation.
#
# The messages are arranged in key and value tuples in a ListResourceBundle.
-#
-# @version $Id: DOMMessages.properties,v 1.2 2005-08-16 22:51:51 jeffsuttor Exp $
BadMessageKey = The error message corresponding to the message key can not be found.
FormatFailed = An internal error occurred while formatting the following message:\n
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages.properties
index 0a601e178a3..72b20151706 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages.properties
@@ -1,8 +1,6 @@
# This file stores localized messages for the Xerces JAXP Datatype API implementation.
#
# The messages are arranged in key and value tuples in a ListResourceBundle.
-#
-# @version $Id: DatatypeMessages.properties 3021 2011-03-01 00:12:28Z joehw $
BadMessageKey = The error message corresponding to the message key can not be found.
FormatFailed = An internal error occurred while formatting the following message:\n
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages.properties
index bdc6c454b6c..60ae45af330 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages.properties
@@ -1,8 +1,6 @@
# This file stores localized messages for the Xerces JAXP Validation API implementation.
#
# The messages are arranged in key and value tuples in a ListResourceBundle.
-#
-# @version $Id: JAXPValidationMessages.properties 3021 2011-03-01 00:12:28Z joehw $
# Messages for message reporting
BadMessageKey = The error message corresponding to the message key can not be found.
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties
index 2373f367b9b..c0c1ad14cd8 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages.properties
@@ -2,8 +2,6 @@
# SAX implementation.
#
# The messages are arranged in key and value tuples in a ListResourceBundle.
-#
-# @version $Id: SAXMessages.properties 3021 2011-03-01 00:12:28Z joehw $
BadMessageKey = The error message corresponding to the message key can not be found.
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
index 0b09746f11d..423728021cf 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
@@ -1,7 +1,5 @@
# This file contains error and warning messages related to XML Schema
# The messages are arranged in key and value tuples in a ListResourceBundle.
-#
-# @version $Id: XMLSchemaMessages.properties 3021 2011-03-01 00:12:28Z joehw $
BadMessageKey = The error message corresponding to the message key can not be found.
FormatFailed = An internal error occurred while formatting the following message:\n
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages.properties
index caad2621a8d..2d81d83628b 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages.properties
@@ -4,8 +4,6 @@
#
# As usual with properties files, the messages are arranged in
# key/value tuples.
-#
-# @version $Id: XMLSerializerMessages.properties 3021 2011-03-01 00:12:28Z joehw $
BadMessageKey = The error message corresponding to the message key can not be found.
FormatFailed = An internal error occurred while formatting the following message:\n
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties
index 1ae480d2bc8..7fe755ebb99 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages.properties
@@ -1,8 +1,6 @@
# This file stores localized messages for the Xerces XPointer implementation.
#
# The messages are arranged in key and value tuples in a ListResourceBundle.
-#
-# @version $Id: XPointerMessages.properties 3021 2011-03-01 00:12:28Z joehw $
# Messages for message reporting
BadMessageKey = The error message corresponding to the message key can not be found.
@@ -24,4 +22,4 @@ InvalidElementSchemeToken = InvalidElementSchemeToken: The element() scheme XPoi
InvalidElementSchemeXPointer = InvalidElementSchemeXPointer: The Element Scheme XPointer expression ''{0}'' is invalid.
XPointerElementSchemeProcessingError = XPointerElementSchemeProcessingError: An error occurred while processing the XPointer element() Scheme expression.
InvalidNCNameInElementSchemeData = InvalidNCNameInElementSchemeData: The element() Scheme contains a ShortHand Pointer ''{0}'' with an invalid NCName.
-InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''.
\ No newline at end of file
+InvalidChildSequenceCharacter = InvalidChildSequenceCharacter: The element() Scheme contains an invalid child sequence character ''{0}''.
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources.java
index 8d1ab9b948d..1c83bc50917 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/res/XMLErrorResources.java
@@ -17,9 +17,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: XMLErrorResources.java,v 1.2.4.1 2005/09/15 07:45:37 suresh_emailid Exp $
- */
package com.sun.org.apache.xml.internal.res;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/DOMSerializerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/DOMSerializerImpl.java
index 926019e7290..6c2eaf15c53 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/DOMSerializerImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serialize/DOMSerializerImpl.java
@@ -28,6 +28,7 @@ import java.io.Writer;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import com.sun.org.apache.xerces.internal.dom.AbortException;
import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl;
import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
import com.sun.org.apache.xerces.internal.dom.DOMLocatorImpl;
@@ -501,11 +502,9 @@ public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
} catch (LSException lse) {
// Rethrow LSException.
throw lse;
+ } catch (AbortException e) {
+ return null;
} catch (RuntimeException e) {
- if (e == DOMNormalizer.abort) {
- // stopped at user request
- return null;
- }
throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
} catch (IOException ioe) {
// REVISIT: A generic IOException doesn't provide enough information
@@ -733,11 +732,9 @@ public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
} catch (LSException lse) {
// Rethrow LSException.
throw lse;
+ } catch (AbortException e) {
+ return false;
} catch (RuntimeException e) {
- if (e == DOMNormalizer.abort) {
- // stopped at user request
- return false;
- }
throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
} catch (Exception e) {
if (ser.fDOMErrorHandler != null) {
@@ -833,11 +830,9 @@ public class DOMSerializerImpl implements LSSerializer, DOMConfiguration {
} catch (LSException lse) {
// Rethrow LSException.
throw lse;
+ } catch (AbortException e) {
+ return false;
} catch (RuntimeException e) {
- if (e == DOMNormalizer.abort) {
- // stopped at user request
- return false;
- }
throw (LSException) DOMUtil.createLSException(LSException.SERIALIZE_ERR, e).fillInStackTrace();
} catch (Exception e) {
if (ser.fDOMErrorHandler != null) {
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages.java
index 60e6955ce1d..e7d50361d81 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/utils/SerializerMessages.java
@@ -19,9 +19,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: SerializerMessages.java,v 1.1.4.1 2005/09/08 11:03:11 suresh_emailid Exp $
- */
package com.sun.org.apache.xml.internal.serializer.utils;
import java.util.ListResourceBundle;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
index 9192e968b7f..38f72b729f7 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
@@ -28,6 +28,7 @@ package com.sun.org.apache.xpath.internal.jaxp;
import com.sun.org.apache.xalan.internal.res.XSLMessages;
import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
import com.sun.org.apache.xml.internal.dtm.DTM;
+import com.sun.org.apache.xpath.internal.axes.LocPathIterator;
import com.sun.org.apache.xpath.internal.objects.XObject;
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
import java.io.IOException;
@@ -73,6 +74,12 @@ class XPathImplUtil {
XObject eval(Object contextItem, com.sun.org.apache.xpath.internal.XPath xpath)
throws javax.xml.transform.TransformerException {
com.sun.org.apache.xpath.internal.XPathContext xpathSupport;
+ if (contextItem == null && xpath.getExpression() instanceof LocPathIterator) {
+ // the operation must have no dependency on the context that is null
+ throw new TransformerException(XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_CONTEXT_CAN_NOT_BE_NULL,
+ new Object[] {}));
+ }
if (functionResolver != null) {
JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
functionResolver, featureSecureProcessing, featureManager);
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
index 68b4853f3d9..0c084ecaf2d 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources.java
@@ -17,9 +17,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/*
- * $Id: XPATHErrorResources.java,v 1.2.4.1 2005/09/15 01:29:15 jeffsuttor Exp $
- */
package com.sun.org.apache.xpath.internal.res;
import java.util.ListResourceBundle;
@@ -93,6 +90,7 @@ public class XPATHErrorResources extends ListResourceBundle
public static final String ER_CURRENT_TAKES_NO_ARGS =
"ER_CURRENT_TAKES_NO_ARGS";
public static final String ER_DOCUMENT_REPLACED = "ER_DOCUMENT_REPLACED";
+ public static final String ER_CONTEXT_CAN_NOT_BE_NULL = "ER_CONTEXT_CAN_NOT_BE_NULL";
public static final String ER_CONTEXT_HAS_NO_OWNERDOC =
"ER_CONTEXT_HAS_NO_OWNERDOC";
public static final String ER_LOCALNAME_HAS_TOO_MANY_ARGS =
@@ -368,6 +366,9 @@ public static final String ER_IGNORABLE_WHITESPACE_NOT_HANDLED =
{ ER_DOCUMENT_REPLACED,
"document() function implementation has been replaced by com.sun.org.apache.xalan.internal.xslt.FuncDocument!"},
+ { ER_CONTEXT_CAN_NOT_BE_NULL,
+ "The context can not be null when the operation is context-dependent."},
+
{ ER_CONTEXT_HAS_NO_OWNERDOC,
"context does not have an owner document!"},
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java
index 92c89ea1274..d7c0a44bf95 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,18 +34,20 @@ import org.xml.sax.InputSource;
*
*
*
- *
- *
- *
Evaluation of XPath Expressions.
- *
- *
- *
- *
context
- *
- * If a request is made to evaluate the expression in the absence
- * of a context item, an empty document node will be used for the context.
- * For the purposes of evaluating XPath expressions, a DocumentFragment
- * is treated like a Document node.
+ *
+ *
+ *
Evaluation of XPath Expressions.
+ *
+ *
+ *
+ *
context
+ *
+ * The type of the context is implementation-dependent. If the value is
+ * null, the operation must have no dependency on the context, otherwise
+ * an XPathExpressionException will be thrown.
+ *
+ * For the purposes of evaluating XPath expressions, a DocumentFragment
+ * is treated like a Document node.
*
*
*
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java
index 1a60f13ca48..697745e92d5 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,19 +33,20 @@ import org.xml.sax.InputSource;
*
*
*
- *
- *
- *
Evaluation of XPath Expressions.
- *
- *
- *
- *
- *
context
- *
- * If a request is made to evaluate the expression in the absence
- * of a context item, an empty document node will be used for the context.
- * For the purposes of evaluating XPath expressions, a DocumentFragment
- * is treated like a Document node.
+ *
+ *
+ *
Evaluation of XPath Expressions.
+ *
+ *
+ *
+ *
context
+ *
+ * The type of the context is implementation-dependent. If the value is
+ * null, the operation must have no dependency on the context, otherwise
+ * an XPathExpressionException will be thrown.
+ *
+ * For the purposes of evaluating XPath expressions, a DocumentFragment
+ * is treated like a Document node.
*
*
*
diff --git a/jaxp/src/java.xml/share/classes/module-info.java b/jaxp/src/java.xml/share/classes/module-info.java
index ed48672adfc..40ca6421302 100644
--- a/jaxp/src/java.xml/share/classes/module-info.java
+++ b/jaxp/src/java.xml/share/classes/module-info.java
@@ -23,6 +23,10 @@
* questions.
*/
+/**
+ * Defines the Java API for XML Processing (JAXP), the Streaming API for XML (StAX),
+ * the Simple API for XML (SAX), and the W3C Document Object Model (DOM) API.
+ */
module java.xml {
exports javax.xml;
exports javax.xml.catalog;
diff --git a/jaxp/test/javax/xml/jaxp/unittest/xpath/XPathTest.java b/jaxp/test/javax/xml/jaxp/unittest/xpath/XPathTest.java
index a6c80541968..ea961181569 100644
--- a/jaxp/test/javax/xml/jaxp/unittest/xpath/XPathTest.java
+++ b/jaxp/test/javax/xml/jaxp/unittest/xpath/XPathTest.java
@@ -24,11 +24,17 @@
package xpath;
import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
-
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
/*
* @test
@@ -36,19 +42,105 @@ import org.testng.annotations.Test;
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true xpath.XPathTest
* @run testng/othervm xpath.XPathTest
- * @summary Test XPath.getNamespaceContext() is supported.
+ * @summary Test XPath functions. See details for each test.
*/
@Listeners({jaxp.library.BasePolicy.class})
public class XPathTest {
+ /*
+ @bug 6211561
+ * Verifies the specification for XPath and XPathExpression:
+ * If a null value is provided for item (the context),
+ * the expression must have no dependency on the context.
+ */
+ @Test(dataProvider = "noContextDependency")
+ public void testNoContextDependency1(String expression, Object item) throws XPathExpressionException {
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ xPath.evaluate(expression, item, XPathConstants.STRING);
+ }
+
+ @Test(dataProvider = "noContextDependency")
+ public void testNoContextDependency2(String expression, Object item) throws XPathExpressionException {
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ xPath.evaluateExpression(expression, item, String.class);
+ }
+
+ /*
+ @bug 6211561
+ * Verifies the specification for XPath and XPathExpression:
+ * If a null value is provided for item (the context) that the operation
+ * depends on, XPathExpressionException will be thrown
+ */
+ @Test(dataProvider = "hasContextDependency", expectedExceptions = XPathExpressionException.class)
+ public void testHasContextDependency1(String expression, Object item) throws XPathExpressionException {
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ xPath.evaluate(expression, item, XPathConstants.STRING);
+ }
+
+ @Test(dataProvider = "hasContextDependency", expectedExceptions = XPathExpressionException.class)
+ public void testHasContextDependency2(String expression, Object item) throws XPathExpressionException {
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ xPath.evaluateExpression(expression, item, String.class);
+ }
+
+ /*
+ @bug 6376058
+ Verifies that XPath.getNamespaceContext() is supported.
+ */
@Test
public void testNamespaceContext() {
-
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
-
NamespaceContext namespaceContext = xPath.getNamespaceContext();
+ }
+ /*
+ * DataProvider: the expression has no dependency on the context
+ */
+ @DataProvider(name = "noContextDependency")
+ public Object[][] getExpressionContext() throws Exception {
+ return new Object[][]{
+ {"1+1", (Node)null},
+ {"5 mod 2", (Node)null},
+ {"8 div 2", (Node)null},
+ {"/node", getEmptyDocument()}
+ };
+ }
+
+ /*
+ * DataProvider: the expression has dependency on the context, but the context
+ * is null.
+ */
+ @DataProvider(name = "hasContextDependency")
+ public Object[][] getExpressionContext1() throws Exception {
+ return new Object[][]{
+ {"/node", (Node)null},
+ {"//@lang", (Node)null},
+ {"bookstore//book", (Node)null},
+ {"/bookstore/book[last()]", (Node)null},
+ {"//title[@lang='en']", (Node)null},
+ {"/bookstore/book[price>9.99]", (Node)null},
+ {"/bookstore/book[price>8.99 and price<9.99]", (Node)null},
+ {"/bookstore/*", (Node)null},
+ {"//title[@*]", (Node)null},
+ {"//title | //price", (Node)null},
+ {"//book/title | //book/price", (Node)null},
+ {"/bookstore/book/title | //price", (Node)null},
+ {"child::book", (Node)null},
+ {"child::text()", (Node)null},
+ {"child::*/child::price", (Node)null}
+ };
+ }
+
+ /**
+ * Returns an empty {@link org.w3c.dom.Document}.
+ * @return a DOM Document, null in case of Exception
+ */
+ public Document getEmptyDocument() {
+ try {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ } catch (ParserConfigurationException e) {
+ return null;
+ }
}
}
-
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 0b957319e81..36eb74d3bb0 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -377,3 +377,4 @@ fe4e11bd2423635dc0f5f5cb9a64eb2f2cce7f4c jdk-9+128
46a02f57218e4a8c334dbccf656fb048f823f163 jdk-9+129
39c6293131d91aec7f2f5120395e070a937b8858 jdk-9+130
783e7e2c587f2c7e1b9998a46d90ec196ab2a195 jdk-9+131
+9fff2477a4cadf2a9618a76f1f4fe0f20bb5ff3b jdk-9+132
diff --git a/jaxws/src/java.activation/share/classes/module-info.java b/jaxws/src/java.activation/share/classes/module-info.java
index d6507874caa..dca632ee776 100644
--- a/jaxws/src/java.activation/share/classes/module-info.java
+++ b/jaxws/src/java.activation/share/classes/module-info.java
@@ -23,6 +23,9 @@
* questions.
*/
+/**
+ * Defines the JavaBeans Activation Framework (JAF) API.
+ */
module java.activation {
requires public java.datatransfer;
// dependence on java.beans.Beans to be eliminated
diff --git a/jaxws/src/java.annotations.common/share/classes/module-info.java b/jaxws/src/java.annotations.common/share/classes/module-info.java
index 0a3a8dd3c6e..fddb78c5efc 100644
--- a/jaxws/src/java.annotations.common/share/classes/module-info.java
+++ b/jaxws/src/java.annotations.common/share/classes/module-info.java
@@ -23,6 +23,10 @@
* questions.
*/
+/**
+ * Defines a subset of the Common Annotations API to support programs running
+ * on the Java SE Platform.
+ */
module java.annotations.common {
exports javax.annotation;
}
diff --git a/jaxws/src/java.xml.bind/share/classes/module-info.java b/jaxws/src/java.xml.bind/share/classes/module-info.java
index 7f7cde8190e..708945a98fc 100644
--- a/jaxws/src/java.xml.bind/share/classes/module-info.java
+++ b/jaxws/src/java.xml.bind/share/classes/module-info.java
@@ -23,6 +23,9 @@
* questions.
*/
+/**
+ * Defines the Java Architecture for XML Binding (JAXB) API.
+ */
module java.xml.bind {
requires public java.activation;
requires public java.xml;
diff --git a/jaxws/src/java.xml.ws/share/classes/module-info.java b/jaxws/src/java.xml.ws/share/classes/module-info.java
index 799e0f23395..cba0cdecb08 100644
--- a/jaxws/src/java.xml.ws/share/classes/module-info.java
+++ b/jaxws/src/java.xml.ws/share/classes/module-info.java
@@ -23,6 +23,10 @@
* questions.
*/
+/**
+ * Defines the Java API for XML-Based Web Services (JAX-WS), and
+ * the Web Services Metadata API.
+ */
module java.xml.ws {
requires public java.activation;
requires public java.xml;
diff --git a/jdk/.hgtags b/jdk/.hgtags
index d0c1a581878..4639f93e55b 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -375,3 +375,4 @@ c40c8739bcdc88892ff58ebee3fd8a3f287be94d jdk-9+123
6c827500e34587061af97ad6fef0e859280255c5 jdk-9+130
8c57f4c293bbc5609928308a6d91ba765760b5f9 jdk-9+131
d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132
+3cdae27c90b5e41afe75eab904fda19fac076330 jdk-9+133
diff --git a/jdk/make/launcher/Launcher-jdk.jdeps.gmk b/jdk/make/launcher/Launcher-jdk.jdeps.gmk
index 6cbcaf47163..4a69deede07 100644
--- a/jdk/make/launcher/Launcher-jdk.jdeps.gmk
+++ b/jdk/make/launcher/Launcher-jdk.jdeps.gmk
@@ -36,3 +36,9 @@ $(eval $(call SetupBuildLauncher, jdeps, \
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
-DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
))
+
+$(eval $(call SetupBuildLauncher, jdeprscan, \
+ MAIN_CLASS := com.sun.tools.jdeprscan.Main, \
+ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \
+ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
+))
diff --git a/jdk/src/java.base/macosx/classes/apple/security/AppleProvider.java b/jdk/src/java.base/macosx/classes/apple/security/AppleProvider.java
index 12dc2592a3b..3b712846d45 100644
--- a/jdk/src/java.base/macosx/classes/apple/security/AppleProvider.java
+++ b/jdk/src/java.base/macosx/classes/apple/security/AppleProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
package apple.security;
import java.security.*;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
/**
* The Apple Security Provider.
@@ -74,7 +75,7 @@ public final class AppleProvider extends Provider {
public AppleProvider() {
/* We are the Apple provider */
- super("Apple", 9.0d, info);
+ super("Apple", PROVIDER_VER, info);
final Provider p = this;
AccessController.doPrivileged(new PrivilegedAction() {
diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
index 592ec411407..106ee91392c 100644
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/CipherCore.java
@@ -986,8 +986,9 @@ final class CipherCore {
if (padding != null) {
int padStart = padding.unpad(outWithPadding, 0, outLen);
if (padStart < 0) {
- throw new BadPaddingException("Given final block not "
- + "properly padded");
+ throw new BadPaddingException("Given final block not " +
+ "properly padded. Such issues can arise if a bad key " +
+ "is used during decryption.");
}
outLen = padStart;
}
diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
index 87c3da39c8c..9d82ebb6ff2 100644
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBKDF2KeyImpl.java
@@ -108,6 +108,11 @@ final class PBKDF2KeyImpl implements javax.crypto.interfaces.PBEKey {
}
try {
this.prf = Mac.getInstance(prfAlgo);
+ // SunPKCS11 requires a non-empty PBE password
+ if (passwdBytes.length == 0 &&
+ this.prf.getProvider().getName().startsWith("SunPKCS11")) {
+ this.prf = Mac.getInstance(prfAlgo, SunJCE.getInstance());
+ }
} catch (NoSuchAlgorithmException nsae) {
// not gonna happen; re-throw just in case
InvalidKeySpecException ike = new InvalidKeySpecException();
diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
index e7ab016b5d9..e44a8476dc2 100644
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* 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,6 +28,7 @@ package com.sun.crypto.provider;
import java.security.AccessController;
import java.security.Provider;
import java.security.SecureRandom;
+import static sun.security.util.SecurityConstants.PROVIDER_VER;
/**
@@ -104,7 +105,7 @@ public final class SunJCE extends Provider {
public SunJCE() {
/* We are the "SunJCE" provider */
- super("SunJCE", 9.0d, info);
+ super("SunJCE", PROVIDER_VER, info);
final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" +
"|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" +
diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java
index 25d4a3b5b9f..8c9957274d6 100644
--- a/jdk/src/java.base/share/classes/java/lang/Class.java
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java
@@ -331,12 +331,6 @@ public final class Class implements java.io.Serializable,
* Note that this method does not check whether the requested class
* is accessible to its caller.
*
- *
If the {@code loader} is {@code null}, and a security
- * manager is present, and the caller's class loader is not null, then this
- * method calls the security manager's {@code checkPermission} method
- * with a {@code RuntimePermission("getClassLoader")} permission to
- * ensure it's ok to access the bootstrap class loader.
- *
* @param name fully qualified name of the desired class
* @param initialize if {@code true} the class will be initialized.
* See Section 12.4 of The Java Language Specification.
@@ -348,6 +342,11 @@ public final class Class implements java.io.Serializable,
* by this method fails
* @exception ClassNotFoundException if the class cannot be located by
* the specified class loader
+ * @exception SecurityException
+ * if a security manager is present, and the {@code loader} is
+ * {@code null}, and the caller's class loader is not
+ * {@code null}, and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @see java.lang.Class#forName(String)
* @see java.lang.ClassLoader
@@ -782,22 +781,17 @@ public final class Class implements java.io.Serializable,
* null in such implementations if this class was loaded by the bootstrap
* class loader.
*
- *
If a security manager is present, and the caller's class loader is
- * not null and the caller's class loader is not the same as or an ancestor of
- * the class loader for the class whose class loader is requested, then
- * this method calls the security manager's {@code checkPermission}
- * method with a {@code RuntimePermission("getClassLoader")}
- * permission to ensure it's ok to access the class loader for the class.
- *
*
If this object
* represents a primitive type or void, null is returned.
*
* @return the class loader that loaded the class or interface
* represented by this object.
- * @throws SecurityException
- * if a security manager exists and its
- * {@code checkPermission} method denies
- * access to the class loader for the class.
+ * @throws SecurityException
+ * if a security manager is present, and the caller's class loader
+ * is not {@code null} and is not the same as or an ancestor of the
+ * class loader for the class whose class loader is requested,
+ * and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
* @see java.lang.ClassLoader
* @see SecurityManager#checkPermission
* @see java.lang.RuntimePermission
diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
index 013912384d8..d8b2dee337d 100644
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java
@@ -1537,22 +1537,13 @@ public abstract class ClassLoader {
* will return null in such implementations if this class loader's
* parent is the bootstrap class loader.
*
- *
If a security manager is present, and the invoker's class loader is
- * not null and is not an ancestor of this class loader, then this
- * method invokes the security manager's {@link
- * SecurityManager#checkPermission(java.security.Permission)
- * checkPermission} method with a {@link
- * RuntimePermission#RuntimePermission(String)
- * RuntimePermission("getClassLoader")} permission to verify
- * access to the parent class loader is permitted. If not, a
- * SecurityException will be thrown.
- *
* @return The parent ClassLoader
*
* @throws SecurityException
- * If a security manager exists and its checkPermission
- * method doesn't allow access to this class loader's parent class
- * loader.
+ * If a security manager is present, and the caller's class loader
+ * is not {@code null} and is not an ancestor of this class loader,
+ * and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @since 1.2
*/
@@ -1590,12 +1581,11 @@ public abstract class ClassLoader {
* @return The platform {@code ClassLoader}.
*
* @throws SecurityException
- * If a security manager exists and the caller's class loader is
- * not {@code null} and the caller's class loader is not the same
+ * If a security manager is present, and the caller's class loader is
+ * not {@code null}, and the caller's class loader is not the same
* as or an ancestor of the platform class loader,
- * and the {@link SecurityManager#checkPermission(java.security.Permission)
- * checkPermission} method denies {@code RuntimePermission("getClassLoader")}
- * to access the platform class loader.
+ * and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @since 9
*/
@@ -1636,17 +1626,6 @@ public abstract class ClassLoader {
* If circular initialization of the system class loader is detected then
* an unspecified error or exception is thrown.
*
- *
If a security manager is present, and the invoker's class loader is
- * not null and the invoker's class loader is not the same as or
- * an ancestor of the system class loader, then this method invokes the
- * security manager's {@link
- * SecurityManager#checkPermission(java.security.Permission)
- * checkPermission} method with a {@link
- * RuntimePermission#RuntimePermission(String)
- * RuntimePermission("getClassLoader")} permission to verify
- * access to the system class loader. If not, a
- * SecurityException will be thrown.
- *
* @implNote The system property to override the system class loader is not
* examined until the VM is almost fully initialized. Code that executes
* this method during startup should take care not to cache the return
@@ -1656,8 +1635,10 @@ public abstract class ClassLoader {
* null if none
*
* @throws SecurityException
- * If a security manager exists and its checkPermission
- * method doesn't allow access to the system class loader.
+ * If a security manager is present, and the caller's class loader
+ * is not {@code null} and is not the same as or an ancestor of the
+ * system class loader, and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @throws IllegalStateException
* If invoked recursively during the construction of the class
diff --git a/jdk/src/java.base/share/classes/java/lang/Math.java b/jdk/src/java.base/share/classes/java/lang/Math.java
index 4261bd2c3f1..37a9d8573c5 100644
--- a/jdk/src/java.base/share/classes/java/lang/Math.java
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java
@@ -1370,8 +1370,13 @@ public final class Math {
* result is positive zero.
*
If the argument is infinite, the result is positive infinity.
*
If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression:
- *
{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code float} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value:
+ * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
@@ -1389,8 +1394,13 @@ public final class Math {
* is positive zero.
*
If the argument is infinite, the result is positive infinity.
*
If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression:
- *
{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code double} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value:
+ * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
diff --git a/jdk/src/java.base/share/classes/java/lang/StrictMath.java b/jdk/src/java.base/share/classes/java/lang/StrictMath.java
index 3ef67145d0c..1491a8478bc 100644
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java
@@ -1070,8 +1070,13 @@ public final class StrictMath {
* result is positive zero.
*
If the argument is infinite, the result is positive infinity.
*
If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression:
- *
{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code float} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value:
+ * {@code Float.intBitsToFloat(0x7fffffff & Float.floatToRawIntBits(a))}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
@@ -1089,8 +1094,13 @@ public final class StrictMath {
* is positive zero.
*
If the argument is infinite, the result is positive infinity.
*
If the argument is NaN, the result is NaN.
- * In other words, the result is the same as the value of the expression:
- *
{@code Double.longBitsToDouble((Double.doubleToLongBits(a)<<1)>>>1)}
+ *
+ * @apiNote As implied by the above, one valid implementation of
+ * this method is given by the expression below which computes a
+ * {@code double} with the same exponent and significand as the
+ * argument but with a guaranteed zero sign bit indicating a
+ * positive value:
+ * {@code Double.longBitsToDouble((Double.doubleToRawLongBits(a)<<1)>>>1)}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
diff --git a/jdk/src/java.base/share/classes/java/lang/Thread.java b/jdk/src/java.base/share/classes/java/lang/Thread.java
index 310ada1b470..4fac9eddf07 100644
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java
@@ -1507,28 +1507,25 @@ class Thread implements Runnable {
}
/**
- * Returns the context ClassLoader for this Thread. The context
- * ClassLoader is provided by the creator of the thread for use
+ * Returns the context {@code ClassLoader} for this thread. The context
+ * {@code ClassLoader} is provided by the creator of the thread for use
* by code running in this thread when loading classes and resources.
* If not {@linkplain #setContextClassLoader set}, the default is the
- * ClassLoader context of the parent Thread. The context ClassLoader of the
+ * {@code ClassLoader} context of the parent thread. The context
+ * {@code ClassLoader} of the
* primordial thread is typically set to the class loader used to load the
* application.
*
- *
If a security manager is present, and the invoker's class loader is not
- * {@code null} and is not the same as or an ancestor of the context class
- * loader, then this method invokes the security manager's {@link
- * SecurityManager#checkPermission(java.security.Permission) checkPermission}
- * method with a {@link RuntimePermission RuntimePermission}{@code
- * ("getClassLoader")} permission to verify that retrieval of the context
- * class loader is permitted.
*
- * @return the context ClassLoader for this Thread, or {@code null}
+ * @return the context {@code ClassLoader} for this thread, or {@code null}
* indicating the system class loader (or, failing that, the
* bootstrap class loader)
*
* @throws SecurityException
- * if the current thread cannot get the context ClassLoader
+ * if a security manager is present, and the caller's class loader
+ * is not {@code null} and is not the same as or an ancestor of the
+ * context class loader, and the caller does not have the
+ * {@link RuntimePermission}{@code ("getClassLoader")}
*
* @since 1.2
*/
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
index 174e914f805..ce1f938583f 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
@@ -492,7 +492,7 @@ class DirectMethodHandle extends MethodHandle {
}
// Caching machinery for field accessors:
- private static final byte
+ static final byte
AF_GETFIELD = 0,
AF_PUTFIELD = 1,
AF_GETSTATIC = 2,
@@ -502,7 +502,7 @@ class DirectMethodHandle extends MethodHandle {
AF_LIMIT = 6;
// Enumerate the different field kinds using Wrapper,
// with an extra case added for checked references.
- private static final int
+ static final int
FT_LAST_WRAPPER = Wrapper.COUNT-1,
FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
FT_CHECKED_REF = FT_LAST_WRAPPER+1,
@@ -515,7 +515,7 @@ class DirectMethodHandle extends MethodHandle {
@Stable
private static final LambdaForm[] ACCESSOR_FORMS
= new LambdaForm[afIndex(AF_LIMIT, false, 0)];
- private static int ftypeKind(Class> ftype) {
+ static int ftypeKind(Class> ftype) {
if (ftype.isPrimitive())
return Wrapper.forPrimitiveType(ftype).ordinal();
else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
@@ -566,7 +566,64 @@ class DirectMethodHandle extends MethodHandle {
private static final Wrapper[] ALL_WRAPPERS = Wrapper.values();
- private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
+ private static Kind getFieldKind(boolean isGetter, boolean isVolatile, Wrapper wrapper) {
+ if (isGetter) {
+ if (isVolatile) {
+ switch (wrapper) {
+ case BOOLEAN: return GET_BOOLEAN_VOLATILE;
+ case BYTE: return GET_BYTE_VOLATILE;
+ case SHORT: return GET_SHORT_VOLATILE;
+ case CHAR: return GET_CHAR_VOLATILE;
+ case INT: return GET_INT_VOLATILE;
+ case LONG: return GET_LONG_VOLATILE;
+ case FLOAT: return GET_FLOAT_VOLATILE;
+ case DOUBLE: return GET_DOUBLE_VOLATILE;
+ case OBJECT: return GET_OBJECT_VOLATILE;
+ }
+ } else {
+ switch (wrapper) {
+ case BOOLEAN: return GET_BOOLEAN;
+ case BYTE: return GET_BYTE;
+ case SHORT: return GET_SHORT;
+ case CHAR: return GET_CHAR;
+ case INT: return GET_INT;
+ case LONG: return GET_LONG;
+ case FLOAT: return GET_FLOAT;
+ case DOUBLE: return GET_DOUBLE;
+ case OBJECT: return GET_OBJECT;
+ }
+ }
+ } else {
+ if (isVolatile) {
+ switch (wrapper) {
+ case BOOLEAN: return PUT_BOOLEAN_VOLATILE;
+ case BYTE: return PUT_BYTE_VOLATILE;
+ case SHORT: return PUT_SHORT_VOLATILE;
+ case CHAR: return PUT_CHAR_VOLATILE;
+ case INT: return PUT_INT_VOLATILE;
+ case LONG: return PUT_LONG_VOLATILE;
+ case FLOAT: return PUT_FLOAT_VOLATILE;
+ case DOUBLE: return PUT_DOUBLE_VOLATILE;
+ case OBJECT: return PUT_OBJECT_VOLATILE;
+ }
+ } else {
+ switch (wrapper) {
+ case BOOLEAN: return PUT_BOOLEAN;
+ case BYTE: return PUT_BYTE;
+ case SHORT: return PUT_SHORT;
+ case CHAR: return PUT_CHAR;
+ case INT: return PUT_INT;
+ case LONG: return PUT_LONG;
+ case FLOAT: return PUT_FLOAT;
+ case DOUBLE: return PUT_DOUBLE;
+ case OBJECT: return PUT_OBJECT;
+ }
+ }
+ }
+ throw new AssertionError("Invalid arguments");
+ }
+
+ static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
boolean isStatic = (formOp >= AF_GETSTATIC);
boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
@@ -576,24 +633,14 @@ class DirectMethodHandle extends MethodHandle {
assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
// getObject, putIntVolatile, etc.
- StringBuilder nameBuilder = new StringBuilder();
- if (isGetter) {
- nameBuilder.append("get");
- } else {
- nameBuilder.append("put");
- }
- nameBuilder.append(fw.primitiveSimpleName());
- nameBuilder.setCharAt(3, Character.toUpperCase(nameBuilder.charAt(3)));
- if (isVolatile) {
- nameBuilder.append("Volatile");
- }
+ Kind kind = getFieldKind(isGetter, isVolatile, fw);
MethodType linkerType;
if (isGetter)
linkerType = MethodType.methodType(ft, Object.class, long.class);
else
linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
- MemberName linker = new MemberName(Unsafe.class, nameBuilder.toString(), linkerType, REF_invokeVirtual);
+ MemberName linker = new MemberName(Unsafe.class, kind.methodName, linkerType, REF_invokeVirtual);
try {
linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
} catch (ReflectiveOperationException ex) {
@@ -620,6 +667,7 @@ class DirectMethodHandle extends MethodHandle {
final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
final int F_OFFSET = nameCursor++; // Either static offset or field offset.
final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
+ final int U_HOLDER = nameCursor++; // UNSAFE holder
final int INIT_BAR = (needsInit ? nameCursor++ : -1);
final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
final int LINKER_CALL = nameCursor++;
@@ -632,7 +680,7 @@ class DirectMethodHandle extends MethodHandle {
names[PRE_CAST] = new Name(NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
Object[] outArgs = new Object[1 + linkerType.parameterCount()];
assert(outArgs.length == (isGetter ? 3 : 4));
- outArgs[0] = UNSAFE;
+ outArgs[0] = names[U_HOLDER] = new Name(NF_UNSAFE);
if (isStatic) {
outArgs[1] = names[F_HOLDER] = new Name(NF_staticBase, names[DMH_THIS]);
outArgs[2] = names[F_OFFSET] = new Name(NF_staticOffset, names[DMH_THIS]);
@@ -650,6 +698,7 @@ class DirectMethodHandle extends MethodHandle {
for (Name n : names) assert(n != null);
// add some detail to the lambdaForm debugname,
// significant only for debugging
+ StringBuilder nameBuilder = new StringBuilder(kind.methodName);
if (isStatic) {
nameBuilder.append("Static");
} else {
@@ -657,7 +706,12 @@ class DirectMethodHandle extends MethodHandle {
}
if (needsCast) nameBuilder.append("Cast");
if (needsInit) nameBuilder.append("Init");
- return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
+ if (needsCast || needsInit) {
+ // can't use the pre-generated form when casting and/or initializing
+ return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT);
+ } else {
+ return new LambdaForm(nameBuilder.toString(), ARG_LIMIT, names, RESULT, kind);
+ }
}
/**
@@ -674,7 +728,8 @@ class DirectMethodHandle extends MethodHandle {
NF_staticOffset,
NF_checkCast,
NF_allocateInstance,
- NF_constructorMethod;
+ NF_constructorMethod,
+ NF_UNSAFE;
static {
try {
NamedFunction nfs[] = {
@@ -697,7 +752,9 @@ class DirectMethodHandle extends MethodHandle {
NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
.getDeclaredMethod("allocateInstance", Object.class)),
NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
- .getDeclaredMethod("constructorMethod", Object.class))
+ .getDeclaredMethod("constructorMethod", Object.class)),
+ NF_UNSAFE = new NamedFunction(new MemberName(MethodHandleStatics.class
+ .getDeclaredField("UNSAFE")))
};
// Each nf must be statically invocable or we get tied up in our bootstraps.
assert(InvokerBytecodeGenerator.isStaticallyInvocable(nfs));
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
index 1f1b50d67c5..d8e6dcd5ed0 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java
@@ -28,9 +28,11 @@ package java.lang.invoke;
import java.util.Map;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
-
import java.util.ArrayList;
import java.util.HashSet;
+import sun.invoke.util.Wrapper;
+
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
/**
* Helper class to assist the GenerateJLIClassesPlugin to get access to
@@ -38,16 +40,66 @@ import java.util.HashSet;
*/
class GenerateJLIClassesHelper {
+ static byte[] generateBasicFormsClassBytes(String className) {
+ ArrayList forms = new ArrayList<>();
+ ArrayList names = new ArrayList<>();
+ HashSet dedupSet = new HashSet<>();
+ for (LambdaForm.BasicType type : LambdaForm.BasicType.values()) {
+ LambdaForm zero = LambdaForm.zeroForm(type);
+ String name = zero.kind.defaultLambdaName
+ + "_" + zero.returnType().basicTypeChar();
+ if (dedupSet.add(name)) {
+ names.add(name);
+ forms.add(zero);
+ }
+
+ LambdaForm identity = LambdaForm.identityForm(type);
+ name = identity.kind.defaultLambdaName
+ + "_" + identity.returnType().basicTypeChar();
+ if (dedupSet.add(name)) {
+ names.add(name);
+ forms.add(identity);
+ }
+ }
+ return generateCodeBytesForLFs(className,
+ names.toArray(new String[0]),
+ forms.toArray(new LambdaForm[0]));
+ }
+
static byte[] generateDirectMethodHandleHolderClassBytes(String className,
MethodType[] methodTypes, int[] types) {
- LambdaForm[] forms = new LambdaForm[methodTypes.length];
- String[] names = new String[methodTypes.length];
- for (int i = 0; i < forms.length; i++) {
- forms[i] = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i],
- types[i]);
- names[i] = forms[i].kind.defaultLambdaName;
+ ArrayList forms = new ArrayList<>();
+ ArrayList names = new ArrayList<>();
+ for (int i = 0; i < methodTypes.length; i++) {
+ LambdaForm form = DirectMethodHandle
+ .makePreparedLambdaForm(methodTypes[i], types[i]);
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
}
- return generateCodeBytesForLFs(className, names, forms);
+ for (Wrapper wrapper : Wrapper.values()) {
+ if (wrapper == Wrapper.VOID) {
+ continue;
+ }
+ for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
+ int ftype = DirectMethodHandle.ftypeKind(wrapper.primitiveType());
+ LambdaForm form = DirectMethodHandle
+ .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
+ if (form.kind != LambdaForm.Kind.GENERIC) {
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
+ }
+ // volatile
+ form = DirectMethodHandle
+ .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
+ if (form.kind != LambdaForm.Kind.GENERIC) {
+ forms.add(form);
+ names.add(form.kind.defaultLambdaName);
+ }
+ }
+ }
+ return generateCodeBytesForLFs(className,
+ names.toArray(new String[0]),
+ forms.toArray(new LambdaForm[0]));
}
static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
@@ -81,6 +133,34 @@ class GenerateJLIClassesHelper {
forms.toArray(new LambdaForm[0]));
}
+ static byte[] generateInvokersHolderClassBytes(String className,
+ MethodType[] methodTypes) {
+
+ HashSet dedupSet = new HashSet<>();
+ ArrayList forms = new ArrayList<>();
+ ArrayList names = new ArrayList<>();
+ int[] types = {
+ MethodTypeForm.LF_EX_LINKER,
+ MethodTypeForm.LF_EX_INVOKER,
+ MethodTypeForm.LF_GEN_LINKER,
+ MethodTypeForm.LF_GEN_INVOKER
+ };
+ for (int i = 0; i < methodTypes.length; i++) {
+ // generate methods representing invokers of the specified type
+ if (dedupSet.add(methodTypes[i])) {
+ for (int type : types) {
+ LambdaForm invokerForm = Invokers.invokeHandleForm(methodTypes[i],
+ /*customized*/false, type);
+ forms.add(invokerForm);
+ names.add(invokerForm.kind.defaultLambdaName);
+ }
+ }
+ }
+ return generateCodeBytesForLFs(className,
+ names.toArray(new String[0]),
+ forms.toArray(new LambdaForm[0]));
+ }
+
/*
* Generate customized code for a set of LambdaForms of specified types into
* a class with a specified name.
@@ -140,4 +220,5 @@ class GenerateJLIClassesHelper {
BoundMethodHandle.Factory.generateConcreteBMHClassBytes(
shortTypes, types, className));
}
+
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
index ebfe415fbf1..b71bd527608 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
@@ -624,6 +624,33 @@ class InvokerBytecodeGenerator {
return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
}
case DELEGATE: return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
+ case ZERO: // fall-through
+ case IDENTITY: {
+ name = name + "_" + form.returnType().basicTypeChar();
+ return resolveFrom(name, invokerType, LambdaForm.Holder.class);
+ }
+ case EXACT_INVOKER: // fall-through
+ case EXACT_LINKER: // fall-through
+ case GENERIC_INVOKER: // fall-through
+ case GENERIC_LINKER: return resolveFrom(name, invokerType.basicType(), Invokers.Holder.class);
+ case GET_OBJECT: // fall-through
+ case GET_BOOLEAN: // fall-through
+ case GET_BYTE: // fall-through
+ case GET_CHAR: // fall-through
+ case GET_SHORT: // fall-through
+ case GET_INT: // fall-through
+ case GET_LONG: // fall-through
+ case GET_FLOAT: // fall-through
+ case GET_DOUBLE: // fall-through
+ case PUT_OBJECT: // fall-through
+ case PUT_BOOLEAN: // fall-through
+ case PUT_BYTE: // fall-through
+ case PUT_CHAR: // fall-through
+ case PUT_SHORT: // fall-through
+ case PUT_INT: // fall-through
+ case PUT_LONG: // fall-through
+ case PUT_FLOAT: // fall-through
+ case PUT_DOUBLE: // fall-through
case DIRECT_INVOKE_INTERFACE: // fall-through
case DIRECT_INVOKE_SPECIAL: // fall-through
case DIRECT_INVOKE_STATIC: // fall-through
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
index 1aca86298fe..0a97622fe84 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
@@ -36,6 +36,7 @@ import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandleNatives.Constants.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
import static java.lang.invoke.LambdaForm.*;
+import static java.lang.invoke.LambdaForm.Kind.*;
/**
* Construction and caching of often-used invokers.
@@ -254,7 +255,7 @@ class Invokers {
* @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker");
* 0x02 whether it is for invokeExact or generic invoke
*/
- private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
+ static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
boolean isCached;
if (!customized) {
mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
@@ -263,12 +264,12 @@ class Invokers {
isCached = false; // maybe cache if mtype == mtype.basicType()
}
boolean isLinker, isGeneric;
- String debugName;
+ Kind kind;
switch (which) {
- case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; debugName = "invokeExact_MT"; break;
- case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
- case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break;
- case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break;
+ case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; kind = EXACT_LINKER; break;
+ case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; kind = EXACT_INVOKER; break;
+ case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; kind = GENERIC_LINKER; break;
+ case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; kind = GENERIC_INVOKER; break;
default: throw new InternalError();
}
LambdaForm lform;
@@ -323,7 +324,11 @@ class Invokers {
names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
}
names[LINKER_CALL] = new Name(outCallType, outArgs);
- lform = new LambdaForm(debugName, INARG_LIMIT, names);
+ if (customized) {
+ lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names);
+ } else {
+ lform = new LambdaForm(kind.defaultLambdaName, INARG_LIMIT, names, kind);
+ }
if (isLinker)
lform.compileToBytecode(); // JVM needs a real methodOop
if (isCached)
@@ -614,4 +619,15 @@ class Invokers {
}
}
}
+
+ static {
+ // The Holder class will contain pre-generated Invokers resolved
+ // speculatively using MemberName.getFactory().resolveOrNull. However, that
+ // doesn't initialize the class, which subtly breaks inlining etc. By forcing
+ // initialization of the Holder class we avoid these issues.
+ UNSAFE.ensureClassInitialized(Holder.class);
+ }
+
+ /* Placeholder class for Invokers generated ahead of time */
+ final class Holder {}
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
index c70d6c4163a..6fdf21e2c91 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
@@ -270,15 +270,57 @@ class LambdaForm {
enum Kind {
GENERIC(""),
+ ZERO("zero"),
+ IDENTITY("identity"),
BOUND_REINVOKER("BMH.reinvoke"),
REINVOKER("MH.reinvoke"),
DELEGATE("MH.delegate"),
+ EXACT_LINKER("MH.invokeExact_MT"),
+ EXACT_INVOKER("MH.exactInvoker"),
+ GENERIC_LINKER("MH.invoke_MT"),
+ GENERIC_INVOKER("MH.invoker"),
DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"),
DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"),
DIRECT_INVOKE_STATIC("DMH.invokeStatic"),
DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"),
DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"),
- DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit");
+ DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit"),
+ GET_OBJECT("getObject"),
+ PUT_OBJECT("putObject"),
+ GET_OBJECT_VOLATILE("getObjectVolatile"),
+ PUT_OBJECT_VOLATILE("putObjectVolatile"),
+ GET_INT("getInt"),
+ PUT_INT("putInt"),
+ GET_INT_VOLATILE("getIntVolatile"),
+ PUT_INT_VOLATILE("putIntVolatile"),
+ GET_BOOLEAN("getBoolean"),
+ PUT_BOOLEAN("putBoolean"),
+ GET_BOOLEAN_VOLATILE("getBooleanVolatile"),
+ PUT_BOOLEAN_VOLATILE("putBooleanVolatile"),
+ GET_BYTE("getByte"),
+ PUT_BYTE("putByte"),
+ GET_BYTE_VOLATILE("getByteVolatile"),
+ PUT_BYTE_VOLATILE("putByteVolatile"),
+ GET_CHAR("getChar"),
+ PUT_CHAR("putChar"),
+ GET_CHAR_VOLATILE("getCharVolatile"),
+ PUT_CHAR_VOLATILE("putCharVolatile"),
+ GET_SHORT("getShort"),
+ PUT_SHORT("putShort"),
+ GET_SHORT_VOLATILE("getShortVolatile"),
+ PUT_SHORT_VOLATILE("putShortVolatile"),
+ GET_LONG("getLong"),
+ PUT_LONG("putLong"),
+ GET_LONG_VOLATILE("getLongVolatile"),
+ PUT_LONG_VOLATILE("putLongVolatile"),
+ GET_FLOAT("getFloat"),
+ PUT_FLOAT("putFloat"),
+ GET_FLOAT_VOLATILE("getFloatVolatile"),
+ PUT_FLOAT_VOLATILE("putFloatVolatile"),
+ GET_DOUBLE("getDouble"),
+ PUT_DOUBLE("putDouble"),
+ GET_DOUBLE_VOLATILE("getDoubleVolatile"),
+ PUT_DOUBLE_VOLATILE("putDoubleVolatile");
final String defaultLambdaName;
final String methodName;
@@ -327,6 +369,10 @@ class LambdaForm {
int arity, Name[] names) {
this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
}
+ LambdaForm(String debugName,
+ int arity, Name[] names, Kind kind) {
+ this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, kind);
+ }
LambdaForm(String debugName,
int arity, Name[] names, boolean forceInline) {
this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
@@ -815,54 +861,6 @@ class LambdaForm {
}
}
- private static void computeInitialPreparedForms() {
- // Find all predefined invokers and associate them with canonical empty lambda forms.
- for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
- if (!m.isStatic() || !m.isPackage()) continue;
- MethodType mt = m.getMethodType();
- if (mt.parameterCount() > 0 &&
- mt.parameterType(0) == MethodHandle.class &&
- m.getName().startsWith("interpret_")) {
- String sig = null;
- assert((sig = basicTypeSignature(mt)) != null &&
- m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
- LambdaForm form = new LambdaForm(mt);
- form.vmentry = m;
- form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
- }
- }
- }
-
- // Set this false to disable use of the interpret_L methods defined in this file.
- private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
-
- // The following are predefined exact invokers. The system must build
- // a separate invoker for each distinct signature.
- static Object interpret_L(MethodHandle mh) throws Throwable {
- Object[] av = {mh};
- String sig = null;
- assert(argumentTypesMatch(sig = "L_L", av));
- Object res = mh.form.interpretWithArguments(av);
- assert(returnTypesMatch(sig, av, res));
- return res;
- }
- static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
- Object[] av = {mh, x1};
- String sig = null;
- assert(argumentTypesMatch(sig = "LL_L", av));
- Object res = mh.form.interpretWithArguments(av);
- assert(returnTypesMatch(sig, av, res));
- return res;
- }
- static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
- Object[] av = {mh, x1, x2};
- String sig = null;
- assert(argumentTypesMatch(sig = "LLL_L", av));
- Object res = mh.form.interpretWithArguments(av);
- assert(returnTypesMatch(sig, av, res));
- return res;
- }
-
// The next few routines are called only from assert expressions
// They verify that the built-in invokers process the correct raw data types.
private static boolean argumentTypesMatch(String sig, Object[] av) {
@@ -1149,113 +1147,6 @@ class LambdaForm {
return super.hashCode();
}
- // Put the predefined NamedFunction invokers into the table.
- static void initializeInvokers() {
- for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
- if (!m.isStatic() || !m.isPackage()) continue;
- MethodType type = m.getMethodType();
- if (type.equals(INVOKER_METHOD_TYPE) &&
- m.getName().startsWith("invoke_")) {
- String sig = m.getName().substring("invoke_".length());
- int arity = LambdaForm.signatureArity(sig);
- MethodType srcType = MethodType.genericMethodType(arity);
- if (LambdaForm.signatureReturn(sig) == V_TYPE)
- srcType = srcType.changeReturnType(void.class);
- MethodTypeForm typeForm = srcType.form();
- typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m));
- }
- }
- }
-
- // The following are predefined NamedFunction invokers. The system must build
- // a separate invoker for each distinct signature.
- /** void return type invokers. */
- @Hidden
- static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(0, void.class, mh, a));
- mh.invokeBasic();
- return null;
- }
- @Hidden
- static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(1, void.class, mh, a));
- mh.invokeBasic(a[0]);
- return null;
- }
- @Hidden
- static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(2, void.class, mh, a));
- mh.invokeBasic(a[0], a[1]);
- return null;
- }
- @Hidden
- static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(3, void.class, mh, a));
- mh.invokeBasic(a[0], a[1], a[2]);
- return null;
- }
- @Hidden
- static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(4, void.class, mh, a));
- mh.invokeBasic(a[0], a[1], a[2], a[3]);
- return null;
- }
- @Hidden
- static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(5, void.class, mh, a));
- mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
- return null;
- }
- /** Object return type invokers. */
- @Hidden
- static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(0, mh, a));
- return mh.invokeBasic();
- }
- @Hidden
- static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(1, mh, a));
- return mh.invokeBasic(a[0]);
- }
- @Hidden
- static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(2, mh, a));
- return mh.invokeBasic(a[0], a[1]);
- }
- @Hidden
- static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(3, mh, a));
- return mh.invokeBasic(a[0], a[1], a[2]);
- }
- @Hidden
- static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(4, mh, a));
- return mh.invokeBasic(a[0], a[1], a[2], a[3]);
- }
- @Hidden
- static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
- assert(arityCheck(5, mh, a));
- return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
- }
- private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) {
- return arityCheck(arity, Object.class, mh, a);
- }
- private static boolean arityCheck(int arity, Class> rtype, MethodHandle mh, Object[] a) {
- assert(a.length == arity)
- : Arrays.asList(a.length, arity);
- assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype))
- : Arrays.asList(mh, rtype, arity);
- MemberName member = mh.internalMemberName();
- if (isInvokeBasic(member)) {
- assert(arity > 0);
- assert(a[0] instanceof MethodHandle);
- MethodHandle mh2 = (MethodHandle) a[0];
- assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype))
- : Arrays.asList(member, mh2, rtype, arity);
- }
- return true;
- }
-
static final MethodType INVOKER_METHOD_TYPE =
MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
@@ -1848,7 +1739,7 @@ class LambdaForm {
// bootstrap dependency on this method in case we're interpreting LFs
if (isVoid) {
Name[] idNames = new Name[] { argument(0, L_TYPE) };
- idForm = new LambdaForm(idMem.getName(), 1, idNames, VOID_RESULT);
+ idForm = new LambdaForm(idMem.getName(), 1, idNames, VOID_RESULT, Kind.IDENTITY);
idForm.compileToBytecode();
idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
@@ -1856,15 +1747,17 @@ class LambdaForm {
zeFun = idFun;
} else {
Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) };
- idForm = new LambdaForm(idMem.getName(), 2, idNames, 1);
+ idForm = new LambdaForm(idMem.getName(), 2, idNames, 1, Kind.IDENTITY);
idForm.compileToBytecode();
- idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
+ idFun = new NamedFunction(idMem, MethodHandleImpl.makeIntrinsic(
+ idMem.getInvocationType(), idForm, MethodHandleImpl.Intrinsic.IDENTITY));
Object zeValue = Wrapper.forBasicType(btChar).zero();
Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) };
- zeForm = new LambdaForm(zeMem.getName(), 1, zeNames, 1);
+ zeForm = new LambdaForm(zeMem.getName(), 1, zeNames, 1, Kind.ZERO);
zeForm.compileToBytecode();
- zeFun = new NamedFunction(zeMem, SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm));
+ zeFun = new NamedFunction(zeMem, MethodHandleImpl.makeIntrinsic(
+ zeMem.getInvocationType(), zeForm, MethodHandleImpl.Intrinsic.ZERO));
}
LF_zero[ord] = zeForm;
@@ -1916,13 +1809,17 @@ class LambdaForm {
DEBUG_NAME_COUNTERS = null;
}
- // Put this last, so that previous static inits can run before.
static {
- if (USE_PREDEFINED_INTERPRET_METHODS)
- computeInitialPreparedForms();
- NamedFunction.initializeInvokers();
+ // The Holder class will contain pre-generated forms resolved
+ // using MemberName.getFactory(). However, that doesn't initialize the
+ // class, which subtly breaks inlining etc. By forcing
+ // initialization of the Holder class we avoid these issues.
+ UNSAFE.ensureClassInitialized(Holder.class);
}
+ /* Placeholder class for zero and identity forms generated ahead of time */
+ final class Holder {}
+
// The following hack is necessary in order to suppress TRACE_INTERPRETER
// during execution of the static initializes of this class.
// Turning on TRACE_INTERPRETER too early will cause
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index a0561589beb..4fe4bb524a7 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -1739,6 +1739,19 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
return GenerateJLIClassesHelper
.generateConcreteBMHClassBytes(types);
}
+
+ @Override
+ public byte[] generateBasicFormsClassBytes(final String className) {
+ return GenerateJLIClassesHelper
+ .generateBasicFormsClassBytes(className);
+ }
+
+ @Override
+ public byte[] generateInvokersHolderClassBytes(final String className,
+ MethodType[] methodTypes) {
+ return GenerateJLIClassesHelper
+ .generateInvokersHolderClassBytes(className, methodTypes);
+ }
});
}
@@ -1934,7 +1947,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* @return whether the counter has reached the limit.
*/
static boolean countedLoopPredicate(int counter, int limit) {
- return counter <= limit;
+ return counter < limit;
}
/**
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index 81dedf3090d..a02e2f18b23 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -4583,7 +4583,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* // assume MH_decrement is a handle to x-1 of type int
* MethodHandle[]
* indexVar = {start, MH_increment}, // i = start; i = i+1
- * loopLimit = {end, null, MH_lessThan, returnVar }, // i
{@code Provider.id name}
*
{@code String.valueOf(provider.getName())}
*
{@code Provider.id version}
- *
{@code String.valueOf(provider.getVersion())}
+ *
{@code String.valueOf(provider.getVersionStr())}
*
{@code Provider.id info}
{@code String.valueOf(provider.getInfo())}
*
{@code Provider.id className}
*
{@code provider.getClass().getName()}
*
*
- *
Each provider has a name and a version number. A provider normally
+ *
Each provider has a name and a version string. A provider normally
* identifies itself with a file named {@code java.security.Provider}
* in the resource directory {@code META-INF/services}.
* Security providers are looked up via the {@link ServiceLoader} mechanism
@@ -102,11 +102,10 @@ import java.util.function.Function;
public abstract class Provider extends Properties {
// Declare serialVersionUID to be compatible with JDK1.1
- static final long serialVersionUID = -4298000515446427739L;
+ private static final long serialVersionUID = -4298000515446427739L;
private static final sun.security.util.Debug debug =
- sun.security.util.Debug.getInstance
- ("provider", "Provider");
+ sun.security.util.Debug.getInstance("provider", "Provider");
/**
* The provider name.
@@ -129,6 +128,12 @@ public abstract class Provider extends Properties {
*/
private double version;
+ /**
+ * The provider version string.
+ *
+ * @serial
+ */
+ private String versionStr;
private transient Set> entrySet = null;
private transient int entrySetCallCount = 0;
@@ -174,19 +179,83 @@ public abstract class Provider extends Properties {
}
}
+ private static double parseVersionStr(String s) {
+ try {
+ int firstDotIdx = s.indexOf('.');
+ int nextDotIdx = s.indexOf('.', firstDotIdx + 1);
+ if (nextDotIdx != -1) {
+ s = s.substring(0, nextDotIdx);
+ }
+ int endIdx = s.indexOf('-');
+ if (endIdx > 0) {
+ s = s.substring(0, endIdx);
+ }
+ endIdx = s.indexOf('+');
+ if (endIdx > 0) {
+ s = s.substring(0, endIdx);
+ }
+ return Double.parseDouble(s);
+ } catch (NullPointerException | NumberFormatException e) {
+ return 0d;
+ }
+ }
+
/**
* Constructs a provider with the specified name, version number,
- * and information.
+ * and information. Calling this constructor is equivalent to call the
+ * {@link #Provider(String, String, String)} with {@code name}
+ * name, {@code Double.toString(version)}, and {@code info}.
*
* @param name the provider name.
*
* @param version the provider version number.
*
* @param info a description of the provider and its services.
+ *
+ * @deprecated use {@link #Provider(String, String, String)} instead.
*/
+ @Deprecated(since="9")
protected Provider(String name, double version, String info) {
this.name = name;
this.version = version;
+ this.versionStr = Double.toString(version);
+ this.info = info;
+ putId();
+ initialized = true;
+ }
+
+ /**
+ * Constructs a provider with the specified name, version string,
+ * and information.
+ *
+ *
The version string contains a version number optionally followed
+ * by other information separated by one of the characters of '+', '-'.
+ *
+ * The format for the version number is:
+ *
+ *
+ * ^[0-9]+(\.[0-9]+)*
+ *
+ *
+ *
In order to return the version number in a double, when there are
+ * more than two components (separated by '.' as defined above), only
+ * the first two components are retained. The resulting string is then
+ * passed to {@link Double#valueOf(String)} to generate version number,
+ * i.e. {@link #getVersion}.
+ *
If the conversion failed, value 0 will be used.
+ *
+ * @param name the provider name.
+ *
+ * @param versionStr the provider version string.
+ *
+ * @param info a description of the provider and its services.
+ *
+ * @since 9
+ */
+ protected Provider(String name, String versionStr, String info) {
+ this.name = name;
+ this.versionStr = versionStr;
+ this.version = parseVersionStr(versionStr);
this.info = info;
putId();
initialized = true;
@@ -250,11 +319,25 @@ public abstract class Provider extends Properties {
* Returns the version number for this provider.
*
* @return the version number for this provider.
+ *
+ * @deprecated use {@link #getVersionStr} instead.
*/
+ @Deprecated(since="9")
public double getVersion() {
return version;
}
+ /**
+ * Returns the version string for this provider.
+ *
+ * @return the version string for this provider.
+ *
+ * @since 9
+ */
+ public String getVersionStr() {
+ return versionStr;
+ }
+
/**
* Returns a human-readable description of the provider and its
* services. This may return an HTML page, with relevant links.
@@ -266,14 +349,14 @@ public abstract class Provider extends Properties {
}
/**
- * Returns a string with the name and the version number
+ * Returns a string with the name and the version string
* of this provider.
*
- * @return the string with the name and the version number
+ * @return the string with the name and the version string
* for this provider.
*/
public String toString() {
- return name + " version " + version;
+ return name + " version " + versionStr;
}
/*
@@ -787,11 +870,21 @@ public abstract class Provider extends Properties {
private void putId() {
// note: name and info may be null
super.put("Provider.id name", String.valueOf(name));
- super.put("Provider.id version", String.valueOf(version));
+ super.put("Provider.id version", String.valueOf(versionStr));
super.put("Provider.id info", String.valueOf(info));
super.put("Provider.id className", this.getClass().getName());
}
+ /**
+ * Reads the {@code ObjectInputStream} for the default serializable fields.
+ * If the serialized field {@code versionStr} is found in the STREAM FIELDS,
+ * its String value will be used to populate both the version string and
+ * version number. If {@code versionStr} is not found, but {@code version}
+ * is, then its double value will be used to populate both fields.
+ *
+ * @param in the {@code ObjectInputStream} to read
+ * @serial
+ */
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
Map