--- a/.hgtags Fri Apr 19 07:55:28 2019 -0400
+++ b/.hgtags Fri Apr 19 08:00:42 2019 -0400
@@ -554,3 +554,4 @@
46cf212cdccaf4fb064d913b12004007d3322b67 jdk-13+14
f855ec13aa2501ae184c8b3e0626a8cec9966116 jdk-13+15
9d0ae9508d5337b0dc7cc4684be42888c4023755 jdk-13+16
+93b702d2a0cb9e32160208f6700aede1f8492773 jdk-13+17
--- a/doc/testing.html Fri Apr 19 07:55:28 2019 -0400
+++ b/doc/testing.html Fri Apr 19 08:00:42 2019 -0400
@@ -41,6 +41,7 @@
</ul></li>
<li><a href="#notes-for-specific-tests">Notes for Specific Tests</a><ul>
<li><a href="#docker-tests">Docker Tests</a></li>
+<li><a href="#non-us-locale">Non-US locale</a></li>
</ul></li>
</ul>
</nav>
@@ -194,5 +195,9 @@
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker"</code></pre>
<p>To run these tests correctly, additional parameters for the correct docker image are required on Ubuntu 18.04 by using <code>JAVA_OPTIONS</code>.</p>
<pre><code>$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"</code></pre>
+<h3 id="non-us-locale">Non-US locale</h3>
+<p>If your locale is non-US, some tests are likely to fail. To work around this you can set the locale to US. On Unix platforms simply setting <code>LANG="en_US"</code> in the environment before running tests should work. On Windows, setting <code>JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"</code> helps for most, but not all test cases. For example:</p>
+<pre><code>$ export LANG="en_US" && make test TEST=...
+$ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...</code></pre>
</body>
</html>
--- a/doc/testing.md Fri Apr 19 07:55:28 2019 -0400
+++ b/doc/testing.md Fri Apr 19 08:00:42 2019 -0400
@@ -388,6 +388,17 @@
$ make test TEST="jtreg:test/hotspot/jtreg/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest"
+### Non-US locale
+
+If your locale is non-US, some tests are likely to fail. To work around this you can
+set the locale to US. On Unix platforms simply setting `LANG="en_US"` in the
+environment before running tests should work. On Windows, setting
+`JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US"` helps for most, but not all test cases.
+For example:
+
+ $ export LANG="en_US" && make test TEST=...
+ $ make test JTREG="VM_OPTIONS=-Duser.language=en -Duser.country=US" TEST=...
+
---
# Override some definitions in the global css file that are not optimal for
# this document.
--- a/make/autoconf/jdk-version.m4 Fri Apr 19 07:55:28 2019 -0400
+++ b/make/autoconf/jdk-version.m4 Fri Apr 19 08:00:42 2019 -0400
@@ -66,7 +66,33 @@
AC_SUBST(PRODUCT_SUFFIX)
AC_SUBST(JDK_RC_PLATFORM_NAME)
AC_SUBST(HOTSPOT_VM_DISTRO)
+
+ # Set the MACOSX Bundle Name base
+ AC_ARG_WITH(macosx-bundle-name-base, [AS_HELP_STRING([--with-macosx-bundle-name-base],
+ [Set the MacOSX Bundle Name base. This is the base name for calculating MacOSX Bundle Names.
+ @<:@not specified@:>@])])
+ if test "x$with_macosx_bundle_name_base" = xyes; then
+ AC_MSG_ERROR([--with-macosx-bundle-name-base must have a value])
+ elif [ ! [[ $with_macosx_bundle_name_base =~ ^[[:print:]]*$ ]] ]; then
+ AC_MSG_ERROR([--with-macosx-bundle-name-base contains non-printing characters: $with_macosx_bundle_name_base])
+ elif test "x$with_macosx_bundle_name_base" != x; then
+ # Set MACOSX_BUNDLE_NAME_BASE to the configured value.
+ MACOSX_BUNDLE_NAME_BASE="$with_macosx_bundle_name_base"
+ fi
AC_SUBST(MACOSX_BUNDLE_NAME_BASE)
+
+ # Set the MACOSX Bundle ID base
+ AC_ARG_WITH(macosx-bundle-id-base, [AS_HELP_STRING([--with-macosx-bundle-id-base],
+ [Set the MacOSX Bundle ID base. This is the base ID for calculating MacOSX Bundle IDs.
+ @<:@not specified@:>@])])
+ if test "x$with_macosx_bundle_id_base" = xyes; then
+ AC_MSG_ERROR([--with-macosx-bundle-id-base must have a value])
+ elif [ ! [[ $with_macosx_bundle_id_base =~ ^[[:print:]]*$ ]] ]; then
+ AC_MSG_ERROR([--with-macosx-bundle-id-base contains non-printing characters: $with_macosx_bundle_id_base])
+ elif test "x$with_macosx_bundle_id_base" != x; then
+ # Set MACOSX_BUNDLE_ID_BASE to the configured value.
+ MACOSX_BUNDLE_ID_BASE="$with_macosx_bundle_id_base"
+ fi
AC_SUBST(MACOSX_BUNDLE_ID_BASE)
# Set the JDK RC name
--- a/make/autoconf/libraries.m4 Fri Apr 19 07:55:28 2019 -0400
+++ b/make/autoconf/libraries.m4 Fri Apr 19 08:00:42 2019 -0400
@@ -130,6 +130,11 @@
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread"
fi
+ # perfstat lib
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat"
+ fi
+
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lsocket -lsched -ldoor -ldemangle -lnsl \
-lrt -lkstat"
--- a/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java Fri Apr 19 07:55:28 2019 -0400
+++ b/make/jdk/src/classes/build/tools/classlist/HelloClasslist.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -67,13 +67,24 @@
.forEach(System.out::println);
// Common concatenation patterns
- String const_I = "string" + args.length;
- String const_S = "string" + String.valueOf(args.length);
- String S_const = String.valueOf(args.length) + "string";
- String S_S = String.valueOf(args.length) + String.valueOf(args.length);
- String const_J = "string" + System.currentTimeMillis();
- String I_const = args.length + "string";
- String J_const = System.currentTimeMillis() + "string";
+ String SS = String.valueOf(args.length) + String.valueOf(args.length);
+ String CS = "string" + String.valueOf(args.length);
+ String SC = String.valueOf(args.length) + "string";
+ String SCS = String.valueOf(args.length) + "string" + String.valueOf(args.length);
+ String CSS = "string" + String.valueOf(args.length) + String.valueOf(args.length);
+ String CSCS = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
+ String SCSC = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
+ String CSCSC = "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string";
+ String SCSCS = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
+ String CI = "string" + args.length;
+ String IC = args.length + "string";
+ String CIC = "string" + args.length + "string";
+ String CICI = "string" + args.length + "string" + args.length;
+ String CJ = "string" + System.currentTimeMillis();
+ String JC = System.currentTimeMillis() + "string";
+ String CJC = "string" + System.currentTimeMillis() + "string";
+ String CJCJ = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis();
+ String CJCJC = "string" + System.currentTimeMillis() + "string" + System.currentTimeMillis() + "string";
String newDate = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(
LocalDateTime.now(ZoneId.of("GMT")));
--- a/make/launcher/Launcher-java.base.gmk Fri Apr 19 07:55:28 2019 -0400
+++ b/make/launcher/Launcher-java.base.gmk Fri Apr 19 08:00:42 2019 -0400
@@ -39,7 +39,6 @@
# overwritten.
$(eval $(call SetupBuildLauncher, java, \
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \
- LDFLAGS_solaris := -R$(OPENWIN_HOME)/lib$(OPENJDK_TARGET_CPU_ISADIR), \
EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \
VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/java_objs, \
--- a/make/launcher/LauncherCommon.gmk Fri Apr 19 07:55:28 2019 -0400
+++ b/make/launcher/LauncherCommon.gmk Fri Apr 19 08:00:42 2019 -0400
@@ -73,8 +73,7 @@
# compile time defines exceeding Visual Studio 2013 limitations.
# CFLAGS Additional CFLAGS
# CFLAGS_windows Additional CFLAGS_windows
-# LDFLAGS_solaris Additional LDFLAGS_solaris
-# RC_FLAGS Additional RC_FLAGS
+# EXTRA_RC_FLAGS Additional EXTRA_RC_FLAGS
# MACOSX_SIGNED On macosx, sign this binary
# OPTIMIZATION Override default optimization level (LOW)
# OUTPUT_DIR Override default output directory
@@ -139,7 +138,7 @@
NAME := $1, \
EXTRA_FILES := $(LAUNCHER_SRC)/main.c, \
OPTIMIZATION := $$($1_OPTIMIZATION), \
- CFLAGS := $$(CFLAGS_JDKEXE) $$($1_CFLAGS) \
+ CFLAGS := $$(CFLAGS_JDKEXE) \
$(LAUNCHER_CFLAGS) \
$(VERSION_CFLAGS) \
-DLAUNCHER_NAME='"$(LAUNCHER_NAME)"' \
--- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -38,6 +38,9 @@
#include "vm_version_ppc.hpp"
#include <sys/sysinfo.h>
+#if defined(_AIX)
+#include <libperfstat.h>
+#endif
#if defined(LINUX) && defined(VM_LITTLE_ENDIAN)
#include <sys/auxv.h>
@@ -382,6 +385,58 @@
}
void VM_Version::print_platform_virtualization_info(outputStream* st) {
+#if defined(_AIX)
+ // more info about perfstat API see
+ // https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.prftools/idprftools_perfstat_glob_partition.htm
+ int rc = 0;
+ perfstat_partition_total_t pinfo;
+ memset(&pinfo, 0, sizeof(perfstat_partition_total_t));
+ rc = perfstat_partition_total(NULL, &pinfo, sizeof(perfstat_partition_total_t), 1);
+ if (rc != 1) {
+ return;
+ } else {
+ st->print_cr("Virtualization type : PowerVM");
+ }
+ // CPU information
+ perfstat_cpu_total_t cpuinfo;
+ memset(&cpuinfo, 0, sizeof(perfstat_cpu_total_t));
+ rc = perfstat_cpu_total(NULL, &cpuinfo, sizeof(perfstat_cpu_total_t), 1);
+ if (rc != 1) {
+ return;
+ }
+
+ st->print_cr("Processor description : %s", cpuinfo.description);
+ st->print_cr("Processor speed : %llu Hz", cpuinfo.processorHZ);
+
+ st->print_cr("LPAR partition name : %s", pinfo.name);
+ st->print_cr("LPAR partition number : %u", pinfo.lpar_id);
+ st->print_cr("LPAR partition type : %s", pinfo.type.b.shared_enabled ? "shared" : "dedicated");
+ st->print_cr("LPAR mode : %s", pinfo.type.b.donate_enabled ? "donating" : pinfo.type.b.capped ? "capped" : "uncapped");
+ st->print_cr("LPAR partition group ID : %u", pinfo.group_id);
+ st->print_cr("LPAR shared pool ID : %u", pinfo.pool_id);
+
+ st->print_cr("AMS (active memory sharing) : %s", pinfo.type.b.ams_capable ? "capable" : "not capable");
+ st->print_cr("AMS (active memory sharing) : %s", pinfo.type.b.ams_enabled ? "on" : "off");
+ st->print_cr("AME (active memory expansion) : %s", pinfo.type.b.ame_enabled ? "on" : "off");
+
+ if (pinfo.type.b.ame_enabled) {
+ st->print_cr("AME true memory in bytes : %llu", pinfo.true_memory);
+ st->print_cr("AME expanded memory in bytes : %llu", pinfo.expanded_memory);
+ }
+
+ st->print_cr("SMT : %s", pinfo.type.b.smt_capable ? "capable" : "not capable");
+ st->print_cr("SMT : %s", pinfo.type.b.smt_enabled ? "on" : "off");
+ int ocpus = pinfo.online_cpus > 0 ? pinfo.online_cpus : 1;
+ st->print_cr("LPAR threads : %d", cpuinfo.ncpus/ocpus);
+ st->print_cr("LPAR online virtual cpus : %d", pinfo.online_cpus);
+ st->print_cr("LPAR logical cpus : %d", cpuinfo.ncpus);
+ st->print_cr("LPAR maximum virtual cpus : %u", pinfo.max_cpus);
+ st->print_cr("LPAR minimum virtual cpus : %u", pinfo.min_cpus);
+ st->print_cr("LPAR entitled capacity : %4.2f", (double) (pinfo.entitled_proc_capacity/100.0));
+ st->print_cr("LPAR online memory : %llu MB", pinfo.online_memory);
+ st->print_cr("LPAR maximum memory : %llu MB", pinfo.max_memory);
+ st->print_cr("LPAR minimum memory : %llu MB", pinfo.min_memory);
+#else
const char* info_file = "/proc/ppc64/lparcfg";
const char* kw[] = { "system_type=", // qemu indicates PowerKVM
"partition_entitled_capacity=", // entitled processor capacity percentage
@@ -400,6 +455,7 @@
if (!print_matching_lines_from_file(info_file, st, kw)) {
st->print_cr(" <%s Not Available>", info_file);
}
+#endif
}
bool VM_Version::use_biased_locking() {
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -4355,12 +4355,9 @@
// Emitter does not KILL cnt and base arguments, since they need to be copied to
// work registers anyway.
// Actually, only r0, r1, and r5 are killed.
-unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len) {
- // Src_addr is evenReg.
- // Src_len is odd_Reg.
+unsigned int MacroAssembler::Clear_Array(Register cnt_arg, Register base_pointer_arg, Register odd_tmp_reg) {
int block_start = offset();
- Register tmp_reg = src_len; // Holds target instr addr for EX.
Register dst_len = Z_R1; // Holds dst len for MVCLE.
Register dst_addr = Z_R0; // Holds dst addr for MVCLE.
@@ -4369,7 +4366,7 @@
BLOCK_COMMENT("Clear_Array {");
// Check for zero len and convert to long.
- z_ltgfr(src_len, cnt_arg); // Remember casted value for doSTG case.
+ z_ltgfr(odd_tmp_reg, cnt_arg);
z_bre(done); // Nothing to do if len == 0.
// Prefetch data to be cleared.
@@ -4378,16 +4375,17 @@
z_pfd(0x02, 256, Z_R0, base_pointer_arg);
}
- z_sllg(dst_len, src_len, 3); // #bytes to clear.
- z_cghi(src_len, 32); // Check for len <= 256 bytes (<=32 DW).
- z_brnh(doXC); // If so, use executed XC to clear.
+ z_sllg(dst_len, odd_tmp_reg, 3); // #bytes to clear.
+ z_cghi(odd_tmp_reg, 32); // Check for len <= 256 bytes (<=32 DW).
+ z_brnh(doXC); // If so, use executed XC to clear.
// MVCLE: initialize long arrays (general case).
bind(doMVCLE);
z_lgr(dst_addr, base_pointer_arg);
- clear_reg(src_len, true, false); // Src len of MVCLE is zero.
-
- MacroAssembler::move_long_ext(dst_addr, src_addr, 0);
+ // Pass 0 as source length to MVCLE: destination will be filled with padding byte 0.
+ // The even register of the register pair is not killed.
+ clear_reg(odd_tmp_reg, true, false);
+ MacroAssembler::move_long_ext(dst_addr, as_Register(odd_tmp_reg->encoding()-1), 0);
z_bru(done);
// XC: initialize short arrays.
@@ -4396,12 +4394,12 @@
z_xc(0,0,base_pointer_arg,0,base_pointer_arg);
bind(doXC);
- add2reg(dst_len, -1); // Get #bytes-1 for EXECUTE.
+ add2reg(dst_len, -1); // Get #bytes-1 for EXECUTE.
if (VM_Version::has_ExecuteExtensions()) {
- z_exrl(dst_len, XC_template); // Execute XC with var. len.
+ z_exrl(dst_len, XC_template); // Execute XC with var. len.
} else {
- z_larl(tmp_reg, XC_template);
- z_ex(dst_len,0,Z_R0,tmp_reg); // Execute XC with var. len.
+ z_larl(odd_tmp_reg, XC_template);
+ z_ex(dst_len,0,Z_R0,odd_tmp_reg); // Execute XC with var. len.
}
// z_bru(done); // fallthru
@@ -4463,7 +4461,7 @@
// Compiler ensures base is doubleword aligned and cnt is #doublewords.
// Emitter does not KILL cnt and base arguments, since they need to be copied to
// work registers anyway.
-// Actually, only r0, r1, r4, and r5 (which are work registers) are killed.
+// Actually, only r0, r1, (which are work registers) and odd_tmp_reg are killed.
//
// For very large arrays, exploit MVCLE H/W support.
// MVCLE instruction automatically exploits H/W-optimized page mover.
@@ -4471,9 +4469,7 @@
// - All full pages are cleared with the page mover H/W assist.
// - Remaining bytes are again cleared by a series of XC to self.
//
-unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register src_addr, Register src_len) {
- // Src_addr is evenReg.
- // Src_len is odd_Reg.
+unsigned int MacroAssembler::Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register odd_tmp_reg) {
int block_start = offset();
Register dst_len = Z_R1; // Holds dst len for MVCLE.
@@ -4486,11 +4482,10 @@
// Prepare other args to MVCLE.
z_lgr(dst_addr, base_pointer_arg);
- // Indicate unused result.
- (void) clear_reg(src_len, true, false); // Src len of MVCLE is zero.
-
- // Clear.
- MacroAssembler::move_long_ext(dst_addr, src_addr, 0);
+ // Pass 0 as source length to MVCLE: destination will be filled with padding byte 0.
+ // The even register of the register pair is not killed.
+ (void) clear_reg(odd_tmp_reg, true, false); // Src len of MVCLE is zero.
+ MacroAssembler::move_long_ext(dst_addr, as_Register(odd_tmp_reg->encoding() - 1), 0);
BLOCK_COMMENT("} Clear_Array_Const_Big");
int block_end = offset();
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -828,9 +828,9 @@
//--------------------------
//--- Operations on arrays.
//--------------------------
- unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register src_addr, Register src_len);
+ unsigned int Clear_Array(Register cnt_arg, Register base_pointer_arg, Register odd_tmp_reg);
unsigned int Clear_Array_Const(long cnt, Register base);
- unsigned int Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register src_addr, Register src_len);
+ unsigned int Clear_Array_Const_Big(long cnt, Register base_pointer_arg, Register odd_tmp_reg);
unsigned int CopyRawMemory_AlignedDisjoint(Register src_reg, Register dst_reg,
Register cnt_reg,
Register tmp1_reg, Register tmp2_reg);
--- a/src/hotspot/cpu/s390/s390.ad Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/s390/s390.ad Fri Apr 19 08:00:42 2019 -0400
@@ -474,6 +474,19 @@
/*Z_R15_H,Z_R15*/ // SP
);
+// z_long_reg without even registers
+reg_class z_long_odd_reg(
+/*Z_R0_H,Z_R0*/ // R0
+/*Z_R1_H,Z_R1*/
+ Z_R3_H,Z_R3,
+ Z_R5_H,Z_R5,
+ Z_R7_H,Z_R7,
+ Z_R9_H,Z_R9,
+ Z_R11_H,Z_R11,
+ Z_R13_H,Z_R13
+/*Z_R14_H,Z_R14,*/ // return_pc
+/*Z_R15_H,Z_R15*/ // SP
+);
// Special Class for Condition Code Flags Register
@@ -3378,6 +3391,7 @@
match(RegL);
match(revenRegL);
match(roddRegL);
+ match(allRoddRegL);
match(rarg1RegL);
match(rarg5RegL);
format %{ %}
@@ -3400,6 +3414,14 @@
interface(REG_INTER);
%}
+// available odd registers for iRegL
+operand allRoddRegL() %{
+ constraint(ALLOC_IN_RC(z_long_odd_reg));
+ match(iRegL);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
operand rarg1RegL() %{
constraint(ALLOC_IN_RC(z_rarg1_long_reg));
match(iRegL);
@@ -9899,23 +9921,23 @@
ins_pipe(pipe_class_dummy);
%}
-instruct inlineCallClearArrayConstBig(immL cnt, iRegP_N2P base, Universe dummy, revenRegL srcA, roddRegL srcL, flagsReg cr) %{
+instruct inlineCallClearArrayConstBig(immL cnt, iRegP_N2P base, Universe dummy, allRoddRegL tmpL, flagsReg cr) %{
match(Set dummy (ClearArray cnt base));
- effect(TEMP srcA, TEMP srcL, KILL cr); // R0, R1 are killed, too.
+ effect(TEMP tmpL, KILL cr); // R0, R1 are killed, too.
ins_cost(200);
// TODO: s390 port size(VARIABLE_SIZE); // Variable in size due to optimized constant loader.
format %{ "ClearArrayConstBig $cnt,$base" %}
- ins_encode %{ __ Clear_Array_Const_Big($cnt$$constant, $base$$Register, $srcA$$Register, $srcL$$Register); %}
- ins_pipe(pipe_class_dummy);
-%}
-
-instruct inlineCallClearArray(iRegL cnt, iRegP_N2P base, Universe dummy, revenRegL srcA, roddRegL srcL, flagsReg cr) %{
+ ins_encode %{ __ Clear_Array_Const_Big($cnt$$constant, $base$$Register, $tmpL$$Register); %}
+ ins_pipe(pipe_class_dummy);
+%}
+
+instruct inlineCallClearArray(iRegL cnt, iRegP_N2P base, Universe dummy, allRoddRegL tmpL, flagsReg cr) %{
match(Set dummy (ClearArray cnt base));
- effect(TEMP srcA, TEMP srcL, KILL cr); // R0, R1 are killed, too.
+ effect(TEMP tmpL, KILL cr); // R0, R1 are killed, too.
ins_cost(300);
// TODO: s390 port size(FIXED_SIZE); // z/Architecture: emitted code depends on PreferLAoverADD being on/off.
format %{ "ClearArrayVar $cnt,$base" %}
- ins_encode %{ __ Clear_Array($cnt$$Register, $base$$Register, $srcA$$Register, $srcL$$Register); %}
+ ins_encode %{ __ Clear_Array($cnt$$Register, $base$$Register, $tmpL$$Register); %}
ins_pipe(pipe_class_dummy);
%}
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -2968,9 +2968,8 @@
__ enter();
__ subptr(rsp, 8 * wordSize);
- if (multi_block) {
- __ push(limit);
- }
+ handleSOERegisters(true /*saving*/);
+
__ movptr(buf, buf_param);
__ movptr(state, state_param);
if (multi_block) {
@@ -2981,9 +2980,7 @@
__ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask,
buf, state, ofs, limit, rsp, multi_block);
- if (multi_block) {
- __ pop(limit);
- }
+ handleSOERegisters(false /*restoring*/);
__ addptr(rsp, 8 * wordSize);
__ leave();
__ ret(0);
--- a/src/hotspot/os/aix/os_aix.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/aix/os_aix.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -1405,13 +1405,7 @@
st->print_cr("type: %s", (wi.app_wpar ? "application" : "system"));
}
- // print partition info
- libperfstat::partitioninfo_t pi;
- if (libperfstat::get_partitioninfo(&pi)) {
- st->print_cr("partition info");
- st->print_cr(" name: %s", pi.name);
- }
-
+ VM_Version::print_platform_virtualization_info(st);
}
void os::print_memory_info(outputStream* st) {
--- a/src/hotspot/os/linux/osContainer_linux.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/linux/osContainer_linux.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -122,7 +122,25 @@
char *subsystem_path() { return _path; }
};
-CgroupSubsystem* memory = NULL;
+class CgroupMemorySubsystem: CgroupSubsystem {
+ friend class OSContainer;
+
+ private:
+ /* Some container runtimes set limits via cgroup
+ * hierarchy. If set to true consider also memory.stat
+ * file if everything else seems unlimited */
+ bool _uses_mem_hierarchy;
+
+ public:
+ CgroupMemorySubsystem(char *root, char *mountpoint) : CgroupSubsystem::CgroupSubsystem(root, mountpoint) {
+ _uses_mem_hierarchy = false;
+ }
+
+ bool is_hierarchical() { return _uses_mem_hierarchy; }
+ void set_hierarchical(bool value) { _uses_mem_hierarchy = value; }
+};
+
+CgroupMemorySubsystem* memory = NULL;
CgroupSubsystem* cpuset = NULL;
CgroupSubsystem* cpu = NULL;
CgroupSubsystem* cpuacct = NULL;
@@ -131,21 +149,24 @@
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_NONLITERAL_IGNORED
-template <typename T> int subsystem_file_contents(CgroupSubsystem* c,
+template <typename T> int subsystem_file_line_contents(CgroupSubsystem* c,
const char *filename,
+ const char *matchline,
const char *scan_fmt,
T returnval) {
FILE *fp = NULL;
char *p;
char file[MAXPATHLEN+1];
char buf[MAXPATHLEN+1];
+ char discard[MAXPATHLEN+1];
+ bool found_match = false;
if (c == NULL) {
- log_debug(os, container)("subsystem_file_contents: CgroupSubsytem* is NULL");
+ log_debug(os, container)("subsystem_file_line_contents: CgroupSubsytem* is NULL");
return OSCONTAINER_ERROR;
}
if (c->subsystem_path() == NULL) {
- log_debug(os, container)("subsystem_file_contents: subsystem path is NULL");
+ log_debug(os, container)("subsystem_file_line_contents: subsystem path is NULL");
return OSCONTAINER_ERROR;
}
@@ -160,16 +181,32 @@
log_trace(os, container)("Path to %s is %s", filename, file);
fp = fopen(file, "r");
if (fp != NULL) {
- p = fgets(buf, MAXPATHLEN, fp);
- if (p != NULL) {
- int matched = sscanf(p, scan_fmt, returnval);
- if (matched == 1) {
+ int err = 0;
+ while ((p = fgets(buf, MAXPATHLEN, fp)) != NULL) {
+ found_match = false;
+ if (matchline == NULL) {
+ // single-line file case
+ int matched = sscanf(p, scan_fmt, returnval);
+ found_match = (matched == 1);
+ } else {
+ // multi-line file case
+ if (strstr(p, matchline) != NULL) {
+ // discard matchline string prefix
+ int matched = sscanf(p, scan_fmt, discard, returnval);
+ found_match = (matched == 2);
+ } else {
+ continue; // substring not found
+ }
+ }
+ if (found_match) {
fclose(fp);
return 0;
} else {
+ err = 1;
log_debug(os, container)("Type %s not found in file %s", scan_fmt, file);
}
- } else {
+ }
+ if (err == 0) {
log_debug(os, container)("Empty file %s", file);
}
} else {
@@ -186,10 +223,11 @@
return_type variable; \
{ \
int err; \
- err = subsystem_file_contents(subsystem, \
- filename, \
- scan_fmt, \
- &variable); \
+ err = subsystem_file_line_contents(subsystem, \
+ filename, \
+ NULL, \
+ scan_fmt, \
+ &variable); \
if (err != 0) \
return (return_type) OSCONTAINER_ERROR; \
\
@@ -201,16 +239,33 @@
char variable[bufsize]; \
{ \
int err; \
- err = subsystem_file_contents(subsystem, \
- filename, \
- scan_fmt, \
- variable); \
+ err = subsystem_file_line_contents(subsystem, \
+ filename, \
+ NULL, \
+ scan_fmt, \
+ variable); \
if (err != 0) \
return (return_type) NULL; \
\
log_trace(os, container)(logstring, variable); \
}
+#define GET_CONTAINER_INFO_LINE(return_type, subsystem, filename, \
+ matchline, logstring, scan_fmt, variable) \
+ return_type variable; \
+{ \
+ int err; \
+ err = subsystem_file_line_contents(subsystem, \
+ filename, \
+ matchline, \
+ scan_fmt, \
+ &variable); \
+ if (err != 0) \
+ return (return_type) OSCONTAINER_ERROR; \
+ \
+ log_trace(os, container)(logstring, variable); \
+}
+
/* init
*
* Initialize the container support and determine if
@@ -266,7 +321,7 @@
}
while ((token = strsep(&cptr, ",")) != NULL) {
if (strcmp(token, "memory") == 0) {
- memory = new CgroupSubsystem(tmproot, tmpmount);
+ memory = new CgroupMemorySubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpuset") == 0) {
cpuset = new CgroupSubsystem(tmproot, tmpmount);
} else if (strcmp(token, "cpu") == 0) {
@@ -344,6 +399,10 @@
while ((token = strsep(&controllers, ",")) != NULL) {
if (strcmp(token, "memory") == 0) {
memory->set_subsystem_path(base);
+ jlong hierarchy = uses_mem_hierarchy();
+ if (hierarchy > 0) {
+ memory->set_hierarchical(true);
+ }
} else if (strcmp(token, "cpuset") == 0) {
cpuset->set_subsystem_path(base);
} else if (strcmp(token, "cpu") == 0) {
@@ -360,6 +419,7 @@
// command line arguments have been processed.
if ((mem_limit = memory_limit_in_bytes()) > 0) {
os::Linux::set_physical_memory(mem_limit);
+ log_info(os, container)("Memory Limit is: " JLONG_FORMAT, mem_limit);
}
_is_containerized = true;
@@ -374,6 +434,21 @@
}
}
+/* uses_mem_hierarchy
+ *
+ * Return whether or not hierarchical cgroup accounting is being
+ * done.
+ *
+ * return:
+ * A number > 0 if true, or
+ * OSCONTAINER_ERROR for not supported
+ */
+jlong OSContainer::uses_mem_hierarchy() {
+ GET_CONTAINER_INFO(jlong, memory, "/memory.use_hierarchy",
+ "Use Hierarchy is: " JLONG_FORMAT, JLONG_FORMAT, use_hierarchy);
+ return use_hierarchy;
+}
+
/* memory_limit_in_bytes
*
@@ -389,7 +464,18 @@
"Memory Limit is: " JULONG_FORMAT, JULONG_FORMAT, memlimit);
if (memlimit >= _unlimited_memory) {
- log_trace(os, container)("Memory Limit is: Unlimited");
+ log_trace(os, container)("Non-Hierarchical Memory Limit is: Unlimited");
+ if (memory->is_hierarchical()) {
+ const char* matchline = "hierarchical_memory_limit";
+ char* format = "%s " JULONG_FORMAT;
+ GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
+ "Hierarchical Memory Limit is: " JULONG_FORMAT, format, hier_memlimit)
+ if (hier_memlimit >= _unlimited_memory) {
+ log_trace(os, container)("Hierarchical Memory Limit is: Unlimited");
+ } else {
+ return (jlong)hier_memlimit;
+ }
+ }
return (jlong)-1;
}
else {
@@ -401,7 +487,18 @@
GET_CONTAINER_INFO(julong, memory, "/memory.memsw.limit_in_bytes",
"Memory and Swap Limit is: " JULONG_FORMAT, JULONG_FORMAT, memswlimit);
if (memswlimit >= _unlimited_memory) {
- log_trace(os, container)("Memory and Swap Limit is: Unlimited");
+ log_trace(os, container)("Non-Hierarchical Memory and Swap Limit is: Unlimited");
+ if (memory->is_hierarchical()) {
+ const char* matchline = "hierarchical_memsw_limit";
+ char* format = "%s " JULONG_FORMAT;
+ GET_CONTAINER_INFO_LINE(julong, memory, "/memory.stat", matchline,
+ "Hierarchical Memory and Swap Limit is : " JULONG_FORMAT, format, hier_memlimit)
+ if (hier_memlimit >= _unlimited_memory) {
+ log_trace(os, container)("Hierarchical Memory and Swap Limit is: Unlimited");
+ } else {
+ return (jlong)hier_memlimit;
+ }
+ }
return (jlong)-1;
} else {
return (jlong)memswlimit;
--- a/src/hotspot/os/linux/osContainer_linux.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/linux/osContainer_linux.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -42,6 +42,7 @@
static inline bool is_containerized();
static const char * container_type();
+ static jlong uses_mem_hierarchy();
static jlong memory_limit_in_bytes();
static jlong memory_and_swap_limit_in_bytes();
static jlong memory_soft_limit_in_bytes();
--- a/src/hotspot/os/windows/os_windows.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -5000,17 +5000,13 @@
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
// This OS does not allow existing memory maps to be remapped so we
- // have to unmap the memory before we remap it.
- if (!os::unmap_memory(addr, bytes)) {
- return NULL;
- }
-
- // There is a very small theoretical window between the unmap_memory()
- // call above and the map_memory() call below where a thread in native
- // code may be able to access an address that is no longer mapped.
-
- return os::map_memory(fd, file_name, file_offset, addr, bytes,
- read_only, allow_exec);
+ // would have to unmap the memory before we remap it.
+
+ // Because there is a small window between unmapping memory and mapping
+ // it in again with different protections, CDS archives are mapped RW
+ // on windows, so this function isn't called.
+ ShouldNotReachHere();
+ return NULL;
}
--- a/src/hotspot/share/adlc/formssel.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/adlc/formssel.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -774,10 +774,16 @@
!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
+#if INCLUDE_ZGC
+ !strcmp(_matrule->_rChild->_opType,"LoadBarrierSlowReg") ||
+ !strcmp(_matrule->_rChild->_opType,"LoadBarrierWeakSlowReg") ||
+#endif
+#if INCLUDE_SHENANDOAHGC
+ !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
+ !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN") ||
+#endif
!strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") ||
- !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN") ||
- !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeP") ||
- !strcmp(_matrule->_rChild->_opType,"ShenandoahCompareAndExchangeN"))) return true;
+ !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true;
else if ( is_ideal_load() == Form::idealP ) return true;
else if ( is_ideal_store() != Form::none ) return true;
--- a/src/hotspot/share/classfile/classFileParser.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/classfile/classFileParser.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -5975,9 +5975,9 @@
_minor_version = stream->get_u2_fast();
_major_version = stream->get_u2_fast();
- if (DumpSharedSpaces && _major_version < JAVA_1_5_VERSION) {
+ if (DumpSharedSpaces && _major_version < JAVA_6_VERSION) {
ResourceMark rm;
- warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s",
+ warning("Pre JDK 6 class not supported by CDS: %u.%u %s",
_major_version, _minor_version, _class_name->as_C_string());
Exceptions::fthrow(
THREAD_AND_LOCATION,
--- a/src/hotspot/share/classfile/javaClasses.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/classfile/javaClasses.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -1714,20 +1714,13 @@
jlong java_lang_Thread::stackSize(oop java_thread) {
- if (_stackSize_offset > 0) {
- return java_thread->long_field(_stackSize_offset);
- } else {
- return 0;
- }
+ return java_thread->long_field(_stackSize_offset);
}
// Write the thread status value to threadStatus field in java.lang.Thread java class.
void java_lang_Thread::set_thread_status(oop java_thread,
java_lang_Thread::ThreadStatus status) {
- // The threadStatus is only present starting in 1.5
- if (_thread_status_offset > 0) {
- java_thread->int_field_put(_thread_status_offset, status);
- }
+ java_thread->int_field_put(_thread_status_offset, status);
}
// Read thread status value from threadStatus field in java.lang.Thread java class.
@@ -1737,62 +1730,31 @@
assert(Threads_lock->owned_by_self() || Thread::current()->is_VM_thread() ||
JavaThread::current()->thread_state() == _thread_in_vm,
"Java Thread is not running in vm");
- // The threadStatus is only present starting in 1.5
- if (_thread_status_offset > 0) {
- return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
- } else {
- // All we can easily figure out is if it is alive, but that is
- // enough info for a valid unknown status.
- // These aren't restricted to valid set ThreadStatus values, so
- // use JVMTI values and cast.
- JavaThread* thr = java_lang_Thread::thread(java_thread);
- if (thr == NULL) {
- // the thread hasn't run yet or is in the process of exiting
- return NEW;
- }
- return (java_lang_Thread::ThreadStatus)JVMTI_THREAD_STATE_ALIVE;
- }
+ return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
}
jlong java_lang_Thread::thread_id(oop java_thread) {
- // The thread ID field is only present starting in 1.5
- if (_tid_offset > 0) {
- return java_thread->long_field(_tid_offset);
- } else {
- return 0;
- }
+ return java_thread->long_field(_tid_offset);
}
oop java_lang_Thread::park_blocker(oop java_thread) {
- assert(JDK_Version::current().supports_thread_park_blocker() &&
- _park_blocker_offset != 0, "Must support parkBlocker field");
-
- if (_park_blocker_offset > 0) {
- return java_thread->obj_field(_park_blocker_offset);
- }
-
- return NULL;
+ assert(JDK_Version::current().supports_thread_park_blocker(),
+ "Must support parkBlocker field");
+
+ return java_thread->obj_field(_park_blocker_offset);
}
jlong java_lang_Thread::park_event(oop java_thread) {
- if (_park_event_offset > 0) {
- return java_thread->long_field(_park_event_offset);
- }
- return 0;
+ return java_thread->long_field(_park_event_offset);
}
bool java_lang_Thread::set_park_event(oop java_thread, jlong ptr) {
- if (_park_event_offset > 0) {
- java_thread->long_field_put(_park_event_offset, ptr);
- return true;
- }
- return false;
-}
-
+ java_thread->long_field_put(_park_event_offset, ptr);
+ return true;
+}
const char* java_lang_Thread::thread_status_name(oop java_thread) {
- assert(_thread_status_offset != 0, "Must have thread status");
ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
switch (status) {
case NEW : return "NEW";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
+
+#include "memory/iterator.hpp"
+
+class ShenandoahHeap;
+class ShenandoahMarkingContext;
+class Thread;
+
+class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
+private:
+ ShenandoahMarkingContext* const _mark_context;
+public:
+ inline ShenandoahForwardedIsAliveClosure();
+ inline bool do_object_b(oop obj);
+};
+
+class ShenandoahIsAliveClosure: public BoolObjectClosure {
+private:
+ ShenandoahMarkingContext* const _mark_context;
+public:
+ inline ShenandoahIsAliveClosure();
+ inline bool do_object_b(oop obj);
+};
+
+class ShenandoahIsAliveSelector : public StackObj {
+private:
+ ShenandoahIsAliveClosure _alive_cl;
+ ShenandoahForwardedIsAliveClosure _fwd_alive_cl;
+public:
+ inline BoolObjectClosure* is_alive_closure();
+};
+
+class ShenandoahUpdateRefsClosure: public OopClosure {
+private:
+ ShenandoahHeap* _heap;
+public:
+ inline ShenandoahUpdateRefsClosure();
+ inline void do_oop(oop* p);
+ inline void do_oop(narrowOop* p);
+private:
+ template <class T>
+ inline void do_oop_work(T* p);
+};
+
+class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
+private:
+ ShenandoahHeap* _heap;
+ Thread* _thread;
+public:
+ inline ShenandoahEvacuateUpdateRootsClosure();
+ inline void do_oop(oop* p);
+ inline void do_oop(narrowOop* p);
+
+private:
+ template <class T>
+ inline void do_oop_work(T* p);
+};
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shenandoah/shenandoahClosures.inline.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
+#define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
+
+#include "gc/shenandoah/shenandoahAsserts.hpp"
+#include "gc/shenandoah/shenandoahClosures.hpp"
+#include "gc/shenandoah/shenandoahHeap.inline.hpp"
+#include "oops/compressedOops.inline.hpp"
+#include "runtime/thread.hpp"
+
+ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
+ _mark_context(ShenandoahHeap::heap()->marking_context()) {
+}
+
+bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
+ if (CompressedOops::is_null(obj)) {
+ return false;
+ }
+ obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
+ shenandoah_assert_not_forwarded_if(NULL, obj,
+ (ShenandoahHeap::heap()->is_concurrent_mark_in_progress() ||
+ ShenandoahHeap::heap()->is_concurrent_traversal_in_progress()));
+ return _mark_context->is_marked(obj);
+}
+
+ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
+ _mark_context(ShenandoahHeap::heap()->marking_context()) {
+}
+
+bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
+ if (CompressedOops::is_null(obj)) {
+ return false;
+ }
+ shenandoah_assert_not_forwarded(NULL, obj);
+ return _mark_context->is_marked(obj);
+}
+
+BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
+ return ShenandoahHeap::heap()->has_forwarded_objects() ?
+ reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl) :
+ reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
+}
+
+ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() :
+ _heap(ShenandoahHeap::heap()) {
+}
+
+template <class T>
+void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
+ T o = RawAccess<>::oop_load(p);
+ if (!CompressedOops::is_null(o)) {
+ oop obj = CompressedOops::decode_not_null(o);
+ _heap->update_with_forwarded_not_null(p, obj);
+ }
+}
+
+void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
+void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
+
+ShenandoahEvacuateUpdateRootsClosure::ShenandoahEvacuateUpdateRootsClosure() :
+ _heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
+}
+
+template <class T>
+void ShenandoahEvacuateUpdateRootsClosure::do_oop_work(T* p) {
+ assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
+
+ T o = RawAccess<>::oop_load(p);
+ if (! CompressedOops::is_null(o)) {
+ oop obj = CompressedOops::decode_not_null(o);
+ if (_heap->in_collection_set(obj)) {
+ shenandoah_assert_marked(p, obj);
+ oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
+ if (oopDesc::equals_raw(resolved, obj)) {
+ resolved = _heap->evacuate_object(obj, _thread);
+ }
+ RawAccess<IS_NOT_NULL>::oop_store(p, resolved);
+ }
+ }
+}
+void ShenandoahEvacuateUpdateRootsClosure::do_oop(oop* p) {
+ do_oop_work(p);
+}
+
+void ShenandoahEvacuateUpdateRootsClosure::do_oop(narrowOop* p) {
+ do_oop_work(p);
+}
+
+#endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_HPP
--- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -33,6 +33,7 @@
#include "gc/shared/referenceProcessorPhaseTimes.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.inline.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
#include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
#include "gc/shenandoah/shenandoahMarkCompact.hpp"
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -33,6 +33,7 @@
#include "gc/shenandoah/shenandoahAllocTracker.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#include "gc/shenandoah/shenandoahBrooksPointer.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
#include "gc/shenandoah/shenandoahConcurrentMark.inline.hpp"
@@ -70,8 +71,6 @@
#include "runtime/vmThread.hpp"
#include "services/mallocTracker.hpp"
-ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() : _heap(ShenandoahHeap::heap()) {}
-
#ifdef ASSERT
template <class T>
void ShenandoahAssertToSpaceClosure::do_oop_work(T* p) {
@@ -940,43 +939,6 @@
return CollectedHeap::min_dummy_object_size() + ShenandoahBrooksPointer::word_size();
}
-class ShenandoahEvacuateUpdateRootsClosure: public BasicOopIterateClosure {
-private:
- ShenandoahHeap* _heap;
- Thread* _thread;
-public:
- ShenandoahEvacuateUpdateRootsClosure() :
- _heap(ShenandoahHeap::heap()), _thread(Thread::current()) {
- }
-
-private:
- template <class T>
- void do_oop_work(T* p) {
- assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
-
- T o = RawAccess<>::oop_load(p);
- if (! CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
- if (_heap->in_collection_set(obj)) {
- shenandoah_assert_marked(p, obj);
- oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
- if (oopDesc::equals_raw(resolved, obj)) {
- resolved = _heap->evacuate_object(obj, _thread);
- }
- RawAccess<IS_NOT_NULL>::oop_store(p, resolved);
- }
- }
- }
-
-public:
- void do_oop(oop* p) {
- do_oop_work(p);
- }
- void do_oop(narrowOop* p) {
- do_oop_work(p);
- }
-};
-
class ShenandoahConcurrentEvacuateRegionObjectClosure : public ObjectClosure {
private:
ShenandoahHeap* const _heap;
@@ -1884,31 +1846,6 @@
return result;
}
-ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
- _mark_context(ShenandoahHeap::heap()->marking_context()) {
-}
-
-ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
- _mark_context(ShenandoahHeap::heap()->marking_context()) {
-}
-
-bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
- if (CompressedOops::is_null(obj)) {
- return false;
- }
- obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
- shenandoah_assert_not_forwarded_if(NULL, obj, ShenandoahHeap::heap()->is_concurrent_mark_in_progress() || ShenandoahHeap::heap()->is_concurrent_traversal_in_progress());
- return _mark_context->is_marked(obj);
-}
-
-bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
- if (CompressedOops::is_null(obj)) {
- return false;
- }
- shenandoah_assert_not_forwarded(NULL, obj);
- return _mark_context->is_marked(obj);
-}
-
void ShenandoahHeap::ref_processing_init() {
assert(_max_workers > 0, "Sanity");
@@ -2879,8 +2816,3 @@
ptrdiff_t ShenandoahHeap::cell_header_size() const {
return ShenandoahBrooksPointer::byte_size();
}
-
-BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
- return ShenandoahHeap::heap()->has_forwarded_objects() ? reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl)
- : reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
-}
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -91,19 +91,6 @@
virtual bool is_thread_safe() { return false; }
};
-class ShenandoahUpdateRefsClosure: public OopClosure {
-private:
- ShenandoahHeap* _heap;
-
- template <class T>
- inline void do_oop_work(T* p);
-
-public:
- ShenandoahUpdateRefsClosure();
- inline void do_oop(oop* p);
- inline void do_oop(narrowOop* p);
-};
-
#ifdef ASSERT
class ShenandoahAssertToSpaceClosure : public OopClosure {
private:
@@ -115,29 +102,6 @@
};
#endif
-class ShenandoahForwardedIsAliveClosure: public BoolObjectClosure {
-private:
- ShenandoahMarkingContext* const _mark_context;
-public:
- ShenandoahForwardedIsAliveClosure();
- bool do_object_b(oop obj);
-};
-
-class ShenandoahIsAliveClosure: public BoolObjectClosure {
-private:
- ShenandoahMarkingContext* const _mark_context;
-public:
- ShenandoahIsAliveClosure();
- bool do_object_b(oop obj);
-};
-
-class ShenandoahIsAliveSelector : public StackObj {
-private:
- ShenandoahIsAliveClosure _alive_cl;
- ShenandoahForwardedIsAliveClosure _fwd_alive_cl;
-public:
- BoolObjectClosure* is_alive_closure();
-};
// Shenandoah GC is low-pause concurrent GC that uses Brooks forwarding pointers
// to encode forwarding data. See BrooksPointer for details on forwarding data encoding.
--- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.inline.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -46,17 +46,6 @@
#include "utilities/copy.hpp"
#include "utilities/globalDefinitions.hpp"
-template <class T>
-void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
- T o = RawAccess<>::oop_load(p);
- if (!CompressedOops::is_null(o)) {
- oop obj = CompressedOops::decode_not_null(o);
- _heap->update_with_forwarded_not_null(p, obj);
- }
-}
-
-void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
-void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
inline ShenandoahHeapRegion* ShenandoahRegionIterator::next() {
size_t new_index = Atomic::add((size_t) 1, &_index);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -27,6 +27,7 @@
#include "classfile/stringTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
#include "gc/shenandoah/shenandoahRootProcessor.hpp"
#include "gc/shenandoah/shenandoahHeap.hpp"
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
@@ -242,10 +243,7 @@
_evacuation_tasks(new SubTasksDone(SHENANDOAH_EVAC_NumElements)),
_srs(n_workers),
_phase(phase),
- _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()),
- _par_state_string(StringTable::weak_storage())
-
-{
+ _coderoots_cset_iterator(ShenandoahCodeRoots::cset_iterator()) {
heap->phase_timings()->record_workers_start(_phase);
if (ShenandoahStringDedup::is_enabled()) {
StringDedup::gc_prologue(false);
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -119,7 +119,6 @@
StrongRootsScope _srs;
ShenandoahPhaseTimings::Phase _phase;
ShenandoahCsetCodeRootsIterator _coderoots_cset_iterator;
- OopStorage::ParState<false, false> _par_state_string;
enum Shenandoah_evacuate_roots_tasks {
SHENANDOAH_EVAC_Universe_oops_do,
--- a/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/shenandoah/shenandoahTraversalGC.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -30,6 +30,7 @@
#include "gc/shared/workgroup.hpp"
#include "gc/shared/weakProcessor.inline.hpp"
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
+#include "gc/shenandoah/shenandoahClosures.inline.hpp"
#include "gc/shenandoah/shenandoahCodeRoots.hpp"
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
--- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -55,11 +55,7 @@
// Heal oops and disarm
ZNMethodOopClosure cl;
- nm->oops_do(&cl);
- nm->fix_oop_relocations();
-
- OrderAccess::release();
-
+ ZNMethod::nmethod_oops_do(nm, &cl);
disarm(nm);
return true;
--- a/src/hotspot/share/gc/z/zUnload.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/gc/z/zUnload.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -71,7 +71,7 @@
ZReentrantLock* const lock = ZNMethod::lock_for_nmethod(nm);
ZLocker<ZReentrantLock> locker(lock);
ZIsUnloadingOopClosure cl;
- nm->oops_do(&cl, true /* allow_zombie */);
+ ZNMethod::nmethod_oops_do(nm, &cl);
return cl.is_unloading();
}
};
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -359,7 +359,7 @@
}
bool ret = false;
- thread->set_trace_flag();
+ thread->set_trace_flag(); // Provides StoreLoad, needed to keep read of thread state from floating up.
if (JAVA_SAMPLE == type) {
if (thread_state_in_java(thread)) {
ret = sample_thread_in_java(thread, frames, max_frames);
--- a/src/hotspot/share/memory/filemap.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/memory/filemap.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -806,13 +806,14 @@
addr, size, false /* !read_only */,
si->_allow_exec);
close();
+ // These have to be errors because the shared region is now unmapped.
if (base == NULL) {
- fail_continue("Unable to remap shared readonly space (errno=%d).", errno);
- return false;
+ log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
+ vm_exit(1);
}
if (base != addr) {
- fail_continue("Unable to remap shared readonly space at required address.");
- return false;
+ log_error(cds)("Unable to remap shared readonly space (errno=%d).", errno);
+ vm_exit(1);
}
si->_read_only = false;
return true;
@@ -849,10 +850,17 @@
size_t size = align_up(used, alignment);
char *requested_addr = region_addr(i);
- // If a tool agent is in use (debugging enabled), we must map the address space RW
- if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space()) {
+#ifdef _WINDOWS
+ // Windows cannot remap read-only shared memory to read-write when required for
+ // RedefineClasses, which is also used by JFR. Always map windows regions as RW.
+ si->_read_only = false;
+#else
+ // If a tool agent is in use (debugging enabled), or JFR, we must map the address space RW
+ if (JvmtiExport::can_modify_any_class() || JvmtiExport::can_walk_any_space() ||
+ Arguments::has_jfr_option()) {
si->_read_only = false;
}
+#endif // _WINDOWS
// map the contents of the CDS archive in this memory
char *base = os::map_memory(_fd, _full_path, si->_file_offset,
@@ -868,7 +876,6 @@
MemTracker::record_virtual_memory_type((address)base, mtClassShared);
#endif
-
if (!verify_region_checksum(i)) {
return NULL;
}
--- a/src/hotspot/share/memory/universe.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/memory/universe.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -1151,6 +1151,8 @@
verify_flags |= Verify_JNIHandles;
} else if (strcmp(token, "codecache_oops") == 0) {
verify_flags |= Verify_CodeCacheOops;
+ } else if (strcmp(token, "resolved_method_table") == 0) {
+ verify_flags |= Verify_ResolvedMethodTable;
} else {
vm_exit_during_initialization(err_msg("VerifySubSet: \'%s\' memory sub-system is unknown, please correct it", token));
}
@@ -1230,6 +1232,10 @@
log_debug(gc, verify)("CodeCache Oops");
CodeCache::verify_oops();
}
+ if (should_verify_subset(Verify_ResolvedMethodTable)) {
+ log_debug(gc, verify)("ResolvedMethodTable Oops");
+ ResolvedMethodTable::verify();
+ }
_verify_in_progress = false;
}
--- a/src/hotspot/share/memory/universe.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/memory/universe.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -478,6 +478,7 @@
Verify_MetaspaceUtils = 128,
Verify_JNIHandles = 256,
Verify_CodeCacheOops = 512,
+ Verify_ResolvedMethodTable = 1024,
Verify_All = -1
};
static void initialize_verify_flags();
--- a/src/hotspot/share/prims/resolvedMethodTable.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/prims/resolvedMethodTable.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -346,16 +346,6 @@
// cleaning. Note it might trigger a resize instead.
void ResolvedMethodTable::finish_dead_counter() {
check_concurrent_work();
-
-#ifdef ASSERT
- if (SafepointSynchronize::is_at_safepoint()) {
- size_t fail_cnt = verify_and_compare_entries();
- if (fail_cnt != 0) {
- tty->print_cr("ERROR: fail_cnt=" SIZE_FORMAT, fail_cnt);
- guarantee(fail_cnt == 0, "unexpected ResolvedMethodTable verification failures");
- }
- }
-#endif // ASSERT
}
#if INCLUDE_JVMTI
@@ -402,26 +392,16 @@
}
#endif // INCLUDE_JVMTI
-// Verification and comp
-class VerifyCompResolvedMethod : StackObj {
- GrowableArray<oop>* _oops;
+// Verification
+class VerifyResolvedMethod : StackObj {
public:
- size_t _errors;
- VerifyCompResolvedMethod(GrowableArray<oop>* oops) : _oops(oops), _errors(0) {}
bool operator()(WeakHandle<vm_resolved_method_table_data>* val) {
- oop s = val->peek();
- if (s == NULL) {
- return true;
+ oop obj = val->peek();
+ if (obj != NULL) {
+ Method* method = (Method*)java_lang_invoke_ResolvedMethodName::vmtarget(obj);
+ guarantee(method->is_method(), "Must be");
+ guarantee(!method->is_old(), "Must be");
}
- int len = _oops->length();
- for (int i = 0; i < len; i++) {
- bool eq = s == _oops->at(i);
- assert(!eq, "Duplicate entries");
- if (eq) {
- _errors++;
- }
- }
- _oops->push(s);
return true;
};
};
@@ -430,16 +410,9 @@
return _items_count;
}
-size_t ResolvedMethodTable::verify_and_compare_entries() {
- Thread* thr = Thread::current();
- GrowableArray<oop>* oops =
- new (ResourceObj::C_HEAP, mtInternal)
- GrowableArray<oop>((int)_current_size, true);
-
- VerifyCompResolvedMethod vcs(oops);
- if (!_local_table->try_scan(thr, vcs)) {
+void ResolvedMethodTable::verify() {
+ VerifyResolvedMethod vcs;
+ if (!_local_table->try_scan(Thread::current(), vcs)) {
log_info(membername, table)("verify unavailable at this moment");
}
- delete oops;
- return vcs._errors;
}
--- a/src/hotspot/share/prims/resolvedMethodTable.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/prims/resolvedMethodTable.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -96,7 +96,7 @@
// Debugging
static size_t items_count();
- static size_t verify_and_compare_entries();
+ static void verify();
};
#endif // SHARE_PRIMS_RESOLVEDMETHODTABLE_HPP
--- a/src/hotspot/share/runtime/arguments.cpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.cpp Fri Apr 19 08:00:42 2019 -0400
@@ -271,17 +271,25 @@
}
#if INCLUDE_JFR
+static bool _has_jfr_option = false; // is using JFR
+
// return true on failure
static bool match_jfr_option(const JavaVMOption** option) {
assert((*option)->optionString != NULL, "invariant");
char* tail = NULL;
if (match_option(*option, "-XX:StartFlightRecording", (const char**)&tail)) {
+ _has_jfr_option = true;
return Jfr::on_start_flight_recording_option(option, tail);
} else if (match_option(*option, "-XX:FlightRecorderOptions", (const char**)&tail)) {
+ _has_jfr_option = true;
return Jfr::on_flight_recorder_option(option, tail);
}
return false;
}
+
+bool Arguments::has_jfr_option() {
+ return _has_jfr_option;
+}
#endif
static void logOption(const char* opt) {
--- a/src/hotspot/share/runtime/arguments.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -649,6 +649,8 @@
static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN0;
static bool atojulong(const char *s, julong* result);
+
+ static bool has_jfr_option() NOT_JFR_RETURN_(false);
};
// Disable options not supported in this release, with a warning if they
--- a/src/hotspot/share/runtime/thread.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/runtime/thread.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -1415,7 +1415,7 @@
// Whenever a thread transitions from native to vm/java it must suspend
// if external|deopt suspend is present.
bool is_suspend_after_native() const {
- return (_suspend_flags & (_external_suspend | _deopt_suspend)) != 0;
+ return (_suspend_flags & (_external_suspend | _deopt_suspend JFR_ONLY(| _trace_flag))) != 0;
}
// external suspend request is completed
--- a/src/hotspot/share/utilities/macros.hpp Fri Apr 19 07:55:28 2019 -0400
+++ b/src/hotspot/share/utilities/macros.hpp Fri Apr 19 08:00:42 2019 -0400
@@ -279,8 +279,10 @@
#if INCLUDE_JFR
#define JFR_ONLY(code) code
+#define NOT_JFR_RETURN_(code) /* next token must be ; */
#else
#define JFR_ONLY(code)
+#define NOT_JFR_RETURN_(code) { return code; }
#endif
#ifndef INCLUDE_JVMCI
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/Metrics.java Fri Apr 19 08:00:42 2019 -0400
@@ -25,15 +25,16 @@
package jdk.internal.platform.cgroupv1;
-import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
+import jdk.internal.platform.cgroupv1.SubSystem.MemorySubSystem;
+
public class Metrics implements jdk.internal.platform.Metrics {
- private SubSystem memory;
+ private MemorySubSystem memory;
private SubSystem cpu;
private SubSystem cpuacct;
private SubSystem cpuset;
@@ -133,7 +134,7 @@
for (String subsystemName: subsystemNames) {
switch (subsystemName) {
case "memory":
- metric.setMemorySubSystem(new SubSystem(mountentry[3], mountentry[4]));
+ metric.setMemorySubSystem(new MemorySubSystem(mountentry[3], mountentry[4]));
break;
case "cpuset":
metric.setCpuSetSubSystem(new SubSystem(mountentry[3], mountentry[4]));
@@ -195,6 +196,11 @@
if (subsystem != null) {
subsystem.setPath(base);
+ if (subsystem instanceof MemorySubSystem) {
+ MemorySubSystem memorySubSystem = (MemorySubSystem)subsystem;
+ boolean isHierarchial = getHierarchical(memorySubSystem);
+ memorySubSystem.setHierarchical(isHierarchial);
+ }
metric.setActiveSubSystems();
}
if (subsystem2 != null) {
@@ -203,6 +209,11 @@
}
+ private static boolean getHierarchical(MemorySubSystem subsystem) {
+ long hierarchical = SubSystem.getLongValue(subsystem, "memory.use_hierarchy");
+ return hierarchical > 0;
+ }
+
private void setActiveSubSystems() {
activeSubSystems = true;
}
@@ -211,7 +222,7 @@
return activeSubSystems;
}
- private void setMemorySubSystem(SubSystem memory) {
+ private void setMemorySubSystem(MemorySubSystem memory) {
this.memory = memory;
}
@@ -366,9 +377,29 @@
public long getMemoryLimit() {
long retval = SubSystem.getLongValue(memory, "memory.limit_in_bytes");
+ if (retval > unlimited_minimum) {
+ if (memory.isHierarchical()) {
+ // memory.limit_in_bytes returned unlimited, attempt
+ // hierarchical memory limit
+ String match = "hierarchical_memory_limit";
+ retval = SubSystem.getLongValueMatchingLine(memory,
+ "memory.stat",
+ match,
+ Metrics::convertHierachicalLimitLine);
+ }
+ }
return retval > unlimited_minimum ? -1L : retval;
}
+ public static long convertHierachicalLimitLine(String line) {
+ String[] tokens = line.split("\\s");
+ if (tokens.length == 2) {
+ String strVal = tokens[1];
+ return SubSystem.convertStringToLong(strVal);
+ }
+ return unlimited_minimum + 1; // unlimited
+ }
+
public long getMemoryMaxUsage() {
return SubSystem.getLongValue(memory, "memory.max_usage_in_bytes");
}
@@ -417,6 +448,17 @@
public long getMemoryAndSwapLimit() {
long retval = SubSystem.getLongValue(memory, "memory.memsw.limit_in_bytes");
+ if (retval > unlimited_minimum) {
+ if (memory.isHierarchical()) {
+ // memory.memsw.limit_in_bytes returned unlimited, attempt
+ // hierarchical memory limit
+ String match = "hierarchical_memsw_limit";
+ retval = SubSystem.getLongValueMatchingLine(memory,
+ "memory.stat",
+ match,
+ Metrics::convertHierachicalLimitLine);
+ }
+ }
return retval > unlimited_minimum ? -1L : retval;
}
--- a/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/linux/classes/jdk/internal/platform/cgroupv1/SubSystem.java Fri Apr 19 08:00:42 2019 -0400
@@ -29,10 +29,11 @@
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
-import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
+import java.util.List;
import java.util.Optional;
+import java.util.function.Function;
import java.util.stream.Stream;
public class SubSystem {
@@ -99,10 +100,32 @@
}
+ public static long getLongValueMatchingLine(SubSystem subsystem,
+ String param,
+ String match,
+ Function<String, Long> conversion) {
+ long retval = Metrics.unlimited_minimum + 1; // default unlimited
+ try {
+ List<String> lines = Files.readAllLines(Paths.get(subsystem.path(), param));
+ for (String line: lines) {
+ if (line.contains(match)) {
+ retval = conversion.apply(line);
+ break;
+ }
+ }
+ } catch (IOException e) {
+ // Ignore. Default is unlimited.
+ }
+ return retval;
+ }
+
public static long getLongValue(SubSystem subsystem, String parm) {
String strval = getStringValue(subsystem, parm);
+ return convertStringToLong(strval);
+ }
+
+ public static long convertStringToLong(String strval) {
long retval = 0;
-
if (strval == null) return 0L;
try {
@@ -215,4 +238,22 @@
return ints;
}
+
+ public static class MemorySubSystem extends SubSystem {
+
+ private boolean hierarchical;
+
+ public MemorySubSystem(String root, String mountPoint) {
+ super(root, mountPoint);
+ }
+
+ boolean isHierarchical() {
+ return hierarchical;
+ }
+
+ void setHierarchical(boolean hierarchical) {
+ this.hierarchical = hierarchical;
+ }
+
+ }
}
--- a/src/java.base/share/classes/java/lang/String.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/String.java Fri Apr 19 08:00:42 2019 -0400
@@ -1965,20 +1965,7 @@
if (str.isEmpty()) {
return this;
}
- if (coder() == str.coder()) {
- byte[] val = this.value;
- byte[] oval = str.value;
- int len = val.length + oval.length;
- byte[] buf = Arrays.copyOf(val, len);
- System.arraycopy(oval, 0, buf, val.length, oval.length);
- return new String(buf, coder);
- }
- int len = length();
- int olen = str.length();
- byte[] buf = StringUTF16.newBytesFor(len + olen);
- getBytes(buf, 0, UTF16);
- str.getBytes(buf, len, UTF16);
- return new String(buf, UTF16);
+ return StringConcatHelper.simpleConcat(this, str);
}
/**
--- a/src/java.base/share/classes/java/lang/StringConcatHelper.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/StringConcatHelper.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@
package java.lang;
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.ForceInline;
+
/**
* Helper for string concatenation. These methods are mostly looked up with private lookups
* from {@link java.lang.invoke.StringConcatFactory}, and used in {@link java.lang.invoke.MethodHandle}
@@ -38,8 +41,10 @@
/**
* Check for overflow, throw exception on overflow.
- * @param lengthCoder String length and coder
- * @return lengthCoder
+ *
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @return the given parameter value, if valid
*/
private static long checkOverflow(long lengthCoder) {
if ((int)lengthCoder >= 0) {
@@ -50,76 +55,83 @@
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, boolean value) {
- return checkOverflow(current + (value ? 4 : 5));
+ static long mix(long lengthCoder, boolean value) {
+ return checkOverflow(lengthCoder + (value ? 4 : 5));
}
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, byte value) {
- return mix(current, (int)value);
+ static long mix(long lengthCoder, byte value) {
+ return mix(lengthCoder, (int)value);
}
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, char value) {
- return checkOverflow(current + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
+ static long mix(long lengthCoder, char value) {
+ return checkOverflow(lengthCoder + 1) | (StringLatin1.canEncode(value) ? 0 : UTF16);
}
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, short value) {
- return mix(current, (int)value);
+ static long mix(long lengthCoder, short value) {
+ return mix(lengthCoder, (int)value);
}
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, int value) {
- return checkOverflow(current + Integer.stringSize(value));
+ static long mix(long lengthCoder, int value) {
+ return checkOverflow(lengthCoder + Integer.stringSize(value));
}
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, long value) {
- return checkOverflow(current + Long.stringSize(value));
+ static long mix(long lengthCoder, long value) {
+ return checkOverflow(lengthCoder + Long.stringSize(value));
}
/**
* Mix value length and coder into current length and coder.
- * @param current current length
- * @param value value to mix in
- * @return new length and coder
+ * @param lengthCoder String length with coder packed into higher bits
+ * the upper word.
+ * @param value value to mix in
+ * @return new length and coder
*/
- static long mix(long current, String value) {
- current += value.length();
+ static long mix(long lengthCoder, String value) {
+ lengthCoder += value.length();
if (value.coder() == String.UTF16) {
- current |= UTF16;
+ lengthCoder |= UTF16;
}
- return checkOverflow(current);
+ return checkOverflow(lengthCoder);
}
/**
@@ -285,10 +297,62 @@
}
}
+ /**
+ * Perform a simple concatenation between two objects. Added for startup
+ * performance, but also demonstrates the code that would be emitted by
+ * {@code java.lang.invoke.StringConcatFactory$MethodHandleInlineCopyStrategy}
+ * for two Object arguments.
+ *
+ * @param first first argument
+ * @param second second argument
+ * @return String resulting string
+ */
+ @ForceInline
+ static String simpleConcat(Object first, Object second) {
+ String s1 = stringOf(first);
+ String s2 = stringOf(second);
+ // start "mixing" in length and coder or arguments, order is not
+ // important
+ long indexCoder = mix(initialCoder(), s2);
+ indexCoder = mix(indexCoder, s1);
+ byte[] buf = newArray(indexCoder);
+ // prepend each argument in reverse order, since we prepending
+ // from the end of the byte array
+ indexCoder = prepend(indexCoder, buf, s2);
+ indexCoder = prepend(indexCoder, buf, s1);
+ return newString(buf, indexCoder);
+ }
+
+ /**
+ * We need some additional conversion for Objects in general, because
+ * {@code String.valueOf(Object)} may return null. String conversion rules
+ * in Java state we need to produce "null" String in this case, so we
+ * provide a customized version that deals with this problematic corner case.
+ */
+ static String stringOf(Object value) {
+ String s;
+ return (value == null || (s = value.toString()) == null) ? "null" : s;
+ }
+
private static final long LATIN1 = (long)String.LATIN1 << 32;
private static final long UTF16 = (long)String.UTF16 << 32;
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+
+ /**
+ * Allocates an uninitialized byte array based on the length and coder information
+ * in indexCoder
+ * @param indexCoder
+ * @return the newly allocated byte array
+ */
+ @ForceInline
+ static byte[] newArray(long indexCoder) {
+ byte coder = (byte)(indexCoder >> 32);
+ int index = (int)indexCoder;
+ return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
+ }
+
/**
* Provides the initial coder for the String.
* @return initial coder, adjusted into the upper half
--- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* 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 java.lang.invoke;
import jdk.internal.misc.Unsafe;
+import jdk.internal.misc.VM;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Label;
import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -191,6 +192,8 @@
*/
private static final ProxyClassesDumper DUMPER;
+ private static final Class<?> STRING_HELPER;
+
static {
// In case we need to double-back onto the StringConcatFactory during this
// static initialization, make sure we have the reasonable defaults to complete
@@ -202,15 +205,20 @@
// DEBUG = false; // implied
// DUMPER = null; // implied
- Properties props = GetPropertyAction.privilegedGetProperties();
+ try {
+ STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
+ } catch (Throwable e) {
+ throw new AssertionError(e);
+ }
+
final String strategy =
- props.getProperty("java.lang.invoke.stringConcat");
+ VM.getSavedProperty("java.lang.invoke.stringConcat");
CACHE_ENABLE = Boolean.parseBoolean(
- props.getProperty("java.lang.invoke.stringConcat.cache"));
+ VM.getSavedProperty("java.lang.invoke.stringConcat.cache"));
DEBUG = Boolean.parseBoolean(
- props.getProperty("java.lang.invoke.stringConcat.debug"));
+ VM.getSavedProperty("java.lang.invoke.stringConcat.debug"));
final String dumpPath =
- props.getProperty("java.lang.invoke.stringConcat.dumpClasses");
+ VM.getSavedProperty("java.lang.invoke.stringConcat.dumpClasses");
STRATEGY = (strategy == null) ? DEFAULT_STRATEGY : Strategy.valueOf(strategy);
CACHE = CACHE_ENABLE ? new ConcurrentHashMap<>() : null;
@@ -1519,6 +1527,33 @@
static MethodHandle generate(MethodType mt, Recipe recipe) throws Throwable {
+ // Fast-path two-argument Object + Object concatenations
+ if (recipe.getElements().size() == 2) {
+ // Two object arguments
+ if (mt.parameterCount() == 2 &&
+ !mt.parameterType(0).isPrimitive() &&
+ !mt.parameterType(1).isPrimitive()) {
+ return SIMPLE;
+ }
+ // One element is a constant
+ if (mt.parameterCount() == 1 && !mt.parameterType(0).isPrimitive()) {
+ MethodHandle mh = SIMPLE;
+ // Insert constant element
+
+ // First recipe element is a constant
+ if (recipe.getElements().get(0).getTag() == TAG_CONST &&
+ recipe.getElements().get(1).getTag() != TAG_CONST) {
+ return MethodHandles.insertArguments(mh, 0,
+ recipe.getElements().get(0).getValue());
+ } else if (recipe.getElements().get(1).getTag() == TAG_CONST &&
+ recipe.getElements().get(0).getTag() != TAG_CONST) {
+ return MethodHandles.insertArguments(mh, 1,
+ recipe.getElements().get(1).getValue());
+ }
+ // else... fall-through to slow-path
+ }
+ }
+
// Create filters and obtain filtered parameter types. Filters would be used in the beginning
// to convert the incoming arguments into the arguments we can process (e.g. Objects -> Strings).
// The filtered argument type list is used all over in the combinators below.
@@ -1626,13 +1661,6 @@
return mh;
}
- @ForceInline
- private static byte[] newArray(long indexCoder) {
- byte coder = (byte)(indexCoder >> 32);
- int index = (int)indexCoder;
- return (byte[]) UNSAFE.allocateUninitializedArray(byte.class, index << coder);
- }
-
private static MethodHandle prepender(Class<?> cl) {
return PREPENDERS.computeIfAbsent(cl, PREPEND);
}
@@ -1659,16 +1687,15 @@
}
};
+ private static final MethodHandle SIMPLE;
private static final MethodHandle NEW_STRING;
private static final MethodHandle NEW_ARRAY;
private static final ConcurrentMap<Class<?>, MethodHandle> PREPENDERS;
private static final ConcurrentMap<Class<?>, MethodHandle> MIXERS;
private static final long INITIAL_CODER;
- static final Class<?> STRING_HELPER;
static {
try {
- STRING_HELPER = Class.forName("java.lang.StringConcatHelper");
MethodHandle initCoder = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "initialCoder", long.class);
INITIAL_CODER = (long) initCoder.invoke();
} catch (Throwable e) {
@@ -1678,8 +1705,9 @@
PREPENDERS = new ConcurrentHashMap<>();
MIXERS = new ConcurrentHashMap<>();
+ SIMPLE = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "simpleConcat", String.class, Object.class, Object.class);
NEW_STRING = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newString", String.class, byte[].class, long.class);
- NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, MethodHandleInlineCopyStrategy.class, "newArray", byte[].class, long.class);
+ NEW_ARRAY = lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "newArray", byte[].class, long.class);
}
}
@@ -1692,22 +1720,8 @@
// no instantiation
}
- private static class ObjectStringifier {
-
- // We need some additional conversion for Objects in general, because String.valueOf(Object)
- // may return null. String conversion rules in Java state we need to produce "null" String
- // in this case, so we provide a customized version that deals with this problematic corner case.
- private static String valueOf(Object value) {
- String s;
- return (value == null || (s = value.toString()) == null) ? "null" : s;
- }
-
- // Could have used MethodHandles.lookup() instead of Lookup.IMPL_LOOKUP, if not for the fact
- // java.lang.invoke Lookups are explicitly forbidden to be retrieved using that API.
- private static final MethodHandle INSTANCE =
- lookupStatic(Lookup.IMPL_LOOKUP, ObjectStringifier.class, "valueOf", String.class, Object.class);
-
- }
+ private static final MethodHandle OBJECT_INSTANCE =
+ lookupStatic(Lookup.IMPL_LOOKUP, STRING_HELPER, "stringOf", String.class, Object.class);
private static class FloatStringifiers {
private static final MethodHandle FLOAT_INSTANCE =
@@ -1751,7 +1765,7 @@
*/
static MethodHandle forMost(Class<?> t) {
if (!t.isPrimitive()) {
- return ObjectStringifier.INSTANCE;
+ return OBJECT_INSTANCE;
} else if (t == float.class) {
return FloatStringifiers.FLOAT_INSTANCE;
} else if (t == double.class) {
--- a/src/java.base/share/classes/java/math/BigDecimal.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/math/BigDecimal.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -3414,9 +3414,32 @@
*/
@Override
public long longValue(){
- return (intCompact != INFLATED && scale == 0) ?
- intCompact:
- toBigInteger().longValue();
+ if (intCompact != INFLATED && scale == 0) {
+ return intCompact;
+ } else {
+ // Fastpath zero and small values
+ if (this.signum() == 0 || fractionOnly() ||
+ // Fastpath very large-scale values that will result
+ // in a truncated value of zero. If the scale is -64
+ // or less, there are at least 64 powers of 10 in the
+ // value of the numerical result. Since 10 = 2*5, in
+ // that case there would also be 64 powers of 2 in the
+ // result, meaning all 64 bits of a long will be zero.
+ scale <= -64) {
+ return 0;
+ } else {
+ return toBigInteger().longValue();
+ }
+ }
+ }
+
+ /**
+ * Return true if a nonzero BigDecimal has an absolute value less
+ * than one; i.e. only has fraction digits.
+ */
+ private boolean fractionOnly() {
+ assert this.signum() != 0;
+ return (this.precision() - this.scale) <= 0;
}
/**
@@ -3434,15 +3457,20 @@
public long longValueExact() {
if (intCompact != INFLATED && scale == 0)
return intCompact;
+
+ // Fastpath zero
+ if (this.signum() == 0)
+ return 0;
+
+ // Fastpath numbers less than 1.0 (the latter can be very slow
+ // to round if very small)
+ if (fractionOnly())
+ throw new ArithmeticException("Rounding necessary");
+
// If more than 19 digits in integer part it cannot possibly fit
if ((precision() - scale) > 19) // [OK for negative scale too]
throw new java.lang.ArithmeticException("Overflow");
- // Fastpath zero and < 1.0 numbers (the latter can be very slow
- // to round if very small)
- if (this.signum() == 0)
- return 0;
- if ((this.precision() - this.scale) <= 0)
- throw new ArithmeticException("Rounding necessary");
+
// round to an integer, with Exception if decimal part non-0
BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
if (num.precision() >= 19) // need to check carefully
@@ -3486,7 +3514,7 @@
public int intValue() {
return (intCompact != INFLATED && scale == 0) ?
(int)intCompact :
- toBigInteger().intValue();
+ (int)longValue();
}
/**
--- a/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Fri Apr 19 08:00:42 2019 -0400
@@ -154,6 +154,8 @@
* The singleton instance for the 'Reiwa' era (2019-05-01 - )
* which has the value 3. The end date of this era is not specified, unless
* the Japanese Government defines it.
+ *
+ * @since 13
*/
public static final JapaneseEra REIWA = new JapaneseEra(3, LocalDate.of(2019, 5, 1));
--- a/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* 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,10 +28,20 @@
package sun.nio.cs;
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.charset.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.Reader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
public class StreamDecoder extends Reader
{
@@ -190,8 +200,11 @@
synchronized (lock) {
if (closed)
return;
- implClose();
- closed = true;
+ try {
+ implClose();
+ } finally {
+ closed = true;
+ }
}
}
--- a/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,21 @@
* questions.
*/
-/*
- */
-
package sun.nio.cs;
-import java.io.*;
-import java.nio.*;
-import java.nio.channels.*;
-import java.nio.charset.*;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.IllegalCharsetNameException;
public class StreamEncoder extends Writer
{
@@ -158,8 +164,11 @@
synchronized (lock) {
if (closed)
return;
- implClose();
- closed = true;
+ try {
+ implClose();
+ } finally {
+ closed = true;
+ }
}
}
@@ -337,8 +346,13 @@
writeBytes();
if (ch != null)
ch.close();
- else
- out.close();
+ else {
+ try {
+ out.flush();
+ } finally {
+ out.close();
+ }
+ }
} catch (IOException x) {
encoder.reset();
throw x;
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Fri Apr 19 08:00:42 2019 -0400
@@ -980,7 +980,7 @@
}
try {
- shutdownInput(false);
+ SSLSocketImpl.this.close();
} catch (IOException ioe) {
// ignore the exception
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
@@ -1146,7 +1146,7 @@
}
try {
- shutdownOutput();
+ SSLSocketImpl.this.close();
} catch (IOException ioe) {
// ignore the exception
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
--- a/src/java.base/share/native/libjli/java.c Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.base/share/native/libjli/java.c Fri Apr 19 08:00:42 2019 -0400
@@ -204,11 +204,14 @@
*/
static jlong threadStackSize = 0; /* stack size of the new thread */
static jlong maxHeapSize = 0; /* max heap size */
-static jlong initialHeapSize = 0; /* inital heap size */
+static jlong initialHeapSize = 0; /* initial heap size */
/*
- * A minimum -Xss stack size suitable for all platforms.
- */
+ * A minimum initial-thread stack size suitable for most platforms.
+ * This is the minimum amount of stack needed to load the JVM such
+ * that it can reject a too small -Xss value. If this is too small
+ * JVM initialization would cause a StackOverflowError.
+ */
#ifndef STACK_SIZE_MINIMUM
#define STACK_SIZE_MINIMUM (64 * KB)
#endif
@@ -934,16 +937,18 @@
options[numOptions].optionString = str;
options[numOptions++].extraInfo = info;
+ /*
+ * -Xss is used both by the JVM and here to establish the stack size of the thread
+ * created to launch the JVM. In the latter case we need to ensure we don't go
+ * below the minimum stack size allowed. If -Xss is zero that tells the JVM to use
+ * 'default' sizes (either from JVM or system configuration, e.g. 'ulimit -s' on linux),
+ * and is not itself a small stack size that will be rejected. So we ignore -Xss0 here.
+ */
if (JLI_StrCCmp(str, "-Xss") == 0) {
jlong tmp;
if (parse_size(str + 4, &tmp)) {
threadStackSize = tmp;
- /*
- * Make sure the thread stack size is big enough that we won't get a stack
- * overflow before the JVM startup code can check to make sure the stack
- * is big enough.
- */
- if (threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
+ if (threadStackSize > 0 && threadStackSize < (jlong)STACK_SIZE_MINIMUM) {
threadStackSize = STACK_SIZE_MINIMUM;
}
}
@@ -2322,38 +2327,38 @@
int argc, char **argv,
int mode, char *what, int ret)
{
-
- /*
- * If user doesn't specify stack size, check if VM has a preference.
- * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
- * return its default stack size through the init args structure.
- */
if (threadStackSize == 0) {
- struct JDK1_1InitArgs args1_1;
- memset((void*)&args1_1, 0, sizeof(args1_1));
- args1_1.version = JNI_VERSION_1_1;
- ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
- if (args1_1.javaStackSize > 0) {
- threadStackSize = args1_1.javaStackSize;
- }
+ /*
+ * If the user hasn't specified a non-zero stack size ask the JVM for its default.
+ * A returned 0 means 'use the system default' for a platform, e.g., Windows.
+ * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will
+ * return its default stack size through the init args structure.
+ */
+ struct JDK1_1InitArgs args1_1;
+ memset((void*)&args1_1, 0, sizeof(args1_1));
+ args1_1.version = JNI_VERSION_1_1;
+ ifn->GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */
+ if (args1_1.javaStackSize > 0) {
+ threadStackSize = args1_1.javaStackSize;
+ }
}
{ /* Create a new thread to create JVM and invoke main method */
- JavaMainArgs args;
- int rslt;
+ JavaMainArgs args;
+ int rslt;
- args.argc = argc;
- args.argv = argv;
- args.mode = mode;
- args.what = what;
- args.ifn = *ifn;
+ args.argc = argc;
+ args.argv = argv;
+ args.mode = mode;
+ args.what = what;
+ args.ifn = *ifn;
- rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
- /* If the caller has deemed there is an error we
- * simply return that, otherwise we return the value of
- * the callee
- */
- return (ret != 0) ? ret : rslt;
+ rslt = CallJavaMainInNewThread(threadStackSize, (void*)&args);
+ /* If the caller has deemed there is an error we
+ * simply return that, otherwise we return the value of
+ * the callee
+ */
+ return (ret != 0) ? ret : rslt;
}
}
--- a/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.compiler/share/classes/javax/annotation/processing/ProcessingEnvironment.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -131,4 +131,18 @@
* effect
*/
Locale getLocale();
+
+ /**
+ * Returns {@code true} if <em>preview features</em> are enabled
+ * and {@code false} otherwise.
+ * @return whether or not preview features are enabled
+ *
+ * @implSpec The default implementation of this method returns
+ * {@code false}.
+ *
+ * @since 13
+ */
+ default boolean isPreviewEnabled() {
+ return false;
+ }
}
--- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,8 @@
HttpClient client = http1Exchange.client();
// Filter overridable headers from userHeaders
- userHeaders = HttpHeaders.of(userHeaders.map(), Utils.CONTEXT_RESTRICTED(client));
+ userHeaders = HttpHeaders.of(userHeaders.map(),
+ connection.contextRestricted(request, client));
final HttpHeaders uh = userHeaders;
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpConnection.java Fri Apr 19 08:00:42 2019 -0400
@@ -285,6 +285,16 @@
}
}
+ BiPredicate<String,String> contextRestricted(HttpRequestImpl request, HttpClient client) {
+ if (!isTunnel() && request.isConnect()) {
+ // establishing a proxy tunnel
+ assert request.proxy() == null;
+ return Utils.PROXY_TUNNEL_RESTRICTED(client);
+ } else {
+ return Utils.CONTEXT_RESTRICTED(client);
+ }
+ }
+
// Composes a new immutable HttpHeaders that combines the
// user and system header but only keeps those headers that
// start with "proxy-"
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java Fri Apr 19 08:00:42 2019 -0400
@@ -178,7 +178,12 @@
! (k.equalsIgnoreCase("Authorization")
&& k.equalsIgnoreCase("Proxy-Authorization"));
}
+ private static final BiPredicate<String, String> HOST_RESTRICTED = (k,v) -> !"host".equalsIgnoreCase(k);
+ public static final BiPredicate<String, String> PROXY_TUNNEL_RESTRICTED(HttpClient client) {
+ return CONTEXT_RESTRICTED(client).and(HOST_RESTRICTED);
+ }
+ private static final Predicate<String> IS_HOST = "host"::equalsIgnoreCase;
private static final Predicate<String> IS_PROXY_HEADER = (k) ->
k != null && k.length() > 6 && "proxy-".equalsIgnoreCase(k.substring(0,6));
private static final Predicate<String> NO_PROXY_HEADER =
@@ -250,7 +255,8 @@
public static final BiPredicate<String, String> PROXY_TUNNEL_FILTER =
(s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_TUNNEL_DISABLED_SCHEMES,
- IS_PROXY_HEADER);
+ // Allows Proxy-* and Host headers when establishing the tunnel.
+ IS_PROXY_HEADER.or(IS_HOST));
public static final BiPredicate<String, String> PROXY_FILTER =
(s,v) -> isAllowedForProxy(s, v, PROXY_AUTH_DISABLED_SCHEMES,
ALL_HEADERS);
--- a/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/registry/RegistryImpl_Skel.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -58,8 +58,24 @@
public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
throws java.lang.Exception {
- if (hash != interfaceHash)
- throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
+ if (opnum < 0) {
+ if (hash == 7583982177005850366L) {
+ opnum = 0;
+ } else if (hash == 2571371476350237748L) {
+ opnum = 1;
+ } else if (hash == -7538657168040752697L) {
+ opnum = 2;
+ } else if (hash == -8381844669958460146L) {
+ opnum = 3;
+ } else if (hash == 7305022919901907578L) {
+ opnum = 4;
+ } else {
+ throw new java.rmi.UnmarshalException("invalid method hash");
+ }
+ } else {
+ if (hash != interfaceHash)
+ throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
+ }
sun.rmi.registry.RegistryImpl server = (sun.rmi.registry.RegistryImpl) obj;
switch (opnum) {
--- a/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.rmi/share/classes/sun/rmi/server/UnicastServerRef.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,7 @@
import java.rmi.ServerException;
import java.rmi.UnmarshalException;
import java.rmi.server.ExportException;
+import java.rmi.server.Operation;
import java.rmi.server.RemoteCall;
import java.rmi.server.RemoteRef;
import java.rmi.server.RemoteStub;
@@ -292,15 +293,14 @@
throw new UnmarshalException("error unmarshalling call header",
readEx);
}
- if (num >= 0) {
- if (skel != null) {
+ if (skel != null) {
+ // If there is a skeleton, use it
oldDispatch(obj, call, num);
return;
- } else {
- throw new UnmarshalException(
- "skeleton class not found but required " +
- "for client version");
- }
+
+ } else if (num >= 0){
+ throw new UnmarshalException(
+ "skeleton class not found but required for client version");
}
try {
op = in.readLong();
@@ -428,8 +428,8 @@
/**
* Handle server-side dispatch using the RMI 1.1 stub/skeleton
- * protocol, given a non-negative operation number that has
- * already been read from the call stream.
+ * protocol, given a non-negative operation number or negative method hash
+ * that has already been read from the call stream.
* Exceptions are handled by the caller to be sent to the remote client.
*
* @param obj the target remote object for the call
@@ -461,7 +461,8 @@
}
// if calls are being logged, write out object id and operation
- logCall(obj, skel.getOperations()[op]);
+ Operation[] operations = skel.getOperations();
+ logCall(obj, op >= 0 && op < operations.length ? operations[op] : "op: " + op);
unmarshalCustomCallData(in);
// dispatch to skeleton for remote object
skel.dispatch(obj, call, op, hash);
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -22,6 +22,7 @@
import com.sun.org.apache.xerces.internal.impl.io.ASCIIReader;
import com.sun.org.apache.xerces.internal.impl.io.UCSReader;
+import com.sun.org.apache.xerces.internal.impl.io.UTF16Reader;
import com.sun.org.apache.xerces.internal.impl.io.UTF8Reader;
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
@@ -89,7 +90,7 @@
* @author K.Venugopal SUN Microsystems
* @author Neeraj Bajaj SUN Microsystems
* @author Sunitha Reddy SUN Microsystems
- * @LastModified: Nov 2018
+ * @LastModified: Apr 2019
*/
public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
@@ -412,9 +413,6 @@
/** Augmentations for entities. */
private final Augmentations fEntityAugs = new AugmentationsImpl();
- /** Pool of character buffers. */
- private CharacterBufferPool fBufferPool = new CharacterBufferPool(fBufferSize, DEFAULT_INTERNAL_BUFFER_SIZE);
-
/** indicate whether Catalog should be used for resolving external resources */
private boolean fUseCatalog = true;
CatalogFeatures fCatalogFeatures;
@@ -694,7 +692,8 @@
}
// wrap this stream in RewindableInputStream
- stream = new RewindableInputStream(stream);
+ RewindableInputStream rewindableStream = new RewindableInputStream(stream);
+ stream = rewindableStream;
// perform auto-detect of encoding if necessary
if (encoding == null) {
@@ -702,27 +701,30 @@
final byte[] b4 = new byte[4];
int count = 0;
for (; count<4; count++ ) {
- b4[count] = (byte)stream.read();
+ b4[count] = (byte)rewindableStream.readAndBuffer();
}
if (count == 4) {
- Object [] encodingDesc = getEncodingName(b4, count);
- encoding = (String)(encodingDesc[0]);
- isBigEndian = (Boolean)(encodingDesc[1]);
-
+ final EncodingInfo info = getEncodingInfo(b4, count);
+ encoding = info.autoDetectedEncoding;
+ final String readerEncoding = info.readerEncoding;
+ isBigEndian = info.isBigEndian;
stream.reset();
- // Special case UTF-8 files with BOM created by Microsoft
- // tools. It's more efficient to consume the BOM than make
- // the reader perform extra checks. -Ac
- if (count > 2 && encoding.equals("UTF-8")) {
- int b0 = b4[0] & 0xFF;
- int b1 = b4[1] & 0xFF;
- int b2 = b4[2] & 0xFF;
- if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
- // ignore first three bytes...
+ if (info.hasBOM) {
+ // Special case UTF-8 files with BOM created by Microsoft
+ // tools. It's more efficient to consume the BOM than make
+ // the reader perform extra checks. -Ac
+ if (EncodingInfo.STR_UTF8.equals(readerEncoding)) {
+ // UTF-8 BOM: 0xEF 0xBB 0xBF
stream.skip(3);
}
+ // It's also more efficient to consume the UTF-16 BOM.
+ else if (EncodingInfo.STR_UTF16.equals(readerEncoding)) {
+ // UTF-16 BE BOM: 0xFE 0xFF
+ // UTF-16 LE BOM: 0xFF 0xFE
+ stream.skip(2);
+ }
}
- reader = createReader(stream, encoding, isBigEndian);
+ reader = createReader(stream, readerEncoding, isBigEndian);
} else {
reader = createReader(stream, encoding, isBigEndian);
}
@@ -733,11 +735,11 @@
encoding = encoding.toUpperCase(Locale.ENGLISH);
// If encoding is UTF-8, consume BOM if one is present.
- if (encoding.equals("UTF-8")) {
+ if (EncodingInfo.STR_UTF8.equals(encoding)) {
final int[] b3 = new int[3];
int count = 0;
for (; count < 3; ++count) {
- b3[count] = stream.read();
+ b3[count] = rewindableStream.readAndBuffer();
if (b3[count] == -1)
break;
}
@@ -750,56 +752,51 @@
stream.reset();
}
}
- // If encoding is UTF-16, we still need to read the first four bytes
- // in order to discover the byte order.
- else if (encoding.equals("UTF-16")) {
+ // If encoding is UTF-16, we still need to read the first
+ // four bytes, in order to discover the byte order.
+ else if (EncodingInfo.STR_UTF16.equals(encoding)) {
final int[] b4 = new int[4];
int count = 0;
for (; count < 4; ++count) {
- b4[count] = stream.read();
+ b4[count] = rewindableStream.readAndBuffer();
if (b4[count] == -1)
break;
}
stream.reset();
-
- String utf16Encoding = "UTF-16";
if (count >= 2) {
final int b0 = b4[0];
final int b1 = b4[1];
if (b0 == 0xFE && b1 == 0xFF) {
// UTF-16, big-endian
- utf16Encoding = "UTF-16BE";
isBigEndian = Boolean.TRUE;
+ stream.skip(2);
}
else if (b0 == 0xFF && b1 == 0xFE) {
// UTF-16, little-endian
- utf16Encoding = "UTF-16LE";
isBigEndian = Boolean.FALSE;
+ stream.skip(2);
}
else if (count == 4) {
final int b2 = b4[2];
final int b3 = b4[3];
if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
// UTF-16, big-endian, no BOM
- utf16Encoding = "UTF-16BE";
isBigEndian = Boolean.TRUE;
}
if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
// UTF-16, little-endian, no BOM
- utf16Encoding = "UTF-16LE";
isBigEndian = Boolean.FALSE;
}
}
}
- reader = createReader(stream, utf16Encoding, isBigEndian);
}
// If encoding is UCS-4, we still need to read the first four bytes
// in order to discover the byte order.
- else if (encoding.equals("ISO-10646-UCS-4")) {
+ else if (EncodingInfo.STR_UCS4.equals(encoding)) {
final int[] b4 = new int[4];
int count = 0;
for (; count < 4; ++count) {
- b4[count] = stream.read();
+ b4[count] = rewindableStream.readAndBuffer();
if (b4[count] == -1)
break;
}
@@ -819,11 +816,11 @@
}
// If encoding is UCS-2, we still need to read the first four bytes
// in order to discover the byte order.
- else if (encoding.equals("ISO-10646-UCS-2")) {
+ else if (EncodingInfo.STR_UCS2.equals(encoding)) {
final int[] b4 = new int[4];
int count = 0;
for (; count < 4; ++count) {
- b4[count] = stream.read();
+ b4[count] = rewindableStream.readAndBuffer();
if (b4[count] == -1)
break;
}
@@ -1798,7 +1795,6 @@
bufferSize.intValue() > DEFAULT_XMLDECL_BUFFER_SIZE) {
fBufferSize = bufferSize.intValue();
fEntityScanner.setBufferSize(fBufferSize);
- fBufferPool.setExternalBufferSize(fBufferSize);
}
}
if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() &&
@@ -2425,14 +2421,12 @@
*
* @param b4 The first four bytes of the input.
* @param count The number of bytes actually read.
- * @return a 2-element array: the first element, an IANA-encoding string,
- * the second element a Boolean which is true iff the document is big endian, false
- * if it's little-endian, and null if the distinction isn't relevant.
+ * @return an instance of EncodingInfo which represents the auto-detected encoding.
*/
- protected Object[] getEncodingName(byte[] b4, int count) {
+ protected EncodingInfo getEncodingInfo(byte[] b4, int count) {
if (count < 2) {
- return defaultEncoding;
+ return EncodingInfo.UTF_8;
}
// UTF-16, with BOM
@@ -2440,69 +2434,70 @@
int b1 = b4[1] & 0xFF;
if (b0 == 0xFE && b1 == 0xFF) {
// UTF-16, big-endian
- return new Object [] {"UTF-16BE", true};
+ return EncodingInfo.UTF_16_BIG_ENDIAN_WITH_BOM;
}
if (b0 == 0xFF && b1 == 0xFE) {
// UTF-16, little-endian
- return new Object [] {"UTF-16LE", false};
+ return EncodingInfo.UTF_16_LITTLE_ENDIAN_WITH_BOM;
}
// default to UTF-8 if we don't have enough bytes to make a
// good determination of the encoding
if (count < 3) {
- return defaultEncoding;
+ return EncodingInfo.UTF_8;
}
// UTF-8 with a BOM
int b2 = b4[2] & 0xFF;
if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) {
- return defaultEncoding;
+ return EncodingInfo.UTF_8_WITH_BOM;
}
// default to UTF-8 if we don't have enough bytes to make a
// good determination of the encoding
if (count < 4) {
- return defaultEncoding;
+ return EncodingInfo.UTF_8;
}
// other encodings
int b3 = b4[3] & 0xFF;
if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) {
// UCS-4, big endian (1234)
- return new Object [] {"ISO-10646-UCS-4", true};
+ return EncodingInfo.UCS_4_BIG_ENDIAN;
}
if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) {
// UCS-4, little endian (4321)
- return new Object [] {"ISO-10646-UCS-4", false};
+ return EncodingInfo.UCS_4_LITTLE_ENDIAN;
}
if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) {
// UCS-4, unusual octet order (2143)
// REVISIT: What should this be?
- return new Object [] {"ISO-10646-UCS-4", null};
+ return EncodingInfo.UCS_4_UNUSUAL_BYTE_ORDER;
}
if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) {
// UCS-4, unusual octect order (3412)
// REVISIT: What should this be?
- return new Object [] {"ISO-10646-UCS-4", null};
+ return EncodingInfo.UCS_4_UNUSUAL_BYTE_ORDER;
}
if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) {
// UTF-16, big-endian, no BOM
// (or could turn out to be UCS-2...
// REVISIT: What should this be?
- return new Object [] {"UTF-16BE", true};
+ return EncodingInfo.UTF_16_BIG_ENDIAN;
}
if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) {
// UTF-16, little-endian, no BOM
// (or could turn out to be UCS-2...
- return new Object [] {"UTF-16LE", false};
+ return EncodingInfo.UTF_16_LITTLE_ENDIAN;
}
if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) {
// EBCDIC
// a la xerces1, return CP037 instead of EBCDIC here
- return new Object [] {"CP037", null};
+ return EncodingInfo.EBCDIC;
}
- return defaultEncoding;
+ // default encoding
+ return EncodingInfo.UTF_8;
} // getEncodingName(byte[],int):Object[]
@@ -2517,95 +2512,95 @@
* encoding name may be a Java encoding name;
* otherwise, it is an ianaEncoding name.
* @param isBigEndian For encodings (like uCS-4), whose names cannot
- * specify a byte order, this tells whether the order is bigEndian. null menas
- * unknown or not relevant.
+ * specify a byte order, this tells whether the order
+ * is bigEndian. null if unknown or irrelevant.
*
* @return Returns a reader.
*/
protected Reader createReader(InputStream inputStream, String encoding, Boolean isBigEndian)
- throws IOException {
-
- // normalize encoding name
- if (encoding == null) {
- encoding = "UTF-8";
- }
-
- // try to use an optimized reader
- String ENCODING = encoding.toUpperCase(Locale.ENGLISH);
- if (ENCODING.equals("UTF-8")) {
- if (DEBUG_ENCODINGS) {
- System.out.println("$$$ creating UTF8Reader");
- }
- return new UTF8Reader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale() );
- }
- if (ENCODING.equals("US-ASCII")) {
- if (DEBUG_ENCODINGS) {
- System.out.println("$$$ creating ASCIIReader");
- }
- return new ASCIIReader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale());
- }
- if(ENCODING.equals("ISO-10646-UCS-4")) {
- if(isBigEndian != null) {
- boolean isBE = isBigEndian.booleanValue();
- if(isBE) {
- return new UCSReader(inputStream, UCSReader.UCS4BE);
+ throws IOException {
+
+ String enc = (encoding != null) ? encoding : EncodingInfo.STR_UTF8;
+ enc = enc.toUpperCase(Locale.ENGLISH);
+ MessageFormatter f = fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN);
+ Locale l = fErrorReporter.getLocale();
+ switch (enc) {
+ case EncodingInfo.STR_UTF8:
+ return new UTF8Reader(inputStream, fBufferSize, f, l);
+ case EncodingInfo.STR_UTF16:
+ if (isBigEndian != null) {
+ return new UTF16Reader(inputStream, fBufferSize, isBigEndian, f, l);
+ }
+ break;
+ case EncodingInfo.STR_UTF16BE:
+ return new UTF16Reader(inputStream, fBufferSize, true, f, l);
+ case EncodingInfo.STR_UTF16LE:
+ return new UTF16Reader(inputStream, fBufferSize, false, f, l);
+ case EncodingInfo.STR_UCS4:
+ if(isBigEndian != null) {
+ if(isBigEndian) {
+ return new UCSReader(inputStream, UCSReader.UCS4BE);
+ } else {
+ return new UCSReader(inputStream, UCSReader.UCS4LE);
+ }
} else {
- return new UCSReader(inputStream, UCSReader.UCS4LE);
+ fErrorReporter.reportError(this.getEntityScanner(),
+ XMLMessageFormatter.XML_DOMAIN,
+ "EncodingByteOrderUnsupported",
+ new Object[] { encoding },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
}
- } else {
- fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
- "EncodingByteOrderUnsupported",
- new Object[] { encoding },
- XMLErrorReporter.SEVERITY_FATAL_ERROR);
- }
- }
- if(ENCODING.equals("ISO-10646-UCS-2")) {
- if(isBigEndian != null) { // sould never happen with this encoding...
- boolean isBE = isBigEndian.booleanValue();
- if(isBE) {
- return new UCSReader(inputStream, UCSReader.UCS2BE);
+ break;
+ case EncodingInfo.STR_UCS2:
+ if(isBigEndian != null) {
+ if(isBigEndian) {
+ return new UCSReader(inputStream, UCSReader.UCS2BE);
+ } else {
+ return new UCSReader(inputStream, UCSReader.UCS2LE);
+ }
} else {
- return new UCSReader(inputStream, UCSReader.UCS2LE);
+ fErrorReporter.reportError(this.getEntityScanner(),
+ XMLMessageFormatter.XML_DOMAIN,
+ "EncodingByteOrderUnsupported",
+ new Object[] { encoding },
+ XMLErrorReporter.SEVERITY_FATAL_ERROR);
}
- } else {
- fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
- "EncodingByteOrderUnsupported",
- new Object[] { encoding },
- XMLErrorReporter.SEVERITY_FATAL_ERROR);
- }
+ break;
}
// check for valid name
boolean validIANA = XMLChar.isValidIANAEncoding(encoding);
boolean validJava = XMLChar.isValidJavaEncoding(encoding);
if (!validIANA || (fAllowJavaEncodings && !validJava)) {
- fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
+ fErrorReporter.reportError(this.getEntityScanner(),
+ XMLMessageFormatter.XML_DOMAIN,
"EncodingDeclInvalid",
new Object[] { encoding },
XMLErrorReporter.SEVERITY_FATAL_ERROR);
- // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
- // because every byte is a valid ISO Latin 1 character.
- // It may not translate correctly but if we failed on
- // the encoding anyway, then we're expecting the content
- // of the document to be bad. This will just prevent an
- // invalid UTF-8 sequence to be detected. This is only
- // important when continue-after-fatal-error is turned
- // on. -Ac
+ // NOTE: AndyH suggested that, on failure, we use ISO Latin 1
+ // because every byte is a valid ISO Latin 1 character.
+ // It may not translate correctly but if we failed on
+ // the encoding anyway, then we're expecting the content
+ // of the document to be bad. This will just prevent an
+ // invalid UTF-8 sequence to be detected. This is only
+ // important when continue-after-fatal-error is turned
+ // on. -Ac
encoding = "ISO-8859-1";
}
// try to use a Java reader
- String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING);
+ String javaEncoding = EncodingMap.getIANA2JavaMapping(enc);
if (javaEncoding == null) {
- if(fAllowJavaEncodings) {
+ if (fAllowJavaEncodings) {
javaEncoding = encoding;
} else {
- fErrorReporter.reportError(this.getEntityScanner(),XMLMessageFormatter.XML_DOMAIN,
+ fErrorReporter.reportError(this.getEntityScanner(),
+ XMLMessageFormatter.XML_DOMAIN,
"EncodingDeclInvalid",
new Object[] { encoding },
XMLErrorReporter.SEVERITY_FATAL_ERROR);
- // see comment above.
- javaEncoding = "ISO8859_1";
+ // see comment above.
+ javaEncoding = "ISO8859_1";
}
}
if (DEBUG_ENCODINGS) {
@@ -2898,108 +2893,78 @@
} // print()
/**
- * Buffer used in entity manager to reuse character arrays instead
- * of creating new ones every time.
- *
- * @xerces.internal
- *
- * @author Ankit Pasricha, IBM
- */
- private static class CharacterBuffer {
-
- /** character buffer */
- private char[] ch;
-
- /** whether the buffer is for an external or internal scanned entity */
- private boolean isExternal;
-
- public CharacterBuffer(boolean isExternal, int size) {
- this.isExternal = isExternal;
- ch = new char[size];
- }
- }
-
-
- /**
- * Stores a number of character buffers and provides it to the entity
- * manager to use when an entity is seen.
+ * Information about auto-detectable encodings.
*
* @xerces.internal
*
- * @author Ankit Pasricha, IBM
+ * @author Michael Glavassevich, IBM
*/
- private static class CharacterBufferPool {
-
- private static final int DEFAULT_POOL_SIZE = 3;
-
- private CharacterBuffer[] fInternalBufferPool;
- private CharacterBuffer[] fExternalBufferPool;
-
- private int fExternalBufferSize;
- private int fInternalBufferSize;
- private int poolSize;
-
- private int fInternalTop;
- private int fExternalTop;
-
- public CharacterBufferPool(int externalBufferSize, int internalBufferSize) {
- this(DEFAULT_POOL_SIZE, externalBufferSize, internalBufferSize);
- }
-
- public CharacterBufferPool(int poolSize, int externalBufferSize, int internalBufferSize) {
- fExternalBufferSize = externalBufferSize;
- fInternalBufferSize = internalBufferSize;
- this.poolSize = poolSize;
- init();
- }
-
- /** Initializes buffer pool. **/
- private void init() {
- fInternalBufferPool = new CharacterBuffer[poolSize];
- fExternalBufferPool = new CharacterBuffer[poolSize];
- fInternalTop = -1;
- fExternalTop = -1;
- }
-
- /** Retrieves buffer from pool. **/
- public CharacterBuffer getBuffer(boolean external) {
- if (external) {
- if (fExternalTop > -1) {
- return fExternalBufferPool[fExternalTop--];
- }
- else {
- return new CharacterBuffer(true, fExternalBufferSize);
- }
- }
- else {
- if (fInternalTop > -1) {
- return fInternalBufferPool[fInternalTop--];
- }
- else {
- return new CharacterBuffer(false, fInternalBufferSize);
- }
- }
- }
-
- /** Returns buffer to pool. **/
- public void returnToPool(CharacterBuffer buffer) {
- if (buffer.isExternal) {
- if (fExternalTop < fExternalBufferPool.length - 1) {
- fExternalBufferPool[++fExternalTop] = buffer;
- }
- }
- else if (fInternalTop < fInternalBufferPool.length - 1) {
- fInternalBufferPool[++fInternalTop] = buffer;
- }
- }
-
- /** Sets the size of external buffers and dumps the old pool. **/
- public void setExternalBufferSize(int bufferSize) {
- fExternalBufferSize = bufferSize;
- fExternalBufferPool = new CharacterBuffer[poolSize];
- fExternalTop = -1;
- }
- }
+ private static class EncodingInfo {
+ public static final String STR_UTF8 = "UTF-8";
+ public static final String STR_UTF16 = "UTF-16";
+ public static final String STR_UTF16BE = "UTF-16BE";
+ public static final String STR_UTF16LE = "UTF-16LE";
+ public static final String STR_UCS4 = "ISO-10646-UCS-4";
+ public static final String STR_UCS2 = "ISO-10646-UCS-2";
+ public static final String STR_CP037 = "CP037";
+
+ /** UTF-8 **/
+ public static final EncodingInfo UTF_8 =
+ new EncodingInfo(STR_UTF8, null, false);
+
+ /** UTF-8, with BOM **/
+ public static final EncodingInfo UTF_8_WITH_BOM =
+ new EncodingInfo(STR_UTF8, null, true);
+
+ /** UTF-16, big-endian **/
+ public static final EncodingInfo UTF_16_BIG_ENDIAN =
+ new EncodingInfo(STR_UTF16BE, STR_UTF16, Boolean.TRUE, false);
+
+ /** UTF-16, big-endian with BOM **/
+ public static final EncodingInfo UTF_16_BIG_ENDIAN_WITH_BOM =
+ new EncodingInfo(STR_UTF16BE, STR_UTF16, Boolean.TRUE, true);
+
+ /** UTF-16, little-endian **/
+ public static final EncodingInfo UTF_16_LITTLE_ENDIAN =
+ new EncodingInfo(STR_UTF16LE, STR_UTF16, Boolean.FALSE, false);
+
+ /** UTF-16, little-endian with BOM **/
+ public static final EncodingInfo UTF_16_LITTLE_ENDIAN_WITH_BOM =
+ new EncodingInfo(STR_UTF16LE, STR_UTF16, Boolean.FALSE, true);
+
+ /** UCS-4, big-endian **/
+ public static final EncodingInfo UCS_4_BIG_ENDIAN =
+ new EncodingInfo(STR_UCS4, Boolean.TRUE, false);
+
+ /** UCS-4, little-endian **/
+ public static final EncodingInfo UCS_4_LITTLE_ENDIAN =
+ new EncodingInfo(STR_UCS4, Boolean.FALSE, false);
+
+ /** UCS-4, unusual byte-order (2143) or (3412) **/
+ public static final EncodingInfo UCS_4_UNUSUAL_BYTE_ORDER =
+ new EncodingInfo(STR_UCS4, null, false);
+
+ /** EBCDIC **/
+ public static final EncodingInfo EBCDIC = new EncodingInfo(STR_CP037, null, false);
+
+ public final String autoDetectedEncoding;
+ public final String readerEncoding;
+ public final Boolean isBigEndian;
+ public final boolean hasBOM;
+
+ private EncodingInfo(String autoDetectedEncoding, Boolean isBigEndian, boolean hasBOM) {
+ this(autoDetectedEncoding, autoDetectedEncoding, isBigEndian, hasBOM);
+ } // <init>(String,Boolean,boolean)
+
+ private EncodingInfo(String autoDetectedEncoding, String readerEncoding,
+ Boolean isBigEndian, boolean hasBOM) {
+ this.autoDetectedEncoding = autoDetectedEncoding;
+ this.readerEncoding = readerEncoding;
+ this.isBigEndian = isBigEndian;
+ this.hasBOM = hasBOM;
+ } // <init>(String,String,Boolean,boolean)
+
+ } // class EncodingInfo
/**
* This class wraps the byte inputstreams we're presented with.
@@ -3052,20 +3017,13 @@
fOffset = fStartOffset;
}
- public int read() throws IOException {
- int b = 0;
- if (fOffset < fLength) {
- return fData[fOffset++] & 0xff;
- }
- if (fOffset == fEndOffset) {
- return -1;
- }
+ public int readAndBuffer() throws IOException {
if (fOffset == fData.length) {
byte[] newData = new byte[fOffset << 1];
System.arraycopy(fData, 0, newData, 0, fOffset);
fData = newData;
}
- b = fInputStream.read();
+ final int b = fInputStream.read();
if (b == -1) {
fEndOffset = fOffset;
return -1;
@@ -3075,18 +3033,27 @@
return b & 0xff;
}
+ public int read() throws IOException {
+ if (fOffset < fLength) {
+ return fData[fOffset++] & 0xff;
+ }
+ if (fOffset == fEndOffset) {
+ return -1;
+ }
+ if (fCurrentEntity.mayReadChunks) {
+ return fInputStream.read();
+ }
+ return readAndBuffer();
+ }
+
public int read(byte[] b, int off, int len) throws IOException {
- int bytesLeft = fLength - fOffset;
+ final int bytesLeft = fLength - fOffset;
if (bytesLeft == 0) {
if (fOffset == fEndOffset) {
return -1;
}
- /**
- * //System.out.println("fCurrentEntitty = " + fCurrentEntity );
- * //System.out.println("fInputStream = " + fInputStream );
- * // better get some more for the voracious reader... */
-
+ // read a block of data as requested
if(fCurrentEntity.mayReadChunks || !fCurrentEntity.xmlDeclChunkRead) {
if (!fCurrentEntity.xmlDeclChunkRead)
@@ -3096,15 +3063,13 @@
}
return fInputStream.read(b, off, len);
}
-
- int returnedVal = read();
- if(returnedVal == -1) {
- fEndOffset = fOffset;
- return -1;
+ int returnedVal = readAndBuffer();
+ if (returnedVal == -1) {
+ fEndOffset = fOffset;
+ return -1;
}
b[off] = (byte)returnedVal;
return 1;
-
}
if (len < bytesLeft) {
if (len <= 0) {
@@ -3120,8 +3085,7 @@
return len;
}
- public long skip(long n)
- throws IOException {
+ public long skip(long n) throws IOException {
int bytesLeft;
if (n <= 0) {
return 0;
@@ -3142,7 +3106,7 @@
return bytesLeft;
}
n -= bytesLeft;
- /*
+ /*
* In a manner of speaking, when this class isn't permitting more
* than one byte at a time to be read, it is "blocking". The
* available() method should indicate how much can be read without
@@ -3154,13 +3118,13 @@
}
public int available() throws IOException {
- int bytesLeft = fLength - fOffset;
+ final int bytesLeft = fLength - fOffset;
if (bytesLeft == 0) {
if (fOffset == fEndOffset) {
return -1;
}
return fCurrentEntity.mayReadChunks ? fInputStream.available()
- : 0;
+ : 0;
}
return bytesLeft;
}
@@ -3171,7 +3135,6 @@
public void reset() {
fOffset = fMark;
- //test();
}
public boolean markSupported() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Fri Apr 19 08:00:42 2019 -0400
@@ -55,6 +55,7 @@
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.jvm.*;
+import com.sun.tools.javac.jvm.PoolConstant;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.Tag;
@@ -91,7 +92,7 @@
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
-public abstract class Symbol extends AnnoConstruct implements Element {
+public abstract class Symbol extends AnnoConstruct implements PoolConstant, Element {
/** The kind of this symbol.
* @see Kinds
@@ -286,6 +287,11 @@
this.name = name;
}
+ @Override
+ public int poolTag() {
+ throw new AssertionError("Invalid pool entry");
+ }
+
/** Clone this symbol with new owner.
* Legal only for fields and methods.
*/
@@ -971,6 +977,11 @@
this.type = new ModuleType(this);
}
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_Module;
+ }
+
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Name getSimpleName() {
return Convert.shortName(name);
@@ -1137,6 +1148,11 @@
return members_field;
}
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_Package;
+ }
+
public long flags() {
complete();
return flags_field;
@@ -1237,10 +1253,6 @@
*/
public List<ClassSymbol> trans_local;
- /** the constant pool of the class
- */
- public Pool pool;
-
/** the annotation metadata attached to this class */
private AnnotationTypeMetadata annotationTypeMetadata;
@@ -1251,7 +1263,6 @@
this.flatname = formFlatName(name, owner);
this.sourcefile = null;
this.classfile = null;
- this.pool = null;
this.annotationTypeMetadata = AnnotationTypeMetadata.notAnAnnotationType();
}
@@ -1543,6 +1554,11 @@
super(VAR, flags, name, type, owner);
}
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_Fieldref;
+ }
+
/** Clone this symbol with new owner.
*/
public VarSymbol clone(Symbol newOwner) {
@@ -1551,6 +1567,11 @@
public Symbol baseSymbol() {
return VarSymbol.this;
}
+
+ @Override
+ public Object poolKey(Types types) {
+ return new Pair<>(newOwner, baseSymbol());
+ }
};
v.pos = pos;
v.adr = adr;
@@ -1711,6 +1732,11 @@
public Symbol baseSymbol() {
return MethodSymbol.this;
}
+
+ @Override
+ public Object poolKey(Types types) {
+ return new Pair<>(newOwner, baseSymbol());
+ }
};
m.code = code;
return m;
@@ -1740,10 +1766,25 @@
}
}
+ @Override
+ public int poolTag() {
+ return owner.isInterface() ?
+ ClassFile.CONSTANT_InterfaceMethodref : ClassFile.CONSTANT_Methodref;
+ }
+
public boolean isDynamic() {
return false;
}
+ public boolean isHandle() {
+ return false;
+ }
+
+
+ public MethodHandleSymbol asHandle() {
+ return new MethodHandleSymbol(this);
+ }
+
/** find a symbol that this (proxy method) symbol implements.
* @param c The class whose members are searched for
* implementations
@@ -2027,16 +2068,14 @@
/** A class for invokedynamic method calls.
*/
- public static class DynamicMethodSymbol extends MethodSymbol {
+ public static class DynamicMethodSymbol extends MethodSymbol implements Dynamic {
- public Object[] staticArgs;
- public Symbol bsm;
- public int bsmKind;
+ public LoadableConstant[] staticArgs;
+ public MethodHandleSymbol bsm;
- public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
+ public DynamicMethodSymbol(Name name, Symbol owner, MethodHandleSymbol bsm, Type type, LoadableConstant[] staticArgs) {
super(0, name, type, owner);
this.bsm = bsm;
- this.bsmKind = bsmKind;
this.staticArgs = staticArgs;
}
@@ -2044,6 +2083,83 @@
public boolean isDynamic() {
return true;
}
+
+ @Override
+ public LoadableConstant[] staticArgs() {
+ return staticArgs;
+ }
+
+ @Override
+ public MethodHandleSymbol bootstrapMethod() {
+ return bsm;
+ }
+
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_InvokeDynamic;
+ }
+
+ @Override
+ public Type dynamicType() {
+ return type;
+ }
+ }
+
+ /** A class for method handles.
+ */
+ public static class MethodHandleSymbol extends MethodSymbol implements LoadableConstant {
+
+ private Symbol refSym;
+
+ public MethodHandleSymbol(Symbol msym) {
+ super(msym.flags_field, msym.name, msym.type, msym.owner);
+ this.refSym = msym;
+ }
+
+ /**
+ * Returns the kind associated with this method handle.
+ */
+ public int referenceKind() {
+ if (refSym.isConstructor()) {
+ return ClassFile.REF_newInvokeSpecial;
+ } else {
+ if (refSym.isStatic()) {
+ return ClassFile.REF_invokeStatic;
+ } else if ((refSym.flags() & PRIVATE) != 0) {
+ return ClassFile.REF_invokeSpecial;
+ } else if (refSym.enclClass().isInterface()) {
+ return ClassFile.REF_invokeInterface;
+ } else {
+ return ClassFile.REF_invokeVirtual;
+ }
+ }
+ }
+
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_MethodHandle;
+ }
+
+ @Override
+ public Object poolKey(Types types) {
+ return new Pair<>(baseSymbol(), referenceKind());
+ }
+
+ @Override
+ public MethodHandleSymbol asHandle() {
+ return this;
+ }
+
+ @Override
+ public Symbol baseSymbol() {
+ return refSym;
+ }
+
+
+ @Override
+ public boolean isHandle() {
+ return true;
+ }
}
/** A class for predefined operators.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Fri Apr 19 08:00:42 2019 -0400
@@ -36,7 +36,10 @@
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.TypeMetadata.Entry;
import com.sun.tools.javac.code.Types.TypeMapping;
+import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.comp.Infer.IncorporationAction;
+import com.sun.tools.javac.jvm.ClassFile;
+import com.sun.tools.javac.jvm.PoolConstant;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
@@ -73,7 +76,7 @@
*
* @see TypeTag
*/
-public abstract class Type extends AnnoConstruct implements TypeMirror {
+public abstract class Type extends AnnoConstruct implements TypeMirror, PoolConstant {
/**
* Type metadata, Should be {@code null} for the default value.
@@ -125,6 +128,16 @@
*/
public TypeSymbol tsym;
+ @Override
+ public int poolTag() {
+ throw new AssertionError("Invalid pool entry");
+ }
+
+ @Override
+ public Object poolKey(Types types) {
+ return new UniqueType(this, types);
+ }
+
/**
* Checks if the current type tag is equal to the given tag.
* @return true if tag is equal to the current type tag.
@@ -930,7 +943,7 @@
}
}
- public static class ClassType extends Type implements DeclaredType,
+ public static class ClassType extends Type implements DeclaredType, LoadableConstant,
javax.lang.model.type.ErrorType {
/** The enclosing type of this type. If this is the type of an inner
@@ -975,6 +988,10 @@
this.interfaces_field = null;
}
+ public int poolTag() {
+ return ClassFile.CONSTANT_Class;
+ }
+
@Override
public ClassType cloneWithMetadata(TypeMetadata md) {
return new ClassType(outer_field, typarams_field, tsym, md) {
@@ -1277,7 +1294,7 @@
}
public static class ArrayType extends Type
- implements javax.lang.model.type.ArrayType {
+ implements LoadableConstant, javax.lang.model.type.ArrayType {
public Type elemtype;
@@ -1297,6 +1314,10 @@
this(that.elemtype, that.tsym, that.getMetadata());
}
+ public int poolTag() {
+ return ClassFile.CONSTANT_Class;
+ }
+
@Override
public ArrayType cloneWithMetadata(TypeMetadata md) {
return new ArrayType(elemtype, tsym, md) {
@@ -1412,7 +1433,7 @@
}
}
- public static class MethodType extends Type implements ExecutableType {
+ public static class MethodType extends Type implements ExecutableType, LoadableConstant {
public List<Type> argtypes;
public Type restype;
@@ -1479,6 +1500,11 @@
restype != null && restype.isErroneous();
}
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_MethodType;
+ }
+
public boolean contains(Type elem) {
return elem.equalsIgnoreMetadata(this) || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Apr 19 08:00:42 2019 -0400
@@ -48,6 +48,8 @@
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Env;
+import com.sun.tools.javac.comp.LambdaToMethod;
+import com.sun.tools.javac.jvm.ClassFile;
import com.sun.tools.javac.util.*;
import static com.sun.tools.javac.code.BoundKind.*;
@@ -5181,6 +5183,29 @@
}
}
}
+
+ public Type constantType(LoadableConstant c) {
+ switch (c.poolTag()) {
+ case ClassFile.CONSTANT_Class:
+ return syms.classType;
+ case ClassFile.CONSTANT_String:
+ return syms.stringType;
+ case ClassFile.CONSTANT_Integer:
+ return syms.intType;
+ case ClassFile.CONSTANT_Float:
+ return syms.floatType;
+ case ClassFile.CONSTANT_Long:
+ return syms.longType;
+ case ClassFile.CONSTANT_Double:
+ return syms.doubleType;
+ case ClassFile.CONSTANT_MethodHandle:
+ return syms.methodHandleType;
+ case ClassFile.CONSTANT_MethodType:
+ return syms.methodTypeType;
+ default:
+ throw new AssertionError("Not a loadable constant: " + c.poolTag());
+ }
+ }
// </editor-fold>
public void newRound() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Fri Apr 19 08:00:42 2019 -0400
@@ -25,7 +25,9 @@
package com.sun.tools.javac.comp;
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.tree.*;
@@ -59,7 +61,6 @@
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
@@ -70,13 +71,10 @@
import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
-import static com.sun.tools.javac.jvm.Pool.DynamicMethod;
import javax.lang.model.element.ElementKind;
import javax.lang.model.type.TypeKind;
-import com.sun.tools.javac.code.Type.IntersectionClassType;
-import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
import com.sun.tools.javac.main.Option;
/**
@@ -214,7 +212,7 @@
private Map<DedupedLambda, DedupedLambda> dedupedLambdas;
- private Map<DynamicMethod, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
+ private Map<Object, DynamicMethodSymbol> dynMethSyms = new HashMap<>();
/**
* list of deserialization cases
@@ -439,11 +437,8 @@
//then, determine the arguments to the indy call
List<JCExpression> indy_args = translate(syntheticInits.toList(), localContext.prev);
- //build a sam instance using an indy call to the meta-factory
- int refKind = referenceKind(sym);
-
//convert to an invokedynamic call
- result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
+ result = makeMetafactoryIndyCall(context, sym.asHandle(), indy_args);
}
// where
@@ -488,7 +483,7 @@
//first determine the method symbol to be used to generate the sam instance
//this is either the method reference symbol, or the bridged reference symbol
- Symbol refSym = tree.sym;
+ MethodSymbol refSym = (MethodSymbol)tree.sym;
//the qualifying expression is treated as a special captured arg
JCExpression init;
@@ -522,7 +517,7 @@
//build a sam instance using an indy call to the meta-factory
- result = makeMetafactoryIndyCall(localContext, localContext.referenceKind(), refSym, indy_args);
+ result = makeMetafactoryIndyCall(localContext, refSym.asHandle(), indy_args);
}
/**
@@ -765,8 +760,8 @@
rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil()));
}
- private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
- DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
+ private void addDeserializationCase(MethodHandleSymbol refSym, Type targetType, MethodSymbol samSym,
+ DiagnosticPosition pos, List<LoadableConstant> staticArgs, MethodType indyType) {
String functionalInterfaceClass = classSig(targetType);
String functionalInterfaceMethodName = samSym.getSimpleName().toString();
String functionalInterfaceMethodSignature = typeSig(types.erasure(samSym.type));
@@ -774,7 +769,8 @@
String implMethodName = refSym.getQualifiedName().toString();
String implMethodSignature = typeSig(types.erasure(refSym.type));
- JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind));
+ JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType),
+ make.Literal(refSym.referenceKind()));
ListBuffer<JCExpression> serArgs = new ListBuffer<>();
int i = 0;
for (Type t : indyType.getParameterTypes()) {
@@ -1106,13 +1102,13 @@
* Generate an indy method call to the meta factory
*/
private JCExpression makeMetafactoryIndyCall(TranslationContext<?> context,
- int refKind, Symbol refSym, List<JCExpression> indy_args) {
+ MethodHandleSymbol refSym, List<JCExpression> indy_args) {
JCFunctionalExpression tree = context.tree;
//determine the static bsm args
MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.target.tsym);
- List<Object> staticArgs = List.of(
+ List<LoadableConstant> staticArgs = List.of(
typeToMethodType(samSym.type),
- new Pool.MethodHandle(refKind, refSym, types),
+ ((MethodSymbol)refSym).asHandle(),
typeToMethodType(tree.getDescriptorType(types)));
//computed indy arg types
@@ -1131,7 +1127,7 @@
names.altMetafactory : names.metafactory;
if (context.needsAltMetafactory()) {
- ListBuffer<Object> markers = new ListBuffer<>();
+ ListBuffer<Type> markers = new ListBuffer<>();
List<Type> targets = tree.target.isIntersection() ?
types.directSupertypes(tree.target) :
List.nil();
@@ -1140,7 +1136,7 @@
if (t.tsym != syms.serializableType.tsym &&
t.tsym != tree.type.tsym &&
t.tsym != syms.objectType.tsym) {
- markers.append(t.tsym);
+ markers.append(t);
}
}
int flags = context.isSerializable() ? FLAG_SERIALIZABLE : 0;
@@ -1152,17 +1148,17 @@
if (hasBridges) {
flags |= FLAG_BRIDGES;
}
- staticArgs = staticArgs.append(flags);
+ staticArgs = staticArgs.append(LoadableConstant.Int(flags));
if (hasMarkers) {
- staticArgs = staticArgs.append(markers.length());
- staticArgs = staticArgs.appendList(markers.toList());
+ staticArgs = staticArgs.append(LoadableConstant.Int(markers.length()));
+ staticArgs = staticArgs.appendList(List.convert(LoadableConstant.class, markers.toList()));
}
if (hasBridges) {
- staticArgs = staticArgs.append(context.bridges.length() - 1);
+ staticArgs = staticArgs.append(LoadableConstant.Int(context.bridges.length() - 1));
for (Symbol s : context.bridges) {
Type s_erasure = s.erasure(types);
if (!types.isSameType(s_erasure, samSym.erasure(types))) {
- staticArgs = staticArgs.append(s.erasure(types));
+ staticArgs = staticArgs.append(((MethodType)s.erasure(types)));
}
}
}
@@ -1170,7 +1166,7 @@
int prevPos = make.pos;
try {
make.at(kInfo.clazz);
- addDeserializationCase(refKind, refSym, tree.type, samSym,
+ addDeserializationCase(refSym, tree.type, samSym,
tree, staticArgs, indyType);
} finally {
make.at(prevPos);
@@ -1186,14 +1182,14 @@
* arguments types
*/
private JCExpression makeIndyCall(DiagnosticPosition pos, Type site, Name bsmName,
- List<Object> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
- Name methName) {
+ List<LoadableConstant> staticArgs, MethodType indyType, List<JCExpression> indyArgs,
+ Name methName) {
int prevPos = make.pos;
try {
make.at(pos);
List<Type> bsm_staticArgs = List.of(syms.methodHandleLookupType,
- syms.stringType,
- syms.methodTypeType).appendList(bsmStaticArgToTypes(staticArgs));
+ syms.stringType,
+ syms.methodTypeType).appendList(staticArgs.map(types::constantType));
Symbol bsm = rs.resolveInternalMethod(pos, attrEnv, site,
bsmName, bsm_staticArgs, List.nil());
@@ -1201,15 +1197,12 @@
DynamicMethodSymbol dynSym =
new DynamicMethodSymbol(methName,
syms.noSymbol,
- bsm.isStatic() ?
- ClassFile.REF_invokeStatic :
- ClassFile.REF_invokeVirtual,
- (MethodSymbol)bsm,
+ ((MethodSymbol)bsm).asHandle(),
indyType,
- staticArgs.toArray());
+ staticArgs.toArray(new LoadableConstant[staticArgs.length()]));
JCFieldAccess qualifier = make.Select(make.QualIdent(site.tsym), bsmName);
DynamicMethodSymbol existing = kInfo.dynMethSyms.putIfAbsent(
- new DynamicMethod(dynSym, types), dynSym);
+ dynSym.poolKey(types), dynSym);
qualifier.sym = existing != null ? existing : dynSym;
qualifier.type = indyType.getReturnType();
@@ -1220,57 +1213,6 @@
make.at(prevPos);
}
}
- //where
- private List<Type> bsmStaticArgToTypes(List<Object> args) {
- ListBuffer<Type> argtypes = new ListBuffer<>();
- for (Object arg : args) {
- argtypes.append(bsmStaticArgToType(arg));
- }
- return argtypes.toList();
- }
-
- private Type bsmStaticArgToType(Object arg) {
- Assert.checkNonNull(arg);
- if (arg instanceof ClassSymbol) {
- return syms.classType;
- } else if (arg instanceof Integer) {
- return syms.intType;
- } else if (arg instanceof Long) {
- return syms.longType;
- } else if (arg instanceof Float) {
- return syms.floatType;
- } else if (arg instanceof Double) {
- return syms.doubleType;
- } else if (arg instanceof String) {
- return syms.stringType;
- } else if (arg instanceof Pool.MethodHandle) {
- return syms.methodHandleType;
- } else if (arg instanceof MethodType) {
- return syms.methodTypeType;
- } else {
- Assert.error("bad static arg " + arg.getClass());
- return null;
- }
- }
-
- /**
- * Get the opcode associated with this method reference
- */
- private int referenceKind(Symbol refSym) {
- if (refSym.isConstructor()) {
- return ClassFile.REF_newInvokeSpecial;
- } else {
- if (refSym.isStatic()) {
- return ClassFile.REF_invokeStatic;
- } else if ((refSym.flags() & PRIVATE) != 0) {
- return ClassFile.REF_invokeSpecial;
- } else if (refSym.enclClass().isInterface()) {
- return ClassFile.REF_invokeInterface;
- } else {
- return ClassFile.REF_invokeVirtual;
- }
- }
- }
// <editor-fold defaultstate="collapsed" desc="Lambda/reference analyzer">
/**
@@ -2312,13 +2254,6 @@
this.isSuper = tree.hasKind(ReferenceKind.SUPER);
}
- /**
- * Get the opcode associated with this method reference
- */
- int referenceKind() {
- return LambdaToMethod.this.referenceKind(tree.sym);
- }
-
boolean needsVarArgsConversion() {
return tree.varargsElement != null;
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Fri Apr 19 08:00:42 2019 -0400
@@ -93,7 +93,6 @@
private final Attr attr;
private TreeMaker make;
private DiagnosticPosition make_pos;
- private final ClassWriter writer;
private final ConstFold cfolder;
private final Target target;
private final Source source;
@@ -116,7 +115,6 @@
chk = Check.instance(context);
attr = Attr.instance(context);
make = TreeMaker.instance(context);
- writer = ClassWriter.instance(context);
cfolder = ConstFold.instance(context);
target = Target.instance(context);
source = Source.instance(context);
@@ -475,7 +473,7 @@
.fromString(target.syntheticNameChar() +
"SwitchMap" +
target.syntheticNameChar() +
- writer.xClassName(forEnum.type).toString()
+ names.fromUtf(ClassWriter.externalize(forEnum.type.tsym.flatName())).toString()
.replace('/', '.')
.replace('.', target.syntheticNameChar()));
ClassSymbol outerCacheClass = outerCacheClass();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java Fri Apr 19 08:00:42 2019 -0400
@@ -25,9 +25,6 @@
package com.sun.tools.javac.jvm;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.util.Name;
@@ -189,38 +186,4 @@
public static byte[] externalize(Name name) {
return externalize(name.getByteArray(), name.getByteOffset(), name.getByteLength());
}
-
-/************************************************************************
- * Name-and-type
- ***********************************************************************/
-
- /** A class for the name-and-type signature of a method or field.
- */
- public static class NameAndType {
- Name name;
- UniqueType uniqueType;
- Types types;
-
- NameAndType(Name name, Type type, Types types) {
- this.name = name;
- this.uniqueType = new UniqueType(type, types);
- this.types = types;
- }
-
- void setType(Type type) {
- this.uniqueType = new UniqueType(type, types);
- }
-
- @Override
- public boolean equals(Object other) {
- return (other instanceof NameAndType &&
- name == ((NameAndType) other).name &&
- uniqueType.equals(((NameAndType) other).uniqueType));
- }
-
- @Override
- public int hashCode() {
- return name.hashCode() * uniqueType.hashCode();
- }
- }
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.function.IntFunction;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
@@ -55,8 +56,8 @@
import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata;
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.PathFileObject;
-import com.sun.tools.javac.jvm.ClassFile.NameAndType;
import com.sun.tools.javac.jvm.ClassFile.Version;
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.resources.CompilerProperties.Warnings;
@@ -100,11 +101,6 @@
*/
boolean verbose;
- /** Switch: read constant pool and code sections. This switch is initially
- * set to false but can be turned on from outside.
- */
- public boolean readAllOfClassFile = false;
-
/** Switch: allow modules.
*/
boolean allowModules;
@@ -170,20 +166,15 @@
/** The buffer containing the currently read class file.
*/
- byte[] buf = new byte[INITIAL_BUFFER_SIZE];
+ ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
/** The current input pointer.
*/
protected int bp;
- /** The objects of the constant pool.
+ /** The pool reader.
*/
- Object[] poolObj;
-
- /** For every constant pool entry, an index into buf where the
- * defining section of the entry is found.
- */
- int[] poolIdx;
+ PoolReader poolReader;
/** The major version number of the class file being read. */
int majorVersion;
@@ -323,294 +314,29 @@
/** Read a character.
*/
char nextChar() {
- return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
+ char res = buf.getChar(bp);
+ bp += 2;
+ return res;
}
/** Read a byte.
*/
int nextByte() {
- return buf[bp++] & 0xFF;
+ return buf.getByte(bp++) & 0xFF;
}
/** Read an integer.
*/
int nextInt() {
- return
- ((buf[bp++] & 0xFF) << 24) +
- ((buf[bp++] & 0xFF) << 16) +
- ((buf[bp++] & 0xFF) << 8) +
- (buf[bp++] & 0xFF);
- }
-
- /** Extract a character at position bp from buf.
- */
- char getChar(int bp) {
- return
- (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
- }
-
- /** Extract an integer at position bp from buf.
- */
- int getInt(int bp) {
- return
- ((buf[bp] & 0xFF) << 24) +
- ((buf[bp+1] & 0xFF) << 16) +
- ((buf[bp+2] & 0xFF) << 8) +
- (buf[bp+3] & 0xFF);
- }
-
-
- /** Extract a long integer at position bp from buf.
- */
- long getLong(int bp) {
- DataInputStream bufin =
- new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
- try {
- return bufin.readLong();
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
- /** Extract a float at position bp from buf.
- */
- float getFloat(int bp) {
- DataInputStream bufin =
- new DataInputStream(new ByteArrayInputStream(buf, bp, 4));
- try {
- return bufin.readFloat();
- } catch (IOException e) {
- throw new AssertionError(e);
- }
- }
-
- /** Extract a double at position bp from buf.
- */
- double getDouble(int bp) {
- DataInputStream bufin =
- new DataInputStream(new ByteArrayInputStream(buf, bp, 8));
- try {
- return bufin.readDouble();
- } catch (IOException e) {
- throw new AssertionError(e);
- }
+ int res = buf.getInt(bp);
+ bp += 4;
+ return res;
}
/************************************************************************
* Constant Pool Access
***********************************************************************/
- /** Index all constant pool entries, writing their start addresses into
- * poolIdx.
- */
- void indexPool() {
- poolIdx = new int[nextChar()];
- poolObj = new Object[poolIdx.length];
- int i = 1;
- while (i < poolIdx.length) {
- poolIdx[i++] = bp;
- byte tag = buf[bp++];
- switch (tag) {
- case CONSTANT_Utf8: case CONSTANT_Unicode: {
- int len = nextChar();
- bp = bp + len;
- break;
- }
- case CONSTANT_Class:
- case CONSTANT_String:
- case CONSTANT_MethodType:
- case CONSTANT_Module:
- case CONSTANT_Package:
- bp = bp + 2;
- break;
- case CONSTANT_MethodHandle:
- bp = bp + 3;
- break;
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- case CONSTANT_NameandType:
- case CONSTANT_Integer:
- case CONSTANT_Float:
- case CONSTANT_Dynamic:
- case CONSTANT_InvokeDynamic:
- bp = bp + 4;
- break;
- case CONSTANT_Long:
- case CONSTANT_Double:
- bp = bp + 8;
- i++;
- break;
- default:
- throw badClassFile("bad.const.pool.tag.at",
- Byte.toString(tag),
- Integer.toString(bp -1));
- }
- }
- }
-
- /** Read constant pool entry at start address i, use pool as a cache.
- */
- Object readPool(int i) {
- Object result = poolObj[i];
- if (result != null) return result;
-
- int index = poolIdx[i];
- if (index == 0) return null;
-
- byte tag = buf[index];
- switch (tag) {
- case CONSTANT_Utf8:
- poolObj[i] = names.fromUtf(buf, index + 3, getChar(index + 1));
- break;
- case CONSTANT_Unicode:
- throw badClassFile("unicode.str.not.supported");
- case CONSTANT_Class:
- poolObj[i] = readClassOrType(getChar(index + 1));
- break;
- case CONSTANT_String:
- // FIXME: (footprint) do not use toString here
- poolObj[i] = readName(getChar(index + 1)).toString();
- break;
- case CONSTANT_Fieldref: {
- ClassSymbol owner = readClassSymbol(getChar(index + 1));
- NameAndType nt = readNameAndType(getChar(index + 3));
- poolObj[i] = new VarSymbol(0, nt.name, nt.uniqueType.type, owner);
- break;
- }
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref: {
- ClassSymbol owner = readClassSymbol(getChar(index + 1));
- NameAndType nt = readNameAndType(getChar(index + 3));
- poolObj[i] = new MethodSymbol(0, nt.name, nt.uniqueType.type, owner);
- break;
- }
- case CONSTANT_NameandType:
- poolObj[i] = new NameAndType(
- readName(getChar(index + 1)),
- readType(getChar(index + 3)), types);
- break;
- case CONSTANT_Integer:
- poolObj[i] = getInt(index + 1);
- break;
- case CONSTANT_Float:
- poolObj[i] = Float.valueOf(getFloat(index + 1));
- break;
- case CONSTANT_Long:
- poolObj[i] = Long.valueOf(getLong(index + 1));
- break;
- case CONSTANT_Double:
- poolObj[i] = Double.valueOf(getDouble(index + 1));
- break;
- case CONSTANT_MethodHandle:
- skipBytes(4);
- break;
- case CONSTANT_MethodType:
- skipBytes(3);
- break;
- case CONSTANT_Dynamic:
- case CONSTANT_InvokeDynamic:
- skipBytes(5);
- break;
- case CONSTANT_Module:
- case CONSTANT_Package:
- // this is temporary for now: treat as a simple reference to the underlying Utf8.
- poolObj[i] = readName(getChar(index + 1));
- break;
- default:
- throw badClassFile("bad.const.pool.tag", Byte.toString(tag));
- }
- return poolObj[i];
- }
-
- /** Read signature and convert to type.
- */
- Type readType(int i) {
- int index = poolIdx[i];
- return sigToType(buf, index + 3, getChar(index + 1));
- }
-
- /** If name is an array type or class signature, return the
- * corresponding type; otherwise return a ClassSymbol with given name.
- */
- Object readClassOrType(int i) {
- int index = poolIdx[i];
- int len = getChar(index + 1);
- int start = index + 3;
- Assert.check(buf[start] == '[' || buf[start + len - 1] != ';');
- // by the above assertion, the following test can be
- // simplified to (buf[start] == '[')
- return (buf[start] == '[' || buf[start + len - 1] == ';')
- ? (Object)sigToType(buf, start, len)
- : (Object)enterClass(names.fromUtf(internalize(buf, start,
- len)));
- }
-
- /** Read signature and convert to type parameters.
- */
- List<Type> readTypeParams(int i) {
- int index = poolIdx[i];
- return sigToTypeParams(buf, index + 3, getChar(index + 1));
- }
-
- /** Read class entry.
- */
- ClassSymbol readClassSymbol(int i) {
- Object obj = readPool(i);
- if (obj != null && !(obj instanceof ClassSymbol))
- throw badClassFile("bad.const.pool.entry",
- currentClassFile.toString(),
- "CONSTANT_Class_info", i);
- return (ClassSymbol)obj;
- }
-
- Name readClassName(int i) {
- int index = poolIdx[i];
- if (index == 0) return null;
- byte tag = buf[index];
- if (tag != CONSTANT_Class) {
- throw badClassFile("bad.const.pool.entry",
- currentClassFile.toString(),
- "CONSTANT_Class_info", i);
- }
- int nameIndex = poolIdx[getChar(index + 1)];
- int len = getChar(nameIndex + 1);
- int start = nameIndex + 3;
- if (buf[start] == '[' || buf[start + len - 1] == ';')
- throw badClassFile("wrong class name"); //TODO: proper diagnostics
- return names.fromUtf(internalize(buf, start, len));
- }
-
- /** Read name.
- */
- Name readName(int i) {
- Object obj = readPool(i);
- if (obj != null && !(obj instanceof Name))
- throw badClassFile("bad.const.pool.entry",
- currentClassFile.toString(),
- "CONSTANT_Utf8_info or CONSTANT_String_info", i);
- return (Name)obj;
- }
-
- /** Read name and type.
- */
- NameAndType readNameAndType(int i) {
- Object obj = readPool(i);
- if (obj != null && !(obj instanceof NameAndType))
- throw badClassFile("bad.const.pool.entry",
- currentClassFile.toString(),
- "CONSTANT_NameAndType_info", i);
- return (NameAndType)obj;
- }
-
- /** Read the name of a module.
- * The name is stored in a CONSTANT_Module entry, in
- * JVMS 4.2 binary form (using ".", not "/")
- */
- Name readModuleName(int i) {
- return readName(i);
- }
-
/** Read module_flags.
*/
Set<ModuleFlags> readModuleFlags(int flags) {
@@ -762,7 +488,7 @@
List<Type> argtypes = sigToTypes(')');
Type restype = sigToType();
List<Type> thrown = List.nil();
- while (signature[sigp] == '^') {
+ while (sigp < siglimit && signature[sigp] == '^') {
sigp++;
thrown = thrown.prepend(sigToType());
}
@@ -855,7 +581,7 @@
};
switch (signature[sigp++]) {
case ';':
- if (sigp < signature.length && signature[sigp] == '.') {
+ if (sigp < siglimit && signature[sigp] == '.') {
// support old-style GJC signatures
// The signature produced was
// Lfoo/Outer<Lfoo/X;>;.Lfoo/Outer$Inner<Lfoo/Y;>;
@@ -1049,7 +775,7 @@
new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
- if (readAllOfClassFile || saveParameterNames)
+ if (saveParameterNames)
((MethodSymbol)sym).code = readCode(sym);
else
bp = bp + attrLen;
@@ -1058,7 +784,7 @@
new AttributeReader(names.ConstantValue, V45_3, MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
- Object v = readPool(nextChar());
+ Object v = poolReader.getConstant(nextChar());
// Ignore ConstantValue attribute if field not final.
if ((sym.flags() & FINAL) == 0) {
return;
@@ -1115,7 +841,7 @@
int nexceptions = nextChar();
List<Type> thrown = List.nil();
for (int j = 0; j < nexceptions; j++)
- thrown = thrown.prepend(readClassSymbol(nextChar()).type);
+ thrown = thrown.prepend(poolReader.getClass(nextChar()).type);
if (sym.type.getThrownTypes().isEmpty())
sym.type.asMethodType().thrown = thrown.reverse();
}
@@ -1173,7 +899,7 @@
new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
ClassSymbol c = (ClassSymbol) sym;
- Name n = readName(nextChar());
+ Name n = poolReader.getName(nextChar());
c.sourcefile = new SourceFileObject(n);
// If the class is a toplevel class, originating from a Java source file,
// but the class name does not match the file name, then it is
@@ -1211,7 +937,8 @@
try {
ClassType ct1 = (ClassType)c.type;
Assert.check(c == currentOwner);
- ct1.typarams_field = readTypeParams(nextChar());
+ ct1.typarams_field = poolReader.getName(nextChar())
+ .map(ClassReader.this::sigToTypeParams);
ct1.supertype_field = sigToType();
ListBuffer<Type> is = new ListBuffer<>();
while (sigp != siglimit) is.append(sigToType());
@@ -1221,7 +948,7 @@
}
} else {
List<Type> thrown = sym.type.getThrownTypes();
- sym.type = readType(nextChar());
+ sym.type = poolReader.getType(nextChar());
//- System.err.println(" # " + sym.type);
if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
sym.type.asMethodType().thrown = thrown;
@@ -1342,19 +1069,19 @@
ModuleSymbol msym = (ModuleSymbol) sym.owner;
ListBuffer<Directive> directives = new ListBuffer<>();
- Name moduleName = readModuleName(nextChar());
+ Name moduleName = poolReader.peekModuleName(nextChar(), names::fromUtf);
if (currentModule.name != moduleName) {
throw badClassFile("module.name.mismatch", moduleName, currentModule.name);
}
Set<ModuleFlags> moduleFlags = readModuleFlags(nextChar());
msym.flags.addAll(moduleFlags);
- msym.version = readName(nextChar());
+ msym.version = optPoolEntry(nextChar(), poolReader::getName, null);
ListBuffer<RequiresDirective> requires = new ListBuffer<>();
int nrequires = nextChar();
for (int i = 0; i < nrequires; i++) {
- ModuleSymbol rsym = syms.enterModule(readModuleName(nextChar()));
+ ModuleSymbol rsym = poolReader.getModule(nextChar());
Set<RequiresFlag> flags = readRequiresFlags(nextChar());
if (rsym == syms.java_base && majorVersion >= V54.major) {
if (flags.contains(RequiresFlag.TRANSITIVE)) {
@@ -1373,8 +1100,7 @@
ListBuffer<ExportsDirective> exports = new ListBuffer<>();
int nexports = nextChar();
for (int i = 0; i < nexports; i++) {
- Name n = readName(nextChar());
- PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+ PackageSymbol p = poolReader.getPackage(nextChar());
Set<ExportsFlag> flags = readExportsFlags(nextChar());
int nto = nextChar();
List<ModuleSymbol> to;
@@ -1383,7 +1109,7 @@
} else {
ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
for (int t = 0; t < nto; t++)
- lb.append(syms.enterModule(readModuleName(nextChar())));
+ lb.append(poolReader.getModule(nextChar()));
to = lb.toList();
}
exports.add(new ExportsDirective(p, to, flags));
@@ -1396,8 +1122,7 @@
throw badClassFile("module.non.zero.opens", currentModule.name);
}
for (int i = 0; i < nopens; i++) {
- Name n = readName(nextChar());
- PackageSymbol p = syms.enterPackage(currentModule, names.fromUtf(internalize(n)));
+ PackageSymbol p = poolReader.getPackage(nextChar());
Set<OpensFlag> flags = readOpensFlags(nextChar());
int nto = nextChar();
List<ModuleSymbol> to;
@@ -1406,7 +1131,7 @@
} else {
ListBuffer<ModuleSymbol> lb = new ListBuffer<>();
for (int t = 0; t < nto; t++)
- lb.append(syms.enterModule(readModuleName(nextChar())));
+ lb.append(poolReader.getModule(nextChar()));
to = lb.toList();
}
opens.add(new OpensDirective(p, to, flags));
@@ -1419,7 +1144,7 @@
ListBuffer<InterimUsesDirective> uses = new ListBuffer<>();
int nuses = nextChar();
for (int i = 0; i < nuses; i++) {
- Name srvc = readClassName(nextChar());
+ Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
uses.add(new InterimUsesDirective(srvc));
}
interimUses = uses.toList();
@@ -1427,17 +1152,21 @@
ListBuffer<InterimProvidesDirective> provides = new ListBuffer<>();
int nprovides = nextChar();
for (int p = 0; p < nprovides; p++) {
- Name srvc = readClassName(nextChar());
+ Name srvc = poolReader.peekClassName(nextChar(), this::classNameMapper);
int nimpls = nextChar();
ListBuffer<Name> impls = new ListBuffer<>();
for (int i = 0; i < nimpls; i++) {
- impls.append(readClassName(nextChar()));
+ impls.append(poolReader.peekClassName(nextChar(), this::classNameMapper));
provides.add(new InterimProvidesDirective(srvc, impls.toList()));
}
}
interimProvides = provides.toList();
}
}
+
+ private Name classNameMapper(byte[] arr, int offset, int length) {
+ return names.fromUtf(ClassFile.internalize(arr, offset, length));
+ }
},
new AttributeReader(names.ModuleResolution, V53, CLASS_ATTRIBUTE) {
@@ -1464,8 +1193,8 @@
// the scope specified by the attribute
sym.owner.members().remove(sym);
ClassSymbol self = (ClassSymbol)sym;
- ClassSymbol c = readClassSymbol(nextChar());
- NameAndType nt = readNameAndType(nextChar());
+ ClassSymbol c = poolReader.getClass(nextChar());
+ NameAndType nt = optPoolEntry(nextChar(), poolReader::getNameAndType, null);
if (c.members_field == null || c.kind != TYP)
throw badClassFile("bad.enclosing.class", self, c);
@@ -1520,7 +1249,7 @@
if (nt == null)
return null;
- MethodType type = nt.uniqueType.type.asMethodType();
+ MethodType type = nt.type.asMethodType();
for (Symbol sym : scope.getSymbolsByName(nt.name)) {
if (sym.kind == MTH && isSameBinaryType(sym.type.asMethodType(), type))
@@ -1533,15 +1262,15 @@
if ((flags & INTERFACE) != 0)
// no enclosing instance
return null;
- if (nt.uniqueType.type.getParameterTypes().isEmpty())
+ if (nt.type.getParameterTypes().isEmpty())
// no parameters
return null;
// A constructor of an inner class.
// Remove the first argument (the enclosing instance)
- nt.setType(new MethodType(nt.uniqueType.type.getParameterTypes().tail,
- nt.uniqueType.type.getReturnType(),
- nt.uniqueType.type.getThrownTypes(),
+ nt = new NameAndType(nt.name, new MethodType(nt.type.getParameterTypes().tail,
+ nt.type.getReturnType(),
+ nt.type.getThrownTypes(),
syms.methodClass));
// Try searching again
return findMethod(nt, scope, flags);
@@ -1578,7 +1307,7 @@
void readAttrs(Symbol sym, AttributeKind kind) {
char ac = nextChar();
for (int i = 0; i < ac; i++) {
- Name attrName = readName(nextChar());
+ Name attrName = poolReader.getName(nextChar());
int attrLen = nextInt();
AttributeReader r = attributeReaders.get(attrName);
if (r != null && r.accepts(kind))
@@ -1681,7 +1410,7 @@
/** Read parameter annotations.
*/
void readParameterAnnotations(Symbol meth) {
- int numParameters = buf[bp++] & 0xFF;
+ int numParameters = buf.getByte(bp++) & 0xFF;
if (parameterAnnotations == null) {
parameterAnnotations = new ParameterAnnotations[numParameters];
} else if (parameterAnnotations.length != numParameters) {
@@ -1725,39 +1454,30 @@
Type readTypeOrClassSymbol(int i) {
// support preliminary jsr175-format class files
- if (buf[poolIdx[i]] == CONSTANT_Class)
- return readClassSymbol(i).type;
- return readTypeToProxy(i);
- }
- Type readEnumType(int i) {
- // support preliminary jsr175-format class files
- int index = poolIdx[i];
- int length = getChar(index + 1);
- if (buf[index + length + 2] != ';')
- return enterClass(readName(i)).type;
+ if (poolReader.hasTag(i, CONSTANT_Class))
+ return poolReader.getClass(i).type;
return readTypeToProxy(i);
}
Type readTypeToProxy(int i) {
if (currentModule.module_info == currentOwner) {
- int index = poolIdx[i];
- return new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
+ return new ProxyType(i);
} else {
- return readType(i);
+ return poolReader.getType(i);
}
}
CompoundAnnotationProxy readCompoundAnnotation() {
Type t;
if (currentModule.module_info == currentOwner) {
- int index = poolIdx[nextChar()];
- t = new ProxyType(Arrays.copyOfRange(buf, index + 3, index + 3 + getChar(index + 1)));
+ int cpIndex = nextChar();
+ t = new ProxyType(cpIndex);
} else {
t = readTypeOrClassSymbol(nextChar());
}
int numFields = nextChar();
ListBuffer<Pair<Name,Attribute>> pairs = new ListBuffer<>();
for (int i=0; i<numFields; i++) {
- Name name = readName(nextChar());
+ Name name = poolReader.getName(nextChar());
Attribute value = readAttributeValue();
pairs.append(new Pair<>(name, value));
}
@@ -1970,29 +1690,40 @@
}
+ /**
+ * Helper function to read an optional pool entry (with given function); this is used while parsing
+ * InnerClasses and EnclosingMethod attributes, as well as when parsing supertype descriptor,
+ * as per JVMS.
+ */
+ <Z> Z optPoolEntry(int index, IntFunction<Z> poolFunc, Z defaultValue) {
+ return (index == 0) ?
+ defaultValue :
+ poolFunc.apply(index);
+ }
+
Attribute readAttributeValue() {
- char c = (char) buf[bp++];
+ char c = (char) buf.getByte(bp++);
switch (c) {
case 'B':
- return new Attribute.Constant(syms.byteType, readPool(nextChar()));
+ return new Attribute.Constant(syms.byteType, poolReader.getConstant(nextChar()));
case 'C':
- return new Attribute.Constant(syms.charType, readPool(nextChar()));
+ return new Attribute.Constant(syms.charType, poolReader.getConstant(nextChar()));
case 'D':
- return new Attribute.Constant(syms.doubleType, readPool(nextChar()));
+ return new Attribute.Constant(syms.doubleType, poolReader.getConstant(nextChar()));
case 'F':
- return new Attribute.Constant(syms.floatType, readPool(nextChar()));
+ return new Attribute.Constant(syms.floatType, poolReader.getConstant(nextChar()));
case 'I':
- return new Attribute.Constant(syms.intType, readPool(nextChar()));
+ return new Attribute.Constant(syms.intType, poolReader.getConstant(nextChar()));
case 'J':
- return new Attribute.Constant(syms.longType, readPool(nextChar()));
+ return new Attribute.Constant(syms.longType, poolReader.getConstant(nextChar()));
case 'S':
- return new Attribute.Constant(syms.shortType, readPool(nextChar()));
+ return new Attribute.Constant(syms.shortType, poolReader.getConstant(nextChar()));
case 'Z':
- return new Attribute.Constant(syms.booleanType, readPool(nextChar()));
+ return new Attribute.Constant(syms.booleanType, poolReader.getConstant(nextChar()));
case 's':
- return new Attribute.Constant(syms.stringType, readPool(nextChar()).toString());
+ return new Attribute.Constant(syms.stringType, poolReader.getName(nextChar()).toString());
case 'e':
- return new EnumAttributeProxy(readEnumType(nextChar()), readName(nextChar()));
+ return new EnumAttributeProxy(readTypeToProxy(nextChar()), poolReader.getName(nextChar()));
case 'c':
return new ClassAttributeProxy(readTypeOrClassSymbol(nextChar()));
case '[': {
@@ -2401,8 +2132,8 @@
*/
VarSymbol readField() {
long flags = adjustFieldFlags(nextChar());
- Name name = readName(nextChar());
- Type type = readType(nextChar());
+ Name name = poolReader.getName(nextChar());
+ Type type = poolReader.getType(nextChar());
VarSymbol v = new VarSymbol(flags, name, type, currentOwner);
readMemberAttrs(v);
return v;
@@ -2412,8 +2143,8 @@
*/
MethodSymbol readMethod() {
long flags = adjustMethodFlags(nextChar());
- Name name = readName(nextChar());
- Type type = readType(nextChar());
+ Name name = poolReader.getName(nextChar());
+ Type type = poolReader.getType(nextChar());
if (currentOwner.isInterface() &&
(flags & ABSTRACT) == 0 && !name.equals(names.clinit)) {
if (majorVersion > Version.V52.major ||
@@ -2592,7 +2323,7 @@
Name argName;
if (parameterNameIndices != null && index < parameterNameIndices.length
&& parameterNameIndices[index] != 0) {
- argName = readName(parameterNameIndices[index]);
+ argName = optPoolEntry(parameterNameIndices[index], poolReader::getName, names.empty);
flags |= NAME_FILLED;
} else {
String prefix = "arg";
@@ -2681,7 +2412,7 @@
if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
// read own class name and check that it matches
currentModule = c.packge().modle;
- ClassSymbol self = readClassSymbol(nextChar());
+ ClassSymbol self = poolReader.getClass(nextChar());
if (c != self) {
throw badClassFile("class.file.wrong.class",
self.flatname);
@@ -2710,11 +2441,6 @@
for (int i = 0; i < methodCount; i++) skipMember();
readClassAttrs(c);
- if (readAllOfClassFile) {
- for (int i = 1; i < poolObj.length; i++) readPool(i);
- c.pool = new Pool(poolObj.length, poolObj, types);
- }
-
// reset and read rest of classinfo
bp = startbp;
int n = nextChar();
@@ -2722,13 +2448,12 @@
throw badClassFile("module.info.invalid.super.class");
}
if (ct.supertype_field == null)
- ct.supertype_field = (n == 0)
- ? Type.noType
- : readClassSymbol(n).erasure(types);
+ ct.supertype_field =
+ optPoolEntry(n, idx -> poolReader.getClass(idx).erasure(types), Type.noType);
n = nextChar();
List<Type> is = List.nil();
for (int i = 0; i < n; i++) {
- Type _inter = readClassSymbol(nextChar()).erasure(types);
+ Type _inter = poolReader.getClass(nextChar()).erasure(types);
is = is.prepend(_inter);
}
if (ct.interfaces_field == null)
@@ -2749,8 +2474,10 @@
int n = nextChar();
for (int i = 0; i < n; i++) {
nextChar(); // skip inner class symbol
- ClassSymbol outer = readClassSymbol(nextChar());
- Name name = readName(nextChar());
+ int outerIdx = nextChar();
+ int nameIdx = nextChar();
+ ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
+ Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
if (name == null) name = names.empty;
long flags = adjustClassFlags(nextChar());
if (outer != null) { // we have a member class
@@ -2804,7 +2531,8 @@
}
}
- indexPool();
+ poolReader = new PoolReader(this, names, syms);
+ bp = poolReader.readPool(buf, bp);
if (signatureBuffer.length < bp) {
int ns = Integer.highestOneBit(bp) << 1;
signatureBuffer = new byte[ns];
@@ -2821,7 +2549,8 @@
repeatable = null;
try {
bp = 0;
- buf = readInputStream(buf, c.classfile.openInputStream());
+ buf.reset();
+ buf.appendStream(c.classfile.openInputStream());
readClassBuffer(c);
if (!missingTypeVariables.isEmpty() && !foundTypeVariables.isEmpty()) {
List<Type> missing = missingTypeVariables;
@@ -2875,43 +2604,6 @@
filling = false;
}
}
- // where
- private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
- try {
- buf = ensureCapacity(buf, s.available());
- int r = s.read(buf);
- int bp = 0;
- while (r != -1) {
- bp += r;
- buf = ensureCapacity(buf, bp);
- r = s.read(buf, bp, buf.length - bp);
- }
- return buf;
- } finally {
- try {
- s.close();
- } catch (IOException e) {
- /* Ignore any errors, as this stream may have already
- * thrown a related exception which is the one that
- * should be reported.
- */
- }
- }
- }
- /*
- * ensureCapacity will increase the buffer as needed, taking note that
- * the new buffer will always be greater than the needed and never
- * exactly equal to the needed size or bp. If equal then the read (above)
- * will infinitely loop as buf.length - bp == 0.
- */
- private static byte[] ensureCapacity(byte[] buf, int needed) {
- if (buf.length <= needed) {
- byte[] old = buf;
- buf = new byte[Integer.highestOneBit(needed) << 1];
- System.arraycopy(old, 0, buf, 0, old.length);
- }
- return buf;
- }
/** We can only read a single class file at a time; this
* flag keeps track of when we are currently reading a class
@@ -3098,11 +2790,11 @@
private class ProxyType extends Type {
- private final byte[] content;
+ private final Name name;
- public ProxyType(byte[] content) {
+ public ProxyType(int index) {
super(syms.noSymbol, TypeMetadata.EMPTY);
- this.content = content;
+ this.name = poolReader.getName(index);
}
@Override
@@ -3116,7 +2808,7 @@
}
public Type resolve() {
- return sigToType(content, 0, content.length);
+ return name.map(ClassReader.this::sigToType);
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Apr 19 08:00:42 2019 -0400
@@ -29,9 +29,7 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
-import java.util.HashSet;
import java.util.LinkedHashSet;
-import java.util.stream.Collectors;
import javax.tools.JavaFileManager;
import javax.tools.FileObject;
@@ -44,13 +42,10 @@
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types.SignatureGenerator.InvalidSignatureException;
-import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.file.PathFileObject;
-import com.sun.tools.javac.jvm.Pool.DynamicMethod;
-import com.sun.tools.javac.jvm.Pool.Method;
-import com.sun.tools.javac.jvm.Pool.MethodHandle;
-import com.sun.tools.javac.jvm.Pool.Variable;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.util.*;
@@ -121,7 +116,7 @@
* Sizes are increased when buffers get full.
*/
static final int DATA_BUF_SIZE = 0x0fff0;
- static final int POOL_BUF_SIZE = 0x1fff0;
+ static final int CLASS_BUF_SIZE = 0x1fff0;
/** An output buffer for member info.
*/
@@ -129,25 +124,11 @@
/** An output buffer for the constant pool.
*/
- ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
-
- /** The constant pool.
- */
- Pool pool;
-
- /** The inner classes to be written, as a set.
- */
- Set<ClassSymbol> innerClasses;
+ ByteBuffer poolbuf = new ByteBuffer(CLASS_BUF_SIZE);
- /** The inner classes to be written, as a queue where
- * enclosing classes come first.
+ /** The constant pool writer.
*/
- ListBuffer<ClassSymbol> innerClassesQueue;
-
- /** The bootstrap methods to be written in the corresponding class attribute
- * (one for each invokedynamic)
- */
- Map<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> bootstrapMethods;
+ final PoolWriter poolWriter;
/** The log to use for verbose output.
*/
@@ -159,9 +140,6 @@
/** Access to files. */
private final JavaFileManager fileManager;
- /** Sole signature generator */
- private final CWSignatureGenerator signatureGen;
-
/** The tags and constants used in compressed stackmap. */
static final int SAME_FRAME_SIZE = 64;
static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
@@ -191,7 +169,7 @@
types = Types.instance(context);
check = Check.instance(context);
fileManager = context.get(JavaFileManager.class);
- signatureGen = new CWSignatureGenerator(types);
+ poolWriter = Gen.instance(context).poolWriter;
verbose = options.isSet(VERBOSE);
genCrt = options.isSet(XJCOV);
@@ -272,108 +250,17 @@
buf.elems[adr+3] = (byte)((x ) & 0xFF);
}
- /**
- * Signature Generation
- */
- private class CWSignatureGenerator extends Types.SignatureGenerator {
-
- /**
- * An output buffer for type signatures.
- */
- ByteBuffer sigbuf = new ByteBuffer();
-
- CWSignatureGenerator(Types types) {
- super(types);
- }
-
- /**
- * Assemble signature of given type in string buffer.
- * Check for uninitialized types before calling the general case.
- */
- @Override
- public void assembleSig(Type type) {
- switch (type.getTag()) {
- case UNINITIALIZED_THIS:
- case UNINITIALIZED_OBJECT:
- // we don't yet have a spec for uninitialized types in the
- // local variable table
- assembleSig(types.erasure(((UninitializedType)type).qtype));
- break;
- default:
- super.assembleSig(type);
- }
- }
-
- @Override
- protected void append(char ch) {
- sigbuf.appendByte(ch);
- }
-
- @Override
- protected void append(byte[] ba) {
- sigbuf.appendBytes(ba);
- }
-
- @Override
- protected void append(Name name) {
- sigbuf.appendName(name);
- }
-
- @Override
- protected void classReference(ClassSymbol c) {
- enterInner(c);
- }
-
- private void reset() {
- sigbuf.reset();
- }
-
- private Name toName() {
- return sigbuf.toName(names);
- }
-
- private boolean isEmpty() {
- return sigbuf.length == 0;
- }
- }
-
- /**
- * Return signature of given type
- */
- Name typeSig(Type type) {
- Assert.check(signatureGen.isEmpty());
- //- System.out.println(" ? " + type);
- signatureGen.assembleSig(type);
- Name n = signatureGen.toName();
- signatureGen.reset();
- //- System.out.println(" " + n);
- return n;
- }
-
- /** Given a type t, return the extended class name of its erasure in
- * external representation.
- */
- public Name xClassName(Type t) {
- if (t.hasTag(CLASS)) {
- return names.fromUtf(externalize(t.tsym.flatName()));
- } else if (t.hasTag(ARRAY)) {
- return typeSig(types.erasure(t));
- } else {
- throw new AssertionError("xClassName expects class or array type, got " + t);
- }
- }
-
/******************************************************************
* Writing the Constant Pool
******************************************************************/
/** Thrown when the constant pool is over full.
*/
- public static class PoolOverflow extends Exception {
+ public static class PoolOverflow extends RuntimeException {
private static final long serialVersionUID = 0;
public PoolOverflow() {}
}
- public static class StringOverflow extends Exception {
+ public static class StringOverflow extends RuntimeException {
private static final long serialVersionUID = 0;
public final String value;
public StringOverflow(String s) {
@@ -381,137 +268,6 @@
}
}
- /** Write constant pool to pool buffer.
- * Note: during writing, constant pool
- * might grow since some parts of constants still need to be entered.
- */
- void writePool(Pool pool) throws PoolOverflow, StringOverflow {
- int poolCountIdx = poolbuf.length;
- poolbuf.appendChar(0);
- int i = 1;
- while (i < pool.pp) {
- Object value = pool.pool[i];
- Assert.checkNonNull(value);
- if (value instanceof Method || value instanceof Variable)
- value = ((DelegatedSymbol)value).getUnderlyingSymbol();
-
- if (value instanceof MethodSymbol) {
- MethodSymbol m = (MethodSymbol)value;
- if (!m.isDynamic()) {
- poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
- ? CONSTANT_InterfaceMethodref
- : CONSTANT_Methodref);
- poolbuf.appendChar(pool.put(m.owner));
- poolbuf.appendChar(pool.put(nameType(m)));
- } else {
- //invokedynamic
- DynamicMethodSymbol dynSym = (DynamicMethodSymbol)m;
- MethodHandle handle = new MethodHandle(dynSym.bsmKind, dynSym.bsm, types);
- DynamicMethod.BootstrapMethodsKey key = new DynamicMethod.BootstrapMethodsKey(dynSym, types);
-
- // Figure out the index for existing BSM; create a new BSM if no key
- DynamicMethod.BootstrapMethodsValue val = bootstrapMethods.get(key);
- if (val == null) {
- int index = bootstrapMethods.size();
- val = new DynamicMethod.BootstrapMethodsValue(handle, index);
- bootstrapMethods.put(key, val);
- }
-
- //init cp entries
- pool.put(names.BootstrapMethods);
- pool.put(handle);
- for (Object staticArg : dynSym.staticArgs) {
- pool.put(staticArg);
- }
- poolbuf.appendByte(CONSTANT_InvokeDynamic);
- poolbuf.appendChar(val.index);
- poolbuf.appendChar(pool.put(nameType(dynSym)));
- }
- } else if (value instanceof VarSymbol) {
- VarSymbol v = (VarSymbol)value;
- poolbuf.appendByte(CONSTANT_Fieldref);
- poolbuf.appendChar(pool.put(v.owner));
- poolbuf.appendChar(pool.put(nameType(v)));
- } else if (value instanceof Name) {
- poolbuf.appendByte(CONSTANT_Utf8);
- byte[] bs = ((Name)value).toUtf();
- poolbuf.appendChar(bs.length);
- poolbuf.appendBytes(bs, 0, bs.length);
- if (bs.length > Pool.MAX_STRING_LENGTH)
- throw new StringOverflow(value.toString());
- } else if (value instanceof ClassSymbol) {
- ClassSymbol c = (ClassSymbol)value;
- if (c.owner.kind == TYP) pool.put(c.owner);
- poolbuf.appendByte(CONSTANT_Class);
- if (c.type.hasTag(ARRAY)) {
- poolbuf.appendChar(pool.put(typeSig(c.type)));
- } else {
- poolbuf.appendChar(pool.put(names.fromUtf(externalize(c.flatname))));
- enterInner(c);
- }
- } else if (value instanceof NameAndType) {
- NameAndType nt = (NameAndType)value;
- poolbuf.appendByte(CONSTANT_NameandType);
- poolbuf.appendChar(pool.put(nt.name));
- poolbuf.appendChar(pool.put(typeSig(nt.uniqueType.type)));
- } else if (value instanceof Integer) {
- poolbuf.appendByte(CONSTANT_Integer);
- poolbuf.appendInt(((Integer)value).intValue());
- } else if (value instanceof Long) {
- poolbuf.appendByte(CONSTANT_Long);
- poolbuf.appendLong(((Long)value).longValue());
- i++;
- } else if (value instanceof Float) {
- poolbuf.appendByte(CONSTANT_Float);
- poolbuf.appendFloat(((Float)value).floatValue());
- } else if (value instanceof Double) {
- poolbuf.appendByte(CONSTANT_Double);
- poolbuf.appendDouble(((Double)value).doubleValue());
- i++;
- } else if (value instanceof String) {
- poolbuf.appendByte(CONSTANT_String);
- poolbuf.appendChar(pool.put(names.fromString((String)value)));
- } else if (value instanceof UniqueType) {
- Type type = ((UniqueType)value).type;
- if (type.hasTag(METHOD)) {
- poolbuf.appendByte(CONSTANT_MethodType);
- poolbuf.appendChar(pool.put(typeSig((MethodType)type)));
- } else {
- Assert.check(type.hasTag(ARRAY));
- poolbuf.appendByte(CONSTANT_Class);
- poolbuf.appendChar(pool.put(xClassName(type)));
- }
- } else if (value instanceof MethodHandle) {
- MethodHandle ref = (MethodHandle)value;
- poolbuf.appendByte(CONSTANT_MethodHandle);
- poolbuf.appendByte(ref.refKind);
- poolbuf.appendChar(pool.put(ref.refSym));
- } else if (value instanceof ModuleSymbol) {
- ModuleSymbol m = (ModuleSymbol)value;
- poolbuf.appendByte(CONSTANT_Module);
- poolbuf.appendChar(pool.put(m.name));
- } else if (value instanceof PackageSymbol) {
- PackageSymbol m = (PackageSymbol)value;
- poolbuf.appendByte(CONSTANT_Package);
- poolbuf.appendChar(pool.put(names.fromUtf(externalize(m.fullname))));
- } else {
- Assert.error("writePool " + value);
- }
- i++;
- }
- if (pool.pp > Pool.MAX_ENTRIES)
- throw new PoolOverflow();
- putChar(poolbuf, poolCountIdx, pool.pp);
- }
-
- /** Given a symbol, return its name-and-type.
- */
- NameAndType nameType(Symbol sym) {
- return new NameAndType(sym.name, sym.externalType(types), types);
- // the NameAndType is generated from a symbol reference, and the
- // adjustment of adding an additional this$n parameter needs to be made.
- }
-
/******************************************************************
* Writing Attributes
******************************************************************/
@@ -520,7 +276,8 @@
* position past attribute length index.
*/
int writeAttr(Name attrName) {
- databuf.appendChar(pool.put(attrName));
+ int index = poolWriter.putName(attrName);
+ databuf.appendChar(index);
databuf.appendInt(0);
return databuf.length;
}
@@ -567,8 +324,8 @@
|| c.owner.kind != MTH) // or member init
? null
: (MethodSymbol)c.owner;
- databuf.appendChar(pool.put(enclClass));
- databuf.appendChar(enclMethod == null ? 0 : pool.put(nameType(c.owner)));
+ databuf.appendChar(poolWriter.putClass(enclClass));
+ databuf.appendChar(enclMethod == null ? 0 : poolWriter.putNameAndType(c.owner));
endAttr(alenIdx);
return 1;
}
@@ -594,11 +351,11 @@
if ((flags & (SYNTHETIC | BRIDGE)) != SYNTHETIC &&
(flags & ANONCONSTR) == 0 &&
(!types.isSameType(sym.type, sym.erasure(types)) ||
- signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
+ poolWriter.signatureGen.hasTypeVar(sym.type.getThrownTypes()))) {
// note that a local class with captured variables
// will get a signature attribute
int alenIdx = writeAttr(names.Signature);
- databuf.appendChar(pool.put(typeSig(sym.type)));
+ databuf.appendChar(poolWriter.putSignature(sym));
endAttr(alenIdx);
acount++;
}
@@ -621,7 +378,7 @@
final int flags =
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
((int) m.flags() & SYNTHETIC);
- databuf.appendChar(pool.put(s.name));
+ databuf.appendChar(poolWriter.putName(s.name));
databuf.appendChar(flags);
}
// Now write the real parameters
@@ -629,7 +386,7 @@
final int flags =
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
((int) m.flags() & SYNTHETIC);
- databuf.appendChar(pool.put(s.name));
+ databuf.appendChar(poolWriter.putName(s.name));
databuf.appendChar(flags);
}
// Now write the captured locals
@@ -637,7 +394,7 @@
final int flags =
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
((int) m.flags() & SYNTHETIC);
- databuf.appendChar(pool.put(s.name));
+ databuf.appendChar(poolWriter.putName(s.name));
databuf.appendChar(flags);
}
endAttr(attrIndex);
@@ -803,50 +560,51 @@
*/
class AttributeWriter implements Attribute.Visitor {
public void visitConstant(Attribute.Constant _value) {
- Object value = _value.value;
- switch (_value.type.getTag()) {
- case BYTE:
- databuf.appendByte('B');
- break;
- case CHAR:
- databuf.appendByte('C');
- break;
- case SHORT:
- databuf.appendByte('S');
- break;
- case INT:
- databuf.appendByte('I');
- break;
- case LONG:
- databuf.appendByte('J');
- break;
- case FLOAT:
- databuf.appendByte('F');
- break;
- case DOUBLE:
- databuf.appendByte('D');
- break;
- case BOOLEAN:
- databuf.appendByte('Z');
- break;
- case CLASS:
- Assert.check(value instanceof String);
+ if (_value.type.getTag() == CLASS) {
+ Assert.check(_value.value instanceof String);
+ String s = (String)_value.value;
databuf.appendByte('s');
- value = names.fromString(value.toString()); // CONSTANT_Utf8
- break;
- default:
- throw new AssertionError(_value.type);
+ databuf.appendChar(poolWriter.putName(names.fromString(s)));
+ } else {
+ switch (_value.type.getTag()) {
+ case BYTE:
+ databuf.appendByte('B');
+ break;
+ case CHAR:
+ databuf.appendByte('C');
+ break;
+ case SHORT:
+ databuf.appendByte('S');
+ break;
+ case INT:
+ databuf.appendByte('I');
+ break;
+ case LONG:
+ databuf.appendByte('J');
+ break;
+ case FLOAT:
+ databuf.appendByte('F');
+ break;
+ case DOUBLE:
+ databuf.appendByte('D');
+ break;
+ case BOOLEAN:
+ databuf.appendByte('Z');
+ break;
+ default:
+ throw new AssertionError(_value.type);
+ }
+ databuf.appendChar(poolWriter.putConstant(_value.value));
}
- databuf.appendChar(pool.put(value));
}
public void visitEnum(Attribute.Enum e) {
databuf.appendByte('e');
- databuf.appendChar(pool.put(typeSig(e.value.type)));
- databuf.appendChar(pool.put(e.value.name));
+ databuf.appendChar(poolWriter.putDescriptor(e.value.type));
+ databuf.appendChar(poolWriter.putName(e.value.name));
}
public void visitClass(Attribute.Class clazz) {
databuf.appendByte('c');
- databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType))));
+ databuf.appendChar(poolWriter.putDescriptor(clazz.classType));
}
public void visitCompound(Attribute.Compound compound) {
databuf.appendByte('@');
@@ -867,10 +625,10 @@
/** Write a compound attribute excluding the '@' marker. */
void writeCompoundAttribute(Attribute.Compound c) {
- databuf.appendChar(pool.put(typeSig(c.type)));
+ databuf.appendChar(poolWriter.putDescriptor(c.type));
databuf.appendChar(c.values.length());
for (Pair<Symbol.MethodSymbol,Attribute> p : c.values) {
- databuf.appendChar(pool.put(p.fst.name));
+ databuf.appendChar(poolWriter.putName(p.fst.name));
p.snd.accept(awriter);
}
}
@@ -974,9 +732,9 @@
int alenIdx = writeAttr(names.Module);
- databuf.appendChar(pool.put(m));
+ databuf.appendChar(poolWriter.putModule(m));
databuf.appendChar(ModuleFlags.value(m.flags)); // module_flags
- databuf.appendChar(m.version != null ? pool.put(m.version) : 0);
+ databuf.appendChar(m.version != null ? poolWriter.putName(m.version) : 0);
ListBuffer<RequiresDirective> requires = new ListBuffer<>();
for (RequiresDirective r: m.requires) {
@@ -985,22 +743,22 @@
}
databuf.appendChar(requires.size());
for (RequiresDirective r: requires) {
- databuf.appendChar(pool.put(r.module));
+ databuf.appendChar(poolWriter.putModule(r.module));
databuf.appendChar(RequiresFlag.value(r.flags));
- databuf.appendChar(r.module.version != null ? pool.put(r.module.version) : 0);
+ databuf.appendChar(r.module.version != null ? poolWriter.putName(r.module.version) : 0);
}
List<ExportsDirective> exports = m.exports;
databuf.appendChar(exports.size());
for (ExportsDirective e: exports) {
- databuf.appendChar(pool.put(e.packge));
+ databuf.appendChar(poolWriter.putPackage(e.packge));
databuf.appendChar(ExportsFlag.value(e.flags));
if (e.modules == null) {
databuf.appendChar(0);
} else {
databuf.appendChar(e.modules.size());
for (ModuleSymbol msym: e.modules) {
- databuf.appendChar(pool.put(msym));
+ databuf.appendChar(poolWriter.putModule(msym));
}
}
}
@@ -1008,14 +766,14 @@
List<OpensDirective> opens = m.opens;
databuf.appendChar(opens.size());
for (OpensDirective o: opens) {
- databuf.appendChar(pool.put(o.packge));
+ databuf.appendChar(poolWriter.putPackage(o.packge));
databuf.appendChar(OpensFlag.value(o.flags));
if (o.modules == null) {
databuf.appendChar(0);
} else {
databuf.appendChar(o.modules.size());
for (ModuleSymbol msym: o.modules) {
- databuf.appendChar(pool.put(msym));
+ databuf.appendChar(poolWriter.putModule(msym));
}
}
}
@@ -1023,7 +781,7 @@
List<UsesDirective> uses = m.uses;
databuf.appendChar(uses.size());
for (UsesDirective s: uses) {
- databuf.appendChar(pool.put(s.service));
+ databuf.appendChar(poolWriter.putClass(s.service));
}
// temporary fix to merge repeated provides clause for same service;
@@ -1035,9 +793,9 @@
}
databuf.appendChar(mergedProvides.size());
mergedProvides.forEach((srvc, impls) -> {
- databuf.appendChar(pool.put(srvc));
+ databuf.appendChar(poolWriter.putClass(srvc));
databuf.appendChar(impls.size());
- impls.forEach(impl -> databuf.appendChar(pool.put(impl)));
+ impls.forEach(impl -> databuf.appendChar(poolWriter.putClass(impl)));
});
endAttr(alenIdx);
@@ -1048,46 +806,12 @@
* Writing Objects
**********************************************************************/
- /** Enter an inner class into the `innerClasses' set/queue.
- */
- void enterInner(ClassSymbol c) {
- if (c.type.isCompound()) {
- throw new AssertionError("Unexpected intersection type: " + c.type);
- }
- try {
- c.complete();
- } catch (CompletionFailure ex) {
- System.err.println("error: " + c + ": " + ex.getMessage());
- throw ex;
- }
- if (!c.type.hasTag(CLASS)) return; // arrays
- if (pool != null && // pool might be null if called from xClassName
- c.owner.enclClass() != null &&
- (innerClasses == null || !innerClasses.contains(c))) {
-// log.errWriter.println("enter inner " + c);//DEBUG
- enterInner(c.owner.enclClass());
- pool.put(c);
- if (c.name != names.empty)
- pool.put(c.name);
- if (innerClasses == null) {
- innerClasses = new HashSet<>();
- innerClassesQueue = new ListBuffer<>();
- pool.put(names.InnerClasses);
- }
- innerClasses.add(c);
- innerClassesQueue.append(c);
- }
- }
-
/** Write "inner classes" attribute.
*/
void writeInnerClasses() {
int alenIdx = writeAttr(names.InnerClasses);
- databuf.appendChar(innerClassesQueue.length());
- for (List<ClassSymbol> l = innerClassesQueue.toList();
- l.nonEmpty();
- l = l.tail) {
- ClassSymbol inner = l.head;
+ databuf.appendChar(poolWriter.innerClasses.size());
+ for (ClassSymbol inner : poolWriter.innerClasses) {
inner.markAbstractIfNeeded(types);
char flags = (char) adjustFlags(inner.flags_field);
if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
@@ -1097,11 +821,11 @@
pw.println("INNERCLASS " + inner.name);
pw.println("---" + flagNames(flags));
}
- databuf.appendChar(pool.get(inner));
+ databuf.appendChar(poolWriter.putClass(inner));
databuf.appendChar(
- inner.owner.kind == TYP && !inner.name.isEmpty() ? pool.get(inner.owner) : 0);
+ inner.owner.kind == TYP && !inner.name.isEmpty() ? poolWriter.putClass((ClassSymbol)inner.owner) : 0);
databuf.appendChar(
- !inner.name.isEmpty() ? pool.get(inner.name) : 0);
+ !inner.name.isEmpty() ? poolWriter.putName(inner.name) : 0);
databuf.appendChar(flags);
}
endAttr(alenIdx);
@@ -1111,14 +835,14 @@
* Write NestMembers attribute (if needed)
*/
int writeNestMembersIfNeeded(ClassSymbol csym) {
- ListBuffer<Symbol> nested = new ListBuffer<>();
+ ListBuffer<ClassSymbol> nested = new ListBuffer<>();
listNested(csym, nested);
- Set<Symbol> nestedUnique = new LinkedHashSet<>(nested);
+ Set<ClassSymbol> nestedUnique = new LinkedHashSet<>(nested);
if (csym.owner.kind == PCK && !nestedUnique.isEmpty()) {
int alenIdx = writeAttr(names.NestMembers);
databuf.appendChar(nestedUnique.size());
- for (Symbol s : nestedUnique) {
- databuf.appendChar(pool.put(s));
+ for (ClassSymbol s : nestedUnique) {
+ databuf.appendChar(poolWriter.putClass(s));
}
endAttr(alenIdx);
return 1;
@@ -1132,14 +856,14 @@
int writeNestHostIfNeeded(ClassSymbol csym) {
if (csym.owner.kind != PCK) {
int alenIdx = writeAttr(names.NestHost);
- databuf.appendChar(pool.put(csym.outermostClass()));
+ databuf.appendChar(poolWriter.putClass(csym.outermostClass()));
endAttr(alenIdx);
return 1;
}
return 0;
}
- private void listNested(Symbol sym, ListBuffer<Symbol> seen) {
+ private void listNested(Symbol sym, ListBuffer<ClassSymbol> seen) {
if (sym.kind != TYP) return;
ClassSymbol csym = (ClassSymbol)sym;
if (csym.owner.kind != PCK) {
@@ -1161,17 +885,16 @@
*/
void writeBootstrapMethods() {
int alenIdx = writeAttr(names.BootstrapMethods);
- databuf.appendChar(bootstrapMethods.size());
- for (Map.Entry<DynamicMethod.BootstrapMethodsKey, DynamicMethod.BootstrapMethodsValue> entry : bootstrapMethods.entrySet()) {
- DynamicMethod.BootstrapMethodsKey bsmKey = entry.getKey();
+ databuf.appendChar(poolWriter.bootstrapMethods.size());
+ for (BsmKey bsmKey : poolWriter.bootstrapMethods.keySet()) {
//write BSM handle
- databuf.appendChar(pool.get(entry.getValue().mh));
- Object[] uniqueArgs = bsmKey.getUniqueArgs();
+ databuf.appendChar(poolWriter.putConstant(bsmKey.bsm));
+ LoadableConstant[] uniqueArgs = bsmKey.staticArgs;
//write static args length
databuf.appendChar(uniqueArgs.length);
//write static args array
- for (Object o : uniqueArgs) {
- databuf.appendChar(pool.get(o));
+ for (LoadableConstant arg : uniqueArgs) {
+ databuf.appendChar(poolWriter.putConstant(arg));
}
}
endAttr(alenIdx);
@@ -1187,13 +910,13 @@
pw.println("FIELD " + v.name);
pw.println("---" + flagNames(v.flags()));
}
- databuf.appendChar(pool.put(v.name));
- databuf.appendChar(pool.put(typeSig(v.erasure(types))));
+ databuf.appendChar(poolWriter.putName(v.name));
+ databuf.appendChar(poolWriter.putDescriptor(v));
int acountIdx = beginAttrs();
int acount = 0;
if (v.getConstValue() != null) {
int alenIdx = writeAttr(names.ConstantValue);
- databuf.appendChar(pool.put(v.getConstValue()));
+ databuf.appendChar(poolWriter.putConstant(v.getConstValue()));
endAttr(alenIdx);
acount++;
}
@@ -1211,8 +934,8 @@
pw.println("METHOD " + m.name);
pw.println("---" + flagNames(m.flags()));
}
- databuf.appendChar(pool.put(m.name));
- databuf.appendChar(pool.put(typeSig(m.externalType(types))));
+ databuf.appendChar(poolWriter.putName(m.name));
+ databuf.appendChar(poolWriter.putDescriptor(m));
int acountIdx = beginAttrs();
int acount = 0;
if (m.code != null) {
@@ -1227,7 +950,7 @@
int alenIdx = writeAttr(names.Exceptions);
databuf.appendChar(thrown.length());
for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
- databuf.appendChar(pool.put(l.head.tsym));
+ databuf.appendChar(poolWriter.putClass(l.head));
endAttr(alenIdx);
acount++;
}
@@ -1303,9 +1026,8 @@
&& (r.start_pc + r.length) <= code.cp);
databuf.appendChar(r.length);
VarSymbol sym = var.sym;
- databuf.appendChar(pool.put(sym.name));
- Type vartype = sym.erasure(types);
- databuf.appendChar(pool.put(typeSig(vartype)));
+ databuf.appendChar(poolWriter.putName(sym.name));
+ databuf.appendChar(poolWriter.putDescriptor(sym));
databuf.appendChar(var.reg);
if (needsLocalVariableTypeEntry(var.sym.type)) {
nGenericVars++;
@@ -1329,8 +1051,8 @@
// write variable info
databuf.appendChar(r.start_pc);
databuf.appendChar(r.length);
- databuf.appendChar(pool.put(sym.name));
- databuf.appendChar(pool.put(typeSig(sym.type)));
+ databuf.appendChar(poolWriter.putName(sym.name));
+ databuf.appendChar(poolWriter.putSignature(sym));
databuf.appendChar(var.reg);
count++;
}
@@ -1457,14 +1179,10 @@
break;
case CLASS:
case ARRAY:
- if (debugstackmap) System.out.print("object(" + t + ")");
- databuf.appendByte(7);
- databuf.appendChar(pool.put(t));
- break;
case TYPEVAR:
if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
databuf.appendByte(7);
- databuf.appendChar(pool.put(types.erasure(t).tsym));
+ databuf.appendChar(poolWriter.putClass(types.erasure(t)));
break;
case UNINITIALIZED_THIS:
if (debugstackmap) System.out.print("uninit_this");
@@ -1763,11 +1481,6 @@
Assert.check((c.flags() & COMPOUND) == 0);
databuf.reset();
poolbuf.reset();
- signatureGen.reset();
- pool = c.pool;
- innerClasses = null;
- innerClassesQueue = null;
- bootstrapMethods = new LinkedHashMap<>();
Type supertype = types.supertype(c.type);
List<Type> interfaces = types.interfaces(c.type);
@@ -1793,14 +1506,14 @@
if (c.owner.kind == MDL) {
PackageSymbol unnamed = ((ModuleSymbol) c.owner).unnamedPackage;
- databuf.appendChar(pool.put(new ClassSymbol(0, names.module_info, unnamed)));
+ databuf.appendChar(poolWriter.putClass(new ClassSymbol(0, names.module_info, unnamed)));
} else {
- databuf.appendChar(pool.put(c));
+ databuf.appendChar(poolWriter.putClass(c));
}
- databuf.appendChar(supertype.hasTag(CLASS) ? pool.put(supertype.tsym) : 0);
+ databuf.appendChar(supertype.hasTag(CLASS) ? poolWriter.putClass((ClassSymbol)supertype.tsym) : 0);
databuf.appendChar(interfaces.length());
for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
- databuf.appendChar(pool.put(l.head.tsym));
+ databuf.appendChar(poolWriter.putClass((ClassSymbol)l.head.tsym));
int fieldsCount = 0;
int methodsCount = 0;
for (Symbol sym : c.members().getSymbols(NON_RECURSIVE)) {
@@ -1808,14 +1521,14 @@
case VAR: fieldsCount++; break;
case MTH: if ((sym.flags() & HYPOTHETICAL) == 0) methodsCount++;
break;
- case TYP: enterInner((ClassSymbol)sym); break;
+ case TYP: poolWriter.enterInner((ClassSymbol)sym); break;
default : Assert.error();
}
}
if (c.trans_local != null) {
for (ClassSymbol local : c.trans_local) {
- enterInner(local);
+ poolWriter.enterInner(local);
}
}
@@ -1833,12 +1546,7 @@
sigReq = l.head.allparams().length() != 0;
if (sigReq) {
int alenIdx = writeAttr(names.Signature);
- if (typarams.length() != 0) signatureGen.assembleParamsSig(typarams);
- signatureGen.assembleSig(supertype);
- for (List<Type> l = interfaces; l.nonEmpty(); l = l.tail)
- signatureGen.assembleSig(l.head);
- databuf.appendChar(pool.put(signatureGen.toName()));
- signatureGen.reset();
+ databuf.appendChar(poolWriter.putSignature(c));
endAttr(alenIdx);
acount++;
}
@@ -1848,9 +1556,8 @@
// WHM 6/29/1999: Strip file path prefix. We do it here at
// the last possible moment because the sourcefile may be used
// elsewhere in error diagnostics. Fixes 4241573.
- //databuf.appendChar(c.pool.put(c.sourcefile));
String simpleName = PathFileObject.getSimpleName(c.sourcefile);
- databuf.appendChar(c.pool.put(names.fromString(simpleName)));
+ databuf.appendChar(poolWriter.putName(names.fromString(simpleName)));
endAttr(alenIdx);
acount++;
}
@@ -1858,12 +1565,12 @@
if (genCrt) {
// Append SourceID attribute
int alenIdx = writeAttr(names.SourceID);
- databuf.appendChar(c.pool.put(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
+ databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(getLastModified(c.sourcefile)))));
endAttr(alenIdx);
acount++;
// Append CompilationID attribute
alenIdx = writeAttr(names.CompilationID);
- databuf.appendChar(c.pool.put(names.fromString(Long.toString(System.currentTimeMillis()))));
+ databuf.appendChar(poolWriter.putName(names.fromString(Long.toString(System.currentTimeMillis()))));
endAttr(alenIdx);
acount++;
}
@@ -1893,24 +1600,24 @@
}
}
- writePool(c.pool);
-
- if (innerClasses != null) {
- writeInnerClasses();
+ if (!poolWriter.bootstrapMethods.isEmpty()) {
+ writeBootstrapMethods();
acount++;
}
- if (!bootstrapMethods.isEmpty()) {
- writeBootstrapMethods();
+ if (!poolWriter.innerClasses.isEmpty()) {
+ writeInnerClasses();
acount++;
}
endAttrs(acountIdx, acount);
- poolbuf.appendBytes(databuf.elems, 0, databuf.length);
out.write(poolbuf.elems, 0, poolbuf.length);
- pool = c.pool = null; // to conserve space
+ poolWriter.writePool(out);
+ poolWriter.reset(); // to save space
+
+ out.write(databuf.elems, 0, databuf.length);
}
/**Allows subclasses to write additional class attributes
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java Fri Apr 19 08:00:42 2019 -0400
@@ -27,15 +27,27 @@
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
-import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import java.util.function.ToIntBiFunction;
+import java.util.function.ToIntFunction;
+
import static com.sun.tools.javac.code.TypeTag.BOT;
import static com.sun.tools.javac.code.TypeTag.INT;
import static com.sun.tools.javac.jvm.ByteCodes.*;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
import static com.sun.tools.javac.jvm.UninitializedType.*;
import static com.sun.tools.javac.jvm.ClassWriter.StackMapTableFrame;
@@ -72,6 +84,7 @@
final Types types;
final Symtab syms;
+ final PoolWriter poolWriter;
/*---------- classfile fields: --------------- */
@@ -177,10 +190,6 @@
*/
Position.LineMap lineMap;
- /** The constant pool of the current class.
- */
- final Pool pool;
-
final MethodSymbol meth;
private int letExprStackPos = 0;
@@ -197,7 +206,7 @@
CRTable crt,
Symtab syms,
Types types,
- Pool pool) {
+ PoolWriter poolWriter) {
this.meth = meth;
this.fatcode = fatcode;
this.lineMap = lineMap;
@@ -206,6 +215,7 @@
this.crt = crt;
this.syms = syms;
this.types = types;
+ this.poolWriter = poolWriter;
this.debugCode = debugCode;
this.stackMap = stackMap;
switch (stackMap) {
@@ -218,7 +228,6 @@
}
state = new State();
lvar = new LocalVar[20];
- this.pool = pool;
}
@@ -389,12 +398,13 @@
/** Emit a ldc (or ldc_w) instruction, taking into account operand size
*/
- public void emitLdc(int od) {
+ public void emitLdc(LoadableConstant constant) {
+ int od = poolWriter.putConstant(constant);
if (od <= 255) {
- emitop1(ldc1, od);
+ emitop1(ldc1, od, constant);
}
else {
- emitop2(ldc2, od);
+ emitop2(ldc2, od, constant);
}
}
@@ -431,11 +441,11 @@
/** Emit an invokeinterface instruction.
*/
- public void emitInvokeinterface(int meth, Type mtype) {
+ public void emitInvokeinterface(Symbol member, Type mtype) {
int argsize = width(mtype.getParameterTypes());
emitop(invokeinterface);
if (!alive) return;
- emit2(meth);
+ emit2(poolWriter.putMember(member));
emit1(argsize + 1);
emit1(0);
state.pop(argsize + 1);
@@ -444,14 +454,13 @@
/** Emit an invokespecial instruction.
*/
- public void emitInvokespecial(int meth, Type mtype) {
+ public void emitInvokespecial(Symbol member, Type mtype) {
int argsize = width(mtype.getParameterTypes());
emitop(invokespecial);
if (!alive) return;
- emit2(meth);
- Symbol sym = (Symbol)pool.pool[meth];
+ emit2(poolWriter.putMember(member));
state.pop(argsize);
- if (sym.isConstructor())
+ if (member.isConstructor())
state.markInitialized((UninitializedType)state.peek());
state.pop(1);
state.push(mtype.getReturnType());
@@ -459,33 +468,33 @@
/** Emit an invokestatic instruction.
*/
- public void emitInvokestatic(int meth, Type mtype) {
+ public void emitInvokestatic(Symbol member, Type mtype) {
int argsize = width(mtype.getParameterTypes());
emitop(invokestatic);
if (!alive) return;
- emit2(meth);
+ emit2(poolWriter.putMember(member));
state.pop(argsize);
state.push(mtype.getReturnType());
}
/** Emit an invokevirtual instruction.
*/
- public void emitInvokevirtual(int meth, Type mtype) {
+ public void emitInvokevirtual(Symbol member, Type mtype) {
int argsize = width(mtype.getParameterTypes());
emitop(invokevirtual);
if (!alive) return;
- emit2(meth);
+ emit2(poolWriter.putMember(member));
state.pop(argsize + 1);
state.push(mtype.getReturnType());
}
/** Emit an invokedynamic instruction.
*/
- public void emitInvokedynamic(int desc, Type mtype) {
+ public void emitInvokedynamic(DynamicMethodSymbol dynMember, Type mtype) {
int argsize = width(mtype.getParameterTypes());
emitop(invokedynamic);
if (!alive) return;
- emit2(desc);
+ emit2(poolWriter.putDynamic(dynMember));
emit2(0);
state.pop(argsize);
state.push(mtype.getReturnType());
@@ -896,6 +905,10 @@
/** Emit an opcode with a one-byte operand field.
*/
public void emitop1(int op, int od) {
+ emitop1(op, od, null);
+ }
+
+ public void emitop1(int op, int od, PoolConstant data) {
emitop(op);
if (!alive) return;
emit1(od);
@@ -904,7 +917,7 @@
state.push(syms.intType);
break;
case ldc1:
- state.push(typeForPool(pool.pool[od]));
+ state.push(types.constantType((LoadableConstant)data));
break;
default:
throw new AssertionError(mnem(op));
@@ -912,25 +925,6 @@
postop();
}
- /** The type of a constant pool entry. */
- private Type typeForPool(Object o) {
- if (o instanceof Integer) return syms.intType;
- if (o instanceof Float) return syms.floatType;
- if (o instanceof String) return syms.stringType;
- if (o instanceof Long) return syms.longType;
- if (o instanceof Double) return syms.doubleType;
- if (o instanceof ClassSymbol) return syms.classType;
- if (o instanceof Pool.MethodHandle) return syms.methodHandleType;
- if (o instanceof UniqueType) return typeForPool(((UniqueType)o).type);
- if (o instanceof Type) {
- Type ty = (Type) o;
-
- if (ty instanceof Type.ArrayType) return syms.classType;
- if (ty instanceof Type.MethodType) return syms.methodTypeType;
- }
- throw new AssertionError("Invalid type of constant pool entry: " + o.getClass());
- }
-
/** Emit an opcode with a one-byte operand field;
* widen if field does not fit in a byte.
*/
@@ -1003,29 +997,31 @@
/** Emit an opcode with a two-byte operand field.
*/
+ public <P extends PoolConstant> void emitop2(int op, P constant, ToIntBiFunction<PoolWriter, P> poolFunc) {
+ int od = poolFunc.applyAsInt(poolWriter, constant);
+ emitop2(op, od, constant);
+ }
+
public void emitop2(int op, int od) {
+ emitop2(op, od, null);
+ }
+
+ public void emitop2(int op, int od, PoolConstant data) {
emitop(op);
if (!alive) return;
emit2(od);
switch (op) {
case getstatic:
- state.push(((Symbol)(pool.pool[od])).erasure(types));
+ state.push(((Symbol)data).erasure(types));
break;
case putstatic:
- state.pop(((Symbol)(pool.pool[od])).erasure(types));
+ state.pop(((Symbol)data).erasure(types));
break;
- case new_:
- Symbol sym;
- if (pool.pool[od] instanceof UniqueType) {
- // Required by change in Gen.makeRef to allow
- // annotated types.
- // TODO: is this needed anywhere else?
- sym = ((UniqueType)(pool.pool[od])).type.tsym;
- } else {
- sym = (Symbol)(pool.pool[od]);
- }
- state.push(uninitializedObject(sym.erasure(types), cp-3));
+ case new_: {
+ Type t = (Type)data;
+ state.push(uninitializedObject(t.tsym.erasure(types), cp-3));
break;
+ }
case sipush:
state.push(syms.intType);
break;
@@ -1053,30 +1049,27 @@
markDead();
break;
case putfield:
- state.pop(((Symbol)(pool.pool[od])).erasure(types));
+ state.pop(((Symbol)data).erasure(types));
state.pop(1); // object ref
break;
case getfield:
state.pop(1); // object ref
- state.push(((Symbol)(pool.pool[od])).erasure(types));
+ state.push(((Symbol)data).erasure(types));
break;
case checkcast: {
state.pop(1); // object ref
- Object o = pool.pool[od];
- Type t = (o instanceof Symbol)
- ? ((Symbol)o).erasure(types)
- : types.erasure((((UniqueType)o).type));
+ Type t = types.erasure((Type)data);
state.push(t);
break; }
case ldc2w:
- state.push(typeForPool(pool.pool[od]));
+ state.push(types.constantType((LoadableConstant)data));
break;
case instanceof_:
state.pop(1);
state.push(syms.intType);
break;
case ldc2:
- state.push(typeForPool(pool.pool[od]));
+ state.push(types.constantType((LoadableConstant)data));
break;
case jsr:
break;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Apr 19 08:00:42 2019 -0400
@@ -25,6 +25,7 @@
package com.sun.tools.javac.jvm;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
import com.sun.tools.javac.tree.TreeInfo.PosKind;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -88,9 +89,9 @@
return instance;
}
- /** Constant pool, reset by genClass.
+ /** Constant pool writer, set by genClass.
*/
- private final Pool pool;
+ final PoolWriter poolWriter;
protected Gen(Context context) {
context.put(genKey, this);
@@ -121,7 +122,7 @@
genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debug.code");
disableVirtualizedPrivateInvoke = options.isSet("disableVirtualizedPrivateInvoke");
- pool = new Pool(types);
+ poolWriter = new PoolWriter(types, names);
// ignore cldc because we cannot have both stackmap formats
this.stackMap = StackMapFormat.JSR202;
@@ -252,17 +253,17 @@
* @param type The type for which a reference is inserted.
*/
int makeRef(DiagnosticPosition pos, Type type) {
- checkDimension(pos, type);
- if (type.isAnnotated()) {
- return pool.put((Object)type);
- } else {
- return pool.put(type.hasTag(CLASS) ? (Object)type.tsym : (Object)type);
- }
+ return poolWriter.putClass(checkDimension(pos, type));
}
/** Check if the given type is an array with too many dimensions.
*/
- private void checkDimension(DiagnosticPosition pos, Type t) {
+ private Type checkDimension(DiagnosticPosition pos, Type t) {
+ checkDimensionInternal(pos, t);
+ return t;
+ }
+
+ private void checkDimensionInternal(DiagnosticPosition pos, Type t) {
switch (t.getTag()) {
case METHOD:
checkDimension(pos, t.getReturnType());
@@ -516,7 +517,7 @@
if (nerrs != 0 || // only complain about a long string once
constValue == null ||
!(constValue instanceof String) ||
- ((String)constValue).length() < Pool.MAX_STRING_LENGTH)
+ ((String)constValue).length() < PoolWriter.MAX_STRING_LENGTH)
return;
log.error(pos, Errors.LimitString);
nerrs++;
@@ -806,7 +807,7 @@
@Override
public void visitIdent(JCIdent tree) {
if (tree.sym.owner instanceof ClassSymbol) {
- pool.put(tree.sym.owner);
+ poolWriter.putClass((ClassSymbol)tree.sym.owner);
}
}
@@ -1007,8 +1008,8 @@
: null,
syms,
types,
- pool);
- items = new Items(pool, code, syms, types);
+ poolWriter);
+ items = new Items(poolWriter, code, syms, types);
if (code.debugCode) {
System.err.println(meth + " for body " + tree);
}
@@ -1886,7 +1887,7 @@
Assert.check(tree.encl == null && tree.def == null);
setTypeAnnotationPositions(tree.pos);
- code.emitop2(new_, makeRef(tree.pos(), tree.type));
+ code.emitop2(new_, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
code.emitop0(dup);
// Generate code for all arguments, where the expected types are
@@ -2162,7 +2163,7 @@
if (!tree.clazz.type.isPrimitive() &&
!types.isSameType(tree.expr.type, tree.clazz.type) &&
types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
- code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
+ code.emitop2(checkcast, checkDimension(tree.pos(), tree.clazz.type), PoolWriter::putClass);
}
}
@@ -2221,7 +2222,7 @@
Symbol sym = tree.sym;
if (tree.name == names._class) {
- code.emitLdc(makeRef(tree.pos(), tree.selected.type));
+ code.emitLdc((LoadableConstant)checkDimension(tree.pos(), tree.selected.type));
result = items.makeStackItem(pt);
return;
}
@@ -2305,7 +2306,7 @@
code.endScopes(limit);
}
- private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) {
+ private void generateReferencesToPrunedTree(ClassSymbol classSymbol) {
List<JCTree> prunedInfo = lower.prunedTree.get(classSymbol);
if (prunedInfo != null) {
for (JCTree prunedTree: prunedInfo) {
@@ -2331,12 +2332,10 @@
ClassSymbol c = cdef.sym;
this.toplevel = env.toplevel;
this.endPosTable = toplevel.endPositions;
- c.pool = pool;
- pool.reset();
/* method normalizeDefs() can add references to external classes into the constant pool
*/
cdef.defs = normalizeDefs(cdef.defs, c);
- generateReferencesToPrunedTree(c, pool);
+ generateReferencesToPrunedTree(c);
Env<GenContext> localEnv = new Env<>(cdef, new GenContext());
localEnv.toplevel = env.toplevel;
localEnv.enclClass = cdef;
@@ -2344,7 +2343,7 @@
for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
genDef(l.head, localEnv);
}
- if (pool.numEntries() > Pool.MAX_ENTRIES) {
+ if (poolWriter.size() > PoolWriter.MAX_ENTRIES) {
log.error(cdef.pos(), Errors.LimitPool);
nerrs++;
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java Fri Apr 19 08:00:42 2019 -0400
@@ -29,6 +29,8 @@
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.jvm.Code.*;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Assert;
@@ -50,9 +52,9 @@
*/
public class Items {
- /** The current constant pool.
+ /** The current constant pool writer.
*/
- Pool pool;
+ PoolWriter poolWriter;
/** The current code buffer.
*/
@@ -72,9 +74,9 @@
private final Item superItem;
private final Item[] stackItem = new Item[TypeCodeCount];
- public Items(Pool pool, Code code, Symtab syms, Types types) {
+ public Items(PoolWriter poolWriter, Code code, Symtab syms, Types types) {
this.code = code;
- this.pool = pool;
+ this.poolWriter = poolWriter;
this.types = types;
voidItem = new Item(VOIDcode) {
public String toString() { return "void"; }
@@ -444,18 +446,18 @@
}
Item load() {
- code.emitop2(getstatic, pool.put(member));
+ code.emitop2(getstatic, member, PoolWriter::putMember);
return stackItem[typecode];
}
void store() {
- code.emitop2(putstatic, pool.put(member));
+ code.emitop2(putstatic, member, PoolWriter::putMember);
}
Item invoke() {
MethodType mtype = (MethodType)member.erasure(types);
int rescode = Code.typecode(mtype.restype);
- code.emitInvokestatic(pool.put(member), mtype);
+ code.emitInvokestatic(member, mtype);
return stackItem[rescode];
}
@@ -484,7 +486,7 @@
// assert target.hasNativeInvokeDynamic();
MethodType mtype = (MethodType)member.erasure(types);
int rescode = Code.typecode(mtype.restype);
- code.emitInvokedynamic(pool.put(member), mtype);
+ code.emitInvokedynamic((DynamicMethodSymbol)member, mtype);
return stackItem[rescode];
}
@@ -512,23 +514,23 @@
}
Item load() {
- code.emitop2(getfield, pool.put(member));
+ code.emitop2(getfield, member, PoolWriter::putMember);
return stackItem[typecode];
}
void store() {
- code.emitop2(putfield, pool.put(member));
+ code.emitop2(putfield, member, PoolWriter::putMember);
}
Item invoke() {
MethodType mtype = (MethodType)member.externalType(types);
int rescode = Code.typecode(mtype.restype);
if ((member.owner.flags() & Flags.INTERFACE) != 0 && !nonvirtual) {
- code.emitInvokeinterface(pool.put(member), mtype);
+ code.emitInvokeinterface(member, mtype);
} else if (nonvirtual) {
- code.emitInvokespecial(pool.put(member), mtype);
+ code.emitInvokespecial(member, mtype);
} else {
- code.emitInvokevirtual(pool.put(member), mtype);
+ code.emitInvokevirtual(member, mtype);
}
return stackItem[rescode];
}
@@ -560,26 +562,50 @@
/** The literal's value.
*/
- Object value;
+ final LoadableConstant value;
ImmediateItem(Type type, Object value) {
super(Code.typecode(type));
- this.value = value;
+ switch (typecode) {
+ case BYTEcode:
+ case SHORTcode:
+ case CHARcode:
+ case INTcode:
+ this.value = LoadableConstant.Int((int)value);
+ break;
+ case LONGcode:
+ this.value = LoadableConstant.Long((long)value);
+ break;
+ case FLOATcode:
+ this.value = LoadableConstant.Float((float)value);
+ break;
+ case DOUBLEcode:
+ this.value = LoadableConstant.Double((double)value);
+ break;
+ case OBJECTcode:
+ this.value = LoadableConstant.String((String)value);
+ break;
+ default:
+ throw new UnsupportedOperationException("unsupported tag: " + typecode);
+ }
}
private void ldc() {
- int idx = pool.put(value);
if (typecode == LONGcode || typecode == DOUBLEcode) {
- code.emitop2(ldc2w, idx);
+ code.emitop2(ldc2w, value, PoolWriter::putConstant);
} else {
- code.emitLdc(idx);
+ code.emitLdc(value);
}
}
+ private Number numericValue() {
+ return (Number)((BasicConstant)value).data;
+ }
+
Item load() {
switch (typecode) {
case INTcode: case BYTEcode: case SHORTcode: case CHARcode:
- int ival = ((Number)value).intValue();
+ int ival = numericValue().intValue();
if (-1 <= ival && ival <= 5)
code.emitop0(iconst_0 + ival);
else if (Byte.MIN_VALUE <= ival && ival <= Byte.MAX_VALUE)
@@ -590,14 +616,14 @@
ldc();
break;
case LONGcode:
- long lval = ((Number)value).longValue();
+ long lval = numericValue().longValue();
if (lval == 0 || lval == 1)
code.emitop0(lconst_0 + (int)lval);
else
ldc();
break;
case FLOATcode:
- float fval = ((Number)value).floatValue();
+ float fval = numericValue().floatValue();
if (isPosZero(fval) || fval == 1.0 || fval == 2.0)
code.emitop0(fconst_0 + (int)fval);
else {
@@ -605,7 +631,7 @@
}
break;
case DOUBLEcode:
- double dval = ((Number)value).doubleValue();
+ double dval = numericValue().doubleValue();
if (isPosZero(dval) || dval == 1.0)
code.emitop0(dconst_0 + (int)dval);
else
@@ -632,7 +658,7 @@
}
CondItem mkCond() {
- int ival = ((Number)value).intValue();
+ int ival = numericValue().intValue();
return makeCondItem(ival != 0 ? goto_ : dontgoto);
}
@@ -647,31 +673,31 @@
else
return new ImmediateItem(
syms.intType,
- ((Number)value).intValue());
+ numericValue().intValue());
case LONGcode:
return new ImmediateItem(
syms.longType,
- ((Number)value).longValue());
+ numericValue().longValue());
case FLOATcode:
return new ImmediateItem(
syms.floatType,
- ((Number)value).floatValue());
+ numericValue().floatValue());
case DOUBLEcode:
return new ImmediateItem(
syms.doubleType,
- ((Number)value).doubleValue());
+ numericValue().doubleValue());
case BYTEcode:
return new ImmediateItem(
syms.byteType,
- (int)(byte)((Number)value).intValue());
+ (int)(byte)numericValue().intValue());
case CHARcode:
return new ImmediateItem(
syms.charType,
- (int)(char)((Number)value).intValue());
+ (int)(char)numericValue().intValue());
case SHORTcode:
return new ImmediateItem(
syms.shortType,
- (int)(short)((Number)value).intValue());
+ (int)(short)numericValue().intValue());
default:
return super.coerce(targetcode);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java Fri Apr 19 08:00:42 2019 -0400
@@ -24,6 +24,9 @@
*/
package com.sun.tools.javac.jvm;
+import com.sun.tools.javac.util.ByteBuffer;
+import com.sun.tools.javac.util.Name.NameMapper;
+
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -55,16 +58,15 @@
/** The buffer containing the currently read class file.
*/
- private byte[] buf = new byte[INITIAL_BUFFER_SIZE];
+ private ByteBuffer buf = new ByteBuffer(INITIAL_BUFFER_SIZE);
/** The current input pointer.
*/
private int bp;
- /** For every constant pool entry, an index into buf where the
- * defining section of the entry is found.
+ /** The constant pool reader.
*/
- private int[] poolIdx;
+ private PoolReader reader;
public ModuleNameReader() {
}
@@ -83,7 +85,8 @@
public String readModuleName(InputStream in) throws IOException, BadClassFile {
bp = 0;
- buf = readInputStream(buf, in);
+ buf.reset();
+ buf.appendStream(in);
int magic = nextInt();
if (magic != JAVA_MAGIC)
@@ -94,7 +97,8 @@
if (majorVersion < 53)
throw new BadClassFile("bad major version number for module: " + majorVersion);
- indexPool();
+ reader = new PoolReader(buf);
+ bp = reader.readPool(buf, bp);
int access_flags = nextChar();
if (access_flags != 0x8000)
@@ -110,8 +114,8 @@
for (int i = 0; i < attributes_count; i++) {
int attr_name = nextChar();
int attr_length = nextInt();
- if (getUtf8Value(attr_name, false).equals("Module") && attr_length > 2) {
- return getModuleName(nextChar());
+ if (reader.peekName(attr_name, utf8Mapper(false)).equals("Module") && attr_length > 2) {
+ return reader.peekModuleName(nextChar(), utf8Mapper(true));
} else {
// skip over unknown attributes
bp += attr_length;
@@ -125,132 +129,26 @@
throw new BadClassFile("invalid " + name + " for module: " + count);
}
- /** Extract a character at position bp from buf.
- */
- char getChar(int bp) {
- return
- (char)(((buf[bp] & 0xFF) << 8) + (buf[bp+1] & 0xFF));
- }
-
/** Read a character.
*/
char nextChar() {
- return (char)(((buf[bp++] & 0xFF) << 8) + (buf[bp++] & 0xFF));
+ char res = buf.getChar(bp);
+ bp += 2;
+ return res;
}
/** Read an integer.
*/
int nextInt() {
- return
- ((buf[bp++] & 0xFF) << 24) +
- ((buf[bp++] & 0xFF) << 16) +
- ((buf[bp++] & 0xFF) << 8) +
- (buf[bp++] & 0xFF);
- }
-
- /** Index all constant pool entries, writing their start addresses into
- * poolIdx.
- */
- void indexPool() throws BadClassFile {
- poolIdx = new int[nextChar()];
- int i = 1;
- while (i < poolIdx.length) {
- poolIdx[i++] = bp;
- byte tag = buf[bp++];
- switch (tag) {
- case CONSTANT_Utf8: case CONSTANT_Unicode: {
- int len = nextChar();
- bp = bp + len;
- break;
- }
- case CONSTANT_Class:
- case CONSTANT_String:
- case CONSTANT_MethodType:
- case CONSTANT_Module:
- case CONSTANT_Package:
- bp = bp + 2;
- break;
- case CONSTANT_MethodHandle:
- bp = bp + 3;
- break;
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- case CONSTANT_NameandType:
- case CONSTANT_Integer:
- case CONSTANT_Float:
- case CONSTANT_InvokeDynamic:
- bp = bp + 4;
- break;
- case CONSTANT_Long:
- case CONSTANT_Double:
- bp = bp + 8;
- i++;
- break;
- default:
- throw new BadClassFile("malformed constant pool");
- }
- }
+ int res = buf.getInt(bp);
+ bp += 4;
+ return res;
}
- String getUtf8Value(int index, boolean internalize) throws BadClassFile {
- int utf8Index = poolIdx[index];
- if (buf[utf8Index] == CONSTANT_Utf8) {
- int len = getChar(utf8Index + 1);
- int start = utf8Index + 3;
- if (internalize) {
- return new String(ClassFile.internalize(buf, start, len));
- } else {
- return new String(buf, start, len);
- }
- }
- throw new BadClassFile("bad name at index " + index);
- }
-
- String getModuleName(int index) throws BadClassFile {
- int infoIndex = poolIdx[index];
- if (buf[infoIndex] == CONSTANT_Module) {
- return getUtf8Value(getChar(infoIndex + 1), true);
- } else {
- throw new BadClassFile("bad module name at index " + index);
- }
+ NameMapper<String> utf8Mapper(boolean internalize) {
+ return internalize ?
+ (buf, offset, len) -> new String(ClassFile.internalize(buf, offset, len)) :
+ String::new;
}
- private static byte[] readInputStream(byte[] buf, InputStream s) throws IOException {
- try {
- buf = ensureCapacity(buf, s.available());
- int r = s.read(buf);
- int bp = 0;
- while (r != -1) {
- bp += r;
- buf = ensureCapacity(buf, bp);
- r = s.read(buf, bp, buf.length - bp);
- }
- return buf;
- } finally {
- try {
- s.close();
- } catch (IOException e) {
- /* Ignore any errors, as this stream may have already
- * thrown a related exception which is the one that
- * should be reported.
- */
- }
- }
- }
-
- /*
- * ensureCapacity will increase the buffer as needed, taking note that
- * the new buffer will always be greater than the needed and never
- * exactly equal to the needed size or bp. If equal then the read (above)
- * will infinitely loop as buf.length - bp == 0.
- */
- private static byte[] ensureCapacity(byte[] buf, int needed) {
- if (buf.length <= needed) {
- byte[] old = buf;
- buf = new byte[Integer.highestOneBit(needed) << 1];
- System.arraycopy(old, 0, buf, 0, old.length);
- }
- return buf;
- }
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,372 +0,0 @@
-/*
- * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.jvm;
-
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.*;
-import com.sun.tools.javac.code.TypeTag;
-import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.code.Types.UniqueType;
-
-import com.sun.tools.javac.util.ArrayUtils;
-import com.sun.tools.javac.util.Assert;
-import com.sun.tools.javac.util.Filter;
-import com.sun.tools.javac.util.Name;
-
-import java.util.*;
-
-import com.sun.tools.javac.util.DefinedBy;
-import com.sun.tools.javac.util.DefinedBy.Api;
-
-import static com.sun.tools.javac.code.Kinds.*;
-import static com.sun.tools.javac.code.Kinds.Kind.*;
-
-/** An internal structure that corresponds to the constant pool of a classfile.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class Pool {
-
- public static final int MAX_ENTRIES = 0xFFFF;
- public static final int MAX_STRING_LENGTH = 0xFFFF;
-
- /** Index of next constant to be entered.
- */
- int pp;
-
- /** The initial pool buffer.
- */
- Object[] pool;
-
- /** A hashtable containing all constants in the pool.
- */
- Map<Object,Integer> indices;
-
- Types types;
-
- /** Construct a pool with given number of elements and element array.
- */
- public Pool(int pp, Object[] pool, Types types) {
- this.pp = pp;
- this.pool = pool;
- this.types = types;
- this.indices = new HashMap<>(pool.length);
- for (int i = 1; i < pp; i++) {
- if (pool[i] != null) indices.put(pool[i], i);
- }
- }
-
- /** Construct an empty pool.
- */
- public Pool(Types types) {
- this(1, new Object[64], types);
- }
-
- /** Return the number of entries in the constant pool.
- */
- public int numEntries() {
- return pp;
- }
-
- /** Remove everything from this pool.
- */
- public void reset() {
- pp = 1;
- indices.clear();
- }
-
- /** Place an object in the pool, unless it is already there.
- * If object is a symbol also enter its owner unless the owner is a
- * package. Return the object's index in the pool.
- */
- public int put(Object value) {
- value = makePoolValue(value);
- Assert.check(!(value instanceof Type.TypeVar));
- Assert.check(!(value instanceof Types.UniqueType &&
- ((UniqueType) value).type instanceof Type.TypeVar));
- Integer index = indices.get(value);
- if (index == null) {
- index = pp;
- indices.put(value, index);
- pool = ArrayUtils.ensureCapacity(pool, pp);
- pool[pp++] = value;
- if (value instanceof Long || value instanceof Double) {
- pool = ArrayUtils.ensureCapacity(pool, pp);
- pool[pp++] = null;
- }
- }
- return index.intValue();
- }
-
- Object makePoolValue(Object o) {
- if (o instanceof DynamicMethodSymbol) {
- return new DynamicMethod((DynamicMethodSymbol)o, types);
- } else if (o instanceof MethodSymbol) {
- return new Method((MethodSymbol)o, types);
- } else if (o instanceof VarSymbol) {
- return new Variable((VarSymbol)o, types);
- } else if (o instanceof Type) {
- Type t = (Type)o;
- // ClassRefs can come from ClassSymbols or from Types.
- // Return the symbol for these types to avoid duplicates
- // in the constant pool
- if (t.hasTag(TypeTag.CLASS))
- return t.tsym;
- else
- return new UniqueType(t, types);
- } else {
- return o;
- }
- }
-
- /** Return the given object's index in the pool,
- * or -1 if object is not in there.
- */
- public int get(Object o) {
- Integer n = indices.get(o);
- return n == null ? -1 : n.intValue();
- }
-
- static class Method extends DelegatedSymbol<MethodSymbol> {
- UniqueType uniqueType;
- Method(MethodSymbol m, Types types) {
- super(m);
- this.uniqueType = new UniqueType(m.type, types);
- }
- @DefinedBy(Api.LANGUAGE_MODEL)
- public boolean equals(Object any) {
- if (!(any instanceof Method)) return false;
- MethodSymbol o = ((Method)any).other;
- MethodSymbol m = this.other;
- return
- o.name == m.name &&
- o.owner == m.owner &&
- ((Method)any).uniqueType.equals(uniqueType);
- }
- @DefinedBy(Api.LANGUAGE_MODEL)
- public int hashCode() {
- MethodSymbol m = this.other;
- return
- m.name.hashCode() * 33 +
- m.owner.hashCode() * 9 +
- uniqueType.hashCode();
- }
- }
-
- public static class DynamicMethod extends Method {
- public Object[] uniqueStaticArgs;
-
- public DynamicMethod(DynamicMethodSymbol m, Types types) {
- super(m, types);
- uniqueStaticArgs = getUniqueTypeArray(m.staticArgs, types);
- }
-
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
- public boolean equals(Object any) {
- return equalsImpl(any, true);
- }
-
- protected boolean equalsImpl(Object any, boolean includeDynamicArgs) {
- if (includeDynamicArgs && !super.equals(any)) return false;
- if (!(any instanceof DynamicMethod)) return false;
- DynamicMethodSymbol dm1 = (DynamicMethodSymbol)other;
- DynamicMethodSymbol dm2 = (DynamicMethodSymbol)((DynamicMethod)any).other;
- return dm1.bsm == dm2.bsm &&
- dm1.bsmKind == dm2.bsmKind &&
- Arrays.equals(uniqueStaticArgs,
- ((DynamicMethod)any).uniqueStaticArgs);
- }
-
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
- public int hashCode() {
- return hashCodeImpl(true);
- }
-
- protected int hashCodeImpl(boolean includeDynamicArgs) {
- int hash = includeDynamicArgs ? super.hashCode() : 0;
- DynamicMethodSymbol dm = (DynamicMethodSymbol)other;
- hash += dm.bsmKind * 7 +
- dm.bsm.hashCode() * 11;
- for (int i = 0; i < dm.staticArgs.length; i++) {
- hash += (uniqueStaticArgs[i].hashCode() * 23);
- }
- return hash;
- }
-
- private Object[] getUniqueTypeArray(Object[] objects, Types types) {
- Object[] result = new Object[objects.length];
- for (int i = 0; i < objects.length; i++) {
- if (objects[i] instanceof Type) {
- result[i] = new UniqueType((Type)objects[i], types);
- } else {
- result[i] = objects[i];
- }
- }
- return result;
- }
-
- static class BootstrapMethodsKey extends DynamicMethod {
- BootstrapMethodsKey(DynamicMethodSymbol m, Types types) {
- super(m, types);
- }
-
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
- public boolean equals(Object any) {
- return equalsImpl(any, false);
- }
-
- @Override @DefinedBy(Api.LANGUAGE_MODEL)
- public int hashCode() {
- return hashCodeImpl(false);
- }
-
- Object[] getUniqueArgs() {
- return uniqueStaticArgs;
- }
- }
-
- static class BootstrapMethodsValue {
- final MethodHandle mh;
- final int index;
-
- public BootstrapMethodsValue(MethodHandle mh, int index) {
- this.mh = mh;
- this.index = index;
- }
- }
- }
-
- static class Variable extends DelegatedSymbol<VarSymbol> {
- UniqueType uniqueType;
- Variable(VarSymbol v, Types types) {
- super(v);
- this.uniqueType = new UniqueType(v.type, types);
- }
- @DefinedBy(Api.LANGUAGE_MODEL)
- public boolean equals(Object any) {
- if (!(any instanceof Variable)) return false;
- VarSymbol o = ((Variable)any).other;
- VarSymbol v = other;
- return
- o.name == v.name &&
- o.owner == v.owner &&
- ((Variable)any).uniqueType.equals(uniqueType);
- }
- @DefinedBy(Api.LANGUAGE_MODEL)
- public int hashCode() {
- VarSymbol v = other;
- return
- v.name.hashCode() * 33 +
- v.owner.hashCode() * 9 +
- uniqueType.hashCode();
- }
- }
-
- public static class MethodHandle {
-
- /** Reference kind - see ClassFile */
- int refKind;
-
- /** Reference symbol */
- Symbol refSym;
-
- UniqueType uniqueType;
-
- public MethodHandle(int refKind, Symbol refSym, Types types) {
- this.refKind = refKind;
- this.refSym = refSym;
- this.uniqueType = new UniqueType(this.refSym.type, types);
- checkConsistent();
- }
- public boolean equals(Object other) {
- if (!(other instanceof MethodHandle)) return false;
- MethodHandle mr = (MethodHandle) other;
- if (mr.refKind != refKind) return false;
- Symbol o = mr.refSym;
- return
- o.name == refSym.name &&
- o.owner == refSym.owner &&
- ((MethodHandle)other).uniqueType.equals(uniqueType);
- }
- public int hashCode() {
- return
- refKind * 65 +
- refSym.name.hashCode() * 33 +
- refSym.owner.hashCode() * 9 +
- uniqueType.hashCode();
- }
-
- /**
- * Check consistency of reference kind and symbol (see JVMS 4.4.8)
- */
- @SuppressWarnings("fallthrough")
- private void checkConsistent() {
- boolean staticOk = false;
- Kind expectedKind = null;
- Filter<Name> nameFilter = nonInitFilter;
- boolean interfaceOwner = false;
- switch (refKind) {
- case ClassFile.REF_getStatic:
- case ClassFile.REF_putStatic:
- staticOk = true;
- case ClassFile.REF_getField:
- case ClassFile.REF_putField:
- expectedKind = VAR;
- break;
- case ClassFile.REF_newInvokeSpecial:
- nameFilter = initFilter;
- expectedKind = MTH;
- break;
- case ClassFile.REF_invokeInterface:
- interfaceOwner = true;
- expectedKind = MTH;
- break;
- case ClassFile.REF_invokeStatic:
- interfaceOwner = true;
- staticOk = true;
- case ClassFile.REF_invokeVirtual:
- expectedKind = MTH;
- break;
- case ClassFile.REF_invokeSpecial:
- interfaceOwner = true;
- expectedKind = MTH;
- break;
- }
- Assert.check(!refSym.isStatic() || staticOk);
- Assert.check(refSym.kind == expectedKind);
- Assert.check(nameFilter.accepts(refSym.name));
- Assert.check(!refSym.owner.isInterface() || interfaceOwner);
- }
- //where
- Filter<Name> nonInitFilter = n -> (n != n.table.names.init && n != n.table.names.clinit);
-
- Filter<Name> initFilter = n -> n == n.table.names.init;
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolConstant.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.code.Types.UniqueType;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Pair;
+
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * This interface models all javac entities that can be used to represent constant pool entries.
+ * A pool constant entity must (i) be associated with a constant pool entry tag and have a function
+ * which generates a key for the desired pool entry (so as to avoid duplicate entries when writing the
+ * constant pool).
+ */
+public interface PoolConstant {
+
+ /**
+ * The constant pool entry key.
+ */
+ default Object poolKey(Types types) { return this; }
+
+ /**
+ * The constant pool entry tag.
+ */
+ int poolTag();
+
+ /**
+ * The root of pool constants that can be loaded (e.g. with {@code ldc}, or appear as static
+ * arguments to a bootstrap method.
+ */
+ interface LoadableConstant extends PoolConstant {
+
+ /**
+ * Create a pool constant describing a given {@code int} value.
+ */
+ static LoadableConstant Int(int i) {
+ return new BasicConstant(ClassFile.CONSTANT_Integer, i);
+ }
+
+ /**
+ * Create a pool constant describing a given {@code float} value.
+ */
+ static LoadableConstant Float(float f) {
+ return new BasicConstant(ClassFile.CONSTANT_Float, f);
+ }
+
+ /**
+ * Create a pool constant describing a given {@code long} value.
+ */
+ static LoadableConstant Long(long l) {
+ return new BasicConstant(ClassFile.CONSTANT_Long, l);
+ }
+
+ /**
+ * Create a pool constant describing a given {@code double} value.
+ */
+ static LoadableConstant Double(double d) {
+ return new BasicConstant(ClassFile.CONSTANT_Double, d);
+ }
+
+ /**
+ * Create a pool constant describing a given {@code String} value.
+ */
+ static LoadableConstant String(String s) {
+ return new BasicConstant(ClassFile.CONSTANT_String, s);
+ }
+
+ /**
+ * This class models a pool constant of given basic type, one of {@code int}, {@code float},
+ * {@code long}, {@code double} or {@code String}.
+ */
+ class BasicConstant implements LoadableConstant {
+ int tag;
+ Object data;
+
+ private BasicConstant(int tag, Object data) {
+ this.tag = tag;
+ this.data = data;
+ }
+
+ @Override
+ public int poolTag() {
+ return tag;
+ }
+
+ @Override
+ public Object poolKey(Types types) {
+ return data;
+ }
+ }
+ }
+
+ /**
+ * This interface models a dynamic pool constant (either of kind {@code InvokeDynamic} or
+ * {@code ConstantDynamic}). In addition to the functionalities provided by the base interface,
+ * a dynamic pool constant must expose its dynamic type, bootstrap method and static argument list.
+ * Finally, a dynamic constant must have a way to compute a bootstrap method key - that is,
+ * a unique key for the bootstrap method entry it refers to, to avoid duplicates when writing
+ * the {@code BootstrapMethods} attribute.
+ */
+ interface Dynamic extends PoolConstant {
+
+ /**
+ * The dynamic constant's dynamic type.
+ */
+ PoolConstant dynamicType();
+
+ /**
+ * The dynamic constant's static argument list.
+ */
+ LoadableConstant[] staticArgs();
+
+ /**
+ * The dynamic constant's bootstrap method.
+ */
+ LoadableConstant bootstrapMethod();
+
+ default BsmKey bsmKey(Types types) {
+ return new BsmKey(types, bootstrapMethod(), staticArgs());
+ }
+
+ @Override
+ default Object poolKey(Types types) {
+ return new Pair<>(bsmKey(types), dynamicType().poolKey(types));
+ }
+
+ /**
+ * A class modelling a bootstrap method key.
+ */
+ class BsmKey {
+ /**
+ * The key's bootstrap method constant.
+ */
+ public final LoadableConstant bsm;
+
+ /**
+ * The key's static argument list.
+ */
+ public final LoadableConstant[] staticArgs;
+
+ private final Object bsmKey;
+ private final List<?> staticArgKeys;
+
+ private BsmKey(Types types, LoadableConstant bsm, LoadableConstant[] staticArgs) {
+ this.bsm = bsm;
+ this.bsmKey = bsm.poolKey(types);
+ this.staticArgs = staticArgs;
+ this.staticArgKeys = Stream.of(staticArgs)
+ .map(p -> p.poolKey(types))
+ .collect(List.collector());
+ }
+
+ @Override
+ public int hashCode() {
+ return bsmKey.hashCode() +
+ staticArgKeys.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof BsmKey) {
+ BsmKey other = (BsmKey)obj;
+ return Objects.equals(bsmKey, other.bsmKey) &&
+ Objects.equals(staticArgKeys, other.staticArgKeys);
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ /**
+ * A pool constant implememntation describing a name and type pool entry.
+ */
+ final class NameAndType implements PoolConstant {
+
+ final Name name;
+ final Type type;
+
+ NameAndType(Name name, Type type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_NameandType;
+ }
+
+ @Override
+ public Object poolKey(Types types) {
+ return new Pair<>(name, new UniqueType(type, types));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolReader.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
+import com.sun.tools.javac.util.ByteBuffer;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Name.NameMapper;
+import com.sun.tools.javac.util.Names;
+
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Double;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Dynamic;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Fieldref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Float;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Integer;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InterfaceMethodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_InvokeDynamic;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Long;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodHandle;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Methodref;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Module;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_NameandType;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Package;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_String;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Utf8;
+import static com.sun.tools.javac.jvm.ClassFile.internalize;
+
+/**
+ * Pool interface towards {@code ClassReader}. Exposes methods to decode and read javac entities
+ * from the constant pool.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class PoolReader {
+
+ private final ClassReader reader;
+ private final ByteBuffer buf;
+ private final Names names;
+ private final Symtab syms;
+
+ private ImmutablePoolHelper pool;
+
+ PoolReader(ByteBuffer buf) {
+ this(null, buf, null, null);
+ }
+
+ PoolReader(ClassReader reader, Names names, Symtab syms) {
+ this(reader, reader.buf, names, syms);
+ }
+
+ PoolReader(ClassReader reader, ByteBuffer buf, Names names, Symtab syms) {
+ this.reader = reader;
+ this.buf = buf;
+ this.names = names;
+ this.syms = syms;
+ }
+
+ /**
+ * Get a class symbol from the pool at given index.
+ */
+ ClassSymbol getClass(int index) {
+ return pool.readIfNeeded(index);
+ }
+
+ /**
+ * Get class name without resolving
+ */
+ <Z> Z peekClassName(int index, NameMapper<Z> mapper) {
+ return peekName(buf.getChar(pool.offset(index)), mapper);
+ }
+
+ /**
+ * Get package name without resolving
+ */
+ <Z> Z peekPackageName(int index, NameMapper<Z> mapper) {
+ return peekName(buf.getChar(pool.offset(index)), mapper);
+ }
+
+ /**
+ * Get module name without resolving
+ */
+ <Z> Z peekModuleName(int index, NameMapper<Z> mapper) {
+ return peekName(buf.getChar(pool.offset(index)), mapper);
+ }
+
+ /**
+ * Get a module symbol from the pool at given index.
+ */
+ ModuleSymbol getModule(int index) {
+ return pool.readIfNeeded(index);
+ }
+
+ /**
+ * Get a module symbol from the pool at given index.
+ */
+ PackageSymbol getPackage(int index) {
+ return pool.readIfNeeded(index);
+ }
+
+ /**
+ * Peek a name from the pool at given index without resolving.
+ */
+ <Z> Z peekName(int index, Name.NameMapper<Z> mapper) {
+ return getUtf8(index, mapper);
+ }
+
+ /**
+ * Get a name from the pool at given index.
+ */
+ Name getName(int index) {
+ return pool.readIfNeeded(index);
+ }
+
+ /**
+ * Get a type from the pool at given index.
+ */
+ Type getType(int index) {
+ return getName(index).map(reader::sigToType);
+ }
+
+ /**
+ * Get a name and type pair from the pool at given index.
+ */
+ NameAndType getNameAndType(int index) {
+ return pool.readIfNeeded(index);
+ }
+
+ /**
+ * Get a class symbol from the pool at given index.
+ */
+ Object getConstant(int index) {
+ return pool.readIfNeeded(index);
+ }
+
+ boolean hasTag(int index, int tag) {
+ return pool.tag(index) == tag;
+ }
+
+ private <Z> Z getUtf8(int index, NameMapper<Z> mapper) {
+ int tag = pool.tag(index);
+ if (tag == CONSTANT_Utf8) {
+ int offset = pool.offset(index);
+ int len = pool.poolbuf.getChar(offset);
+ return mapper.map(pool.poolbuf.elems, offset + 2, len);
+ } else {
+ throw new AssertionError("Unexpected constant tag: " + tag);
+ }
+ }
+
+ private Object resolve(ByteBuffer poolbuf, int tag, int offset) {
+ switch (tag) {
+ case CONSTANT_Utf8: {
+ int len = poolbuf.getChar(offset);
+ return names.fromUtf(poolbuf.elems, offset + 2, len);
+ }
+ case CONSTANT_Class: {
+ int index = poolbuf.getChar(offset);
+ Name name = names.fromUtf(getName(index).map(ClassFile::internalize));
+ return syms.enterClass(reader.currentModule, name);
+ }
+ case CONSTANT_NameandType: {
+ Name name = getName(poolbuf.getChar(offset));
+ Type type = getType(poolbuf.getChar(offset + 2));
+ return new NameAndType(name, type);
+ }
+ case CONSTANT_Integer:
+ return poolbuf.getInt(offset);
+ case CONSTANT_Float:
+ return poolbuf.getFloat(offset);
+ case CONSTANT_Long:
+ return poolbuf.getLong(offset);
+ case CONSTANT_Double:
+ return poolbuf.getDouble(offset);
+ case CONSTANT_String:
+ return getName(poolbuf.getChar(offset)).toString();
+ case CONSTANT_Package: {
+ Name name = getName(poolbuf.getChar(offset));
+ return syms.enterPackage(reader.currentModule, names.fromUtf(internalize(name)));
+ }
+ case CONSTANT_Module: {
+ Name name = getName(poolbuf.getChar(offset));
+ return syms.enterModule(name);
+ }
+ default:
+ throw new AssertionError("Unexpected constant tag: " + tag);
+ }
+ }
+
+ /**
+ * Parse all constant pool entries, and keep track of their offsets. For performance and laziness
+ * reasons, it would be unwise to eagerly turn all pool entries into corresponding javac
+ * entities. First, not all entries are actually going to be read/used by javac; secondly,
+ * there are cases where creating a symbol too early might result in issues (hence methods like
+ * {@link PoolReader#peekClassName(int, NameMapper)}.
+ */
+ int readPool(ByteBuffer poolbuf, int offset) {
+ int poolSize = poolbuf.getChar(offset);
+ int index = 1;
+ offset += 2;
+ int[] offsets = new int[poolSize];
+ while (index < poolSize) {
+ byte tag = poolbuf.getByte(offset++);
+ offsets[index] = offset;
+ switch (tag) {
+ case CONSTANT_Utf8: {
+ int len = poolbuf.getChar(offset);
+ offset += 2 + len;
+ break;
+ }
+ case CONSTANT_Class:
+ case CONSTANT_String:
+ case CONSTANT_Module:
+ case CONSTANT_Package:
+ case CONSTANT_MethodType:
+ offset += 2;
+ break;
+ case CONSTANT_MethodHandle:
+ offset += 3;
+ break;
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ case CONSTANT_NameandType:
+ case CONSTANT_Integer:
+ case CONSTANT_Float:
+ case CONSTANT_Dynamic:
+ case CONSTANT_InvokeDynamic:
+ offset += 4;
+ break;
+ case CONSTANT_Long:
+ case CONSTANT_Double:
+ offset += 8;
+ break;
+ default:
+ throw reader.badClassFile("bad.const.pool.tag.at",
+ Byte.toString(tag),
+ Integer.toString(offset - 1));
+ }
+ index += sizeof(tag);
+ }
+ pool = new ImmutablePoolHelper(poolbuf, offsets);
+ return offset;
+ }
+
+ private int sizeof(int tag) {
+ switch (tag) {
+ case ClassFile.CONSTANT_Double: case ClassFile.CONSTANT_Long:
+ return 2;
+ default:
+ return 1;
+ }
+ }
+
+ class ImmutablePoolHelper {
+
+ final Object[] values;
+ final int[] offsets;
+ final ByteBuffer poolbuf;
+
+ public ImmutablePoolHelper(ByteBuffer poolbuf, int[] offsets) {
+ this.offsets = offsets;
+ this.values = new Object[offsets.length];
+ this.poolbuf = poolbuf;
+ }
+
+ private int checkIndex(int index) {
+ if (index <= 0 || index >= offsets.length) {
+ //pool index is outside valid range.
+ throw reader.badClassFile("bad.const.pool.index", reader.currentClassFile,
+ index, offsets.length);
+ } else {
+ return index;
+ }
+ }
+
+ int offset(int index) {
+ return offsets[checkIndex(index)];
+ }
+
+ @SuppressWarnings("unchecked")
+ <P> P readIfNeeded(int index) {
+ Object v = values[checkIndex(index)];
+ if (v != null) {
+ return (P)v;
+ } else {
+ P p = (P)resolve(poolbuf, tag(index), offset(index));
+ values[index] = p;
+ return p;
+ }
+ }
+
+ int tag(int index) {
+ return poolbuf.elems[offset(index) - 1];
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.jvm;
+
+import com.sun.tools.javac.code.Kinds.Kind;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.DynamicMethodSymbol;
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.jvm.ClassWriter.PoolOverflow;
+import com.sun.tools.javac.jvm.ClassWriter.StringOverflow;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant.BasicConstant;
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic;
+import com.sun.tools.javac.jvm.PoolConstant.Dynamic.BsmKey;
+import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
+import com.sun.tools.javac.util.ByteBuffer;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayDeque;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+
+import static com.sun.tools.javac.code.Kinds.Kind.TYP;
+import static com.sun.tools.javac.code.TypeTag.ARRAY;
+import static com.sun.tools.javac.code.TypeTag.CLASS;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_Class;
+import static com.sun.tools.javac.jvm.ClassFile.CONSTANT_MethodType;
+import static com.sun.tools.javac.jvm.ClassFile.externalize;
+
+/**
+ * Pool interface towards {@code ClassWriter}. Exposes methods to encode and write javac entities
+ * into the constant pool.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class PoolWriter {
+
+ /** Max number of constant pool entries. */
+ public static final int MAX_ENTRIES = 0xFFFF;
+
+ /** Max number of char in a string constant. */
+ public static final int MAX_STRING_LENGTH = 0xFFFF;
+
+ private static final int POOL_BUF_SIZE = 0x7fff;
+
+ private final Types types;
+
+ private final Names names;
+
+ /** Pool helper **/
+ final WriteablePoolHelper pool;
+
+ /** Sole signature generator */
+ final SharedSignatureGenerator signatureGen;
+
+ /** The inner classes to be written, as an ordered set (enclosing first). */
+ LinkedHashSet<ClassSymbol> innerClasses = new LinkedHashSet<>();
+
+ /** The list of entries in the BootstrapMethods attribute. */
+ Map<BsmKey, Integer> bootstrapMethods = new LinkedHashMap<>();
+
+ public PoolWriter(Types types, Names names) {
+ this.types = types;
+ this.names = names;
+ this.signatureGen = new SharedSignatureGenerator(types);
+ this.pool = new WriteablePoolHelper();
+ }
+
+ /**
+ * Puts a class symbol into the pool and return its index.
+ */
+ int putClass(ClassSymbol csym) {
+ return putClass(csym.type);
+ }
+
+ /**
+ * Puts a type into the pool and return its index. The type could be either a class, a type variable
+ * or an array type.
+ */
+ int putClass(Type t) {
+ return pool.writeIfNeeded(types.erasure(t));
+ }
+
+ /**
+ * Puts a member reference into the constant pool. Valid members are either field or method symbols.
+ */
+ int putMember(Symbol s) {
+ return pool.writeIfNeeded(s);
+ }
+
+ /**
+ * Puts a dynamic reference into the constant pool and return its index.
+ */
+ int putDynamic(DynamicMethodSymbol d) {
+ return pool.writeIfNeeded(d);
+ }
+
+ /**
+ * Puts a field or method descriptor into the constant pool and return its index.
+ */
+ int putDescriptor(Type t) {
+ return putName(typeSig(types.erasure(t)));
+ }
+
+ /**
+ * Puts a field or method descriptor into the constant pool and return its index.
+ */
+ int putDescriptor(Symbol s) {
+ return putDescriptor(descriptorType(s));
+ }
+
+ /**
+ * Puts a signature (see {@code Signature} attribute in JVMS 4.4) into the constant pool and
+ * return its index.
+ */
+ int putSignature(Symbol s) {
+ if (s.kind == TYP) {
+ return putName(classSig(s.type));
+ } else {
+ return putName(typeSig(s.type));
+ }
+ }
+
+ /**
+ * Puts a constant value into the pool and return its index. Supported values are int, float, long,
+ * double and String.
+ */
+ int putConstant(Object o) {
+ if (o instanceof Integer) {
+ return putConstant(LoadableConstant.Int((int)o));
+ } else if (o instanceof Float) {
+ return putConstant(LoadableConstant.Float((float)o));
+ } else if (o instanceof Long) {
+ return putConstant(LoadableConstant.Long((long)o));
+ } else if (o instanceof Double) {
+ return putConstant(LoadableConstant.Double((double)o));
+ } else if (o instanceof String) {
+ return putConstant(LoadableConstant.String((String)o));
+ } else {
+ throw new AssertionError("unexpected constant: " + o);
+ }
+ }
+
+ /**
+ * Puts a constant into the pool and return its index.
+ */
+ int putConstant(LoadableConstant c) {
+ switch (c.poolTag()) {
+ case CONSTANT_Class:
+ return putClass((Type)c);
+ case CONSTANT_MethodType:
+ return pool.writeIfNeeded(types.erasure((Type)c));
+ default:
+ return pool.writeIfNeeded(c);
+ }
+ }
+
+ int putName(Name name) {
+ return pool.writeIfNeeded(name);
+ }
+
+ /**
+ * Puts a name and type pair into the pool and returns its index.
+ */
+ int putNameAndType(Symbol s) {
+ return pool.writeIfNeeded(new NameAndType(s.name, descriptorType(s)));
+ }
+
+ /**
+ * Puts a package entry into the pool and returns its index.
+ */
+ int putPackage(PackageSymbol pkg) {
+ return pool.writeIfNeeded(pkg);
+ }
+
+ /**
+ * Puts a module entry into the pool and returns its index.
+ */
+ int putModule(ModuleSymbol mod) {
+ return pool.writeIfNeeded(mod);
+ }
+
+ /**
+ * Enter an inner class into the `innerClasses' set.
+ */
+ void enterInner(ClassSymbol c) {
+ if (c.type.isCompound()) {
+ throw new AssertionError("Unexpected intersection type: " + c.type);
+ }
+ c.complete();
+ if (c.owner.enclClass() != null && !innerClasses.contains(c)) {
+ enterInner(c.owner.enclClass());
+ innerClasses.add(c);
+ }
+ }
+
+ /**
+ * Create a new Utf8 entry representing a descriptor for given (member) symbol.
+ */
+ private Type descriptorType(Symbol s) {
+ return s.kind == Kind.MTH ? s.externalType(types) : s.erasure(types);
+ }
+
+ private int makeBoostrapEntry(Dynamic dynamic) {
+ BsmKey bsmKey = dynamic.bsmKey(types);
+
+ // Figure out the index for existing BSM; create a new BSM if no key
+ Integer index = bootstrapMethods.get(bsmKey);
+ if (index == null) {
+ index = bootstrapMethods.size();
+ bootstrapMethods.put(bsmKey, index);
+ }
+
+ return index;
+ }
+
+ /**
+ * Write pool contents into given byte buffer.
+ */
+ void writePool(OutputStream out) throws IOException, PoolOverflow {
+ if (pool.overflowString != null) {
+ throw new StringOverflow(pool.overflowString);
+ }
+ int size = size();
+ if (size > MAX_ENTRIES) {
+ throw new PoolOverflow();
+ }
+ out.write(size >> 8);
+ out.write(size);
+ out.write(pool.poolbuf.elems, 0, pool.poolbuf.length);
+ }
+
+ /**
+ * Signature Generation
+ */
+ class SharedSignatureGenerator extends Types.SignatureGenerator {
+
+ /**
+ * An output buffer for type signatures.
+ */
+ ByteBuffer sigbuf = new ByteBuffer();
+
+ SharedSignatureGenerator(Types types) {
+ super(types);
+ }
+
+ /**
+ * Assemble signature of given type in string buffer.
+ * Check for uninitialized types before calling the general case.
+ */
+ @Override
+ public void assembleSig(Type type) {
+ switch (type.getTag()) {
+ case UNINITIALIZED_THIS:
+ case UNINITIALIZED_OBJECT:
+ // we don't yet have a spec for uninitialized types in the
+ // local variable table
+ assembleSig(types.erasure(((UninitializedType)type).qtype));
+ break;
+ default:
+ super.assembleSig(type);
+ }
+ }
+
+ @Override
+ protected void append(char ch) {
+ sigbuf.appendByte(ch);
+ }
+
+ @Override
+ protected void append(byte[] ba) {
+ sigbuf.appendBytes(ba);
+ }
+
+ @Override
+ protected void append(Name name) {
+ sigbuf.appendName(name);
+ }
+
+ @Override
+ protected void classReference(ClassSymbol c) {
+ enterInner(c);
+ }
+
+ protected void reset() {
+ sigbuf.reset();
+ }
+
+ protected Name toName() {
+ return sigbuf.toName(names);
+ }
+ }
+
+ class WriteablePoolHelper {
+
+ /** Pool entries. */
+ private final Map<Object, Integer> keysToPos = new HashMap<>(64);
+
+ final ByteBuffer poolbuf = new ByteBuffer(POOL_BUF_SIZE);
+
+ int currentIndex = 1;
+
+ ArrayDeque<PoolConstant> todo = new ArrayDeque<>();
+
+ String overflowString = null;
+
+ private <P extends PoolConstant> int writeIfNeeded(P p) {
+ Object key = p.poolKey(types);
+ Integer index = keysToPos.get(key);
+ if (index == null) {
+ keysToPos.put(key, index = currentIndex++);
+ boolean first = todo.isEmpty();
+ todo.addLast(p);
+ if (first) {
+ while (!todo.isEmpty()) {
+ writeConstant(todo.peekFirst());
+ todo.removeFirst();
+ }
+ }
+ }
+ return index;
+ }
+
+ void writeConstant(PoolConstant c) {
+ int tag = c.poolTag();
+ switch (tag) {
+ case ClassFile.CONSTANT_Class: {
+ Type ct = (Type)c;
+ Name name = ct.hasTag(ARRAY) ?
+ typeSig(ct) :
+ names.fromUtf(externalize(ct.tsym.flatName()));
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(putName(name));
+ if (ct.hasTag(CLASS)) {
+ enterInner((ClassSymbol)ct.tsym);
+ }
+ break;
+ }
+ case ClassFile.CONSTANT_Utf8: {
+ Name name = (Name)c;
+ poolbuf.appendByte(tag);
+ byte[] bs = name.toUtf();
+ poolbuf.appendChar(bs.length);
+ poolbuf.appendBytes(bs, 0, bs.length);
+ if (overflowString == null && bs.length > MAX_STRING_LENGTH) {
+ //report error only once
+ overflowString = new String(bs);
+ }
+ break;
+ }
+ case ClassFile.CONSTANT_InterfaceMethodref:
+ case ClassFile.CONSTANT_Methodref:
+ case ClassFile.CONSTANT_Fieldref: {
+ Symbol sym = (Symbol)c;
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(putClass((ClassSymbol)sym.owner));
+ poolbuf.appendChar(putNameAndType(sym));
+ break;
+ }
+ case ClassFile.CONSTANT_Package: {
+ PackageSymbol pkg = (PackageSymbol)c;
+ Name pkgName = names.fromUtf(externalize(pkg.flatName()));
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(putName(pkgName));
+ break;
+ }
+ case ClassFile.CONSTANT_Module: {
+ ModuleSymbol mod = (ModuleSymbol)c;
+ int modName = putName(mod.name);
+ poolbuf.appendByte(mod.poolTag());
+ poolbuf.appendChar(modName);
+ break;
+ }
+ case ClassFile.CONSTANT_Integer:
+ poolbuf.appendByte(tag);
+ poolbuf.appendInt((int)((BasicConstant)c).data);
+ break;
+ case ClassFile.CONSTANT_Float:
+ poolbuf.appendByte(tag);
+ poolbuf.appendFloat((float)((BasicConstant)c).data);
+ break;
+ case ClassFile.CONSTANT_Long:
+ currentIndex++;
+ poolbuf.appendByte(tag);
+ poolbuf.appendLong((long)((BasicConstant)c).data);
+ break;
+ case ClassFile.CONSTANT_Double:
+ currentIndex++;
+ poolbuf.appendByte(tag);
+ poolbuf.appendDouble((double)((BasicConstant)c).data);
+ break;
+ case ClassFile.CONSTANT_MethodHandle: {
+ MethodHandleSymbol h = (MethodHandleSymbol)c;
+ poolbuf.appendByte(tag);
+ poolbuf.appendByte(h.referenceKind());
+ poolbuf.appendChar(putMember(h.baseSymbol()));
+ break;
+ }
+ case ClassFile.CONSTANT_MethodType: {
+ Type.MethodType mt = (Type.MethodType)c;
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(putDescriptor(mt.baseType()));
+ break;
+ }
+ case ClassFile.CONSTANT_String: {
+ Name utf = names.fromString((String)((BasicConstant)c).data);
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(putName(utf));
+ break;
+ }
+ case ClassFile.CONSTANT_NameandType: {
+ NameAndType nt = (NameAndType)c;
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(putName(nt.name));
+ poolbuf.appendChar(putDescriptor(nt.type));
+ break;
+ }
+ case ClassFile.CONSTANT_InvokeDynamic: {
+ DynamicMethodSymbol d = (DynamicMethodSymbol)c;
+ poolbuf.appendByte(tag);
+ poolbuf.appendChar(makeBoostrapEntry(d));
+ poolbuf.appendChar(putNameAndType(d));
+ break;
+ }
+ default:
+ throw new AssertionError("Unexpected constant tag: " + tag);
+ }
+ }
+
+ void reset() {
+ keysToPos.clear();
+ currentIndex = 1;
+ todo.clear();
+ overflowString = null;
+ poolbuf.reset();
+ }
+ }
+
+ int size() {
+ return pool.currentIndex;
+ }
+
+ /**
+ * Return signature of given type
+ */
+ private Name typeSig(Type type) {
+ signatureGen.reset();
+ signatureGen.assembleSig(type);
+ return signatureGen.toName();
+ }
+
+ private Name classSig(Type t) {
+ signatureGen.reset();
+ List<Type> typarams = t.getTypeArguments();
+ if (typarams.nonEmpty()) {
+ signatureGen.assembleParamsSig(typarams);
+ }
+ signatureGen.assembleSig(types.supertype(t));
+ for (Type i : types.interfaces(t))
+ signatureGen.assembleSig(i);
+ return signatureGen.toName();
+ }
+
+ void reset() {
+ innerClasses.clear();
+ bootstrapMethods.clear();
+ pool.reset();
+ }
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java Fri Apr 19 08:00:42 2019 -0400
@@ -26,7 +26,9 @@
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.comp.Resolve;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeMaker;
@@ -222,7 +224,7 @@
private JCDiagnostic.DiagnosticPosition newStringBuilder(JCTree tree) {
JCDiagnostic.DiagnosticPosition pos = tree.pos();
- gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType));
+ gen.getCode().emitop2(new_, gen.makeRef(pos, syms.stringBuilderType), syms.stringBuilderType);
gen.getCode().emitop0(dup);
gen.callMethod(pos, syms.stringBuilderType, names.init, List.nil(), false);
return pos;
@@ -378,10 +380,9 @@
Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcat,
syms.noSymbol,
- ClassFile.REF_invokeStatic,
- (Symbol.MethodSymbol)bsm,
+ ((MethodSymbol)bsm).asHandle(),
indyType,
- List.nil().toArray());
+ List.nil().toArray(new LoadableConstant[0]));
Items.Item item = gen.getItems().makeDynamicItem(dynSym);
item.invoke();
@@ -416,7 +417,7 @@
StringBuilder recipe = new StringBuilder(t.size());
ListBuffer<Type> dynamicArgs = new ListBuffer<>();
- ListBuffer<Object> staticArgs = new ListBuffer<>();
+ ListBuffer<LoadableConstant> staticArgs = new ListBuffer<>();
for (JCTree arg : t) {
Object constVal = arg.type.constValue();
@@ -431,7 +432,7 @@
String a = arg.type.stringValue();
if (a.indexOf(TAG_CONST) != -1 || a.indexOf(TAG_ARG) != -1) {
recipe.append(TAG_CONST);
- staticArgs.add(a);
+ staticArgs.add(LoadableConstant.String(a));
} else {
recipe.append(a);
}
@@ -463,7 +464,7 @@
}
/** Produce the actual invokedynamic call to StringConcatFactory */
- private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<Object> staticArgs, List<Type> dynamicArgTypes) {
+ private void doCall(Type type, JCDiagnostic.DiagnosticPosition pos, String recipe, List<LoadableConstant> staticArgs, List<Type> dynamicArgTypes) {
Type.MethodType indyType = new Type.MethodType(dynamicArgTypes,
type,
List.nil(),
@@ -474,8 +475,8 @@
make.at(pos);
ListBuffer<Type> constTypes = new ListBuffer<>();
- ListBuffer<Object> constants = new ListBuffer<>();
- for (Object t : staticArgs) {
+ ListBuffer<LoadableConstant> constants = new ListBuffer<>();
+ for (LoadableConstant t : staticArgs) {
constants.add(t);
constTypes.add(syms.stringType);
}
@@ -495,10 +496,10 @@
Symbol.DynamicMethodSymbol dynSym = new Symbol.DynamicMethodSymbol(names.makeConcatWithConstants,
syms.noSymbol,
- ClassFile.REF_invokeStatic,
- (Symbol.MethodSymbol)bsm,
+ ((MethodSymbol)bsm).asHandle(),
indyType,
- List.<Object>of(recipe).appendList(constants).toArray());
+ List.of(LoadableConstant.String(recipe))
+ .appendList(constants).toArray(new LoadableConstant[constants.size()]));
Items.Item item = gen.getItems().makeDynamicItem(dynSym);
item.invoke();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -188,6 +188,11 @@
private final Context context;
+ /**
+ * Support for preview language features.
+ */
+ private final Preview preview;
+
/** Get the JavacProcessingEnvironment instance for this context. */
public static JavacProcessingEnvironment instance(Context context) {
JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
@@ -236,6 +241,7 @@
enter = Enter.instance(context);
initialCompleter = ClassFinder.instance(context).getCompleter();
chk = Check.instance(context);
+ preview = Preview.instance(context);
initProcessorLoader();
}
@@ -1675,6 +1681,11 @@
return messages.getCurrentLocale();
}
+ @DefinedBy(Api.ANNOTATION_PROCESSING)
+ public boolean isPreviewEnabled() {
+ return preview.isEnabled();
+ }
+
public Set<Symbol.PackageSymbol> getSpecifiedPackages() {
return specifiedPackages;
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Apr 19 08:00:42 2019 -0400
@@ -2164,6 +2164,11 @@
bad constant pool entry in {0}\n\
expected {1} at index {2}
+# 0: file name, 1: number (constant pool index), 2: number (constant pool size)
+compiler.misc.bad.const.pool.index=\
+ bad constant pool index in {0}\n\
+ index {1} is not within pool size {2}.
+
# 0: file name, 1: message segment
compiler.misc.bad.class.file.header=\
bad class file: {0}\n\
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ByteBuffer.java Fri Apr 19 08:00:42 2019 -0400
@@ -147,6 +147,90 @@
appendBytes(name.getByteArray(), name.getByteOffset(), name.getByteLength());
}
+ /** Append the content of a given input stream.
+ */
+ public void appendStream(InputStream is) throws IOException {
+ try {
+ int start = length;
+ int initialSize = is.available();
+ elems = ArrayUtils.ensureCapacity(elems, length + initialSize);
+ int r = is.read(elems, start, initialSize);
+ int bp = start;
+ while (r != -1) {
+ bp += r;
+ elems = ArrayUtils.ensureCapacity(elems, bp);
+ r = is.read(elems, bp, elems.length - bp);
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ /* Ignore any errors, as this stream may have already
+ * thrown a related exception which is the one that
+ * should be reported.
+ */
+ }
+ }
+ }
+
+ /** Extract an integer at position bp from elems.
+ */
+ public int getInt(int bp) {
+ return
+ ((elems[bp] & 0xFF) << 24) +
+ ((elems[bp+1] & 0xFF) << 16) +
+ ((elems[bp+2] & 0xFF) << 8) +
+ (elems[bp+3] & 0xFF);
+ }
+
+
+ /** Extract a long integer at position bp from elems.
+ */
+ public long getLong(int bp) {
+ DataInputStream elemsin =
+ new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
+ try {
+ return elemsin.readLong();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** Extract a float at position bp from elems.
+ */
+ public float getFloat(int bp) {
+ DataInputStream elemsin =
+ new DataInputStream(new ByteArrayInputStream(elems, bp, 4));
+ try {
+ return elemsin.readFloat();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** Extract a double at position bp from elems.
+ */
+ public double getDouble(int bp) {
+ DataInputStream elemsin =
+ new DataInputStream(new ByteArrayInputStream(elems, bp, 8));
+ try {
+ return elemsin.readDouble();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /** Extract a character at position bp from elems.
+ */
+ public char getChar(int bp) {
+ return
+ (char)(((elems[bp] & 0xFF) << 8) + (elems[bp+1] & 0xFF));
+ }
+
+ public byte getByte(int bp) {
+ return elems[bp];
+ }
+
/** Reset to zero length.
*/
public void reset() {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Name.java Fri Apr 19 08:00:42 2019 -0400
@@ -25,6 +25,8 @@
package com.sun.tools.javac.util;
+import com.sun.tools.javac.jvm.ClassFile;
+import com.sun.tools.javac.jvm.PoolConstant;
import com.sun.tools.javac.util.DefinedBy.Api;
/** An abstraction for internal compiler strings. They are stored in
@@ -36,7 +38,7 @@
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
-public abstract class Name implements javax.lang.model.element.Name {
+public abstract class Name implements javax.lang.model.element.Name, PoolConstant {
public final Table table;
@@ -52,6 +54,11 @@
return toString().equals(cs.toString());
}
+ @Override
+ public int poolTag() {
+ return ClassFile.CONSTANT_Utf8;
+ }
+
/**
* {@inheritDoc}
*/
@@ -188,6 +195,14 @@
*/
public abstract int getByteOffset();
+ public interface NameMapper<X> {
+ X map(byte[] bytes, int offset, int len);
+ }
+
+ public <X> X map(NameMapper<X> mapper) {
+ return mapper.map(getByteArray(), getByteOffset(), getByteLength());
+ }
+
/** An abstraction for the hash table used to create unique Name instances.
*/
public static abstract class Table {
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java Fri Apr 19 08:00:42 2019 -0400
@@ -1137,20 +1137,79 @@
private static long nativeKeyWrapperKeyID = 0;
private static CK_MECHANISM nativeKeyWrapperMechanism = null;
+ private static long nativeKeyWrapperRefCount = 0;
+ private static Session nativeKeyWrapperSession = null;
private final P11Key p11Key;
private final byte[] nativeKeyInfo;
+ private boolean wrapperKeyUsed;
// destroyed and recreated when refCount toggles to 1
private long keyID;
- private boolean isTokenObject;
-
// phantom reference notification clean up for session keys
private SessionKeyRef ref;
private int refCount;
+ private static void createNativeKeyWrapper(Token token)
+ throws PKCS11Exception {
+ assert(nativeKeyWrapperKeyID == 0);
+ assert(nativeKeyWrapperRefCount == 0);
+ assert(nativeKeyWrapperSession == null);
+ // Create a global wrapping/unwrapping key
+ CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes(O_GENERATE,
+ CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
+ new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+ new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3)});
+ Session s = null;
+ try {
+ s = token.getObjSession();
+ nativeKeyWrapperKeyID = token.p11.C_GenerateKey(
+ s.id(), new CK_MECHANISM(CKM_AES_KEY_GEN),
+ wrappingAttributes);
+ nativeKeyWrapperSession = s;
+ nativeKeyWrapperSession.addObject();
+ byte[] iv = new byte[16];
+ JCAUtil.getSecureRandom().nextBytes(iv);
+ nativeKeyWrapperMechanism = new CK_MECHANISM(CKM_AES_CBC_PAD, iv);
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
+ }
+
+ private static void deleteNativeKeyWrapper() {
+ Token token = nativeKeyWrapperSession.token;
+ if (token.isValid()) {
+ Session s = null;
+ try {
+ s = token.getOpSession();
+ token.p11.C_DestroyObject(s.id(), nativeKeyWrapperKeyID);
+ nativeKeyWrapperSession.removeObject();
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
+ }
+ nativeKeyWrapperKeyID = 0;
+ nativeKeyWrapperMechanism = null;
+ nativeKeyWrapperSession = null;
+ }
+
+ static void decWrapperKeyRef() {
+ synchronized(NativeKeyHolder.class) {
+ assert(nativeKeyWrapperKeyID != 0);
+ assert(nativeKeyWrapperRefCount > 0);
+ nativeKeyWrapperRefCount--;
+ if (nativeKeyWrapperRefCount == 0) {
+ deleteNativeKeyWrapper();
+ }
+ }
+ }
+
NativeKeyHolder(P11Key p11Key, long keyID, Session keySession,
boolean extractKeyInfo, boolean isTokenObject) {
this.p11Key = p11Key;
@@ -1160,35 +1219,23 @@
if (isTokenObject) {
this.ref = null;
} else {
- this.ref = new SessionKeyRef(p11Key, keyID, keySession);
-
// Try extracting key info, if any error, disable it
Token token = p11Key.token;
if (extractKeyInfo) {
try {
- if (p11Key.sensitive && nativeKeyWrapperKeyID == 0) {
+ if (p11Key.sensitive) {
+ // p11Key native key information has to be wrapped
synchronized(NativeKeyHolder.class) {
- // Create a global wrapping/unwrapping key
- CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes
- (O_GENERATE, CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
- new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
- new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3),
- });
- Session wrappingSession = null;
- try {
- wrappingSession = token.getObjSession();
- nativeKeyWrapperKeyID = token.p11.C_GenerateKey
- (wrappingSession.id(),
- new CK_MECHANISM(CKM_AES_KEY_GEN),
- wrappingAttributes);
- byte[] iv = new byte[16];
- JCAUtil.getSecureRandom().nextBytes(iv);
- nativeKeyWrapperMechanism = new CK_MECHANISM
- (CKM_AES_CBC_PAD, iv);
- } catch (PKCS11Exception e) {
- // best effort
- } finally {
- token.releaseSession(wrappingSession);
+ if (nativeKeyWrapperKeyID == 0) {
+ createNativeKeyWrapper(token);
+ }
+ // If a wrapper-key was successfully created or
+ // already exists, increment its reference
+ // counter to keep it alive while native key
+ // information is being held.
+ if (nativeKeyWrapperKeyID != 0) {
+ nativeKeyWrapperRefCount++;
+ wrapperKeyUsed = true;
}
}
}
@@ -1196,7 +1243,8 @@
try {
opSession = token.getOpSession();
ki = p11Key.token.p11.getNativeKeyInfo(opSession.id(),
- keyID, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
+ keyID, nativeKeyWrapperKeyID,
+ nativeKeyWrapperMechanism);
} catch (PKCS11Exception e) {
// best effort
} finally {
@@ -1206,6 +1254,8 @@
// best effort
}
}
+ this.ref = new SessionKeyRef(p11Key, keyID, wrapperKeyUsed,
+ keySession);
}
this.nativeKeyInfo = ((ki == null || ki.length == 0)? null : ki);
}
@@ -1222,18 +1272,15 @@
throw new RuntimeException(
"Error: null keyID with non-zero refCount " + cnt);
}
- if (this.ref != null) {
- throw new RuntimeException(
- "Error: null keyID with non-null session ref");
- }
Token token = p11Key.token;
// Create keyID using nativeKeyInfo
Session session = null;
try {
session = token.getObjSession();
this.keyID = token.p11.createNativeKey(session.id(),
- nativeKeyInfo, nativeKeyWrapperKeyID, nativeKeyWrapperMechanism);
- this.ref = new SessionKeyRef(p11Key, this.keyID, session);
+ nativeKeyInfo, nativeKeyWrapperKeyID,
+ nativeKeyWrapperMechanism);
+ this.ref.registerNativeKey(this.keyID, session);
} catch (PKCS11Exception e) {
this.refCount--;
throw new ProviderException("Error recreating native key", e);
@@ -1263,12 +1310,9 @@
throw new RuntimeException("ERROR: null keyID can't be destroyed");
}
- if (this.ref == null) {
- throw new RuntimeException("ERROR: null session ref can't be disposed");
- }
// destroy
this.keyID = 0;
- this.ref = this.ref.dispose();
+ this.ref.removeNativeKey();
} else {
if (cnt < 0) {
// should never happen as we start count at 1 and pair get/release calls
@@ -1285,12 +1329,11 @@
* otherwise the key maybe cleared before other objects which
* still use these keys during finalization such as SSLSocket.
*/
-final class SessionKeyRef extends PhantomReference<P11Key>
- implements Comparable<SessionKeyRef> {
+final class SessionKeyRef extends PhantomReference<P11Key> {
private static ReferenceQueue<P11Key> refQueue =
new ReferenceQueue<P11Key>();
- private static Set<SessionKeyRef> refList =
- Collections.synchronizedSortedSet(new TreeSet<SessionKeyRef>());
+ private static Set<SessionKeyRef> refSet =
+ Collections.synchronizedSet(new HashSet<SessionKeyRef>());
static ReferenceQueue<P11Key> referenceQueue() {
return refQueue;
@@ -1307,47 +1350,69 @@
}
// handle to the native key and the session it is generated under
- private final long keyID;
- private final Session session;
+ private long keyID;
+ private Session session;
+ private boolean wrapperKeyUsed;
- SessionKeyRef(P11Key p11Key, long keyID, Session session) {
+ SessionKeyRef(P11Key p11Key, long keyID, boolean wrapperKeyUsed,
+ Session session) {
super(p11Key, refQueue);
if (session == null) {
throw new ProviderException("key must be associated with a session");
}
- this.keyID = keyID;
- this.session = session;
- this.session.addObject();
+ registerNativeKey(keyID, session);
+ this.wrapperKeyUsed = wrapperKeyUsed;
- refList.add(this);
+ refSet.add(this);
drainRefQueueBounded();
}
- SessionKeyRef dispose() {
- Token token = session.token;
- // If the token is still valid, try to remove the key object
- if (token.isValid()) {
- Session s = null;
- try {
- s = token.getOpSession();
- token.p11.C_DestroyObject(s.id(), keyID);
- } catch (PKCS11Exception e) {
- // best effort
- } finally {
- token.releaseSession(s);
- }
- }
- refList.remove(this);
- this.clear();
- session.removeObject();
- return null;
+ void registerNativeKey(long newKeyID, Session newSession) {
+ assert(newKeyID != 0);
+ assert(newSession != null);
+ updateNativeKey(newKeyID, newSession);
+ }
+
+ void removeNativeKey() {
+ assert(session != null);
+ updateNativeKey(0, null);
}
- public int compareTo(SessionKeyRef other) {
- if (this.keyID == other.keyID) {
- return 0;
+ private void updateNativeKey(long newKeyID, Session newSession) {
+ if (newKeyID == 0) {
+ assert(newSession == null);
+ Token token = session.token;
+ // If the token is still valid, try to remove the key object
+ if (token.isValid()) {
+ Session s = null;
+ try {
+ s = token.getOpSession();
+ token.p11.C_DestroyObject(s.id(), this.keyID);
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
+ }
+ session.removeObject();
} else {
- return (this.keyID < other.keyID) ? -1 : 1;
+ newSession.addObject();
}
+ keyID = newKeyID;
+ session = newSession;
+ }
+
+ // Called when the GC disposes a p11Key
+ void dispose() {
+ if (wrapperKeyUsed) {
+ // Wrapper-key no longer needed for
+ // p11Key native key information
+ NativeKeyHolder.decWrapperKeyRef();
+ }
+ if (keyID != 0) {
+ removeNativeKey();
+ }
+ refSet.remove(this);
+ this.clear();
}
}
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_keymgmt.c Fri Apr 19 08:00:42 2019 -0400
@@ -308,7 +308,7 @@
*(CK_BBOOL*)(((CK_ATTRIBUTE_PTR)(((CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes)
+sensitiveAttributePosition))->pValue) == CK_TRUE) {
// Key is sensitive. Need to extract it wrapped.
- if (jWrappingKeyHandle != -1) {
+ if (jWrappingKeyHandle != 0) {
jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
@@ -351,6 +351,7 @@
goto cleanup;
}
} else {
+ ckAssertReturnValueOK(env, CKR_KEY_HANDLE_INVALID);
goto cleanup;
}
returnValue = nativeKeyInfoWrappedKeyArray;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java Fri Apr 19 08:00:42 2019 -0400
@@ -89,7 +89,7 @@
* .withNamespace(StandardNamespace.PROPERTY)
* .named("color");
* </pre>
- * <h3>Operations on multiple namespaces</h3>
+ * <h2>Operations on multiple namespaces</h2>
* If multiple namespaces are specified, the namespaces are treated as
* alternatives to each other in order of preference. The semantics of
* such operation is "first applicable".
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractModuleIndexWriter.java Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,253 +0,0 @@
-/*
- * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
- * 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 jdk.javadoc.internal.doclets.formats.html;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-
-import javax.lang.model.element.ModuleElement;
-import javax.lang.model.element.PackageElement;
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-
-/**
- * Abstract class to generate the module overview files.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- *
- * @author Bhavesh Patel
- */
-public abstract class AbstractModuleIndexWriter extends HtmlDocletWriter {
-
- /**
- * Modules to be documented.
- */
- protected SortedMap<ModuleElement, Set<PackageElement>> modules;
-
- protected Navigation navBar;
-
- /**
- * Constructor. Also initializes the modules variable.
- *
- * @param configuration The current configuration
- * @param filename Name of the module index file to be generated.
- */
- public AbstractModuleIndexWriter(HtmlConfiguration configuration,
- DocPath filename) {
- super(configuration, filename);
- modules = configuration.modulePackages;
- this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
- }
-
- /**
- * Adds the navigation bar header to the documentation tree.
- *
- * @param header the document tree to which the navigation bar header will be added
- */
- protected abstract void addNavigationBarHeader(Content header);
-
- /**
- * Adds the navigation bar footer to the documentation tree.
- *
- * @param footer the document tree to which the navigation bar footer will be added
- */
- protected abstract void addNavigationBarFooter(Content footer);
-
- /**
- * Adds the overview header to the documentation tree.
- *
- * @param main the document tree to which the overview header will be added
- */
- protected abstract void addOverviewHeader(Content main);
-
- /**
- * Adds the modules list to the documentation tree.
- *
- * @param main the document tree to which the modules list will be added
- */
- protected abstract void addModulesList(Content main);
-
- /**
- * Adds the module packages list to the documentation tree.
- *
- * @param modules the set of modules
- * @param text caption for the table
- * @param tableSummary summary for the table
- * @param main the document tree to which the modules list will be added
- * @param mdle the module being documented
- */
- protected abstract void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
- String tableSummary, Content main, ModuleElement mdle);
-
- /**
- * Generate and prints the contents in the module index file.
- *
- * @param title the title of the window
- * @param description the content for the description META tag
- * @throws DocFileIOException if there is a problem building the module index file
- */
- protected void buildModuleIndexFile(String title, String description)
- throws DocFileIOException {
- String windowOverview = resources.getText(title);
- Content body = getBody(getWindowTitle(windowOverview));
- Content header = HtmlTree.HEADER();
- addNavigationBarHeader(header);
- Content main = HtmlTree.MAIN();
- addOverviewHeader(main);
- addIndex(header, main);
- addOverview(main);
- Content footer = HtmlTree.FOOTER();
- addNavigationBarFooter(footer);
- body.add(header);
- body.add(main);
- body.add(footer);
- printHtmlDocument(
- configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
- description,
- body);
- }
-
- /**
- * Generate and prints the contents in the module packages index file.
- *
- * @param title the title of the window.
- * @param description the content for the description META tag
- * @param mdle the name of the module being documented
- * @throws DocFileIOException if there is an exception building the module packages index file
- */
- protected void buildModulePackagesIndexFile(String title, String description,
- ModuleElement mdle) throws DocFileIOException {
- String windowOverview = resources.getText(title);
- Content body = getBody(getWindowTitle(windowOverview));
- Content header = HtmlTree.HEADER();
- addNavigationBarHeader(header);
- Content main = HtmlTree.MAIN();
- addOverviewHeader(main);
- addModulePackagesIndex(header, main, mdle);
- addOverview(main);
- Content footer = HtmlTree.FOOTER();
- addNavigationBarFooter(footer);
- body.add(header);
- body.add(main);
- body.add(footer);
- printHtmlDocument(
- configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
- description,
- body);
- }
-
- /**
- * Default to no overview, override to add overview.
- *
- * @param main the document tree to which the overview will be added
- */
- protected void addOverview(Content main) { }
-
- /**
- * Adds the module index to the documentation tree.
- *
- * @param header the document tree to which the navigational links will be added
- * @param main the document tree to which the modules list will be added
- */
- protected void addIndex(Content header, Content main) {
- addIndexContents(configuration.modules, "doclet.Module_Summary",
- resources.getText("doclet.Member_Table_Summary",
- resources.getText("doclet.Module_Summary"),
- resources.getText("doclet.modules")), header, main);
- }
-
- /**
- * Adds the module packages index to the documentation tree.
- *
- * @param header the document tree to which the navigational links will be added
- * @param main the document tree to which the module packages list will be added
- * @param mdle the module being documented
- */
- protected void addModulePackagesIndex(Content header, Content main, ModuleElement mdle) {
- addModulePackagesIndexContents("doclet.Module_Summary",
- resources.getText("doclet.Member_Table_Summary",
- resources.getText("doclet.Module_Summary"),
- resources.getText("doclet.modules")), header, main, mdle);
- }
-
- /**
- * Adds module index contents. Call appropriate methods from
- * the sub-classes. Adds it to the body HtmlTree
- *
- * @param modules the modules to be documented
- * @param text string which will be used as the heading
- * @param tableSummary summary for the table
- * @param header the document tree to which the navigational links will be added
- * @param main the document tree to which the modules list will be added
- */
- protected void addIndexContents(Collection<ModuleElement> modules, String text,
- String tableSummary, Content header, Content main) {
- addModulesList(main);
- }
-
- /**
- * Adds module packages index contents. Call appropriate methods from
- * the sub-classes. Adds it to the body HtmlTree
- *
- * @param text string which will be used as the heading
- * @param tableSummary summary for the table
- * @param header the document tree to which the navigational links will be added
- * @param main the document tree to which the module packages list will be added
- * @param mdle the module being documented
- */
- protected void addModulePackagesIndexContents(String text,
- String tableSummary, Content header, Content main, ModuleElement mdle) {
- addModulePackagesList(modules, text, tableSummary, main, mdle);
- }
-
- /**
- * Adds the doctitle to the documentation tree, if it is specified on the command line.
- *
- * @param body the document tree to which the title will be added
- */
- protected void addConfigurationTitle(Content body) {
- if (configuration.doctitle.length() > 0) {
- Content title = new RawHtml(configuration.doctitle);
- Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
- HtmlStyle.title, title);
- Content div = HtmlTree.DIV(HtmlStyle.header, heading);
- body.add(div);
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractOverviewIndexWriter.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * 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 jdk.javadoc.internal.doclets.formats.html;
+
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
+import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
+import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
+import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
+import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.toolkit.Content;
+import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
+import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
+
+/**
+ * Abstract class to generate the overview files.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ *
+ */
+public abstract class AbstractOverviewIndexWriter extends HtmlDocletWriter {
+
+ protected Navigation navBar;
+
+ /**
+ * Constructs the AbstractOverviewIndexWriter.
+ *
+ * @param configuration The current configuration
+ * @param filename Name of the module index file to be generated.
+ */
+ public AbstractOverviewIndexWriter(HtmlConfiguration configuration,
+ DocPath filename) {
+ super(configuration, filename);
+ this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
+ }
+
+ /**
+ * Adds the top text (from the -top option), the upper
+ * navigation bar, and then the title (from the"-title"
+ * option), at the top of page.
+ *
+ * @param header the documentation tree to which the navigation bar header will be added
+ */
+ protected void addNavigationBarHeader(Content header) {
+ addTop(header);
+ navBar.setUserHeader(getUserHeaderFooter(true));
+ header.add(navBar.getContent(true));
+ }
+
+ /**
+ * Adds the lower navigation bar and the bottom text
+ * (from the -bottom option) at the bottom of page.
+ *
+ * @param footer the documentation tree to which the navigation bar footer will be added
+ */
+ protected void addNavigationBarFooter(Content footer) {
+ navBar.setUserFooter(getUserHeaderFooter(false));
+ footer.add(navBar.getContent(false));
+ addBottom(footer);
+ }
+
+ /**
+ * Adds the overview summary comment for this documentation. Add one line
+ * summary at the top of the page and generate a link to the description,
+ * which is added at the end of this page.
+ *
+ * @param main the documentation tree to which the overview header will be added
+ */
+ protected void addOverviewHeader(Content main) {
+ addConfigurationTitle(main);
+ if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
+ HtmlTree div = new HtmlTree(HtmlTag.DIV);
+ div.setStyle(HtmlStyle.contentContainer);
+ addOverviewComment(div);
+ main.add(div);
+ }
+ }
+
+ /**
+ * Adds the overview comment as provided in the file specified by the
+ * "-overview" option on the command line.
+ *
+ * @param htmltree the documentation tree to which the overview comment will
+ * be added
+ */
+ protected void addOverviewComment(Content htmltree) {
+ if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
+ addInlineComment(configuration.overviewElement, htmltree);
+ }
+ }
+
+ /**
+ * Generate and prints the contents in the index file.
+ *
+ * @param title the title of the window
+ * @param description the content for the description META tag
+ * @throws DocFileIOException if there is a problem building the package index file
+ */
+ protected void buildOverviewIndexFile(String title, String description)
+ throws DocFileIOException {
+ String windowOverview = resources.getText(title);
+ Content body = getBody(getWindowTitle(windowOverview));
+ Content header = HtmlTree.HEADER();
+ addNavigationBarHeader(header);
+ Content main = HtmlTree.MAIN();
+ addOverviewHeader(main);
+ addIndex(main);
+ Content footer = HtmlTree.FOOTER();
+ addNavigationBarFooter(footer);
+ body.add(header);
+ body.add(main);
+ body.add(footer);
+ printHtmlDocument(
+ configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
+ description, body);
+ }
+
+ /**
+ * Adds the index to the documentation tree.
+ *
+ * @param main the document tree to which the packages/modules list will be added
+ */
+ protected abstract void addIndex(Content main);
+
+ /**
+ * Adds the doctitle to the documentation tree, if it is specified on the command line.
+ *
+ * @param body the document tree to which the title will be added
+ */
+ protected void addConfigurationTitle(Content body) {
+ if (configuration.doctitle.length() > 0) {
+ Content title = new RawHtml(configuration.doctitle);
+ Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
+ HtmlStyle.title, title);
+ Content div = HtmlTree.DIV(HtmlStyle.header, heading);
+ body.add(div);
+ }
+ }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractPackageIndexWriter.java Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
- * 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 jdk.javadoc.internal.doclets.formats.html;
-
-import java.util.*;
-
-import javax.lang.model.element.PackageElement;
-
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation.PageMode;
-import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
-import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
-
-/**
- * Abstract class to generate the overview files. This will be sub-classed to
- * generate overview-summary.html.
- *
- * <p><b>This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- * @author Bhavesh Patel (Modified)
- */
-public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter {
-
- /**
- * A Set of Packages to be documented.
- */
- protected SortedSet<PackageElement> packages;
-
- protected Navigation navBar;
-
- /**
- * Constructor. Also initializes the packages variable.
- *
- * @param configuration The current configuration
- * @param filename Name of the package index file to be generated.
- */
- public AbstractPackageIndexWriter(HtmlConfiguration configuration,
- DocPath filename) {
- super(configuration, filename);
- packages = configuration.packages;
- this.navBar = new Navigation(null, configuration, fixedNavDiv, PageMode.OVERVIEW, path);
- }
-
- /**
- * Adds the navigation bar header to the documentation tree.
- *
- * @param header the document tree to which the navigation bar header will be added
- */
- protected abstract void addNavigationBarHeader(Content header);
-
- /**
- * Adds the navigation bar footer to the documentation tree.
- *
- * @param body the document tree to which the navigation bar footer will be added
- */
- protected abstract void addNavigationBarFooter(Content body);
-
- /**
- * Adds the overview header to the documentation tree.
- *
- * @param footer the document tree to which the overview header will be added
- */
- protected abstract void addOverviewHeader(Content footer);
-
- /**
- * Adds the packages list to the documentation tree.
- *
- * @param main the document tree to which the packages list will be added
- */
- protected abstract void addPackagesList(Content main);
-
- /**
- * Generate and prints the contents in the package index file.
- *
- * @param title the title of the window
- * @param description the content for the description META tag
- * @throws DocFileIOException if there is a problem building the package index file
- */
- protected void buildPackageIndexFile(String title, String description)
- throws DocFileIOException {
- String windowOverview = resources.getText(title);
- Content body = getBody(getWindowTitle(windowOverview));
- Content header = HtmlTree.HEADER();
- addNavigationBarHeader(header);
- Content main = HtmlTree.MAIN();
- addOverviewHeader(main);
- addIndex(header, main);
- addOverview(main);
- Content footer = HtmlTree.FOOTER();
- addNavigationBarFooter(footer);
- body.add(header);
- body.add(main);
- body.add(footer);
- printHtmlDocument(
- configuration.metakeywords.getOverviewMetaKeywords(title, configuration.doctitle),
- description, body);
- }
-
- /**
- * Default to no overview, override to add overview.
- *
- * @param main the document tree to which the overview will be added
- */
- protected void addOverview(Content main) { }
-
- /**
- * Adds the package index to the documentation tree.
- *
- * @param header the document tree to which the navigation links will be added
- * @param main the document tree to which the packages list will be added
- */
- protected void addIndex(Content header, Content main) {
- addIndexContents(header, main);
- }
-
- /**
- * Adds package index contents. Call appropriate methods from
- * the sub-classes. Adds it to the body HtmlTree
- *
- * @param header the document tree to which navigation links will be added
- * @param main the document tree to which the packages list will be added
- */
- protected void addIndexContents(Content header, Content main) {
- if (!packages.isEmpty()) {
- HtmlTree htmlTree = HtmlTree.NAV();
- htmlTree.setStyle(HtmlStyle.indexNav);
- HtmlTree ul = new HtmlTree(HtmlTag.UL);
- addAllClassesLink(ul);
- if (configuration.showModules && configuration.modules.size() > 1) {
- addAllModulesLink(ul);
- }
- htmlTree.add(ul);
- header.add(htmlTree);
- addPackagesList(main);
- }
- }
-
- /**
- * Adds the doctitle to the documentation tree, if it is specified on the command line.
- *
- * @param body the document tree to which the title will be added
- */
- protected void addConfigurationTitle(Content body) {
- if (configuration.doctitle.length() > 0) {
- Content title = new RawHtml(configuration.doctitle);
- Content heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
- HtmlStyle.title, title);
- Content div = HtmlTree.DIV(HtmlStyle.header, heading);
- body.add(div);
- }
- }
-
- /**
- * Do nothing. This will be overridden.
- *
- * @param div the document tree to which the all classes link will be added
- */
- protected void addAllClassesLink(Content div) {
- }
-
- /**
- * Do nothing. This will be overridden.
- *
- * @param div the document tree to which the all modules link will be added
- */
- protected void addAllModulesLink(Content div) {
- }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java Fri Apr 19 08:00:42 2019 -0400
@@ -53,15 +53,22 @@
*
* @author Bhavesh Patel
*/
-public class ModuleIndexWriter extends AbstractModuleIndexWriter {
+public class ModuleIndexWriter extends AbstractOverviewIndexWriter {
+
+ /**
+ * Modules to be documented.
+ */
+ protected SortedSet<ModuleElement> modules;
/**
* Construct the ModuleIndexWriter.
+ *
* @param configuration the configuration object
* @param filename the name of the generated file
*/
public ModuleIndexWriter(HtmlConfiguration configuration, DocPath filename) {
super(configuration, filename);
+ modules = configuration.modules;
}
/**
@@ -73,46 +80,23 @@
public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
DocPath filename = DocPaths.INDEX;
ModuleIndexWriter mdlgen = new ModuleIndexWriter(configuration, filename);
- mdlgen.buildModuleIndexFile("doclet.Window_Overview_Summary", "module index");
- }
-
- /**
- * Add the module index.
- *
- * @param header the documentation tree to which the navigational links will be added
- * @param main the documentation tree to which the modules list will be added
- */
- @Override
- protected void addIndex(Content header, Content main) {
- addIndexContents(header, main);
+ mdlgen.buildOverviewIndexFile("doclet.Window_Overview_Summary", "module index");
}
/**
- * Adds module index contents.
+ * Adds the list of modules.
*
- * @param header the document tree to which the navigational links will be added
- * @param main the document tree to which the modules list will be added
- */
- protected void addIndexContents(Content header, Content main) {
- addModulesList(main);
- }
-
- /**
- * Add the list of modules.
- *
- * @param main the content tree to which the module list will be added
+ * @param main the documentation tree to which the modules list will be added
*/
@Override
- protected void addModulesList(Content main) {
+ protected void addIndex(Content main) {
Map<String, SortedSet<ModuleElement>> groupModuleMap
- = configuration.group.groupModules(configuration.modules);
+ = configuration.group.groupModules(modules);
if (!groupModuleMap.keySet().isEmpty()) {
- String tableSummary = resources.getText("doclet.Member_Table_Summary",
- resources.getText("doclet.Module_Summary"), resources.getText("doclet.modules"));
- TableHeader header = new TableHeader(contents.moduleLabel, contents.descriptionLabel);
+ TableHeader tableHeader = new TableHeader(contents.moduleLabel, contents.descriptionLabel);
Table table = new Table(HtmlStyle.overviewSummary)
- .setHeader(header)
+ .setHeader(tableHeader)
.setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast)
.setDefaultTab(resources.getText("doclet.All_Modules"))
.setTabScript(i -> "show(" + i + ");")
@@ -126,7 +110,7 @@
}
}
- for (ModuleElement mdle : configuration.modules) {
+ for (ModuleElement mdle : modules) {
if (!mdle.isUnnamed()) {
if (!(configuration.nodeprecated && utils.isDeprecated(mdle))) {
Content moduleLinkContent = getModuleLink(mdle, new StringContent(mdle.getQualifiedName().toString()));
@@ -145,67 +129,4 @@
}
}
}
-
- /**
- * Adds the overview summary comment for this documentation. Add one line
- * summary at the top of the page and generate a link to the description,
- * which is added at the end of this page.
- *
- * @param main the documentation tree to which the overview header will be added
- */
- @Override
- protected void addOverviewHeader(Content main) {
- addConfigurationTitle(main);
- if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
- HtmlTree div = new HtmlTree(HtmlTag.DIV);
- div.setStyle(HtmlStyle.contentContainer);
- addOverviewComment(div);
- main.add(div);
- }
- }
-
- /**
- * Adds the overview comment as provided in the file specified by the
- * "-overview" option on the command line.
- *
- * @param htmltree the documentation tree to which the overview comment will
- * be added
- */
- protected void addOverviewComment(Content htmltree) {
- if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
- addInlineComment(configuration.overviewElement, htmltree);
- }
- }
-
- /**
- * Adds the top text (from the -top option), the upper
- * navigation bar, and then the title (from the"-title"
- * option), at the top of page.
- *
- * @param header the documentation tree to which the navigation bar header will be added
- */
- @Override
- protected void addNavigationBarHeader(Content header) {
- addTop(header);
- navBar.setUserHeader(getUserHeaderFooter(true));
- header.add(navBar.getContent(true));
- }
-
- /**
- * Adds the lower navigation bar and the bottom text
- * (from the -bottom option) at the bottom of page.
- *
- * @param footer the documentation tree to which the navigation bar footer will be added
- */
- @Override
- protected void addNavigationBarFooter(Content footer) {
- navBar.setUserFooter(getUserHeaderFooter(false));
- footer.add(navBar.getContent(false));
- addBottom(footer);
- }
-
- @Override
- protected void addModulePackagesList(Map<ModuleElement, Set<PackageElement>> modules, String text,
- String tableSummary, Content main, ModuleElement mdle) {
- }
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java Fri Apr 19 08:00:42 2019 -0400
@@ -52,7 +52,12 @@
* @author Atul M Dambalkar
* @author Bhavesh Patel (Modified)
*/
-public class PackageIndexWriter extends AbstractPackageIndexWriter {
+public class PackageIndexWriter extends AbstractOverviewIndexWriter {
+
+ /**
+ * A Set of Packages to be documented.
+ */
+ protected SortedSet<PackageElement> packages;
/**
* Construct the PackageIndexWriter. Also constructs the grouping
@@ -65,6 +70,7 @@
*/
public PackageIndexWriter(HtmlConfiguration configuration, DocPath filename) {
super(configuration, filename);
+ packages = configuration.packages;
}
/**
@@ -76,26 +82,16 @@
public static void generate(HtmlConfiguration configuration) throws DocFileIOException {
DocPath filename = DocPaths.INDEX;
PackageIndexWriter packgen = new PackageIndexWriter(configuration, filename);
- packgen.buildPackageIndexFile("doclet.Window_Overview_Summary", "package index");
+ packgen.buildOverviewIndexFile("doclet.Window_Overview_Summary", "package index");
}
/**
- * Depending upon the grouping information and their titles, add
- * separate table indices for each package group.
+ * Adds the packages list to the documentation tree.
*
- * @param header the documentation tree to which the navigational links will be added
* @param main the documentation tree to which the packages list will be added
*/
@Override
- protected void addIndex(Content header, Content main) {
- addIndexContents(header, main);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected void addPackagesList(Content main) {
+ protected void addIndex(Content main) {
Map<String, SortedSet<PackageElement>> groupPackageMap
= configuration.group.groupPackages(packages);
@@ -134,62 +130,4 @@
}
}
}
-
- /**
- * Adds the overview summary comment for this documentation. Add one line
- * summary at the top of the page and generate a link to the description,
- * which is added at the end of this page.
- *
- * @param main the documentation tree to which the overview header will be added
- */
- @Override
- protected void addOverviewHeader(Content main) {
- addConfigurationTitle(main);
- if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
- HtmlTree div = new HtmlTree(HtmlTag.DIV);
- div.setStyle(HtmlStyle.contentContainer);
- addOverviewComment(div);
- main.add(div);
- }
- }
-
- /**
- * Adds the overview comment as provided in the file specified by the
- * "-overview" option on the command line.
- *
- * @param htmltree the documentation tree to which the overview comment will
- * be added
- */
- protected void addOverviewComment(Content htmltree) {
- if (!utils.getFullBody(configuration.overviewElement).isEmpty()) {
- addInlineComment(configuration.overviewElement, htmltree);
- }
- }
-
- /**
- * Adds the top text (from the -top option), the upper
- * navigation bar, and then the title (from the"-title"
- * option), at the top of page.
- *
- * @param header the documentation tree to which the navigation bar header will be added
- */
- @Override
- protected void addNavigationBarHeader(Content header) {
- addTop(header);
- navBar.setUserHeader(getUserHeaderFooter(true));
- header.add(navBar.getContent(true));
- }
-
- /**
- * Adds the lower navigation bar and the bottom text
- * (from the -bottom option) at the bottom of page.
- *
- * @param footer the documentation tree to which the navigation bar footer will be added
- */
- @Override
- protected void addNavigationBarFooter(Content footer) {
- navBar.setUserFooter(getUserHeaderFooter(false));
- footer.add(navBar.getContent(false));
- addBottom(footer);
- }
}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties Fri Apr 19 08:00:42 2019 -0400
@@ -98,7 +98,6 @@
doclet.From=From
doclet.Uses_Summary=Uses
doclet.Provides_Summary=Provides
-doclet.Module_Summary=Module Summary
doclet.Interface_Summary=Interface Summary
doclet.Annotation_Types_Summary=Annotation Types Summary
doclet.Enum_Summary=Enum Summary
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java Fri Apr 19 08:00:42 2019 -0400
@@ -374,7 +374,7 @@
// locale, doclet and maybe taglet, needs to be determined first
try {
- docletClass = preprocess(fileManager, options);
+ doclet = preprocess(fileManager, options);
} catch (ToolException te) {
if (!te.result.isOK()) {
if (te.message != null) {
@@ -393,24 +393,6 @@
dumpStack(t == null ? oe : t);
return oe.result;
}
- if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
- // no need to dispatch to old, safe to init now
- initMessager();
- messager.setLocale(locale);
- try {
- Object o = docletClass.getConstructor().newInstance();
- doclet = (Doclet) o;
- } catch (ReflectiveOperationException exc) {
- if (apiMode) {
- throw new ClientCodeException(exc);
- }
- error("main.could_not_instantiate_class", docletClass.getName());
- return ERROR;
- }
- } else {
- error("main.not_a_doclet", docletClass.getName());
- return ERROR;
- }
Result result = OK;
try {
@@ -649,7 +631,7 @@
return idx;
}
- private Class<?> preprocess(JavaFileManager jfm,
+ private Doclet preprocess(JavaFileManager jfm,
List<String> argv) throws ToolException, OptionException {
// doclet specifying arguments
String userDocletPath = null;
@@ -706,71 +688,77 @@
}
}
- // Step 2: a doclet is provided, nothing more to do.
- if (docletClass != null) {
- return docletClass;
- }
// Step 3: doclet name specified ? if so find a ClassLoader,
// and load it.
- if (userDocletName != null) {
- ClassLoader cl = classLoader;
- if (cl == null) {
- if (!fileManager.hasLocation(DOCLET_PATH)) {
- List<File> paths = new ArrayList<>();
- if (userDocletPath != null) {
- for (String pathname : userDocletPath.split(File.pathSeparator)) {
- paths.add(new File(pathname));
+ if(docletClass == null) {
+ if (userDocletName != null) {
+ ClassLoader cl = classLoader;
+ if (cl == null) {
+ if (!fileManager.hasLocation(DOCLET_PATH)) {
+ List<File> paths = new ArrayList<>();
+ if (userDocletPath != null) {
+ for (String pathname : userDocletPath.split(File.pathSeparator)) {
+ paths.add(new File(pathname));
+ }
+ }
+ try {
+ ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
+ } catch (IOException ioe) {
+ if (apiMode) {
+ throw new IllegalArgumentException("Could not set location for " +
+ userDocletPath, ioe);
+ }
+ String text = messager.getText("main.doclet_could_not_set_location",
+ userDocletPath);
+ throw new ToolException(CMDERR, text, ioe);
}
}
- try {
- ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
- } catch (IOException ioe) {
+ cl = fileManager.getClassLoader(DOCLET_PATH);
+ if (cl == null) {
+ // despite doclet specified on cmdline no classloader found!
if (apiMode) {
- throw new IllegalArgumentException("Could not set location for " +
- userDocletPath, ioe);
+ throw new IllegalArgumentException("Could not obtain classloader to load "
+
+ + userDocletPath);
}
- String text = messager.getText("main.doclet_could_not_set_location",
- userDocletPath);
- throw new ToolException(CMDERR, text, ioe);
+ String text = messager.getText("main.doclet_no_classloader_found",
+ userDocletName);
+ throw new ToolException(CMDERR, text);
}
}
- cl = fileManager.getClassLoader(DOCLET_PATH);
- if (cl == null) {
- // despite doclet specified on cmdline no classloader found!
- if (apiMode) {
- throw new IllegalArgumentException("Could not obtain classloader to load "
- + userDocletPath);
- }
- String text = messager.getText("main.doclet_no_classloader_found",
- userDocletName);
- throw new ToolException(CMDERR, text);
- }
- }
- try {
- return cl.loadClass(userDocletName);
- } catch (ClassNotFoundException cnfe) {
- if (apiMode) {
- throw new IllegalArgumentException("Cannot find doclet class " + userDocletName,
- cnfe);
- }
- String text = messager.getText("main.doclet_class_not_found", userDocletName);
- throw new ToolException(CMDERR, text, cnfe);
+ docletClass = loadDocletClass(userDocletName, cl);
+ } else if (docletName != null){
+ docletClass = loadDocletClass(docletName, getClass().getClassLoader());
+ } else {
+ docletClass = StdDoclet;
}
}
- // Step 4: we have a doclet, try loading it
- if (docletName != null) {
- return loadDocletClass(docletName);
+ if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
+ // no need to dispatch to old, safe to init now
+ initMessager();
+ messager.setLocale(locale);
+ try {
+ Object o = docletClass.getConstructor().newInstance();
+ doclet = (Doclet) o;
+ } catch (ReflectiveOperationException exc) {
+ if (apiMode) {
+ throw new ClientCodeException(exc);
+ }
+ String text = messager.getText("main.could_not_instantiate_class", docletClass.getName());
+ throw new ToolException(ERROR, text);
+ }
+ } else {
+ String text = messager.getText("main.not_a_doclet", docletClass.getName());
+ throw new ToolException(ERROR, text);
}
-
- // finally
- return StdDoclet;
+ return doclet;
}
- private Class<?> loadDocletClass(String docletName) throws ToolException {
+ private Class<?> loadDocletClass(String docletName, ClassLoader classLoader) throws ToolException {
try {
- return Class.forName(docletName, true, getClass().getClassLoader());
+ return classLoader == null ? Class.forName(docletName) : classLoader.loadClass(docletName);
} catch (ClassNotFoundException cnfe) {
if (apiMode) {
throw new IllegalArgumentException("Cannot find doclet class " + docletName);
--- a/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.jcmd/share/classes/sun/tools/jcmd/JCmd.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
* 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 sun.tools.jcmd;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
@@ -121,15 +122,16 @@
if (line.trim().equals("stop")) {
break;
}
- try (InputStream in = hvm.executeJCmd(line);) {
+ try (InputStream in = hvm.executeJCmd(line);
+ InputStreamReader isr = new InputStreamReader(in, "UTF-8")) {
// read to EOF and just print output
- byte b[] = new byte[256];
+ char c[] = new char[256];
int n;
boolean messagePrinted = false;
do {
- n = in.read(b);
+ n = isr.read(c);
if (n > 0) {
- String s = new String(b, 0, n, "UTF-8");
+ String s = new String(c, 0, n);
System.out.print(s);
messagePrinted = true;
}
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NameCodec.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NameCodec.java Fri Apr 19 08:00:42 2019 -0400
@@ -39,11 +39,11 @@
* to nashorn module.
* </p>
*
- * <h3>Comment from BytecodeName class reproduced here:</h3>
+ * <h2>Comment from BytecodeName class reproduced here:</h2>
*
* Includes universal mangling rules for the JVM.
*
- * <h3>Avoiding Dangerous Characters </h3>
+ * <h2>Avoiding Dangerous Characters </h2>
*
* <p>
* The JVM defines a very small set of characters which are illegal
@@ -74,7 +74,7 @@
* but traditional in the proposed role.
*
* </p>
- * <h3> Replacement Characters </h3>
+ * <h2> Replacement Characters </h2>
*
*
* <p>
@@ -159,7 +159,7 @@
* to check for dangerous characters.
*
* </p>
- * <h3> Nice Properties </h3>
+ * <h2> Nice Properties </h2>
*
* <p>
* If a bytecode name does not contain any escape sequence,
@@ -222,7 +222,7 @@
* </ul>
*
*
- * <h3> Suggestions for Human Readable Presentations </h3>
+ * <h2> Suggestions for Human Readable Presentations </h2>
*
*
* <p>
--- a/src/jdk.scripting.nashorn/share/classes/module-info.java Fri Apr 19 07:55:28 2019 -0400
+++ b/src/jdk.scripting.nashorn/share/classes/module-info.java Fri Apr 19 08:00:42 2019 -0400
@@ -30,7 +30,7 @@
* Nashorn is a runtime environment for programs written in ECMAScript 5.1.
* </p>
*
- * <h1>Usage</h1>
+ * <h2>Usage</h2>
*
* The recommended way to use Nashorn is through the
* <a href="http://jcp.org/en/jsr/detail?id=223" target="_top">JSR-223
@@ -45,7 +45,7 @@
*
* and then use it just as you would any other JSR-223 script engine. See
* {@link jdk.nashorn.api.scripting} package for details.
- * <h1>Compatibility</h1>
+ * <h2>Compatibility</h2>
* Nashorn is 100% compliant with the
* <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm"
* target="_top">ECMA-262 Standard, Edition 5.1</a>.
@@ -55,7 +55,7 @@
* specification (often referred to as "invokedynamic"), as well as
* the already mentioned JSR-223.
*
- * <h1>Interoperability with the Java platform</h1>
+ * <h2>Interoperability with the Java platform</h2>
*
* In addition to being a 100% ECMAScript 5.1 runtime, Nashorn provides features
* for interoperability of the ECMAScript programs with the Java platform.
@@ -68,7 +68,7 @@
* their properties. In most cases, though, you can't add arbitrary properties
* to them, nor can you remove existing properties.
*
- * <h2>Java collection handling</h2>
+ * <h3>Java collection handling</h3>
*
* Native Java arrays and {@link java.util.List}s support indexed access to
* their elements through the property accessors, and {@link java.util.Map}s
@@ -79,7 +79,7 @@
* operator gives precedence to map elements. Native Java arrays expose
* the {@code length} property.
*
- * <h2>ECMAScript primitive types</h2>
+ * <h3>ECMAScript primitive types</h3>
*
* ECMAScript primitive types for number, string, and boolean are represented
* with {@link java.lang.Number}, {@link java.lang.CharSequence}, and
@@ -89,7 +89,7 @@
* cause other subclasses of {@code Number} and internal implementations of
* {@code CharSequence} to be used.
*
- * <h2>Type conversions</h2>
+ * <h3>Type conversions</h3>
*
* When a method on a Java object is invoked, the arguments are converted to
* the formal parameter types of the Java method using all allowed ECMAScript
@@ -106,7 +106,7 @@
* {@code java.lang.Double}), then Nashorn will of course ensure
* the required type is passed.
*
- * <h2>SAM types</h2>
+ * <h3>SAM types</h3>
*
* As a special extension when invoking Java methods, ECMAScript function
* objects can be passed in place of an argument whose Java type is so-called
@@ -122,14 +122,14 @@
* the same name</em>. This is done to be consistent with the fact that
* ECMAScript does not have the concept of overloaded methods.
*
- * <h2>The {@code Java} object</h2>
+ * <h3>The {@code Java} object</h3>
*
* Nashorn exposes a non-standard global object named {@code Java} that is
* the primary API entry point into Java platform-specific functionality.
* You can use it to create instances of Java classes, convert from Java arrays
* to native arrays and back, and so on.
*
- * <h2>Other non-standard built-in objects</h2>
+ * <h3>Other non-standard built-in objects</h3>
*
* In addition to {@code Java}, Nashorn also exposes some other
* non-standard built-in objects:
--- a/test/hotspot/jtreg/ProblemList-graal.txt Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/ProblemList-graal.txt Fri Apr 19 08:00:42 2019 -0400
@@ -218,6 +218,9 @@
compiler/jsr292/InvokerSignatureMismatch.java 8221577 generic-all
+compiler/arguments/TestScavengeRootsInCode.java 8207267 generic-all
+compiler/loopopts/TestOverunrolling.java 8207267 generic-all
+
# Graal unit tests
org.graalvm.compiler.core.test.CheckGraalInvariants 8205081
org.graalvm.compiler.core.test.OptionsVerifierTest 8205081
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/containers/docker/JfrNetwork.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.file.Paths;
+import java.util.List;
+import jdk.jfr.Recording;
+import jdk.jfr.consumer.RecordedEvent;
+import jdk.jfr.consumer.RecordingFile;
+import jdk.test.lib.process.OutputAnalyzer;
+
+
+// This class is intended to run inside a container
+public class JfrNetwork {
+ // use a unique hostname for container
+ public static final String HOST_NAME = "container-unique-8221711";
+ public static final String JFR_REPORTED_CONTAINER_HOSTNAME_TAG = "jfr_reported_container_hostname=";
+
+ public static void main(String[] args) throws Exception {
+ String event = args[0];
+ try (ServerSocket ss = new ServerSocket()) {
+ testNetworkInfo(ss, event);
+ }
+ }
+
+ private static void assertTrue(boolean expr, String msg) {
+ if (!expr) {
+ throw new RuntimeException(msg);
+ }
+ }
+
+ private static void testNetworkInfo(ServerSocket ss, String event) throws Exception {
+ ServerSocketListener server = new ServerSocketListener(ss);
+ server.start();
+ SocketWriter writer = new SocketWriter(ss.getLocalSocketAddress());
+
+ // setup and start the recording
+ String recordingPath = event + ".jfr";
+ log("========= Recording event: " + event);
+ Recording r = new Recording();
+ r.enable(event);
+ r.setDestination(Paths.get("/", "tmp", recordingPath));
+ r.start();
+
+ // start the socker writer thread, write some data into the socket
+ writer.start();
+
+ // wait for writer thread to terminate, then for server thread, then stop recording
+ writer.joinAndThrow();
+ server.joinAndThrow();
+ r.stop();
+
+ // analyze the recording
+ List<RecordedEvent> events = RecordingFile.readAllEvents(r.getDestination());
+ events.forEach(e -> log ("event = " + e));
+ assertTrue(!events.isEmpty(), "No recorded network events");
+ RecordedEvent e = events.get(0);
+ log(JFR_REPORTED_CONTAINER_HOSTNAME_TAG + e.getString("host"));
+ verifyIpAddress(e.getString("address"));
+ }
+
+ private static void verifyIpAddress(String eventIp) throws Exception {
+ ProcessBuilder pb = new ProcessBuilder("hostname", "--ip-address");
+ OutputAnalyzer out = new OutputAnalyzer(pb.start());
+ out.shouldHaveExitValue(0);
+ log("hostname --ip-address returned: " + out.getOutput());
+ out.shouldContain(eventIp);
+ }
+
+ private static void log(String msg) {
+ System.out.println(msg);
+ }
+
+
+ private static class ServerSocketListener extends Thread {
+ Exception exception;
+ ServerSocket ss;
+
+ ServerSocketListener(ServerSocket socket) throws Exception {
+ ss = socket;
+ ss.setReuseAddress(true);
+ ss.bind(null);
+ log("ServerSocker Local Address: " + ss.getLocalSocketAddress());
+ }
+
+ public void joinAndThrow() throws Exception {
+ join();
+ if (exception != null) {
+ throw exception;
+ }
+ }
+
+ public void run() {
+ try {
+ try (Socket s = ss.accept(); InputStream is = s.getInputStream()) {
+ System.out.println("ServerSocketListener: accepted socket connection: s = " + s);
+ is.read();
+ is.read();
+ is.read();
+ }
+ } catch (Exception e) {
+ exception = e;
+ }
+ }
+ }
+
+
+ private static class SocketWriter extends Thread {
+ Exception exception;
+ private SocketAddress ssAddr;
+
+ public SocketWriter(SocketAddress sa) {
+ this.ssAddr = sa;
+ System.out.println("SocketWriter(): sa = " + sa);
+ }
+
+ public void joinAndThrow() throws Exception {
+ join();
+ if (exception != null) {
+ throw exception;
+ }
+ }
+
+ public void run() {
+ try (Socket s = new Socket()) {
+ s.connect(ssAddr);
+ try (OutputStream os = s.getOutputStream()) {
+ os.write('A');
+ os.write('B');
+ os.write('C');
+ }
+ } catch (Exception e) {
+ exception = e;
+ }
+ }
+ }
+
+}
--- a/test/hotspot/jtreg/containers/docker/JfrReporter.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/containers/docker/JfrReporter.java Fri Apr 19 08:00:42 2019 -0400
@@ -22,53 +22,30 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-
+import java.nio.file.Path;
import java.nio.file.Paths;
import jdk.jfr.Recording;
+import jdk.jfr.ValueDescriptor;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordingFile;
-
// This class is intended to run inside a container
public class JfrReporter {
- public static final String TEST_REPORTED_CORES="TEST_REPORTED_CORES";
- public static final String TEST_REPORTED_MEMORY="TEST_REPORTED_MEMORY";
- public static final String TEST_REPORTED_PID="TEST_REPORTED_PID";
- public static final String TESTCASE_CPU="cpu";
- public static final String TESTCASE_MEMORY="memory";
- public static final String TESTCASE_PROCESS="process";
-
public static void main(String[] args) throws Exception {
- String testCase = args[0];
- System.out.println("Testcase: " + testCase);
- switch (testCase) {
- case TESTCASE_CPU:
- RecordedEvent event = testEvent("jdk.CPUInformation", "cpu.jfr");
- System.out.println(TEST_REPORTED_CORES + "=" + event.getInt("cores"));
- break;
- case TESTCASE_MEMORY:
- event = testEvent("jdk.PhysicalMemory", "memory.jfr");
- System.out.println(TEST_REPORTED_MEMORY + "=" + event.getLong("totalSize"));
- break;
- case TESTCASE_PROCESS:
- event = testEvent("jdk.SystemProcess", "process.jfr");
- System.out.println(TEST_REPORTED_PID + "=" + event.getString("pid"));
- break;
- default:
- throw new IllegalArgumentException("Invalid test case");
+ String eventName = args[0];
+ try(Recording r = new Recording()) {
+ r.enable(eventName);
+ r.start();
+ r.stop();
+ Path p = Paths.get("/", "tmp", eventName + ".jfr");
+ r.dump(p);
+ for (RecordedEvent e : RecordingFile.readAllEvents(p)) {
+ System.out.println("===== EventType: " + e.getEventType().getName());
+ for (ValueDescriptor v : e.getEventType().getFields()) {
+ System.out.println(v.getName() + " = " + e.getValue(v.getName()));
+ }
+ }
}
}
-
- private static RecordedEvent testEvent(String event, String recordingPath) throws Exception {
- System.out.println("========= Testing event: " + event);
- Recording r = new Recording();
- r.enable(event);
- r.setDestination(Paths.get("tmp", recordingPath));
- r.start();
- r.stop();
-
- RecordedEvent recordedEvent = RecordingFile.readAllEvents(r.getDestination()).get(0);
- System.out.println("RecordedEvent: " + recordedEvent);
- return recordedEvent;
- }
}
+
\ No newline at end of file
--- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java Fri Apr 19 08:00:42 2019 -0400
@@ -39,6 +39,8 @@
import jdk.test.lib.containers.docker.Common;
import jdk.test.lib.containers.docker.DockerRunOptions;
import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.Asserts;
+import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.Utils;
@@ -68,6 +70,7 @@
testProcessInfo();
+ testEnvironmentVariables();
} finally {
DockerTestUtils.removeDockerImage(imageName);
}
@@ -79,14 +82,12 @@
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addDockerOpts("--cpus=" + valueToSet)
- .addClassOptions(JfrReporter.TESTCASE_CPU))
- .shouldHaveExitValue(0)
- .shouldContain(JfrReporter.TEST_REPORTED_CORES);
-
+ .addClassOptions("jdk.CPUInformation"))
+ .shouldHaveExitValue(0);
// The following assertion is currently disabled due to JFR reporting incorrect values.
// JFR reports values for the host system as opposed to values for the container.
// @ignore 8219999
- // .shouldContain(JfrReporter.TEST_REPORTED_CORES + "=" + expectedValue);
+ // .shouldContain("cores = " + expectedValue");
}
@@ -95,9 +96,9 @@
DockerTestUtils.dockerRunJava(
commonDockerOpts()
.addDockerOpts("--memory=" + valueToSet)
- .addClassOptions(JfrReporter.TESTCASE_MEMORY))
+ .addClassOptions("jdk.PhysicalMemory"))
.shouldHaveExitValue(0)
- .shouldContain(JfrReporter.TEST_REPORTED_MEMORY + "=" + expectedValue);
+ .shouldContain("totalSize = " + expectedValue);
}
@@ -105,10 +106,9 @@
Common.logNewTestCase("ProcessInfo");
DockerTestUtils.dockerRunJava(
commonDockerOpts()
- .addClassOptions(JfrReporter.TESTCASE_PROCESS))
+ .addClassOptions("jdk.SystemProcess"))
.shouldHaveExitValue(0)
- .shouldContain(JfrReporter.TEST_REPORTED_PID + "=1");
-
+ .shouldContain("pid = 1");
}
@@ -117,4 +117,28 @@
.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
.addJavaOpts("-cp", "/test-classes/");
}
+
+
+ // JTReg always defines the environment variable JAVA_MAIN_CLASS_<SOME_NUMBER>.
+ // This variable fits well for use in this test, since it is rather unique.
+ private static String getTestEnvironmentVariable() throws Exception {
+ for (String key : System.getenv().keySet()) {
+ if (key.startsWith("JAVA_MAIN_CLASS")) {
+ return key;
+ }
+ }
+ throw new RuntimeException("JAVA_MAIN_CLASS_* is not defined");
+ }
+
+
+ private static void testEnvironmentVariables() throws Exception {
+ Common.logNewTestCase("EnvironmentVariables");
+
+ DockerTestUtils.dockerRunJava(
+ commonDockerOpts()
+ .addClassOptions("jdk.InitialEnvironmentVariable"))
+ .shouldHaveExitValue(0)
+ .shouldContain("key = JAVA_HOME")
+ .shouldNotContain(getTestEnvironmentVariable());
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * 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 Test JFR network related events inside a container; make sure
+ * the reported host ip and host name are correctly reported within
+ * the container.
+ * @requires docker.support
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * @build JfrNetwork
+ * @run driver TestJFRNetworkEvents
+ */
+import jdk.test.lib.containers.docker.Common;
+import jdk.test.lib.containers.docker.DockerRunOptions;
+import jdk.test.lib.containers.docker.DockerTestUtils;
+import jdk.test.lib.Utils;
+
+
+public class TestJFRNetworkEvents {
+ private static final String imageName = Common.imageName("jfr-network");
+ private static final int availableCPUs = Runtime.getRuntime().availableProcessors();
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("Test Environment: detected availableCPUs = " + availableCPUs);
+ if (!DockerTestUtils.canTestDocker()) {
+ return;
+ }
+
+ DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
+
+ try {
+ runTest("jdk.SocketWrite");
+ } finally {
+ DockerTestUtils.removeDockerImage(imageName);
+ }
+ }
+
+ private static void runTest(String event) throws Exception {
+ DockerRunOptions opts = new DockerRunOptions(imageName, "/jdk/bin/java", "JfrNetwork")
+ .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/")
+ .addJavaOpts("-cp", "/test-classes/")
+ .addDockerOpts("--hostname", JfrNetwork.HOST_NAME)
+ .addClassOptions(event);
+ DockerTestUtils.dockerRunJava(opts)
+ .shouldHaveExitValue(0)
+ .shouldContain(JfrNetwork.JFR_REPORTED_CONTAINER_HOSTNAME_TAG + JfrNetwork.HOST_NAME);
+ }
+}
--- a/test/hotspot/jtreg/runtime/ErrorHandling/ExplicitArithmeticCheck.java Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4221448
- * @summary Use explicit check for integer arithmetic exception on win32.
- */
-
-public class ExplicitArithmeticCheck {
- public static void main(String argv[]) throws Exception {
- for (int i = 0; i < 64; i++) {
- boolean result = false;
- int n;
- try {
- n = 0 / 0;
- } catch (ArithmeticException e) {
- result = true;
- }
- if (result == false) {
- throw new Error("Failed to throw correct exception!");
- }
- result = false;
- try {
- n = 0 % 0;
- } catch (ArithmeticException e) {
- result = true;
- }
- if (result == false) {
- throw new Error("Failed to throw correct exception!");
- }
- try {
- n = 0x80000000 / -1;
- } catch (Throwable t) {
- throw new Error("Failed to throw correct exception!");
- }
- if (n != 0x80000000) {
- throw new Error("Incorrect integer arithmetic ! ");
- }
- try {
- n = 0x80000000 % -1;
- } catch (Throwable t) {
- throw new Error("Failed to throw correct exception!");
- }
- if (n != 0) {
- throw new Error("Incorrect integer arithmetic!");
- }
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/MemberName/MemberNameLeak.java Fri Apr 19 08:00:42 2019 -0400
@@ -33,10 +33,15 @@
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MemberNameLeak
*/
+import java.io.*;
+import java.nio.file.*;
import java.lang.invoke.*;
import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Utils;
import sun.hotspot.WhiteBox;
import sun.hotspot.code.Compiler;
import sun.hotspot.gc.GC;
@@ -47,6 +52,7 @@
// The size of the ResolvedMethodTable is 1024. 2000 entries
// is enough to trigger a grow/cleaning of the table after a GC.
private static int methodCount = 2000;
+ public static ArrayList<MethodHandle> keepAlive;
static class Leak {
public void callMe() {
@@ -56,6 +62,8 @@
Leak leak = new Leak();
WhiteBox wb = WhiteBox.getWhiteBox();
+ keepAlive = new ArrayList<>(methodCount);
+
ClassWithManyMethodsClassLoader classLoader = new ClassWithManyMethodsClassLoader();
Class<?> clazz = classLoader.create(className, methodPrefix, methodCount);
@@ -74,14 +82,20 @@
MethodHandle mh1 = lookup.findSpecial(clazz, methodName, mt, clazz);
mh1.invoke(o);
+
+ keepAlive.add(mh1);
}
long after = wb.resolvedMethodItemsCount();
+ System.out.println("wb.resolvedMethodItemsCount() after setup: " + after);
+
if (after == before) {
throw new RuntimeException("Too few resolved methods");
}
+ keepAlive = null;
+
// Wait until ServiceThread cleans ResolvedMethod table
int cnt = 0;
while (true) {
@@ -99,27 +113,48 @@
}
}
+ private static Path createGcLogPath(String prefix) throws IOException {
+ Path gcLog = Utils.createTempFile(prefix, "log");
+ Files.delete(gcLog);
+ return gcLog;
+ }
+
+ private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
public static void test(GC gc, boolean doConcurrent) throws Throwable {
- System.err.println("test(" + gc + ", " + doConcurrent + ")");
+ Path gcLogPath = createGcLogPath("gc." + gc + "." + doConcurrent);
+ System.err.println("test(" + gc + ", " + doConcurrent + ")" + " " + dateFormat.format(new Date()));
// Run this Leak class with logging
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-Xlog:membername+table=trace",
+ "-Xlog:membername+table=trace,gc+verify=debug,gc:" + gcLogPath + ":time,utctime,uptime,pid,level,tags",
"-XX:+UnlockExperimentalVMOptions",
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xbootclasspath/a:.",
+ "-XX:+VerifyBeforeGC",
+ "-XX:+VerifyAfterGC",
doConcurrent ? "-XX:+ExplicitGCInvokesConcurrent" : "-XX:-ExplicitGCInvokesConcurrent",
"-XX:+ClassUnloading",
"-XX:+ClassUnloadingWithConcurrentMark",
"-XX:+Use" + gc + "GC",
Leak.class.getName());
+
+ // Check process
OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.outputTo(System.out);
+ output.errorTo(System.err);
+ output.shouldHaveExitValue(0);
+
+ // Check gc log file
+ OutputAnalyzer gcLogOutput = new OutputAnalyzer(gcLogPath);
+
// Hardcoded names for classes generated by GeneratedClassLoader
String descriptor = className + "." + methodPrefix + "0()V";
- output.shouldContain("ResolvedMethod entry added for " + descriptor);
- output.shouldContain("ResolvedMethod entry found for " + descriptor);
- output.shouldContain("ResolvedMethod entry removed");
- output.shouldHaveExitValue(0);
+ gcLogOutput.shouldContain("ResolvedMethod entry added for " + descriptor);
+ gcLogOutput.shouldContain("ResolvedMethod entry found for " + descriptor);
+ gcLogOutput.shouldContain("ResolvedMethod entry removed");
+
+ System.err.println("test(" + gc + ", " + doConcurrent + ")" + " done " + dateFormat.format(new Date()));
}
private static boolean supportsSTW(GC gc) {
--- a/test/hotspot/jtreg/runtime/Thread/MonitorCacheMaybeExpand_DeadLock.java Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4087516
- * @summary Incorrect locking leads to deadlock in monitorCacheMaybeExpand.
- * @author Anand Palaniswamy
- * @build MonitorCacheMaybeExpand_DeadLock
- * @run main/othervm MonitorCacheMaybeExpand_DeadLock
- */
-
-/**
- * Background on the bug:
- *
- * The thread local monitor cache had a locking bug (till
- * 1.2beta1) where two threads trying to expand the monitor cache
- * at the same time would cause deadlock. The code paths that the
- * two threads must be executing for this to happen is described
- * in the bug report.
- *
- * Caveat and red-flag:
- *
- * Since deadlocks are very timing dependent, there is a good
- * chance this test case will not catch the bug most of the time
- * -- on your machine and setting, it is _possible_ that the two
- * threads might not try a monitorCacheExpand at the same
- * time. But in practice, on Solaris native threads, this program
- * deadlocks the VM in about 2 seconds pretty consistently,
- * whether MP or not.
- *
- * The rationale for running this test despite this rather large
- * caveat is that at worst, it can do no harm.
- *
- * The idea:
- *
- * Is to create two monitor hungry threads.
- *
- * Originally Tom Rodriguez and I suspected that this weird state
- * of two threads trying to expand monitor cache can happen only
- * if:
- *
- * Thread 1: Is in the middle of a monitorCacheMaybeExpand.
- * Thread 2: Runs GC and tries to freeClasses(). This causes
- * sysFree() to be invoked, which in turn needs a
- * mutex_lock -- and oops, we end up deadlocking
- * with 1 on green_threads.
- *
- * Which is why this test tries to cause class GC at regular
- * intervals.
- *
- * Turns out that the GC is not required. Two instances of the
- * monitor hungry threads deadlock the VM pretty quick. :-) Infact
- * the static initializer in the forName'd classes running
- * alongside one of the hungry threads is sufficient to
- * deadlock. Still keep the GC stuff just-in-case (and also
- * because I wrote it :-).
- *
- */
-public class MonitorCacheMaybeExpand_DeadLock {
-
- /**
- * A monitor-hungry thread.
- */
- static class LotsaMonitors extends Thread {
-
- /** How many recursions? Could cause Java stack overflow. */
- static final int MAX_DEPTH = 800;
-
- /** What is our depth? */
- int depth = 0;
-
- /** Thread ID */
- int tid;
-
- /** So output will have thread number. */
- public LotsaMonitors(int tid, int depth) {
- super("LotsaMonitors #" + new Integer(tid).toString());
- this.tid = tid;
- this.depth = depth;
- }
-
- /** Start a recursion that grabs monitors. */
- public void run() {
- System.out.println(">>>Starting " + this.toString() + " ...");
- Thread.currentThread().yield();
- this.recurse();
- System.out.println("<<<Finished " + this.toString());
- }
-
- /** Every call to this method grabs an extra monitor. */
- synchronized void recurse() {
- if (this.depth > 0) {
- new LotsaMonitors(tid, depth-1).recurse();
- }
- }
- }
-
- /**
- * The test.
- */
- public static void main(String[] args) {
- /* Start the two of these crazy threads. */
- new LotsaMonitors(1, LotsaMonitors.MAX_DEPTH).start();
- new LotsaMonitors(2, LotsaMonitors.MAX_DEPTH).start();
-
- /* And sit there and GC for good measure. */
- for (int i = 0; i < MAX_GC_ITERATIONS; i++) {
- new LotsaMonitors(i+3, LotsaMonitors.MAX_DEPTH).start();
- System.out.println(">>>Loading 10 classes and gc'ing ...");
- Class[] classes = new Class[10];
- fillClasses(classes);
- classes = null;
- System.gc();
- Thread.currentThread().yield();
- System.out.println("<<<Finished loading 10 classes and gc'ing");
- }
- }
-
- /** How many times to GC? */
- static final int MAX_GC_ITERATIONS = 10;
-
- /** Load some classes into the array. */
- static void fillClasses(Class[] classes) {
- for (int i = 0; i < classes.length; i++) {
- try {
- classes[i] = Class.forName(classnames[i]);
- } catch (ClassNotFoundException cnfe) {
- cnfe.printStackTrace();
- }
- }
- }
-
- /** Some random classes to load. */
- private static String[] classnames = {
- "java.text.DecimalFormat",
- "java.text.MessageFormat",
- "java.util.GregorianCalendar",
- "java.util.ResourceBundle",
- "java.text.Collator",
- "java.util.Date",
- "java.io.Reader",
- "java.io.Writer",
- "java.lang.IllegalAccessException",
- "java.lang.InstantiationException",
- "java.lang.ClassNotFoundException",
- "java.lang.CloneNotSupportedException",
- "java.lang.InterruptedException",
- "java.lang.NoSuchFieldException",
- "java.lang.NoSuchMethodException",
- "java.lang.RuntimeException",
- "java.lang.ArithmeticException",
- "java.lang.ArrayStoreException",
- "java.lang.ClassCastException",
- "java.lang.StringIndexOutOfBoundsException",
- "java.lang.NegativeArraySizeException",
- "java.lang.IllegalStateException",
- "java.lang.IllegalArgumentException",
- "java.lang.NumberFormatException",
- "java.lang.IllegalThreadStateException",
- "java.lang.IllegalMonitorStateException",
- "java.lang.SecurityException",
- "java.lang.ExceptionInInitializerError"
- };
-
-}
--- a/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/Thread/TooSmallStackSize.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -187,12 +187,18 @@
checkMinStackAllowed("-XX:ThreadStackSize=", ThreadStackSizeString, "513");
/*
+ * Try with 0k which indicates that the default thread stack size from JVM will be used.
+ */
+ checkMinStackAllowed("-XX:ThreadStackSize=", ThreadStackSizeString, "0");
+
+ /*
* Now redo the same tests with the compiler thread stack size:
*/
checkStack("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "16");
min_stack_allowed = checkStack("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "64");
checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, min_stack_allowed);
checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "513");
+ checkMinStackAllowed("-XX:CompilerThreadStackSize=", CompilerThreadStackSizeString, "0");
/*
* Now redo the same tests with the VM thread stack size:
@@ -201,5 +207,6 @@
min_stack_allowed = checkStack("-XX:VMThreadStackSize=", VMThreadStackSizeString, "64");
checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, min_stack_allowed);
checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, "513");
+ checkMinStackAllowed("-XX:VMThreadStackSize=", VMThreadStackSizeString, "0");
}
}
--- a/test/hotspot/jtreg/runtime/appcds/OldClassTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/OldClassTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -24,7 +24,7 @@
/*
* @test
- * @summary classes with major version < JDK_1.5 (48) should not be included in CDS
+ * @summary classes with major version < JDK_6 (50) should not be included in CDS
* @requires vm.cds
* @library /test/lib
* @modules java.base/jdk.internal.org.objectweb.asm
@@ -61,9 +61,9 @@
String appClasses[] = TestCommon.list("Hello");
- // CASE 1: pre-JDK 1.5 compiled classes should be excluded from the dump
+ // CASE 1: pre-JDK 6 compiled classes should be excluded from the dump
OutputAnalyzer output = TestCommon.dump(jar, appClasses);
- TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS");
+ TestCommon.checkExecReturn(output, 0, true, "Pre JDK 6 class not supported by CDS");
TestCommon.run(
"-cp", jar,
@@ -74,7 +74,7 @@
// the newer version of this class in a subsequent classpath element.
String classpath = jar + File.pathSeparator + jarSrcFile.getPath();
output = TestCommon.dump(classpath, appClasses);
- TestCommon.checkExecReturn(output, 0, true, "Pre JDK 1.5 class not supported by CDS");
+ TestCommon.checkExecReturn(output, 0, true, "Pre JDK 6 class not supported by CDS");
TestCommon.run(
"-cp", classpath,
@@ -127,8 +127,7 @@
MethodVisitor mv;
AnnotationVisitor av0;
-//WAS cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
- cw.visit(V1_4, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
+ cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "Hello", null, "java/lang/Object", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
--- a/test/hotspot/jtreg/runtime/interpreter/WideStrictInline.java Fri Apr 19 07:55:28 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 4169183
- * @summary Check for correct inlining by the interpreter (widefp and strictfp).
- * The default is widefp. A strictfp method was getting inlined
- * into a widefp method.
- */
-
-import java.io.PrintStream;
-
-public class WideStrictInline {
- static PrintStream out;
- static float halfUlp;
-
- static {
- halfUlp = 1;
- for ( int i = 127 - 24; i > 0; i-- )
- halfUlp *= 2;
- }
-
- public static void main(String argv[]) throws Exception {
- out = System.err;
- pr(-1,"halfUlp",halfUlp);
- WideStrictInline obj = new WideStrictInline();
- for( int i=0; i<48; i++ )
- obj.instanceMethod( i );
- }
-
- private static void pr(int i, String desc, float r) {
- out.print(" i=("+i+") "+desc+" ; == "+r);
- out.println(" , 0x"+Integer.toHexString(Float.floatToIntBits(r)));
- }
-
- private static strictfp float WideStrictInline(float par) {
- return par;
- }
-
- public static strictfp float strictValue(int i) {
- float r;
- switch (i%4) {
- case 0: r = -Float.MAX_VALUE; break;
- case 1: r = Float.MAX_VALUE; break;
- case 2: r = Float.MIN_VALUE; break;
- default : r = 1L << 24;
- }
- return r;
- }
-
- void instanceMethod (int i) throws Exception {
- float r;
- switch (i%4) {
- case 0:
- if (!Float.isInfinite( WideStrictInline(strictValue(i)*2) +
- Float.MAX_VALUE ))
- {
- pr(i,
- "WideStrictInline(-Float.MAX_VALUE * 2) " +
- "!= Float.NEGATIVE_INFINITY"
- ,WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE);
- }
- r = WideStrictInline(strictValue(i)*2) + Float.MAX_VALUE;
- if ( !Float.isInfinite( r ) ) {
- pr(i,"r != Float.NEGATIVE_INFINITY",r);
- throw new RuntimeException();
- }
- break;
- case 1:
- if (!Float.isInfinite(WideStrictInline(strictValue(i)+halfUlp) -
- Float.MAX_VALUE )) {
- pr(i,"WideStrictInline(Float.MAX_VALUE+halfUlp) " +
- "!= Float.POSITIVE_INFINITY"
- ,WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE);
- }
- r = WideStrictInline(strictValue(i)+halfUlp) - Float.MAX_VALUE;
- if ( !Float.isInfinite( r ) ) {
- pr(i,"r != Float.POSITIVE_INFINITY",r);
- throw new RuntimeException();
- }
- break;
- case 2:
- if (WideStrictInline(strictValue(i)/2) != 0) {
- pr(i,"WideStrictInline(Float.MIN_VALUE/2) != 0",
- WideStrictInline(strictValue(i)/2));
- }
- r = WideStrictInline(strictValue(i)/2);
- if ( r != 0 ) {
- pr(i,"r != 0",r);
- throw new RuntimeException();
- }
- break;
- default:
- if (WideStrictInline(strictValue(i)-0.5f) - strictValue(i) != 0) {
- pr(i,"WideStrictInline(2^24-0.5) != 2^24",
- WideStrictInline(strictValue(i)-0.5f));
- }
- r = WideStrictInline(strictValue(i)-0.5f);
- if ( r - strictValue(i) != 0 ) {
- pr(i,"r != 2^24",r);
- throw new RuntimeException();
- }
- }
- }
-
-}
--- a/test/jaxp/javax/xml/jaxp/unittest/parsers/BaseParsingTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jaxp/javax/xml/jaxp/unittest/parsers/BaseParsingTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,19 +22,22 @@
*/
package parsers;
+import java.io.ByteArrayInputStream;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
+import static org.testng.Assert.assertEquals;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
+import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* @test
- * @bug 8169450
+ * @bug 8169450 8222415
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @run testng/othervm -DrunSecMngr=true parsers.BaseParsingTest
* @run testng/othervm parsers.BaseParsingTest
@@ -143,7 +146,7 @@
* @bug 8169450
* This particular issue does not appear in DOM parsing since the spaces are
* normalized during version detection. This test case then serves as a guard
- * against such an issue from occuring in the version detection.
+ * against such an issue from occurring in the version detection.
*
* @param xml the test xml
* @throws Exception if the parser fails to parse the xml
@@ -151,8 +154,24 @@
@Test(dataProvider = "xmlDeclarations")
public void testWithDOM(String xml) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setValidating(true);
DocumentBuilder db = dbf.newDocumentBuilder();
db.parse(new InputSource(new StringReader(xml)));
}
+
+ /**
+ * @bug 8222415
+ * Verifies that the parser is configured properly for UTF-16BE or LE.
+ * @throws Exception
+ */
+ @Test
+ public void testEncoding() throws Exception {
+ ByteArrayInputStream bis = new ByteArrayInputStream(
+ "<?xml version=\"1.0\" encoding=\"UTF-16\"?> <a/>".getBytes("UnicodeLittle"));
+ InputSource is = new InputSource(bis);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ Document doc = db.parse(is);
+ assertEquals("UTF-16LE", doc.getInputEncoding());
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/math/BigDecimal/IntValueExactTests.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8211936
+ * @summary Tests of BigDecimal.intValueExact
+ */
+import java.math.*;
+import java.util.List;
+import java.util.Map;
+import static java.util.Map.entry;
+
+public class IntValueExactTests {
+ public static void main(String... args) {
+ int failures = 0;
+
+ failures += intValueExactSuccessful();
+ failures += intValueExactExceptional();
+
+ if (failures > 0) {
+ throw new RuntimeException("Incurred " + failures +
+ " failures while testing intValueExact.");
+ }
+ }
+
+ private static int simpleIntValueExact(BigDecimal bd) {
+ return bd.toBigIntegerExact().intValue();
+ }
+
+ private static int intValueExactSuccessful() {
+ int failures = 0;
+
+ // Strings used to create BigDecimal instances on which invoking
+ // intValueExact() will succeed.
+ Map<BigDecimal, Integer> successCases =
+ Map.ofEntries(entry(new BigDecimal("2147483647"), Integer.MAX_VALUE), // 2^31 -1
+ entry(new BigDecimal("2147483647.0"), Integer.MAX_VALUE),
+ entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE),
+
+ entry(new BigDecimal("-2147483648"), Integer.MIN_VALUE), // -2^31
+ entry(new BigDecimal("-2147483648.0"), Integer.MIN_VALUE),
+ entry(new BigDecimal("-2147483648.00"),Integer.MIN_VALUE),
+
+ entry(new BigDecimal("1e0"), 1),
+ entry(new BigDecimal(BigInteger.ONE, -9), 1_000_000_000),
+
+ entry(new BigDecimal("0e13"), 0), // Fast path zero
+ entry(new BigDecimal("0e32"), 0),
+ entry(new BigDecimal("0e512"), 0),
+
+ entry(new BigDecimal("10.000000000000000000000000000000000"), 10));
+
+ for (var testCase : successCases.entrySet()) {
+ BigDecimal bd = testCase.getKey();
+ int expected = testCase.getValue();
+ try {
+ int intValueExact = bd.intValueExact();
+ if (expected != intValueExact ||
+ intValueExact != simpleIntValueExact(bd)) {
+ failures++;
+ System.err.println("Unexpected intValueExact result " + intValueExact +
+ " on " + bd);
+ }
+ } catch (Exception e) {
+ failures++;
+ System.err.println("Error on " + bd + "\tException message:" + e.getMessage());
+ }
+ }
+ return failures;
+ }
+
+ private static int intValueExactExceptional() {
+ int failures = 0;
+ List<BigDecimal> exceptionalCases =
+ List.of(new BigDecimal("2147483648"), // Integer.MAX_VALUE + 1
+ new BigDecimal("2147483648.0"),
+ new BigDecimal("2147483648.00"),
+ new BigDecimal("-2147483649"), // Integer.MIN_VALUE - 1
+ new BigDecimal("-2147483649.1"),
+ new BigDecimal("-2147483649.01"),
+
+ new BigDecimal("9999999999999999999999999999999"),
+ new BigDecimal("10000000000000000000000000000000"),
+
+ new BigDecimal("0.99"),
+ new BigDecimal("0.999999999999999999999"));
+
+ for (BigDecimal bd : exceptionalCases) {
+ try {
+ int intValueExact = bd.intValueExact();
+ failures++;
+ System.err.println("Unexpected non-exceptional intValueExact on " + bd);
+ } catch (ArithmeticException e) {
+ // Success;
+ }
+ }
+ return failures;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/math/BigDecimal/IntegralValueTests.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8211936
+ * @summary Tests of BigDecimal.intValue() and BigDecimal.longValue()
+ */
+import java.math.BigDecimal;
+import java.util.Map;
+
+public class IntegralValueTests {
+ public static void main(String... args) {
+ int failures =
+ integralValuesTest(INT_VALUES, true) +
+ integralValuesTest(LONG_VALUES, false);
+ if (failures != 0) {
+ throw new RuntimeException
+ ("Incurred " + failures + " failures for {int,long}Value().");
+ }
+ }
+
+ private static final Map<BigDecimal, Number> INT_VALUES =
+ Map.ofEntries(
+
+ // 2**31 - 1
+ Map.entry(new BigDecimal("2147483647"), Integer.MAX_VALUE),
+ Map.entry(new BigDecimal("2147483647.0"), Integer.MAX_VALUE),
+ Map.entry(new BigDecimal("2147483647.00"), Integer.MAX_VALUE),
+
+ Map.entry(new BigDecimal("-2147483647"), -Integer.MAX_VALUE),
+ Map.entry(new BigDecimal("-2147483647.0"), -Integer.MAX_VALUE),
+
+ // -2**31
+ Map.entry(new BigDecimal("-2147483648"), Integer.MIN_VALUE),
+ Map.entry(new BigDecimal("-2147483648.1"), Integer.MIN_VALUE),
+ Map.entry(new BigDecimal("-2147483648.01"), Integer.MIN_VALUE),
+
+ // -2**31 + 1 truncation to 2**31 - 1
+ Map.entry(new BigDecimal("-2147483649"), Integer.MAX_VALUE),
+
+ // 2**64 - 1 truncation to 1
+ Map.entry(new BigDecimal("4294967295"), -1),
+
+ // 2**64 truncation to 0
+ Map.entry(new BigDecimal("4294967296"), 0),
+
+ // Fast path truncation to 0
+ Map.entry(new BigDecimal("1e32"), 0),
+
+ // Slow path truncation to -2**31
+ Map.entry(new BigDecimal("1e31"), Integer.MIN_VALUE),
+
+ // Slow path
+ Map.entry(new BigDecimal("1e0"), 1),
+
+ // Fast path round to 0
+ Map.entry(new BigDecimal("9e-1"), 0),
+
+ // Some random values
+ Map.entry(new BigDecimal("900e-1"), 90), // Increasing negative exponents
+ Map.entry(new BigDecimal("900e-2"), 9),
+ Map.entry(new BigDecimal("900e-3"), 0),
+
+ // Fast path round to 0
+ Map.entry(new BigDecimal("123456789e-9"), 0),
+
+ // Slow path round to 1
+ Map.entry(new BigDecimal("123456789e-8"), 1),
+
+ // Increasing positive exponents
+ Map.entry(new BigDecimal("10000001e1"), 100000010),
+ Map.entry(new BigDecimal("10000001e10"), -1315576832),
+ Map.entry(new BigDecimal("10000001e100"), 0),
+ Map.entry(new BigDecimal("10000001e1000"), 0),
+ Map.entry(new BigDecimal("10000001e10000"), 0),
+ Map.entry(new BigDecimal("10000001e100000"), 0),
+ Map.entry(new BigDecimal("10000001e1000000"), 0),
+ Map.entry(new BigDecimal("10000001e10000000"), 0),
+ Map.entry(new BigDecimal("10000001e100000000"), 0),
+ Map.entry(new BigDecimal("10000001e1000000000"), 0),
+
+ // Increasing negative exponents
+ Map.entry(new BigDecimal("10000001e-1"), 1000000),
+ Map.entry(new BigDecimal("10000001e-10"), 0),
+ Map.entry(new BigDecimal("10000001e-100"), 0),
+ Map.entry(new BigDecimal("10000001e-1000"), 0),
+ Map.entry(new BigDecimal("10000001e-10000"), 0),
+ Map.entry(new BigDecimal("10000001e-100000"), 0),
+ Map.entry(new BigDecimal("10000001e-1000000"), 0),
+ Map.entry(new BigDecimal("10000001e-10000000"), 0),
+ Map.entry(new BigDecimal("10000001e-100000000"), 0),
+ Map.entry(new BigDecimal("10000001e-1000000000"), 0),
+
+ // Currency calculation to 4 places
+ Map.entry(new BigDecimal("12345.0001"), 12345),
+ Map.entry(new BigDecimal("12345.9999"), 12345),
+ Map.entry(new BigDecimal("-12345.0001"), -12345),
+ Map.entry(new BigDecimal("-12345.9999"), -12345));
+
+ private static final Map<BigDecimal, Number> LONG_VALUES =
+ Map.ofEntries(
+ // 2**63 - 1
+ Map.entry(new BigDecimal("9223372036854775807"), Long.MAX_VALUE),
+ Map.entry(new BigDecimal("9223372036854775807.0"), Long.MAX_VALUE),
+ Map.entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE),
+
+ // 2**63 truncation to -2**63
+ Map.entry(new BigDecimal("-9223372036854775808"), Long.MIN_VALUE),
+ Map.entry(new BigDecimal("-9223372036854775808.1"), Long.MIN_VALUE),
+ Map.entry(new BigDecimal("-9223372036854775808.01"), Long.MIN_VALUE),
+
+ // -2**63 + 1 truncation to 2**63 - 1
+ Map.entry(new BigDecimal("-9223372036854775809"), 9223372036854775807L),
+
+ // 2**64 - 1 truncation to -1
+ Map.entry(new BigDecimal("18446744073709551615"), -1L),
+
+ // 2**64 truncation to 0
+ Map.entry(new BigDecimal("18446744073709551616"), 0L),
+
+ // Slow path truncation to -2**63
+ Map.entry(new BigDecimal("1e63"), -9223372036854775808L),
+ Map.entry(new BigDecimal("-1e63"), -9223372036854775808L),
+ // Fast path with larger magnitude scale
+ Map.entry(new BigDecimal("1e64"), 0L),
+ Map.entry(new BigDecimal("-1e64"), 0L),
+ Map.entry(new BigDecimal("1e65"), 0L),
+ Map.entry(new BigDecimal("-1e65"), 0L),
+
+ // Slow path
+ Map.entry(new BigDecimal("1e0"), 1L),
+
+ // Fast path round to 0
+ Map.entry(new BigDecimal("9e-1"), 0L),
+
+ // Some random values
+ Map.entry(new BigDecimal("900e-1"), 90L), // Increasing negative exponents
+ Map.entry(new BigDecimal("900e-2"), 9L),
+ Map.entry(new BigDecimal("900e-3"), 0L),
+
+ // Fast path round to 0
+ Map.entry(new BigDecimal("123456789e-9"), 0L),
+
+ // Slow path round to 1
+ Map.entry(new BigDecimal("123456789e-8"), 1L),
+
+ // Increasing positive exponents
+ Map.entry(new BigDecimal("10000001e1"), 100000010L),
+ Map.entry(new BigDecimal("10000001e10"), 100000010000000000L),
+ Map.entry(new BigDecimal("10000001e100"), 0L),
+ Map.entry(new BigDecimal("10000001e1000"), 0L),
+ Map.entry(new BigDecimal("10000001e10000"), 0L),
+ Map.entry(new BigDecimal("10000001e100000"), 0L),
+ Map.entry(new BigDecimal("10000001e1000000"), 0L),
+ Map.entry(new BigDecimal("10000001e10000000"), 0L),
+ Map.entry(new BigDecimal("10000001e100000000"), 0L),
+ Map.entry(new BigDecimal("10000001e1000000000"), 0L),
+
+ // Increasing negative exponents
+ Map.entry(new BigDecimal("10000001e-1"), 1000000L),
+ Map.entry(new BigDecimal("10000001e-10"), 0L),
+ Map.entry(new BigDecimal("10000001e-100"), 0L),
+ Map.entry(new BigDecimal("10000001e-1000"), 0L),
+ Map.entry(new BigDecimal("10000001e-10000"), 0L),
+ Map.entry(new BigDecimal("10000001e-100000"), 0L),
+ Map.entry(new BigDecimal("10000001e-1000000"), 0L),
+ Map.entry(new BigDecimal("10000001e-10000000"), 0L),
+ Map.entry(new BigDecimal("10000001e-100000000"), 0L),
+ Map.entry(new BigDecimal("10000001e-1000000000"), 0L),
+
+ // Currency calculation to 4 places
+ Map.entry(new BigDecimal("12345.0001"), 12345L),
+ Map.entry(new BigDecimal("12345.9999"), 12345L),
+ Map.entry(new BigDecimal("-12345.0001"), -12345L),
+ Map.entry(new BigDecimal("-12345.9999"), -12345L));
+
+ private static int integralValuesTest(Map<BigDecimal, Number> v, boolean isInt) {
+ System.err.format("Testing %s%n", isInt ? "Integer" : "Long");
+ int failures = 0;
+ for (var testCase : v.entrySet()) {
+ BigDecimal bd = testCase.getKey();
+ Number expected = testCase.getValue();
+ try {
+ if (isInt) {
+ int intValue = bd.intValue();
+ if (intValue != (int)expected) {
+ failures += reportError(bd, expected, intValue, isInt);
+ }
+ } else {
+ long longValue = bd.longValue();
+ if (longValue != (long)expected) {
+ failures += reportError(bd, expected, longValue, isInt);
+ }
+ }
+ } catch (Exception e) {
+ failures++;
+ System.err.format("Unexpected exception %s for %s%n",
+ e, bd.toString());
+ }
+ }
+ return failures;
+ }
+
+ private static int reportError(BigDecimal bd, Number expected, long longValue, boolean isInt) {
+ System.err.format("For %s, scale=%d, expected %d, actual %d, simple %d%n",
+ bd.toString(), bd.scale(),
+ (isInt ? (Integer) expected : (Long) expected ),
+ longValue,
+ (isInt ? simpleIntValue(bd): simpleLongValue(bd) ));
+ return 1;
+ }
+
+ private static long simpleLongValue(BigDecimal bd) {
+ return bd.toBigInteger().longValue();
+ }
+
+ private static int simpleIntValue(BigDecimal bd) {
+ return bd.toBigInteger().intValue();
+ }
+}
--- a/test/jdk/java/math/BigDecimal/LongValueExactTests.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/math/BigDecimal/LongValueExactTests.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,65 +23,98 @@
/**
* @test
- * @bug 6806261
+ * @bug 6806261 8211936
* @summary Tests of BigDecimal.longValueExact
*/
import java.math.*;
+import java.util.List;
+import java.util.Map;
+import static java.util.Map.entry;
public class LongValueExactTests {
+ public static void main(String... args) {
+ int failures = 0;
- private static int longValueExactTests() {
+ failures += longValueExactSuccessful();
+ failures += longValueExactExceptional();
+
+ if (failures > 0) {
+ throw new RuntimeException("Incurred " + failures +
+ " failures while testing longValueExact.");
+ }
+ }
+
+ private static long simpleLongValueExact(BigDecimal bd) {
+ return bd.toBigIntegerExact().longValue();
+ }
+
+ private static int longValueExactSuccessful() {
int failures = 0;
- String[] testStrings = {
- "9223372036854775807",
- "9223372036854775807.0",
- "9223372036854775807.00",
- "-9223372036854775808",
- "-9223372036854775808.0",
- "-9223372036854775808.00",
- };
+ // Strings used to create BigDecimal instances on which invoking
+ // longValueExact() will succeed.
+ Map<BigDecimal, Long> successCases =
+ Map.ofEntries(entry(new BigDecimal("9223372036854775807"), Long.MAX_VALUE), // 2^63 -1
+ entry(new BigDecimal("9223372036854775807.0"), Long.MAX_VALUE),
+ entry(new BigDecimal("9223372036854775807.00"), Long.MAX_VALUE),
+
+ entry(new BigDecimal("-9223372036854775808"), Long.MIN_VALUE), // -2^63
+ entry(new BigDecimal("-9223372036854775808.0"), Long.MIN_VALUE),
+ entry(new BigDecimal("-9223372036854775808.00"),Long.MIN_VALUE),
+
+ entry(new BigDecimal("1e0"), 1L),
+ entry(new BigDecimal(BigInteger.ONE, -18), 1_000_000_000_000_000_000L),
- for (String longValue : testStrings) {
+ entry(new BigDecimal("0e13"), 0L), // Fast path zero
+ entry(new BigDecimal("0e64"), 0L),
+ entry(new BigDecimal("0e1024"), 0L),
+
+ entry(new BigDecimal("10.000000000000000000000000000000000"), 10L));
+
+ for (var testCase : successCases.entrySet()) {
+ BigDecimal bd = testCase.getKey();
+ long expected = testCase.getValue();
try {
- BigDecimal bd = new BigDecimal(longValue);
long longValueExact = bd.longValueExact();
+ if (expected != longValueExact ||
+ longValueExact != simpleLongValueExact(bd)) {
+ failures++;
+ System.err.println("Unexpected longValueExact result " + longValueExact +
+ " on " + bd);
+ }
} catch (Exception e) {
failures++;
+ System.err.println("Error on " + bd + "\tException message:" + e.getMessage());
}
}
+ return failures;
+ }
- // The following Strings are supposed to make longValueExact throw
- // ArithmeticException.
- String[] testStrings2 = {
- "9223372036854775808",
- "9223372036854775808.0",
- "9223372036854775808.00",
- "-9223372036854775809",
- "-9223372036854775808.1",
- "-9223372036854775808.01",
- };
+ private static int longValueExactExceptional() {
+ int failures = 0;
+ List<BigDecimal> exceptionalCases =
+ List.of(new BigDecimal("9223372036854775808"), // Long.MAX_VALUE + 1
+ new BigDecimal("9223372036854775808.0"),
+ new BigDecimal("9223372036854775808.00"),
+ new BigDecimal("-9223372036854775809"), // Long.MIN_VALUE - 1
+ new BigDecimal("-9223372036854775808.1"),
+ new BigDecimal("-9223372036854775808.01"),
- for (String bigValue : testStrings2) {
+ new BigDecimal("9999999999999999999"),
+ new BigDecimal("10000000000000000000"),
+
+ new BigDecimal("0.99"),
+ new BigDecimal("0.999999999999999999999"));
+
+ for (BigDecimal bd : exceptionalCases) {
try {
- BigDecimal bd = new BigDecimal(bigValue);
long longValueExact = bd.longValueExact();
failures++;
+ System.err.println("Unexpected non-exceptional longValueExact on " + bd);
} catch (ArithmeticException e) {
// Success;
}
}
return failures;
}
-
- public static void main(String argv[]) {
- int failures = 0;
-
- failures += longValueExactTests();
-
- if (failures > 0) {
- throw new RuntimeException("Incurred " + failures +
- " failures while testing longValueExact.");
- }
- }
}
--- a/test/jdk/java/net/httpclient/DigestEchoServer.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/net/httpclient/DigestEchoServer.java Fri Apr 19 08:00:42 2019 -0400
@@ -80,6 +80,8 @@
Boolean.parseBoolean(System.getProperty("test.debug", "false"));
public static final boolean NO_LINGER =
Boolean.parseBoolean(System.getProperty("test.nolinger", "false"));
+ public static final boolean TUNNEL_REQUIRES_HOST =
+ Boolean.parseBoolean(System.getProperty("test.requiresHost", "false"));
public enum HttpAuthType {
SERVER, PROXY, SERVER307, PROXY305
/* add PROXY_AND_SERVER and SERVER_PROXY_NONE */
@@ -1522,6 +1524,36 @@
}
}
+ boolean badRequest(StringBuilder response, String hostport, List<String> hosts) {
+ String message = null;
+ if (hosts.isEmpty()) {
+ message = "No host header provided\r\n";
+ } else if (hosts.size() > 1) {
+ message = "Multiple host headers provided\r\n";
+ for (String h : hosts) {
+ message = message + "host: " + h + "\r\n";
+ }
+ } else {
+ String h = hosts.get(0);
+ if (!hostport.equalsIgnoreCase(h)
+ && !hostport.equalsIgnoreCase(h + ":80")
+ && !hostport.equalsIgnoreCase(h + ":443")) {
+ message = "Bad host provided: [" + h
+ + "] doesnot match [" + hostport + "]\r\n";
+ }
+ }
+ if (message != null) {
+ int length = message.getBytes(StandardCharsets.UTF_8).length;
+ response.append("HTTP/1.1 400 BadRequest\r\n")
+ .append("Content-Length: " + length)
+ .append("\r\n\r\n")
+ .append(message);
+ return true;
+ }
+
+ return false;
+ }
+
boolean authorize(StringBuilder response, String requestLine, String headers) {
if (authorization != null) {
return authorization.authorize(response, requestLine, headers);
@@ -1635,6 +1667,7 @@
assert connect.equalsIgnoreCase("connect");
String hostport = tokenizer.nextToken();
InetSocketAddress targetAddress;
+ List<String> hosts = new ArrayList<>();
try {
URI uri = new URI("https", hostport, "/", null, null);
int port = uri.getPort();
@@ -1659,9 +1692,30 @@
System.out.println(now() + "Tunnel: Reading header: "
+ (line = readLine(ccis)));
headers.append(line).append("\r\n");
+ int index = line.indexOf(':');
+ if (index >= 0) {
+ String key = line.substring(0, index).trim();
+ if (key.equalsIgnoreCase("host")) {
+ hosts.add(line.substring(index+1).trim());
+ }
+ }
+ }
+ StringBuilder response = new StringBuilder();
+ if (TUNNEL_REQUIRES_HOST) {
+ if (badRequest(response, hostport, hosts)) {
+ System.out.println(now() + "Tunnel: Sending " + response);
+ // send the 400 response
+ pw.print(response.toString());
+ pw.flush();
+ toClose.close();
+ continue;
+ } else {
+ assert hosts.size() == 1;
+ System.out.println(now()
+ + "Tunnel: Host header verified " + hosts);
+ }
}
- StringBuilder response = new StringBuilder();
final boolean authorize = authorize(response, requestLine, headers.toString());
if (!authorize) {
System.out.println(now() + "Tunnel: Sending "
--- a/test/jdk/java/net/httpclient/HttpsTunnelTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/net/httpclient/HttpsTunnelTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,8 +47,9 @@
* proxy P is downgraded to HTTP/1.1, then a new h2 request
* going to a different host through the same proxy will not
* be preemptively downgraded. That, is the stack should attempt
- * a new h2 connection to the new host.
- * @bug 8196967
+ * a new h2 connection to the new host. It also verifies that
+ * the stack sends the appropriate "host" header to the proxy.
+ * @bug 8196967 8222527
* @library /test/lib http2/server
* @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters DigestEchoServer HttpsTunnelTest
* @modules java.net.http/jdk.internal.net.http.common
@@ -58,7 +59,14 @@
* java.base/sun.net.www.http
* java.base/sun.net.www
* java.base/sun.net
- * @run main/othervm -Djdk.internal.httpclient.debug=true HttpsTunnelTest
+ * @run main/othervm -Dtest.requiresHost=true
+ * -Djdk.httpclient.HttpClient.log=headers
+ * -Djdk.internal.httpclient.debug=true HttpsTunnelTest
+ * @run main/othervm -Dtest.requiresHost=true
+ * -Djdk.httpclient.allowRestrictedHeaders=host
+ * -Djdk.httpclient.HttpClient.log=headers
+ * -Djdk.internal.httpclient.debug=true HttpsTunnelTest
+ *
*/
public class HttpsTunnelTest implements HttpServerAdapters {
@@ -116,6 +124,18 @@
try {
URI uri1 = new URI("https://" + http1Server.serverAuthority() + "/foo/https1");
URI uri2 = new URI("https://" + http2Server.serverAuthority() + "/foo/https2");
+
+ boolean provideCustomHost = "host".equalsIgnoreCase(
+ System.getProperty("jdk.httpclient.allowRestrictedHeaders",""));
+
+ String customHttp1Host = null, customHttp2Host = null;
+ if (provideCustomHost) {
+ customHttp1Host = makeCustomHostString(http1Server, uri1);
+ out.println("HTTP/1.1: <" + uri1 + "> [custom host: " + customHttp1Host + "]");
+ customHttp2Host = makeCustomHostString(http2Server, uri2);
+ out.println("HTTP/2: <" + uri2 + "> [custom host: " + customHttp2Host + "]");
+ }
+
ProxySelector ps = ProxySelector.of(proxy.getProxyAddress());
//HttpClient.Builder.NO_PROXY;
HttpsTunnelTest test = new HttpsTunnelTest();
@@ -126,11 +146,12 @@
assert lines.size() == data.length;
String body = lines.stream().collect(Collectors.joining("\r\n"));
HttpRequest.BodyPublisher reqBody = HttpRequest.BodyPublishers.ofString(body);
- HttpRequest req1 = HttpRequest
+ HttpRequest.Builder req1Builder = HttpRequest
.newBuilder(uri1)
.version(Version.HTTP_2)
- .POST(reqBody)
- .build();
+ .POST(reqBody);
+ if (provideCustomHost) req1Builder.header("host", customHttp1Host);
+ HttpRequest req1 = req1Builder.build();
out.println("\nPosting to HTTP/1.1 server at: " + req1);
HttpResponse<Stream<String>> response = client.send(req1, BodyHandlers.ofLines());
out.println("Checking response...");
@@ -145,12 +166,14 @@
if (!lines.equals(respLines)) {
throw new RuntimeException("Unexpected response 1: " + respLines);
}
+
HttpRequest.BodyPublisher reqBody2 = HttpRequest.BodyPublishers.ofString(body);
- HttpRequest req2 = HttpRequest
+ HttpRequest.Builder req2Builder = HttpRequest
.newBuilder(uri2)
.version(Version.HTTP_2)
- .POST(reqBody2)
- .build();
+ .POST(reqBody2);
+ if (provideCustomHost) req2Builder.header("host", customHttp2Host);
+ HttpRequest req2 = req2Builder.build();
out.println("\nPosting to HTTP/2 server at: " + req2);
response = client.send(req2, BodyHandlers.ofLines());
out.println("Checking response...");
@@ -176,4 +199,26 @@
}
}
+ /**
+ * Builds a custom host string that is different to what is in the URI
+ * authority, that is textually different than what the stack would
+ * send. For CONNECT we should ignore any custom host settings.
+ * The tunnelling proxy will fail with badRequest 400 if it receives
+ * the custom host instead of the expected URI authority string.
+ * @param server The target server.
+ * @param uri The URI to the target server
+ * @return a host value for the custom host header.
+ */
+ static final String makeCustomHostString(HttpTestServer server, URI uri) {
+ String customHttpHost;
+ if (server.serverAuthority().contains("localhost")) {
+ customHttpHost = InetAddress.getLoopbackAddress().getHostAddress();
+ } else {
+ customHttpHost = InetAddress.getLoopbackAddress().getHostName();
+ }
+ if (customHttpHost.contains(":")) customHttpHost = "[" + customHttpHost + "]";
+ if (uri.getPort() != -1) customHttpHost = customHttpHost + ":" + uri.getPort();
+ return customHttpHost;
+ }
+
}
--- a/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/net/httpclient/ProxyAuthDisabledSchemesSSL.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8087112
+ * @bug 8087112 8222527
* @summary this test verifies that a client may provides authorization
* headers directly when connecting with a server over SSL, and
* it verifies that the client honor the jdk.http.auth.*.disabledSchemes
@@ -45,10 +45,12 @@
* @run main/othervm/timeout=300
* -Djdk.http.auth.proxying.disabledSchemes=Basic
* -Djdk.http.auth.tunneling.disabledSchemes=Basic
+ * -Dtest.requiresHost=true
* ProxyAuthDisabledSchemesSSL SSL PROXY
* @run main/othervm/timeout=300
* -Djdk.http.auth.proxying.disabledSchemes=Digest
* -Djdk.http.auth.tunneling.disabledSchemes=Digest
+ * -Dtest.requiresHost=true
* ProxyAuthDisabledSchemesSSL SSL PROXY
*/
--- a/test/jdk/java/nio/channels/Channels/Basic.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/nio/channels/Channels/Basic.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4417152 4481572 6248930 6725399 6884800
+ * @bug 4417152 4481572 6248930 6725399 6884800 8220477
* @summary Test Channels basic functionality
*/
@@ -31,7 +31,6 @@
import java.nio.charset.*;
import java.nio.channels.*;
-
public class Basic {
static String message;
@@ -204,6 +203,8 @@
writeOut(blah, ITERATIONS);
testNewReader(blah);
+ testNewWriterClose();
+ testNewReaderClose();
} finally {
blah.delete();
}
@@ -399,6 +400,98 @@
r.close();
fis.close();
}
+
+ private static void testNewWriterClose() throws Exception {
+ Writer writer = null;
+ try {
+ WritableByteChannel channel = new WritableByteChannel() {
+ @Override
+ public int write(ByteBuffer src) throws IOException {
+ return 0;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return true;
+ }
+
+ @Override
+ public void close() throws IOException {
+ throw new IOException();
+ }
+ };
+ writer = Channels.newWriter(channel,
+ StandardCharsets.UTF_8.newEncoder(), -1);
+ writer.close();
+ } catch (IOException ioe) {
+ Exception theException = null;
+ try {
+ writer.write(1);
+ writer.flush();
+ } catch (Exception e) {
+ theException = e;
+ } finally {
+ if (theException == null) {
+ throw new RuntimeException("IOException not thrown");
+ } else if (!(theException instanceof IOException)) {
+ throw new RuntimeException("Exception not an IOException: "
+ + theException);
+ } else {
+ String message = theException.getMessage();
+ if (!message.equals("Stream closed")) {
+ throw new RuntimeException("Unexpected message "
+ + message);
+ }
+ }
+ }
+ }
+ }
+
+ private static void testNewReaderClose() throws Exception {
+ Reader reader = null;
+ try {
+ ReadableByteChannel channel = new ReadableByteChannel() {
+ @Override
+ public int read(ByteBuffer dst) throws IOException {
+ dst.put((byte)7);
+ return 1;
+ }
+
+ @Override
+ public boolean isOpen() {
+ return true;
+ }
+
+ @Override
+ public void close() throws IOException {
+ throw new IOException();
+ }
+ };
+ reader = Channels.newReader(channel,
+ StandardCharsets.UTF_8.newDecoder(), -1);
+ reader.close();
+ } catch (IOException ioe) {
+ Exception theException = null;
+ try {
+ reader.read();
+ } catch (Exception e) {
+ theException = e;
+ } finally {
+ if (theException == null) {
+ throw new RuntimeException("IOException not thrown");
+ } else if (!(theException instanceof IOException)) {
+ throw new RuntimeException("Exception not an IOException: "
+ + theException);
+ } else {
+ String message = theException.getMessage();
+ if (!message.equals("Stream closed")) {
+ throw new RuntimeException("Unexpected message "
+ + message);
+ }
+ }
+ }
+ }
+ }
}
class ExtendedFileInputStream extends java.io.FileInputStream {
--- a/test/jdk/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/java/nio/file/attribute/BasicFileAttributeView/UnixSocketFile.java Fri Apr 19 08:00:42 2019 -0400
@@ -61,6 +61,14 @@
return;
}
+ // Verify that 'nc' accepts '-U' for Unix domain sockets.
+ // Skip the test if it is not.
+ Process procHelp = Runtime.getRuntime().exec(CMD_BASE + " -h");
+ if (procHelp.waitFor() != 0) {
+ System.err.println("Netcat does not accept required options; skipping test.");
+ return;
+ }
+
// Create a new sub-directory of the nominal test directory in which
// 'nc' will create the socket file.
String testSubDir = System.getProperty("test.dir", ".")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/rmi/registry/nonLocalRegistry/NonLocalSkeletonTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.rmi.server.UnicastRef;
+import sun.rmi.transport.LiveRef;
+import sun.rmi.transport.tcp.TCPEndpoint;
+
+import java.lang.reflect.InvocationHandler;
+
+import java.lang.reflect.Proxy;
+import java.net.InetAddress;
+import java.rmi.AccessException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.ObjID;
+import java.rmi.server.RemoteObjectInvocationHandler;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Set;
+
+
+/* @test
+ * @bug 8218453
+ * @library ../../testlibrary
+ * @modules java.rmi/sun.rmi.registry:+open java.rmi/sun.rmi.server:+open
+ * java.rmi/sun.rmi.transport:+open java.rmi/sun.rmi.transport.tcp:+open
+ * @summary Verify that Registry rejects non-local access for bind, unbind, rebind.
+ * The test is manual because the (non-local) host running rmiregistry must be supplied as a property.
+ * @run main/othervm -Dregistry.host=localhost NonLocalSkeletonTest
+ */
+
+/*
+ * @test
+ * @library ../../testlibrary
+ * @modules java.rmi/sun.rmi.registry:+open java.rmi/sun.rmi.server:+open
+ * java.rmi/sun.rmi.transport:+open java.rmi/sun.rmi.transport.tcp:+open
+ * @summary Verify that Registry rejects non-local access for bind, unbind, rebind.
+ * The test is manual because the (non-local) host running rmiregistry must be supplied as a property.
+ * @run main/othervm/manual -Dregistry.host=rmi-registry-host NonLocalSkeletonTest
+ */
+
+/**
+ * Verify that access checks for Registry.bind(), .rebind(), and .unbind()
+ * are prevented on remote access to the registry.
+ *
+ * This test is a manual test and uses a standard rmiregistry running
+ * on a *different* host.
+ * The test verifies that the access check is performed *before* the object to be
+ * bound or rebound is deserialized.
+ *
+ * Login or ssh to the different host and invoke {@code $JDK_HOME/bin/rmiregistry}.
+ * It will not show any output.
+ *
+ * On the first host modify the @run command above to replace "rmi-registry-host"
+ * with the hostname or IP address of the different host and run the test with jtreg.
+ */
+public class NonLocalSkeletonTest {
+
+ public static void main(String[] args) throws Exception {
+ String host = System.getProperty("registry.host");
+ if (host == null || host.isEmpty()) {
+ throw new RuntimeException("supply a remote host with -Dregistry.host=hostname");
+ }
+
+ // Check if running the test on a local system; it only applies to remote
+ String myHostName = InetAddress.getLocalHost().getHostName();
+ Set<InetAddress> myAddrs = Set.of(InetAddress.getAllByName(myHostName));
+ Set<InetAddress> hostAddrs = Set.of(InetAddress.getAllByName(host));
+ boolean isLocal = (hostAddrs.stream().anyMatch(i -> myAddrs.contains(i))
+ || hostAddrs.stream().anyMatch(h -> h.isLoopbackAddress()));
+
+ int port;
+ if (isLocal) {
+ // Create a local Registry to use for the test
+ port = TestLibrary.getUnusedRandomPort();
+ Registry registry = LocateRegistry.createRegistry(port);
+ System.out.printf("local registry port: %s%n", registry);
+ } else {
+ // Use regular rmi registry for non-local test
+ port = Registry.REGISTRY_PORT;
+ }
+
+ try {
+
+ Registry r = nonStaticRegistryProxy(host, port);
+
+ System.out.printf("RegistryRef: %s%n", r);
+
+ r.rebind("anyRef", r);
+ if (!isLocal) {
+ throw new RuntimeException("non-local bind should have failed to host: " + host);
+ } else {
+ System.out.printf("local rebind succeeded%n");
+ }
+ } catch (RemoteException rex) {
+ if (!isLocal) {
+ assertIsAccessException(rex);
+ } else {
+ throw rex;
+ }
+ }
+ }
+
+ /* Returns a non-static proxy for the registry.
+ * Follows the form of sun.rmi.server.Util.createProxy.
+ * @param implClass the RegistryImpl
+ * @param clientRef the registry reference
+ **/
+ static Registry nonStaticRegistryProxy(String host, int port) {
+ final ClassLoader loader = Registry.class.getClassLoader();
+ final Class<?>[] interfaces = new Class<?>[]{Registry.class};
+
+ LiveRef liveRef = new LiveRef(new ObjID(ObjID.REGISTRY_ID),
+ new TCPEndpoint(host, port, null, null),
+ false);
+
+ final InvocationHandler handler = new RemoteObjectInvocationHandler(new UnicastRef(liveRef));
+
+ PrivilegedAction<Registry> action = () -> (Registry) Proxy.newProxyInstance(loader,
+ interfaces, handler);
+ return AccessController.doPrivileged(action);
+ }
+
+ /**
+ * Check the exception chain for the expected AccessException and message.
+ * @param ex the exception from the remote invocation.
+ */
+ private static void assertIsAccessException(Throwable ex) {
+ Throwable t = ex;
+ while (!(t instanceof AccessException) && t.getCause() != null) {
+ t = t.getCause();
+ }
+ if (t instanceof AccessException) {
+ String msg = t.getMessage();
+ int asIndex = msg.indexOf("Registry");
+ int rrIndex = msg.indexOf("Registry.Registry"); // Obsolete error text
+ int disallowIndex = msg.indexOf("disallowed");
+ int nonLocalHostIndex = msg.indexOf("non-local host");
+ if (asIndex < 0 ||
+ rrIndex != -1 ||
+ disallowIndex < 0 ||
+ nonLocalHostIndex < 0 ) {
+ throw new RuntimeException("exception message is malformed", t);
+ }
+ System.out.printf("Found expected AccessException: %s%n%n", t);
+ } else {
+ throw new RuntimeException("AccessException did not occur when expected", ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/SSLSocket/InputStreamClosure.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+//
+// Please run in othervm mode. SunJSSE does not support dynamic system
+// properties, no way to re-use system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8216326
+ * @modules jdk.crypto.ec
+ * @library /javax/net/ssl/templates
+ * @summary SSLSocket stream close() does not close the associated socket
+ * @run main/othervm InputStreamClosure
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.net.ssl.SSLSocket;
+
+public class InputStreamClosure extends SSLSocketTemplate {
+
+ // Run the test case.
+ public static void main(String[] args) throws Exception {
+ (new InputStreamClosure()).run();
+ }
+
+ @Override
+ protected void runServerApplication(SSLSocket socket) throws Exception {
+ // here comes the test logic
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ }
+
+ /*
+ * Define the client side application of the test for the specified socket.
+ * This method is used if the returned value of
+ * isCustomizedClientConnection() is false.
+ *
+ * @param socket may be null is no client socket is generated.
+ *
+ * @see #isCustomizedClientConnection()
+ */
+ protected void runClientApplication(SSLSocket socket) throws Exception {
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ sslIS.close();
+ if (!socket.isClosed()) {
+ throw new Exception("Closing the SSLSocket InputStream does " +
+ "not close the associated socket");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/SSLSocket/OutputStreamClosure.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * 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.
+ */
+
+//
+// Please run in othervm mode. SunJSSE does not support dynamic system
+// properties, no way to re-use system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8216326
+ * @modules jdk.crypto.ec
+ * @library /javax/net/ssl/templates
+ * @summary SSLSocket stream close() does not close the associated socket
+ * @run main/othervm OutputStreamClosure
+ */
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.net.ssl.SSLSocket;
+
+public class OutputStreamClosure extends SSLSocketTemplate {
+
+ // Run the test case.
+ public static void main(String[] args) throws Exception {
+ (new OutputStreamClosure()).run();
+ }
+
+ @Override
+ protected void runServerApplication(SSLSocket socket) throws Exception {
+ // here comes the test logic
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+ }
+
+ /*
+ * Define the client side application of the test for the specified socket.
+ * This method is used if the returned value of
+ * isCustomizedClientConnection() is false.
+ *
+ * @param socket may be null is no client socket is generated.
+ *
+ * @see #isCustomizedClientConnection()
+ */
+ protected void runClientApplication(SSLSocket socket) throws Exception {
+ InputStream sslIS = socket.getInputStream();
+ OutputStream sslOS = socket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ sslOS.close();
+ if (!socket.isClosed()) {
+ throw new Exception("Closing the SSLSocket OutputStream does " +
+ "not close the associated socket");
+ }
+ }
+}
--- a/test/jdk/tools/launcher/Settings.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/tools/launcher/Settings.java Fri Apr 19 08:00:42 2019 -0400
@@ -68,6 +68,7 @@
private static final String PROP_SETTINGS = "Property settings:";
private static final String LOCALE_SETTINGS = "Locale settings:";
private static final String SYSTEM_SETTINGS = "Operating System Metrics:";
+ private static final String STACKSIZE_SETTINGS = "Stack Size:";
static void containsAllOptions(TestResult tr) {
checkContains(tr, VM_SETTINGS);
@@ -82,10 +83,22 @@
int stackSize = 256; // in kb
if (getArch().equals("ppc64") || getArch().equals("ppc64le")) {
stackSize = 800;
+ } else if (getArch().equals("aarch64")) {
+ /*
+ * The max value of minimum stack size allowed for aarch64 can be estimated as
+ * such: suppose the vm page size is 64KB and the test runs with a debug build,
+ * the initial _java_thread_min_stack_allowed defined in os_linux_aarch64.cpp is
+ * 72K, stack guard zones could take 192KB, and the shadow zone needs 128KB,
+ * after aligning up all parts to the page size, the final size would be 448KB.
+ * See details in JDK-8163363
+ */
+ stackSize = 448;
}
TestResult tr;
tr = doExec(javaCmd, "-Xms64m", "-Xmx512m",
"-Xss" + stackSize + "k", "-XshowSettings", "-jar", testJar.getAbsolutePath());
+ // Check the stack size logs printed by -XshowSettings to verify -Xss meaningfully.
+ checkContains(tr, STACKSIZE_SETTINGS);
containsAllOptions(tr);
if (!tr.isOK()) {
System.out.println(tr);
@@ -93,6 +106,7 @@
}
tr = doExec(javaCmd, "-Xms65536k", "-Xmx712m",
"-Xss" + (stackSize * 1024), "-XshowSettings", "-jar", testJar.getAbsolutePath());
+ checkContains(tr, STACKSIZE_SETTINGS);
containsAllOptions(tr);
if (!tr.isOK()) {
System.out.println(tr);
--- a/test/jdk/tools/launcher/TooSmallStackSize.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/jdk/tools/launcher/TooSmallStackSize.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 6762191
+ * @bug 6762191 8222334
* @summary Setting stack size to 16K causes segmentation fault
* @compile TooSmallStackSize.java
* @run main TooSmallStackSize
@@ -171,5 +171,11 @@
* asserts added for 8176768 are not triggered.
*/
checkMinStackAllowed("513k");
+
+ /*
+ * Try with 0k which indicates that the default thread stack size either from JVM or system
+ * will be used, this should always succeed.
+ */
+ checkMinStackAllowed("0k");
}
}
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/AnnotatedExtendsTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -59,7 +59,7 @@
.classes(classPath.toString())
.run()
.getOutput(Task.OutputKind.DIRECT);
- if (!javapOut.contains("0: #21(): CLASS_EXTENDS, type_index=65535"))
+ if (!javapOut.contains("0: #22(): CLASS_EXTENDS, type_index=65535"))
throw new AssertionError("Expected output missing: " + javapOut);
}
}
\ No newline at end of file
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/BridgeShouldHaveNoInteriorAnnotationsTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -74,14 +74,14 @@
// Expected output can't be directly encoded into NestedLambdasCastedTest !!!
static class OutputExpectedOnceHolder {
public String[] outputs = {
- "0: #61(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
- "1: #61(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
+ "0: #120(): CAST, offset=1, type_index=0, location=[TYPE_ARGUMENT(0)]",
+ "1: #120(): LOCAL_VARIABLE, {start_pc=5, length=2, index=1}, location=[TYPE_ARGUMENT(0)]",
};
}
static class OutputExpectedTwiceHolder {
public String[] outputs = {
- "0: #61(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
+ "0: #120(): METHOD_RETURN, location=[TYPE_ARGUMENT(0)]",
};
}
--- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/NestedLambdasCastedTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -53,10 +53,10 @@
"private static strictfp void lambda$main$2();",
"private static strictfp void lambda$main$1();",
"private static strictfp void lambda$main$0();",
- "0: #62(#63=s#64): CAST, offset=5, type_index=0",
- "0: #62(#63=s#69): CAST, offset=5, type_index=0",
- "0: #62(#63=s#72): CAST, offset=5, type_index=0",
- "0: #62(#63=s#75): CAST, offset=5, type_index=0"
+ "0: #111(#112=s#113): CAST, offset=5, type_index=0",
+ "0: #111(#112=s#119): CAST, offset=5, type_index=0",
+ "0: #111(#112=s#122): CAST, offset=5, type_index=0",
+ "0: #111(#112=s#125): CAST, offset=5, type_index=0"
};
}
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt Fri Apr 19 08:00:42 2019 -0400
@@ -46,6 +46,7 @@
compiler.misc.bad.class.signature # bad class file
compiler.misc.bad.const.pool.tag # bad class file
compiler.misc.bad.const.pool.tag.at # bad class file
+compiler.misc.bad.const.pool.index # bad class file
compiler.misc.bad.constant.range # bad class file
compiler.misc.bad.constant.value # bad class file
compiler.misc.bad.enclosing.class # bad class file
--- a/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/lambda/TestBootstrapMethodsCount.java Fri Apr 19 08:00:42 2019 -0400
@@ -61,6 +61,7 @@
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCIdent;
@@ -190,7 +191,7 @@
Symbol oldSym = ident.sym;
if (!oldSym.isConstructor()) {
ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
- oldSym.owner, REF_invokeStatic, bsm, oldSym.type, new Object[0]);
+ oldSym.owner, bsm.asHandle(), oldSym.type, new LoadableConstant[0]);
}
return null;
}
--- a/test/langtools/tools/javac/lambda/TestInvokeDynamic.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/lambda/TestInvokeDynamic.java Fri Apr 19 08:00:42 2019 -0400
@@ -60,26 +60,23 @@
import com.sun.tools.classfile.LineNumberTable_attribute;
import com.sun.tools.classfile.Method;
-import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.MethodHandleSymbol;
import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type.ClassType;
+import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.code.Types;
-import com.sun.tools.javac.jvm.Pool;
+import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCIdent;
-import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Names;
import combo.ComboParameter;
-import combo.ComboTask;
import combo.ComboTestHelper;
import combo.ComboInstance;
import combo.ComboTask.Result;
-import static com.sun.tools.javac.jvm.ClassFile.*;
-
public class TestInvokeDynamic extends ComboInstance<TestInvokeDynamic> {
enum StaticArgumentKind implements ComboParameter {
@@ -168,21 +165,24 @@
abstract boolean check(CPInfo cpInfo) throws Exception;
- Object getValue(Symtab syms, Names names, Types types) {
+ LoadableConstant getValue(Symtab syms) {
switch (this) {
case STRING:
+ return LoadableConstant.String((String)value);
case INTEGER:
+ return LoadableConstant.Int((Integer)value);
case LONG:
+ return LoadableConstant.Long((Long)value);
case FLOAT:
+ return LoadableConstant.Float((Float)value);
case DOUBLE:
- return value;
+ return LoadableConstant.Double((Double)value);
case CLASS:
- return syms.stringType.tsym;
+ return (ClassType)syms.stringType;
case METHOD_HANDLE:
- return new Pool.MethodHandle(REF_invokeVirtual,
- syms.arrayCloneMethod, types);
+ return syms.arrayCloneMethod.asHandle();
case METHOD_TYPE:
- return syms.arrayCloneMethod.type;
+ return ((MethodType)syms.arrayCloneMethod.type);
default:
throw new AssertionError();
}
@@ -394,7 +394,7 @@
class Indifier extends TreeScanner<Void, Void> implements TaskListener {
- MethodSymbol bsm;
+ MethodHandleSymbol bsm;
Symtab syms;
Names names;
Types types;
@@ -424,12 +424,12 @@
JCIdent ident = (JCIdent)apply.meth;
Symbol oldSym = ident.sym;
if (!oldSym.isConstructor()) {
- Object[] staticArgs = new Object[arity.arity];
+ LoadableConstant[] staticArgs = new LoadableConstant[arity.arity];
for (int i = 0; i < arity.arity ; i++) {
- staticArgs[i] = saks[i].getValue(syms, names, types);
+ staticArgs[i] = saks[i].getValue(syms);
}
ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
- oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
+ oldSym.owner, bsm, oldSym.type, staticArgs);
}
return null;
}
@@ -438,7 +438,7 @@
public Void visitMethod(MethodTree node, Void p) {
super.visitMethod(node, p);
if (node.getName().toString().equals("bsm")) {
- bsm = ((JCMethodDecl)node).sym;
+ bsm = ((JCMethodDecl)node).sym.asHandle();
}
return null;
}
--- a/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.out Fri Apr 19 08:00:42 2019 -0400
@@ -1,2 +1,2 @@
-- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: mod/module-info, <error>))
+- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.bad.const.pool.index: module-info.class, 15, 10))
1 error
--- a/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javac/nestmates/CheckNestmateAttrs.java Fri Apr 19 08:00:42 2019 -0400
@@ -90,8 +90,8 @@
"NestHost: class CheckNestmateAttrs",
"0: aload_0",
"1: getfield #1 // Field this$1:LCheckNestmateAttrs$Inner;",
- "4: getfield #3 // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
- "7: invokevirtual #4 // Method CheckNestmateAttrs.test:()V",
+ "4: getfield #13 // Field CheckNestmateAttrs$Inner.this$0:LCheckNestmateAttrs;",
+ "7: invokevirtual #19 // Method CheckNestmateAttrs.test:()V",
"10: return"
});
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/environment/TestPreviewEnabled.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8222378
+ * @summary Test that ProcessingEnvironment.isPreviewEnabled works properly
+ * @library /tools/javac/lib
+ * @modules java.compiler
+ * @build JavacTestingAbstractProcessor
+ * @compile TestPreviewEnabled.java
+ * @compile -processor TestPreviewEnabled -proc:only -source ${jdk.version} -AExpectedPreview=false TestSourceVersion.java
+ * @compile -processor TestPreviewEnabled -proc:only -source ${jdk.version} -AExpectedPreview=true --enable-preview TestSourceVersion.java
+ */
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+import javax.annotation.processing.*;
+import javax.lang.model.util.*;
+
+/**
+ * This processor checks that ProcessingEnvironment.isPreviewEnabled
+ * is consistent with the compiler options.
+ */
+@SupportedOptions("ExpectedPreview")
+public class TestPreviewEnabled extends JavacTestingAbstractProcessor {
+ public boolean process(Set<? extends TypeElement> annotations,
+ RoundEnvironment roundEnvironment) {
+ if (!roundEnvironment.processingOver()) {
+ boolean expectedPreview =
+ Boolean.valueOf(processingEnv.getOptions().get("ExpectedPreview"));
+ boolean actualPreview = processingEnv.isPreviewEnabled();
+ System.out.println("Expected PreviewEnabled: " + expectedPreview +
+ "\n actual PreviewEnabled: " + actualPreview);
+ if (expectedPreview != actualPreview)
+ throw new RuntimeException();
+
+ if (expectedPreview) {
+ // Create a ProcessingEnvironment that uses the
+ // default implemention of isPreviewEnabled.
+ ProcessingEnvironment testEnv = new ProcessingEnvironment() {
+ @Override public Elements getElementUtils() {return null;}
+ @Override public Filer getFiler() {return null;}
+ @Override public Locale getLocale() {return null;}
+ @Override public Messager getMessager() {return null;}
+ @Override public Map<String,String> getOptions() {return null;}
+ @Override public SourceVersion getSourceVersion() {return null;}
+ @Override public Types getTypeUtils() {return null;}
+ };
+ if (testEnv.isPreviewEnabled()) {
+ throw new RuntimeException("Bad true return value from default " +
+ "ProcessingEnvironment.isPreviewEnabled.");
+ }
+ }
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/element/TestElementKindPredicates.java Fri Apr 19 08:00:42 2019 -0400
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8222430
+ * @summary Test various predicates of ElementKind.
+ */
+
+import java.util.Set;
+import java.util.function.Predicate;
+import javax.lang.model.element.ElementKind;
+
+/**
+ * Test the isClass, isField, and isInterface predicates of ElementKind.
+ */
+public class TestElementKindPredicates {
+ public static void main(String... args) {
+ Set<ElementKind> ALL_KINDS = Set.of(ElementKind.values());
+
+ // isClass: Returns true if this is a kind of class: either CLASS or ENUM.
+ test(ALL_KINDS,
+ (ElementKind k) -> Set.of(ElementKind.CLASS,
+ ElementKind.ENUM).contains(k),
+ (ElementKind k) -> k.isClass(), "isClass");
+
+ // isField: Returns true if this is a kind of field: either FIELD or ENUM_CONSTANT.
+ test(ALL_KINDS,
+ (ElementKind k) -> Set.of(ElementKind.FIELD,
+ ElementKind.ENUM_CONSTANT).contains(k),
+ (ElementKind k) -> k.isField(), "isField");
+
+ // isInterface: Returns true if this is a kind of interface: either INTERFACE or ANNOTATION_TYPE.
+ test(ALL_KINDS,
+ (ElementKind k) -> Set.of(ElementKind.INTERFACE,
+ ElementKind.ANNOTATION_TYPE).contains(k),
+ (ElementKind k) -> k.isInterface(), "isInterface");
+ }
+
+ private static void test(Set<ElementKind> kinds,
+ Predicate<ElementKind> expectedPred,
+ Predicate<ElementKind> actualPred,
+ String errorMessage) {
+ for(ElementKind kind : kinds) {
+ boolean expected = expectedPred.test(kind);
+ boolean actual = actualPred.test(kind);
+
+ if (expected != actual) {
+ throw new RuntimeException("Error testing ElementKind." + errorMessage + "(" + kind +
+ "):\texpected " + expected + "\tgot " + actual);
+ }
+ }
+ }
+}
--- a/test/langtools/tools/javap/AnnoTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javap/AnnoTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -49,50 +49,50 @@
expect(out,
"RuntimeVisibleAnnotations:\n" +
- " 0: #18(#19=B#20)\n" +
+ " 0: #21(#22=B#23)\n" +
" AnnoTest$ByteAnno(\n" +
" value=(byte) 42\n" +
" )\n" +
- " 1: #23(#19=S#24)\n" +
+ " 1: #24(#22=S#25)\n" +
" AnnoTest$ShortAnno(\n" +
" value=(short) 3\n" +
" )");
expect(out,
"RuntimeInvisibleAnnotations:\n" +
- " 0: #28(#19=[J#29,J#31,J#33,J#35,J#37])\n" +
+ " 0: #27(#22=[J#28,J#30,J#32,J#34,J#36])\n" +
" AnnoTest$ArrayAnno(\n" +
" value=[1l,2l,3l,4l,5l]\n" +
" )\n" +
- " 1: #41(#19=Z#42)\n" +
+ " 1: #38(#22=Z#39)\n" +
" AnnoTest$BooleanAnno(\n" +
" value=false\n" +
" )\n" +
- " 2: #45(#46=c#47)\n" +
+ " 2: #40(#41=c#42)\n" +
" AnnoTest$ClassAnno(\n" +
" type=class Ljava/lang/Object;\n" +
" )\n" +
- " 3: #50(#51=e#52.#53)\n" +
+ " 3: #43(#44=e#45.#46)\n" +
" AnnoTest$EnumAnno(\n" +
" kind=Ljavax/lang/model/element/ElementKind;.PACKAGE\n" +
" )\n" +
- " 4: #56(#19=I#57)\n" +
+ " 4: #47(#22=I#48)\n" +
" AnnoTest$IntAnno(\n" +
" value=2\n" +
" )\n" +
- " 5: #60()\n" +
+ " 5: #49()\n" +
" AnnoTest$IntDefaultAnno\n" +
- " 6: #63(#64=s#65)\n" +
+ " 6: #50(#51=s#52)\n" +
" AnnoTest$NameAnno(\n" +
" name=\"NAME\"\n" +
" )\n" +
- " 7: #68(#69=D#70,#72=F#73)\n" +
+ " 7: #53(#54=D#55,#57=F#58)\n" +
" AnnoTest$MultiAnno(\n" +
" d=3.14159d\n" +
" f=2.71828f\n" +
" )\n" +
- " 8: #76()\n" +
+ " 8: #59()\n" +
" AnnoTest$SimpleAnno\n" +
- " 9: #79(#19=@#56(#19=I#80))\n" +
+ " 9: #60(#22=@#47(#22=I#61))\n" +
" AnnoTest$AnnoAnno(\n" +
" value=@AnnoTest$IntAnno(\n" +
" value=5\n" +
@@ -100,7 +100,7 @@
" )");
expect(out,
"RuntimeInvisibleTypeAnnotations:\n" +
- " 0: #84(): CLASS_EXTENDS, type_index=0\n" +
+ " 0: #63(): CLASS_EXTENDS, type_index=0\n" +
" AnnoTest$TypeAnno");
if (errors > 0)
--- a/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javap/typeAnnotations/AnnotationDefaultNewlineTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -51,7 +51,7 @@
private static final String ExpectedSubstring =
" AnnotationDefault:\n" +
- " default_value: I#7\n";
+ " default_value: I#9\n";
public static void main(String[] args) throws Exception {
ToolBox tb = new ToolBox();
--- a/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/langtools/tools/javap/typeAnnotations/InvisibleParameterAnnotationsTest.java Fri Apr 19 08:00:42 2019 -0400
@@ -62,11 +62,11 @@
" RuntimeVisibleParameterAnnotations:\n" +
" parameter 0:\n" +
" parameter 1:\n" +
- " 0: #16()\n" +
+ " 0: #14()\n" +
" Sample$VisAnno\n" +
" RuntimeInvisibleParameterAnnotations:\n" +
" parameter 0:\n" +
- " 0: #18()\n" +
+ " 0: #16()\n" +
" Sample$InvisAnno\n" +
" parameter 1:";
--- a/test/lib/jdk/test/lib/process/OutputAnalyzer.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
import java.io.IOException;
import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@@ -59,6 +61,15 @@
/**
* Create an OutputAnalyzer, a utility class for verifying output
*
+ * @param file File to analyze
+ */
+ public OutputAnalyzer(Path file) throws IOException {
+ this(Files.readString(file));
+ }
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
* @param stdout stdout buffer to analyze
* @param stderr stderr buffer to analyze
*/
--- a/test/micro/org/openjdk/bench/java/lang/StringConcat.java Fri Apr 19 07:55:28 2019 -0400
+++ b/test/micro/org/openjdk/bench/java/lang/StringConcat.java Fri Apr 19 08:00:42 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -63,6 +63,11 @@
}
@Benchmark
+ public String concatMethodConstString() {
+ return "string".concat(stringValue);
+ }
+
+ @Benchmark
public String concatConstIntConstInt() {
return "string" + intValue + "string" + intValue;
}