# HG changeset patch # User herrick # Date 1557264614 14400 # Node ID 51709d9aab6980c3ea59a8a85559cbf2d3b06feb # Parent bf3d37105ef92d66c7d6717dce99eeadcefea600# Parent 1851a532ddfebb914d14a1c82be6c83cf5029fde Merge diff -r bf3d37105ef9 -r 51709d9aab69 make/Docs.gmk --- a/make/Docs.gmk Fri May 03 14:59:32 2019 -0400 +++ b/make/Docs.gmk Tue May 07 17:30:14 2019 -0400 @@ -32,6 +32,7 @@ include ProcessMarkdown.gmk include ToolsJdk.gmk include ZipArchive.gmk +include TextFileProcessing.gmk # This is needed to properly setup DOCS_MODULES. $(eval $(call ReadImportMetaData)) @@ -64,7 +65,7 @@ # URLs JAVADOC_BASE_URL := https://docs.oracle.com/pls/topic/lookup?ctx=javase$(VERSION_NUMBER)&id=homepage BUG_SUBMIT_URL := https://bugreport.java.com/bugreport/ -COPYRIGHT_URL := {@docroot}/../legal/copyright.html +COPYRIGHT_URL := legal/copyright.html LICENSE_URL := https://www.oracle.com/technetwork/java/javase/terms/license/java$(VERSION_NUMBER)speclicense.html REDISTRIBUTION_URL := https://www.oracle.com/technetwork/java/redist-137594.html @@ -148,6 +149,15 @@ HEADER_STYLE := style="margin-top: 14px;" endif +# $1 - Relative prefix to COPYRIGHT_URL +COPYRIGHT_BOTTOM = \ + <a href="$(strip $1)$(COPYRIGHT_URL)">Copyright</a> \ + © 1993, $(COPYRIGHT_YEAR), $(FULL_COMPANY_NAME), \ + $(COMPANY_ADDRESS).<br>All rights reserved. \ + Use is subject to <a href="$(LICENSE_URL)">license terms</a> and the \ + <a href="$(REDISTRIBUTION_URL)">documentation redistribution policy</a>. \ + $(DRAFT_MARKER_STR) <!-- Version $(VERSION_STRING) --> + JAVADOC_BOTTOM := \ <a href="$(BUG_SUBMIT_URL)">Report a bug or suggest an enhancement</a><br> \ For further API reference and developer documentation see the \ @@ -157,12 +167,7 @@ of terms, workarounds, and working code examples.<br> \ Java is a trademark or registered trademark of $(FULL_COMPANY_NAME) in \ the US and other countries.<br> \ - <a href="$(COPYRIGHT_URL)">Copyright</a> \ - © 1993, $(COPYRIGHT_YEAR), $(FULL_COMPANY_NAME), \ - $(COMPANY_ADDRESS).<br>All rights reserved. \ - Use is subject to <a href="$(LICENSE_URL)">license terms</a> and the \ - <a href="$(REDISTRIBUTION_URL)">documentation redistribution policy</a>. \ - $(DRAFT_MARKER_STR) <!-- Version $(VERSION_STRING) --> + $(call COPYRIGHT_BOTTOM, {@docroot}/../) JAVADOC_TOP := \ <div style="padding: 6px; text-align: center; font-size: 80%; \ @@ -500,11 +505,11 @@ ################################################################################ # Copy JDK specs files -# For all html documentation in $module/share/specs directories, copy it +# For all non html/md files in $module/share/specs directories, copy them # unmodified ALL_MODULES := $(call FindAllModules) -COPY_SPEC_FILTER := %.html %.gif %.jpg %.mib %.css +COPY_SPEC_FILTER := %.gif %.jpg %.mib %.css $(foreach m, $(ALL_MODULES), \ $(eval SPECS_$m := $(call FindModuleSpecsDirs, $m)) \ @@ -520,6 +525,45 @@ ) \ ) +# Create copyright footer files that can be provided as input to pandoc. We +# need different files for different relative paths to the copyright.html +# file. The number 0-2 below represent how many extra directory levels down +# below the specs dir the specs html file is located. Each file name is +# stored in a variable SPECS_BOTTOM_FILE_$n where $n is 0, 1 or 2. +SPECS_BOTTOM = <hr/>$(COPYRIGHT_BOTTOM) +# The legal dir is one ../ below the specs dir, so start with one ../. +specs_bottom_rel_path := ../ +$(foreach n, 0 1 2, \ + $(eval SPECS_BOTTOM_FILE_$n := $(SUPPORT_OUTPUTDIR)/docs/full-specs-bottom-$n.txt) \ + $(eval SPECS_BOTTOM_$n := $(call SPECS_BOTTOM,$(specs_bottom_rel_path))) \ + $(eval $(SPECS_BOTTOM_FILE_$n): \ + $(call DependOnVariable, SPECS_BOTTOM_$n) ; \ + $(PRINTF) '$(SPECS_BOTTOM_$n)' > $$@ \ + ) \ + $(eval specs_bottom_rel_path := $(specs_bottom_rel_path)../) \ +) + +# For all html files in $module/share/specs directories, copy and add the +# copyright footer. + +$(foreach m, $(ALL_MODULES), \ + $(eval SPECS_$m := $(call FindModuleSpecsDirs, $m)) \ + $(foreach d, $(SPECS_$m), \ + $(foreach f, $(filter %.html, $(call FindFiles, $d)), \ + $(eval $m_$f_NOF_SUBDIRS := $(words $(subst /, $(SPACE), $(subst $d, , $(dir $f))))) \ + $(eval $m_$f_NAME := PROCESS_HTML_$m_$(strip $(call RelativePath, $f, $(TOPDIR)))) \ + $(eval $(call SetupTextFileProcessing, $($m_$f_NAME), \ + SOURCE_FILES := $f, \ + SOURCE_BASE_DIR := $d, \ + OUTPUT_DIR := $(DOCS_OUTPUTDIR)/specs/, \ + REPLACEMENTS := \ + </body> => $(SPECS_BOTTOM_$($m_$f_NOF_SUBDIRS))</body>, \ + )) \ + $(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \ + ) \ + ) \ +) + ifeq ($(ENABLE_PANDOC), true) # For all markdown files in $module/share/specs directories, convert them to # html, if we have pandoc (otherwise we'll just skip this). @@ -529,15 +573,19 @@ $(foreach m, $(ALL_MODULES), \ $(eval SPECS_$m := $(call FindModuleSpecsDirs, $m)) \ $(foreach d, $(SPECS_$m), \ - $(if $(filter %.md, $(call FindFiles, $d)), \ - $(eval $m_$d_NAME := SPECS_TO_HTML_$m_$(strip $(call RelativePath, $d, $(TOPDIR)))) \ - $(eval $(call SetupProcessMarkdown, $($m_$d_NAME), \ + $(foreach f, $(filter %.md, $(call FindFiles, $d)), \ + $(eval $m_$f_NOF_SUBDIRS := $(words $(subst /, $(SPACE), $(subst $d, , $(dir $f))))) \ + $(eval $m_$f_BOTTOM_FILE := $(SPECS_BOTTOM_FILE_$($m_$f_NOF_SUBDIRS))) \ + $(eval $m_$f_NAME := SPECS_TO_HTML_$m_$(strip $(call RelativePath, $f, $(TOPDIR)))) \ + $(eval $(call SetupProcessMarkdown, $($m_$f_NAME), \ SRC := $d, \ - FILES := $(filter %.md, $(call FindFiles, $d)), \ + FILES := $f, \ DEST := $(DOCS_OUTPUTDIR)/specs/, \ CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ + OPTIONS := -A $($m_$f_BOTTOM_FILE), \ + EXTRA_DEPS := $($m_$f_BOTTOM_FILE), \ )) \ - $(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \ + $(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \ ) \ ) \ ) @@ -556,19 +604,21 @@ $(foreach m, $(ALL_MODULES), \ $(eval MAN_$m := $(call FindModuleManDirs, $m)) \ $(foreach d, $(MAN_$m), \ - $(if $(filter %.md, $(call FindFiles, $d)), \ - $(eval $m_$d_NAME := MAN_TO_HTML_$m_$(strip $(call RelativePath, $d, $(TOPDIR)))) \ - $(eval $(call SetupProcessMarkdown, $($m_$d_NAME), \ + $(foreach f, $(filter %.md, $(call FindFiles, $d)), \ + $(eval $m_$f_NAME := MAN_TO_HTML_$m_$(strip $(call RelativePath, $f, $(TOPDIR)))) \ + $(eval $(call SetupProcessMarkdown, $($m_$f_NAME), \ SRC := $d, \ - FILES := $(filter %.md, $(call FindFiles, $d)), \ + FILES := $f, \ DEST := $(DOCS_OUTPUTDIR)/specs/man, \ FILTER := $(PANDOC_HTML_MANPAGE_FILTER), \ CSS := $(GLOBAL_SPECS_DEFAULT_CSS_FILE), \ REPLACEMENTS := @@VERSION_SHORT@@ => $(VERSION_SHORT), \ + OPTIONS := -A $(SPECS_BOTTOM_FILE_1), \ EXTRA_DEPS := $(PANDOC_HTML_MANPAGE_FILTER) \ - $(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT), \ + $(PANDOC_HTML_MANPAGE_FILTER_JAVASCRIPT) \ + $(SPECS_BOTTOM_FILE_1), \ )) \ - $(eval JDK_SPECS_TARGETS += $($($m_$d_NAME))) \ + $(eval JDK_SPECS_TARGETS += $($($m_$f_NAME))) \ ) \ ) \ ) @@ -580,19 +630,23 @@ # Special treatment for generated documentation JDWP_PROTOCOL := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/jdwp-protocol.html -$(eval $(call SetupCopyFiles, COPY_JDWP_PROTOCOL, \ - FILES := $(JDWP_PROTOCOL), \ - DEST := $(DOCS_OUTPUTDIR)/specs/jdwp, \ +$(eval $(call SetupTextFileProcessing, PROCESS_JDWP_PROTOCOL, \ + SOURCE_FILES := $(JDWP_PROTOCOL), \ + OUTPUT_DIR := $(DOCS_OUTPUTDIR)/specs/jdwp, \ + REPLACEMENTS := \ + </body> => $(SPECS_BOTTOM_1)</body>, \ )) -JDK_SPECS_TARGETS += $(COPY_JDWP_PROTOCOL) +JDK_SPECS_TARGETS += $(PROCESS_JDWP_PROTOCOL) # Get jvmti.html from the main jvm variant (all variants' jvmti.html are identical). JVMTI_HTML ?= $(HOTSPOT_OUTPUTDIR)/variant-$(JVM_VARIANT_MAIN)/gensrc/jvmtifiles/jvmti.html -$(eval $(call SetupCopyFiles, COPY_JVMTI_HTML, \ - FILES := $(JVMTI_HTML), \ - DEST := $(DOCS_OUTPUTDIR)/specs, \ +$(eval $(call SetupTextFileProcessing, PROCESS_JVMTI_HTML, \ + SOURCE_FILES := $(JVMTI_HTML), \ + OUTPUT_DIR := $(DOCS_OUTPUTDIR)/specs/, \ + REPLACEMENTS := \ + </body> => $(SPECS_BOTTOM_0)</body>, \ )) -JDK_SPECS_TARGETS += $(COPY_JVMTI_HTML) +JDK_SPECS_TARGETS += $(PROCESS_JVMTI_HTML) ################################################################################ # Optional target which bundles all generated javadocs into a zip archive. @@ -610,6 +664,10 @@ ZIP_TARGETS += $(BUILD_JAVADOC_ZIP) ################################################################################ +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, Docs-post.gmk)) + +################################################################################ docs-jdk-api-javadoc: $(JDK_API_JAVADOC_TARGETS) $(JDK_API_CUSTOM_TARGETS) diff -r bf3d37105ef9 -r 51709d9aab69 make/InitSupport.gmk --- a/make/InitSupport.gmk Fri May 03 14:59:32 2019 -0400 +++ b/make/InitSupport.gmk Tue May 07 17:30:14 2019 -0400 @@ -387,7 +387,7 @@ fi # Re-run configure with the same arguments (and possibly some additional), # must be done after patching. - ( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \ + ( cd $(CONFIGURE_START_DIR) && PATH="$(ORIGINAL_PATH)" \ $(BASH) $(topdir)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF)) endef diff -r bf3d37105ef9 -r 51709d9aab69 make/common/TextFileProcessing.gmk --- a/make/common/TextFileProcessing.gmk Fri May 03 14:59:32 2019 -0400 +++ b/make/common/TextFileProcessing.gmk Tue May 07 17:30:14 2019 -0400 @@ -58,7 +58,7 @@ # OUTPUT_DIR the directory where we store the processed files. # OUTPUT_FILE the name of the resulting file. Only allowed if processing a # single file. -# SOURCE_BASE_DIR a common root to all SOURCE_DIRS. +# SOURCE_BASE_DIR a common root to all SOURCE_DIRS or SOURCE_FILES. # If specified, files will keep the path relative to the base in the # OUTPUT_DIR. Otherwise, the hierarchy will be flattened into the OUTPUT_DIR. # INCLUDE_FILES only include files matching these patterns (used only with @@ -84,9 +84,6 @@ ifneq ($$($1_SOURCE_DIRS),) $$(error Cannot use both SOURCE_FILES and SOURCE_DIRS (in $1)) endif - ifneq ($$($1_SOURCE_BASE_DIR),) - $$(error Cannot use SOURCE_BASE_DIR without SOURCE_DIRS (in $1)) - endif ifneq ($$($1_EXCLUDE_FILES)$$($1_INCLUDE_FILES),) $$(error Cannot INCLUDE/EXCLUDE_FILES with SOURCE_FILES (in $1)) endif @@ -155,9 +152,10 @@ # Convert the REPLACEMENTS syntax ( A => B ; C => D ; ...) to a sed command # line (-e "s/A/B/g" -e "s/C/D/g" ...), basically by replacing '=>' with '/' # and ';' with '/g" -e "s/', and adjusting for edge cases. + # '&' has special meaning in sed so needs to be escaped. $1_REPLACEMENTS_COMMAND_LINE := $(SED) -e 's$$($1_SEP)$$(subst $$(SPACE);$$(SPACE),$$($1_SEP)g' \ -e 's$$($1_SEP),$$(subst $$(SPACE)=>$$(SPACE),$$($1_SEP),$$(subst $$(SPACE)=>$$(SPACE);$$(SPACE),$$($1_SEP)$$($1_SEP)g' \ - -e 's$$($1_SEP),$$(strip $$($1_REPLACEMENTS)))))$$($1_SEP)g' + -e 's$$($1_SEP),$$(subst &,\&,$$(strip $$($1_REPLACEMENTS))))))$$($1_SEP)g' else # We don't have any replacements, just pipe the file through cat. $1_REPLACEMENTS_COMMAND_LINE := $(CAT) diff -r bf3d37105ef9 -r 51709d9aab69 make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java Fri May 03 14:59:32 2019 -0400 +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -346,17 +346,26 @@ if (sb.indexOf("root") == -1) { sb.append("root"); } - Bundle b = new Bundle(id, sb.toString(), null, null); - // Insert the bundle for root at the top so that it will get - // processed first. - if ("root".equals(id)) { - retList.add(0, b); - } else { - retList.add(b); - } + retList.add(new Bundle(id, sb.toString(), null, null)); } } } + + // Sort the bundles based on id. This will make sure all the parent bundles are + // processed first, e.g., for en_GB bundle, en_001, and "root" comes before + // en_GB. In order for "root" to come at the beginning, "root" is replaced with + // empty string on comparison. + retList.sort((o1, o2) -> { + String id1 = o1.getID(); + String id2 = o2.getID(); + if(id1.equals("root")) { + id1 = ""; + } + if(id2.equals("root")) { + id2 = ""; + } + return id1.compareTo(id2); + }); return retList; } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/assembler_x86.cpp --- a/src/hotspot/cpu/x86/assembler_x86.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/assembler_x86.cpp Tue May 07 17:30:14 2019 -0400 @@ -1894,6 +1894,69 @@ emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::pabsb(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_ssse3(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x1C); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::pabsw(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_ssse3(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x1D); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::pabsd(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_ssse3(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x1E); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vpabsb(XMMRegister dst, XMMRegister src, int vector_len) { + assert(vector_len == AVX_128bit? VM_Version::supports_avx() : + vector_len == AVX_256bit? VM_Version::supports_avx2() : + vector_len == AVX_512bit? VM_Version::supports_avx512bw() : 0, ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0x1C); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vpabsw(XMMRegister dst, XMMRegister src, int vector_len) { + assert(vector_len == AVX_128bit? VM_Version::supports_avx() : + vector_len == AVX_256bit? VM_Version::supports_avx2() : + vector_len == AVX_512bit? VM_Version::supports_avx512bw() : 0, ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0x1D); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vpabsd(XMMRegister dst, XMMRegister src, int vector_len) { + assert(vector_len == AVX_128bit? VM_Version::supports_avx() : + vector_len == AVX_256bit? VM_Version::supports_avx2() : + vector_len == AVX_512bit? VM_Version::supports_evex() : 0, ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0x1E); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::evpabsq(XMMRegister dst, XMMRegister src, int vector_len) { + assert(UseAVX > 2, ""); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0x1F); + emit_int8((unsigned char)(0xC0 | encode)); +} + void Assembler::decl(Address dst) { // Don't use it directly. Use MacroAssembler::decrement() instead. InstructionMark im(this); @@ -3416,10 +3479,19 @@ InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x00); - emit_int8(0xC0 | encode); + emit_int8((unsigned char)(0xC0 | encode)); emit_int8(imm8); } +void Assembler::vpermq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(UseAVX > 2, "requires AVX512F"); + InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0x36); + emit_int8((unsigned char)(0xC0 | encode)); +} + void Assembler::vperm2i128(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8) { assert(VM_Version::supports_avx2(), ""); InstructionAttr attributes(AVX_256bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); @@ -3884,6 +3956,14 @@ emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::pmovsxbw(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x20); + emit_int8((unsigned char)(0xC0 | encode)); +} + void Assembler::vpmovzxbw(XMMRegister dst, Address src, int vector_len) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); @@ -3905,6 +3985,15 @@ emit_int8((unsigned char) (0xC0 | encode)); } +void Assembler::vpmovsxbw(XMMRegister dst, XMMRegister src, int vector_len) { + assert(vector_len == AVX_128bit? VM_Version::supports_avx() : + vector_len == AVX_256bit? VM_Version::supports_avx2() : + vector_len == AVX_512bit? VM_Version::supports_avx512bw() : 0, ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ true, /* uses_vl */ true); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x20); + emit_int8((unsigned char)(0xC0 | encode)); +} void Assembler::evpmovzxbw(XMMRegister dst, KRegister mask, Address src, int vector_len) { assert(VM_Version::supports_avx512vlbw(), ""); @@ -6277,6 +6366,26 @@ emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::evpsraq(XMMRegister dst, XMMRegister src, int shift, int vector_len) { + assert(UseAVX > 2, "requires AVX512"); + assert ((VM_Version::supports_avx512vl() || vector_len == 2), "requires AVX512vl"); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(xmm4->encoding(), dst->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0x72); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(shift & 0xFF); +} + +void Assembler::evpsraq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len) { + assert(UseAVX > 2, "requires AVX512"); + assert ((VM_Version::supports_avx512vl() || vector_len == 2), "requires AVX512vl"); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), src->encoding(), shift->encoding(), VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xE2); + emit_int8((unsigned char)(0xC0 | encode)); +} // logical operations packed integers void Assembler::pand(XMMRegister dst, XMMRegister src) { diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/assembler_x86.hpp --- a/src/hotspot/cpu/x86/assembler_x86.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/assembler_x86.hpp Tue May 07 17:30:14 2019 -0400 @@ -1102,6 +1102,15 @@ void cvttpd2dq(XMMRegister dst, XMMRegister src); + //Abs of packed Integer values + void pabsb(XMMRegister dst, XMMRegister src); + void pabsw(XMMRegister dst, XMMRegister src); + void pabsd(XMMRegister dst, XMMRegister src); + void vpabsb(XMMRegister dst, XMMRegister src, int vector_len); + void vpabsw(XMMRegister dst, XMMRegister src, int vector_len); + void vpabsd(XMMRegister dst, XMMRegister src, int vector_len); + void evpabsq(XMMRegister dst, XMMRegister src, int vector_len); + // Divide Scalar Double-Precision Floating-Point Values void divsd(XMMRegister dst, Address src); void divsd(XMMRegister dst, XMMRegister src); @@ -1589,6 +1598,7 @@ // Pemutation of 64bit words void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len); void vpermq(XMMRegister dst, XMMRegister src, int imm8); + void vpermq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vperm2i128(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); void vperm2f128(XMMRegister dst, XMMRegister nds, XMMRegister src, int imm8); void evpermi2q(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); @@ -1668,6 +1678,10 @@ void evpmovdb(Address dst, XMMRegister src, int vector_len); + // Sign extend moves + void pmovsxbw(XMMRegister dst, XMMRegister src); + void vpmovsxbw(XMMRegister dst, XMMRegister src, int vector_len); + // Multiply add void pmaddwd(XMMRegister dst, XMMRegister src); void vpmaddwd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); @@ -2094,6 +2108,8 @@ void vpsrad(XMMRegister dst, XMMRegister src, int shift, int vector_len); void vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); void vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); + void evpsraq(XMMRegister dst, XMMRegister src, int shift, int vector_len); + void evpsraq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len); // And packed integers void pand(XMMRegister dst, XMMRegister src); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp Tue May 07 17:30:14 2019 -0400 @@ -46,12 +46,14 @@ // Apply storeval barrier to newval. ShenandoahBarrierSet::assembler()->storeval_barrier(masm->masm(), newval, tmp1); +#ifdef _LP64 if (UseCompressedOops) { __ encode_heap_oop(cmpval); __ mov(rscratch1, newval); __ encode_heap_oop(rscratch1); newval = rscratch1; } +#endif ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), result, Address(addr, 0), cmpval, newval, false, tmp1, tmp2); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/macroAssembler_x86.cpp --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp Tue May 07 17:30:14 2019 -0400 @@ -1003,25 +1003,25 @@ } } -void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src) { +void MacroAssembler::andpd(XMMRegister dst, AddressLiteral src, Register scratch_reg) { // Used in sign-masking with aligned address. assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { Assembler::andpd(dst, as_Address(src)); } else { - lea(rscratch1, src); - Assembler::andpd(dst, Address(rscratch1, 0)); - } -} - -void MacroAssembler::andps(XMMRegister dst, AddressLiteral src) { + lea(scratch_reg, src); + Assembler::andpd(dst, Address(scratch_reg, 0)); + } +} + +void MacroAssembler::andps(XMMRegister dst, AddressLiteral src, Register scratch_reg) { // Used in sign-masking with aligned address. assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { Assembler::andps(dst, as_Address(src)); } else { - lea(rscratch1, src); - Assembler::andps(dst, Address(rscratch1, 0)); + lea(scratch_reg, src); + Assembler::andps(dst, Address(scratch_reg, 0)); } } @@ -3340,13 +3340,13 @@ Assembler::vmovdqu(dst, src); } -void MacroAssembler::vmovdqu(XMMRegister dst, AddressLiteral src) { +void MacroAssembler::vmovdqu(XMMRegister dst, AddressLiteral src, Register scratch_reg) { if (reachable(src)) { vmovdqu(dst, as_Address(src)); } else { - lea(rscratch1, src); - vmovdqu(dst, Address(rscratch1, 0)); + lea(scratch_reg, src); + vmovdqu(dst, Address(scratch_reg, 0)); } } @@ -3698,14 +3698,14 @@ } } -void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src) { +void MacroAssembler::xorpd(XMMRegister dst, AddressLiteral src, Register scratch_reg) { // Used in sign-bit flipping with aligned address. assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { Assembler::xorpd(dst, as_Address(src)); } else { - lea(rscratch1, src); - Assembler::xorpd(dst, Address(rscratch1, 0)); + lea(scratch_reg, src); + Assembler::xorpd(dst, Address(scratch_reg, 0)); } } @@ -3726,14 +3726,14 @@ } } -void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src) { +void MacroAssembler::xorps(XMMRegister dst, AddressLiteral src, Register scratch_reg) { // Used in sign-bit flipping with aligned address. assert((UseAVX > 0) || (((intptr_t)src.target() & 15) == 0), "SSE mode requires address alignment 16 bytes"); if (reachable(src)) { Assembler::xorps(dst, as_Address(src)); } else { - lea(rscratch1, src); - Assembler::xorps(dst, Address(rscratch1, 0)); + lea(scratch_reg, src); + Assembler::xorps(dst, Address(scratch_reg, 0)); } } @@ -3799,12 +3799,12 @@ Assembler::vpaddw(dst, nds, src, vector_len); } -void MacroAssembler::vpand(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) { +void MacroAssembler::vpand(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg) { if (reachable(src)) { Assembler::vpand(dst, nds, as_Address(src), vector_len); } else { - lea(rscratch1, src); - Assembler::vpand(dst, nds, Address(rscratch1, 0), vector_len); + lea(scratch_reg, src); + Assembler::vpand(dst, nds, Address(scratch_reg, 0), vector_len); } } @@ -3873,6 +3873,22 @@ Assembler::vpsraw(dst, nds, shift, vector_len); } +void MacroAssembler::evpsraq(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len) { + assert(UseAVX > 2,""); + if (!VM_Version::supports_avx512vl() && vector_len < 2) { + vector_len = 2; + } + Assembler::evpsraq(dst, nds, shift, vector_len); +} + +void MacroAssembler::evpsraq(XMMRegister dst, XMMRegister nds, int shift, int vector_len) { + assert(UseAVX > 2,""); + if (!VM_Version::supports_avx512vl() && vector_len < 2) { + vector_len = 2; + } + Assembler::evpsraq(dst, nds, shift, vector_len); +} + void MacroAssembler::vpsrlw(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len) { assert(((dst->encoding() < 16 && shift->encoding() < 16 && nds->encoding() < 16) || VM_Version::supports_avx512vlbw()),"XMM register should be 0-15"); Assembler::vpsrlw(dst, nds, shift, vector_len); @@ -3913,21 +3929,21 @@ Assembler::pshuflw(dst, src, mode); } -void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) { +void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg) { if (reachable(src)) { vandpd(dst, nds, as_Address(src), vector_len); } else { - lea(rscratch1, src); - vandpd(dst, nds, Address(rscratch1, 0), vector_len); - } -} - -void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) { + lea(scratch_reg, src); + vandpd(dst, nds, Address(scratch_reg, 0), vector_len); + } +} + +void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg) { if (reachable(src)) { vandps(dst, nds, as_Address(src), vector_len); } else { - lea(rscratch1, src); - vandps(dst, nds, Address(rscratch1, 0), vector_len); + lea(scratch_reg, src); + vandps(dst, nds, Address(scratch_reg, 0), vector_len); } } @@ -3995,23 +4011,161 @@ vxorpd(dst, nds, src, Assembler::AVX_128bit); } -void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) { +void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg) { if (reachable(src)) { vxorpd(dst, nds, as_Address(src), vector_len); } else { - lea(rscratch1, src); - vxorpd(dst, nds, Address(rscratch1, 0), vector_len); - } -} - -void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) { + lea(scratch_reg, src); + vxorpd(dst, nds, Address(scratch_reg, 0), vector_len); + } +} + +void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg) { if (reachable(src)) { vxorps(dst, nds, as_Address(src), vector_len); } else { - lea(rscratch1, src); - vxorps(dst, nds, Address(rscratch1, 0), vector_len); - } -} + lea(scratch_reg, src); + vxorps(dst, nds, Address(scratch_reg, 0), vector_len); + } +} + +void MacroAssembler::vpxor(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg) { + if (UseAVX > 1 || (vector_len < 1)) { + if (reachable(src)) { + Assembler::vpxor(dst, nds, as_Address(src), vector_len); + } else { + lea(scratch_reg, src); + Assembler::vpxor(dst, nds, Address(scratch_reg, 0), vector_len); + } + } + else { + MacroAssembler::vxorpd(dst, nds, src, vector_len, scratch_reg); + } +} + +//------------------------------------------------------------------------------------------- +#ifdef COMPILER2 +// Generic instructions support for use in .ad files C2 code generation + +void MacroAssembler::vabsnegd(int opcode, XMMRegister dst, Register scr) { + if (opcode == Op_AbsVD) { + andpd(dst, ExternalAddress(StubRoutines::x86::vector_double_sign_mask()), scr); + } else { + assert((opcode == Op_NegVD),"opcode should be Op_NegD"); + xorpd(dst, ExternalAddress(StubRoutines::x86::vector_double_sign_flip()), scr); + } +} + +void MacroAssembler::vabsnegd(int opcode, XMMRegister dst, XMMRegister src, int vector_len, Register scr) { + if (opcode == Op_AbsVD) { + vandpd(dst, src, ExternalAddress(StubRoutines::x86::vector_double_sign_mask()), vector_len, scr); + } else { + assert((opcode == Op_NegVD),"opcode should be Op_NegD"); + vxorpd(dst, src, ExternalAddress(StubRoutines::x86::vector_double_sign_flip()), vector_len, scr); + } +} + +void MacroAssembler::vabsnegf(int opcode, XMMRegister dst, Register scr) { + if (opcode == Op_AbsVF) { + andps(dst, ExternalAddress(StubRoutines::x86::vector_float_sign_mask()), scr); + } else { + assert((opcode == Op_NegVF),"opcode should be Op_NegF"); + xorps(dst, ExternalAddress(StubRoutines::x86::vector_float_sign_flip()), scr); + } +} + +void MacroAssembler::vabsnegf(int opcode, XMMRegister dst, XMMRegister src, int vector_len, Register scr) { + if (opcode == Op_AbsVF) { + vandps(dst, src, ExternalAddress(StubRoutines::x86::vector_float_sign_mask()), vector_len, scr); + } else { + assert((opcode == Op_NegVF),"opcode should be Op_NegF"); + vxorps(dst, src, ExternalAddress(StubRoutines::x86::vector_float_sign_flip()), vector_len, scr); + } +} + +void MacroAssembler::vextendbw(bool sign, XMMRegister dst, XMMRegister src) { + if (sign) { + pmovsxbw(dst, src); + } else { + pmovzxbw(dst, src); + } +} + +void MacroAssembler::vextendbw(bool sign, XMMRegister dst, XMMRegister src, int vector_len) { + if (sign) { + vpmovsxbw(dst, src, vector_len); + } else { + vpmovzxbw(dst, src, vector_len); + } +} + +void MacroAssembler::vshiftd(int opcode, XMMRegister dst, XMMRegister src) { + if (opcode == Op_RShiftVI) { + psrad(dst, src); + } else if (opcode == Op_LShiftVI) { + pslld(dst, src); + } else { + assert((opcode == Op_URShiftVI),"opcode should be Op_URShiftVI"); + psrld(dst, src); + } +} + +void MacroAssembler::vshiftd(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + if (opcode == Op_RShiftVI) { + vpsrad(dst, nds, src, vector_len); + } else if (opcode == Op_LShiftVI) { + vpslld(dst, nds, src, vector_len); + } else { + assert((opcode == Op_URShiftVI),"opcode should be Op_URShiftVI"); + vpsrld(dst, nds, src, vector_len); + } +} + +void MacroAssembler::vshiftw(int opcode, XMMRegister dst, XMMRegister src) { + if ((opcode == Op_RShiftVS) || (opcode == Op_RShiftVB)) { + psraw(dst, src); + } else if ((opcode == Op_LShiftVS) || (opcode == Op_LShiftVB)) { + psllw(dst, src); + } else { + assert(((opcode == Op_URShiftVS) || (opcode == Op_URShiftVB)),"opcode should be one of Op_URShiftVS or Op_URShiftVB"); + psrlw(dst, src); + } +} + +void MacroAssembler::vshiftw(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + if ((opcode == Op_RShiftVS) || (opcode == Op_RShiftVB)) { + vpsraw(dst, nds, src, vector_len); + } else if ((opcode == Op_LShiftVS) || (opcode == Op_LShiftVB)) { + vpsllw(dst, nds, src, vector_len); + } else { + assert(((opcode == Op_URShiftVS) || (opcode == Op_URShiftVB)),"opcode should be one of Op_URShiftVS or Op_URShiftVB"); + vpsrlw(dst, nds, src, vector_len); + } +} + +void MacroAssembler::vshiftq(int opcode, XMMRegister dst, XMMRegister src) { + if (opcode == Op_RShiftVL) { + psrlq(dst, src); // using srl to implement sra on pre-avs512 systems + } else if (opcode == Op_LShiftVL) { + psllq(dst, src); + } else { + assert((opcode == Op_URShiftVL),"opcode should be Op_URShiftVL"); + psrlq(dst, src); + } +} + +void MacroAssembler::vshiftq(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + if (opcode == Op_RShiftVL) { + evpsraq(dst, nds, src, vector_len); + } else if (opcode == Op_LShiftVL) { + vpsllq(dst, nds, src, vector_len); + } else { + assert((opcode == Op_URShiftVL),"opcode should be Op_URShiftVL"); + vpsrlq(dst, nds, src, vector_len); + } +} +#endif +//------------------------------------------------------------------------------------------- void MacroAssembler::clear_jweak_tag(Register possibly_jweak) { const int32_t inverted_jweak_mask = ~static_cast<int32_t>(JNIHandles::weak_tag_mask); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/macroAssembler_x86.hpp --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp Tue May 07 17:30:14 2019 -0400 @@ -877,12 +877,12 @@ // Floating void andpd(XMMRegister dst, Address src) { Assembler::andpd(dst, src); } - void andpd(XMMRegister dst, AddressLiteral src); + void andpd(XMMRegister dst, AddressLiteral src, Register scratch_reg = rscratch1); void andpd(XMMRegister dst, XMMRegister src) { Assembler::andpd(dst, src); } void andps(XMMRegister dst, XMMRegister src) { Assembler::andps(dst, src); } void andps(XMMRegister dst, Address src) { Assembler::andps(dst, src); } - void andps(XMMRegister dst, AddressLiteral src); + void andps(XMMRegister dst, AddressLiteral src, Register scratch_reg = rscratch1); void comiss(XMMRegister dst, XMMRegister src) { Assembler::comiss(dst, src); } void comiss(XMMRegister dst, Address src) { Assembler::comiss(dst, src); } @@ -1066,8 +1066,8 @@ // these are private because users should be doing movflt/movdbl + void movss(XMMRegister dst, XMMRegister src) { Assembler::movss(dst, src); } void movss(Address dst, XMMRegister src) { Assembler::movss(dst, src); } - void movss(XMMRegister dst, XMMRegister src) { Assembler::movss(dst, src); } void movss(XMMRegister dst, Address src) { Assembler::movss(dst, src); } void movss(XMMRegister dst, AddressLiteral src); @@ -1105,7 +1105,7 @@ void vmovdqu(Address dst, XMMRegister src); void vmovdqu(XMMRegister dst, Address src); void vmovdqu(XMMRegister dst, XMMRegister src); - void vmovdqu(XMMRegister dst, AddressLiteral src); + void vmovdqu(XMMRegister dst, AddressLiteral src, Register scratch_reg = rscratch1); void evmovdquq(XMMRegister dst, Address src, int vector_len) { Assembler::evmovdquq(dst, src, vector_len); } void evmovdquq(XMMRegister dst, XMMRegister src, int vector_len) { Assembler::evmovdquq(dst, src, vector_len); } void evmovdquq(Address dst, XMMRegister src, int vector_len) { Assembler::evmovdquq(dst, src, vector_len); } @@ -1183,12 +1183,12 @@ // Bitwise Logical XOR of Packed Double-Precision Floating-Point Values void xorpd(XMMRegister dst, XMMRegister src); void xorpd(XMMRegister dst, Address src) { Assembler::xorpd(dst, src); } - void xorpd(XMMRegister dst, AddressLiteral src); + void xorpd(XMMRegister dst, AddressLiteral src, Register scratch_reg = rscratch1); // Bitwise Logical XOR of Packed Single-Precision Floating-Point Values void xorps(XMMRegister dst, XMMRegister src); void xorps(XMMRegister dst, Address src) { Assembler::xorps(dst, src); } - void xorps(XMMRegister dst, AddressLiteral src); + void xorps(XMMRegister dst, AddressLiteral src, Register scratch_reg = rscratch1); // Shuffle Bytes void pshufb(XMMRegister dst, XMMRegister src) { Assembler::pshufb(dst, src); } @@ -1215,7 +1215,7 @@ void vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vpand(dst, nds, src, vector_len); } void vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vpand(dst, nds, src, vector_len); } - void vpand(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len); + void vpand(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); void vpbroadcastw(XMMRegister dst, XMMRegister src, int vector_len); void vpbroadcastw(XMMRegister dst, Address src, int vector_len) { Assembler::vpbroadcastw(dst, src, vector_len); } @@ -1241,6 +1241,9 @@ void vpsraw(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len); void vpsraw(XMMRegister dst, XMMRegister nds, int shift, int vector_len); + void evpsraq(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len); + void evpsraq(XMMRegister dst, XMMRegister nds, int shift, int vector_len); + void vpsrlw(XMMRegister dst, XMMRegister nds, XMMRegister shift, int vector_len); void vpsrlw(XMMRegister dst, XMMRegister nds, int shift, int vector_len); @@ -1260,11 +1263,11 @@ void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vandpd(dst, nds, src, vector_len); } void vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vandpd(dst, nds, src, vector_len); } - void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len); + void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vandps(dst, nds, src, vector_len); } void vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vandps(dst, nds, src, vector_len); } - void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len); + void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivsd(dst, nds, src); } void vdivsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivsd(dst, nds, src); } @@ -1297,11 +1300,11 @@ void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); } void vxorpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); } - void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len); + void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorps(dst, nds, src, vector_len); } void vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vxorps(dst, nds, src, vector_len); } - void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len); + void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { if (UseAVX > 1 || (vector_len < 1)) // vpxor 256 bit is available only in AVX2 @@ -1315,6 +1318,7 @@ else Assembler::vxorpd(dst, nds, src, vector_len); } + void vpxor(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len, Register scratch_reg = rscratch1); // Simple version for AVX2 256bit vectors void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); } @@ -1601,6 +1605,22 @@ void movl2ptr(Register dst, Address src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(movl(dst, src)); } void movl2ptr(Register dst, Register src) { LP64_ONLY(movslq(dst, src)) NOT_LP64(if (dst != src) movl(dst, src)); } +#ifdef COMPILER2 + // Generic instructions support for use in .ad files C2 code generation + void vabsnegd(int opcode, XMMRegister dst, Register scr); + void vabsnegd(int opcode, XMMRegister dst, XMMRegister src, int vector_len, Register scr); + void vabsnegf(int opcode, XMMRegister dst, Register scr); + void vabsnegf(int opcode, XMMRegister dst, XMMRegister src, int vector_len, Register scr); + void vextendbw(bool sign, XMMRegister dst, XMMRegister src, int vector_len); + void vextendbw(bool sign, XMMRegister dst, XMMRegister src); + void vshiftd(int opcode, XMMRegister dst, XMMRegister src); + void vshiftd(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vshiftw(int opcode, XMMRegister dst, XMMRegister src); + void vshiftw(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vshiftq(int opcode, XMMRegister dst, XMMRegister src); + void vshiftq(int opcode, XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); +#endif + // C2 compiled method's prolog code. void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b, bool is_stub); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/stubGenerator_x86_32.cpp --- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp Tue May 07 17:30:14 2019 -0400 @@ -602,7 +602,59 @@ return start; } - + //--------------------------------------------------------------------------------------------------- + + address generate_vector_mask(const char *stub_name, int32_t mask) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + + for (int i = 0; i < 16; i++) { + __ emit_data(mask, relocInfo::none, 0); + } + + return start; + } + + address generate_vector_mask_long_double(const char *stub_name, int32_t maskhi, int32_t masklo) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + + for (int i = 0; i < 8; i++) { + __ emit_data(masklo, relocInfo::none, 0); + __ emit_data(maskhi, relocInfo::none, 0); + } + + return start; + } + + //---------------------------------------------------------------------------------------------------- + + address generate_vector_byte_perm_mask(const char *stub_name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + + __ emit_data(0x00000001, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000003, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000005, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000007, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000002, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000004, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000006, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + + return start; + } //---------------------------------------------------------------------------------------------------- // Non-destructive plausibility checks for oops @@ -3823,6 +3875,14 @@ //------------------------------------------------------------------------------------------------------------------------ // entry points that are platform specific + StubRoutines::x86::_vector_float_sign_mask = generate_vector_mask("vector_float_sign_mask", 0x7FFFFFFF); + StubRoutines::x86::_vector_float_sign_flip = generate_vector_mask("vector_float_sign_flip", 0x80000000); + StubRoutines::x86::_vector_double_sign_mask = generate_vector_mask_long_double("vector_double_sign_mask", 0x7FFFFFFF, 0xFFFFFFFF); + StubRoutines::x86::_vector_double_sign_flip = generate_vector_mask_long_double("vector_double_sign_flip", 0x80000000, 0x00000000); + StubRoutines::x86::_vector_short_to_byte_mask = generate_vector_mask("vector_short_to_byte_mask", 0x00ff00ff); + StubRoutines::x86::_vector_byte_perm_mask = generate_vector_byte_perm_mask("vector_byte_perm_mask"); + StubRoutines::x86::_vector_long_sign_mask = generate_vector_mask_long_double("vector_long_sign_mask", 0x80000000, 0x00000000); + // support for verify_oop (must happen after universe_init) StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/stubGenerator_x86_64.cpp --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp Tue May 07 17:30:14 2019 -0400 @@ -979,6 +979,40 @@ return start; } + address generate_vector_mask(const char *stub_name, int64_t mask) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + __ emit_data64(mask, relocInfo::none); + + return start; + } + + address generate_vector_byte_perm_mask(const char *stub_name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", stub_name); + address start = __ pc(); + + __ emit_data64(0x0000000000000001, relocInfo::none); + __ emit_data64(0x0000000000000003, relocInfo::none); + __ emit_data64(0x0000000000000005, relocInfo::none); + __ emit_data64(0x0000000000000007, relocInfo::none); + __ emit_data64(0x0000000000000000, relocInfo::none); + __ emit_data64(0x0000000000000002, relocInfo::none); + __ emit_data64(0x0000000000000004, relocInfo::none); + __ emit_data64(0x0000000000000006, relocInfo::none); + + return start; + } + // Non-destructive plausibility checks for oops // // Arguments: @@ -5871,6 +5905,13 @@ StubRoutines::x86::_float_sign_flip = generate_fp_mask("float_sign_flip", 0x8000000080000000); StubRoutines::x86::_double_sign_mask = generate_fp_mask("double_sign_mask", 0x7FFFFFFFFFFFFFFF); StubRoutines::x86::_double_sign_flip = generate_fp_mask("double_sign_flip", 0x8000000000000000); + StubRoutines::x86::_vector_float_sign_mask = generate_vector_mask("vector_float_sign_mask", 0x7FFFFFFF7FFFFFFF); + StubRoutines::x86::_vector_float_sign_flip = generate_vector_mask("vector_float_sign_flip", 0x8000000080000000); + StubRoutines::x86::_vector_double_sign_mask = generate_vector_mask("vector_double_sign_mask", 0x7FFFFFFFFFFFFFFF); + StubRoutines::x86::_vector_double_sign_flip = generate_vector_mask("vector_double_sign_flip", 0x8000000000000000); + StubRoutines::x86::_vector_short_to_byte_mask = generate_vector_mask("vector_short_to_byte_mask", 0x00ff00ff00ff00ff); + StubRoutines::x86::_vector_byte_perm_mask = generate_vector_byte_perm_mask("vector_byte_perm_mask"); + StubRoutines::x86::_vector_long_sign_mask = generate_vector_mask("vector_long_sign_mask", 0x8000000000000000); // support for verify_oop (must happen after universe_init) StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/stubRoutines_x86.cpp --- a/src/hotspot/cpu/x86/stubRoutines_x86.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/stubRoutines_x86.cpp Tue May 07 17:30:14 2019 -0400 @@ -43,6 +43,13 @@ address StubRoutines::x86::_upper_word_mask_addr = NULL; address StubRoutines::x86::_shuffle_byte_flip_mask_addr = NULL; address StubRoutines::x86::_k256_adr = NULL; +address StubRoutines::x86::_vector_short_to_byte_mask = NULL; +address StubRoutines::x86::_vector_float_sign_mask = NULL; +address StubRoutines::x86::_vector_float_sign_flip = NULL; +address StubRoutines::x86::_vector_double_sign_mask = NULL; +address StubRoutines::x86::_vector_double_sign_flip = NULL; +address StubRoutines::x86::_vector_byte_perm_mask = NULL; +address StubRoutines::x86::_vector_long_sign_mask = NULL; #ifdef _LP64 address StubRoutines::x86::_k256_W_adr = NULL; address StubRoutines::x86::_k512_W_addr = NULL; diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/stubRoutines_x86.hpp --- a/src/hotspot/cpu/x86/stubRoutines_x86.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/stubRoutines_x86.hpp Tue May 07 17:30:14 2019 -0400 @@ -102,6 +102,7 @@ static address double_sign_flip() { return _double_sign_flip; } + #else // !LP64 private: @@ -139,6 +140,13 @@ //k256 table for sha256 static juint _k256[]; static address _k256_adr; + static address _vector_short_to_byte_mask; + static address _vector_float_sign_mask; + static address _vector_float_sign_flip; + static address _vector_double_sign_mask; + static address _vector_double_sign_flip; + static address _vector_byte_perm_mask; + static address _vector_long_sign_mask; #ifdef _LP64 static juint _k256_W[]; static address _k256_W_adr; @@ -212,6 +220,33 @@ static address upper_word_mask_addr() { return _upper_word_mask_addr; } static address shuffle_byte_flip_mask_addr() { return _shuffle_byte_flip_mask_addr; } static address k256_addr() { return _k256_adr; } + + static address vector_short_to_byte_mask() { + return _vector_short_to_byte_mask; + } + static address vector_float_sign_mask() { + return _vector_float_sign_mask; + } + + static address vector_float_sign_flip() { + return _vector_float_sign_flip; + } + + static address vector_double_sign_mask() { + return _vector_double_sign_mask; + } + + static address vector_double_sign_flip() { + return _vector_double_sign_flip; + } + + static address vector_byte_perm_mask() { + return _vector_byte_perm_mask; + } + + static address vector_long_sign_mask() { + return _vector_long_sign_mask; + } #ifdef _LP64 static address k256_W_addr() { return _k256_W_adr; } static address k512_W_addr() { return _k512_W_addr; } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/x86.ad --- a/src/hotspot/cpu/x86/x86.ad Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/x86.ad Tue May 07 17:30:14 2019 -0400 @@ -1372,14 +1372,20 @@ static address double_signmask() { return (address)double_signmask_pool; } static address double_signflip() { return (address)double_signflip_pool; } #endif - - + static address vector_short_to_byte_mask() { return StubRoutines::x86::vector_short_to_byte_mask(); } + static address vector_byte_perm_mask() { return StubRoutines::x86::vector_byte_perm_mask(); } + static address vector_long_sign_mask() { return StubRoutines::x86::vector_long_sign_mask(); } + +//============================================================================= const bool Matcher::match_rule_supported(int opcode) { if (!has_match_rule(opcode)) return false; bool ret_value = true; switch (opcode) { + case Op_AbsVL: + if (UseAVX < 3) + ret_value = false; case Op_PopCountI: case Op_PopCountL: if (!UsePopCountInstruction) @@ -1402,6 +1408,9 @@ if (UseAVX < 3) // only EVEX : vector connectivity becomes an issue here ret_value = false; break; + case Op_AbsVB: + case Op_AbsVS: + case Op_AbsVI: case Op_AddReductionVI: if (UseSSE < 3) // requires at least SSE3 ret_value = false; @@ -1447,9 +1456,19 @@ ret_value = false; break; case Op_MulAddVS2VI: + case Op_RShiftVL: + case Op_AbsVD: + case Op_NegVD: if (UseSSE < 2) ret_value = false; break; + case Op_MulVB: + case Op_LShiftVB: + case Op_RShiftVB: + case Op_URShiftVB: + if (UseSSE < 4) + ret_value = false; + break; #ifdef _LP64 case Op_MaxD: case Op_MaxF: @@ -1470,24 +1489,42 @@ bool ret_value = match_rule_supported(opcode); if (ret_value) { switch (opcode) { + case Op_AbsVB: case Op_AddVB: case Op_SubVB: if ((vlen == 64) && (VM_Version::supports_avx512bw() == false)) ret_value = false; break; - case Op_URShiftVS: - case Op_RShiftVS: - case Op_LShiftVS: - case Op_MulVS: + case Op_AbsVS: case Op_AddVS: case Op_SubVS: + case Op_MulVS: + case Op_LShiftVS: + case Op_RShiftVS: + case Op_URShiftVS: if ((vlen == 32) && (VM_Version::supports_avx512bw() == false)) ret_value = false; break; + case Op_MulVB: + case Op_LShiftVB: + case Op_RShiftVB: + case Op_URShiftVB: + if ((vlen == 32 && UseAVX < 2) || + ((vlen == 64) && (VM_Version::supports_avx512bw() == false))) + ret_value = false; + break; + case Op_NegVF: + if ((vlen == 16) && (VM_Version::supports_avx512dq() == false)) + ret_value = false; + break; case Op_CMoveVF: if (vlen != 8) ret_value = false; break; + case Op_NegVD: + if ((vlen == 8) && (VM_Version::supports_avx512dq() == false)) + ret_value = false; + break; case Op_CMoveVD: if (vlen != 4) ret_value = false; @@ -7302,6 +7339,186 @@ // --------------------------------- MUL -------------------------------------- +// Byte vector mul +instruct mul4B_reg(vecS dst, vecS src1, vecS src2, vecS tmp, rRegI scratch) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 4); + match(Set dst (MulVB src1 src2)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"pmovsxbw $tmp,$src1\n\t" + "pmovsxbw $dst,$src2\n\t" + "pmullw $tmp,$dst\n\t" + "movdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "pand $dst,$tmp\n\t" + "packuswb $dst,$dst\t! mul packed4B" %} + ins_encode %{ + __ pmovsxbw($tmp$$XMMRegister, $src1$$XMMRegister); + __ pmovsxbw($dst$$XMMRegister, $src2$$XMMRegister); + __ pmullw($tmp$$XMMRegister, $dst$$XMMRegister); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ pand($dst$$XMMRegister, $tmp$$XMMRegister); + __ packuswb($dst$$XMMRegister, $dst$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct mul8B_reg(vecD dst, vecD src1, vecD src2, vecD tmp, rRegI scratch) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 8); + match(Set dst (MulVB src1 src2)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"pmovsxbw $tmp,$src1\n\t" + "pmovsxbw $dst,$src2\n\t" + "pmullw $tmp,$dst\n\t" + "movdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "pand $dst,$tmp\n\t" + "packuswb $dst,$dst\t! mul packed8B" %} + ins_encode %{ + __ pmovsxbw($tmp$$XMMRegister, $src1$$XMMRegister); + __ pmovsxbw($dst$$XMMRegister, $src2$$XMMRegister); + __ pmullw($tmp$$XMMRegister, $dst$$XMMRegister); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ pand($dst$$XMMRegister, $tmp$$XMMRegister); + __ packuswb($dst$$XMMRegister, $dst$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct mul16B_reg(vecX dst, vecX src1, vecX src2, vecX tmp1, vecX tmp2, rRegI scratch) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 16); + match(Set dst (MulVB src1 src2)); + effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); + format %{"pmovsxbw $tmp1,$src1\n\t" + "pmovsxbw $tmp2,$src2\n\t" + "pmullw $tmp1,$tmp2\n\t" + "pshufd $tmp2,$src1,0xEE\n\t" + "pshufd $dst,$src2,0xEE\n\t" + "pmovsxbw $tmp2,$tmp2\n\t" + "pmovsxbw $dst,$dst\n\t" + "pmullw $tmp2,$dst\n\t" + "movdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "pand $tmp2,$dst\n\t" + "pand $dst,$tmp1\n\t" + "packuswb $dst,$tmp2\t! mul packed16B" %} + ins_encode %{ + __ pmovsxbw($tmp1$$XMMRegister, $src1$$XMMRegister); + __ pmovsxbw($tmp2$$XMMRegister, $src2$$XMMRegister); + __ pmullw($tmp1$$XMMRegister, $tmp2$$XMMRegister); + __ pshufd($tmp2$$XMMRegister, $src1$$XMMRegister, 0xEE); + __ pshufd($dst$$XMMRegister, $src2$$XMMRegister, 0xEE); + __ pmovsxbw($tmp2$$XMMRegister, $tmp2$$XMMRegister); + __ pmovsxbw($dst$$XMMRegister, $dst$$XMMRegister); + __ pmullw($tmp2$$XMMRegister, $dst$$XMMRegister); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ pand($tmp2$$XMMRegister, $dst$$XMMRegister); + __ pand($dst$$XMMRegister, $tmp1$$XMMRegister); + __ packuswb($dst$$XMMRegister, $tmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul16B_reg_avx(vecX dst, vecX src1, vecX src2, vecX tmp, rRegI scratch) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (MulVB src1 src2)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"vpmovsxbw $tmp,$src1\n\t" + "vpmovsxbw $dst,$src2\n\t" + "vpmullw $tmp,$tmp,$dst\n\t" + "vmovdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "vpand $dst,$dst,$tmp\n\t" + "vextracti128_high $tmp,$dst\n\t" + "vpackuswb $dst,$dst,$dst\n\t! mul packed16B" %} + ins_encode %{ + int vector_len = 1; + __ vpmovsxbw($tmp$$XMMRegister, $src1$$XMMRegister, vector_len); + __ vpmovsxbw($dst$$XMMRegister, $src2$$XMMRegister, vector_len); + __ vpmullw($tmp$$XMMRegister, $tmp$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vmovdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ vpand($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister, vector_len); + __ vextracti128_high($tmp$$XMMRegister, $dst$$XMMRegister); + __ vpackuswb($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister, 0); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul32B_reg_avx(vecY dst, vecY src1, vecY src2, vecY tmp1, vecY tmp2, rRegI scratch) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (MulVB src1 src2)); + effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); + format %{"vextracti128_high $tmp1,$src1\n\t" + "vextracti128_high $dst,$src2\n\t" + "vpmovsxbw $tmp1,$tmp1\n\t" + "vpmovsxbw $dst,$dst\n\t" + "vpmullw $tmp1,$tmp1,$dst\n\t" + "vpmovsxbw $tmp2,$src1\n\t" + "vpmovsxbw $dst,$src2\n\t" + "vpmullw $tmp2,$tmp2,$dst\n\t" + "vmovdqu $dst, [0x00ff00ff0x00ff00ff]\n\t" + "vpbroadcastd $dst, $dst\n\t" + "vpand $tmp1,$tmp1,$dst\n\t" + "vpand $dst,$dst,$tmp2\n\t" + "vpackuswb $dst,$dst,$tmp1\n\t" + "vpermq $dst, $dst, 0xD8\t! mul packed32B" %} + ins_encode %{ + int vector_len = 1; + __ vextracti128_high($tmp1$$XMMRegister, $src1$$XMMRegister); + __ vextracti128_high($dst$$XMMRegister, $src2$$XMMRegister); + __ vpmovsxbw($tmp1$$XMMRegister, $tmp1$$XMMRegister, vector_len); + __ vpmovsxbw($dst$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpmullw($tmp1$$XMMRegister, $tmp1$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpmovsxbw($tmp2$$XMMRegister, $src1$$XMMRegister, vector_len); + __ vpmovsxbw($dst$$XMMRegister, $src2$$XMMRegister, vector_len); + __ vpmullw($tmp2$$XMMRegister, $tmp2$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vmovdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ vpbroadcastd($dst$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpand($tmp1$$XMMRegister, $tmp1$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpand($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister, vector_len); + __ vpackuswb($dst$$XMMRegister, $dst$$XMMRegister, $tmp1$$XMMRegister, vector_len); + __ vpermq($dst$$XMMRegister, $dst$$XMMRegister, 0xD8, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vmul64B_reg_avx(vecZ dst, vecZ src1, vecZ src2, vecZ tmp1, vecZ tmp2, rRegI scratch) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 64); + match(Set dst (MulVB src1 src2)); + effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); + format %{"vextracti64x4_high $tmp1,$src1\n\t" + "vextracti64x4_high $dst,$src2\n\t" + "vpmovsxbw $tmp1,$tmp1\n\t" + "vpmovsxbw $dst,$dst\n\t" + "vpmullw $tmp1,$tmp1,$dst\n\t" + "vpmovsxbw $tmp2,$src1\n\t" + "vpmovsxbw $dst,$src2\n\t" + "vpmullw $tmp2,$tmp2,$dst\n\t" + "vmovdqu $dst, [0x00ff00ff0x00ff00ff]\n\t" + "vpbroadcastd $dst, $dst\n\t" + "vpand $tmp1,$tmp1,$dst\n\t" + "vpand $tmp2,$tmp2,$dst\n\t" + "vpackuswb $dst,$tmp1,$tmp2\n\t" + "evmovdquq $tmp2,[0x0604020007050301]\n\t" + "vpermq $dst,$tmp2,$dst,0x01\t! mul packed64B" %} + + ins_encode %{ + int vector_len = 2; + __ vextracti64x4_high($tmp1$$XMMRegister, $src1$$XMMRegister); + __ vextracti64x4_high($dst$$XMMRegister, $src2$$XMMRegister); + __ vpmovsxbw($tmp1$$XMMRegister, $tmp1$$XMMRegister, vector_len); + __ vpmovsxbw($dst$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpmullw($tmp1$$XMMRegister, $tmp1$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpmovsxbw($tmp2$$XMMRegister, $src1$$XMMRegister, vector_len); + __ vpmovsxbw($dst$$XMMRegister, $src2$$XMMRegister, vector_len); + __ vpmullw($tmp2$$XMMRegister, $tmp2$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vmovdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ vpbroadcastd($dst$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpand($tmp1$$XMMRegister, $tmp1$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpand($tmp2$$XMMRegister, $tmp2$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpackuswb($dst$$XMMRegister, $tmp1$$XMMRegister, $tmp2$$XMMRegister, vector_len); + __ evmovdquq($tmp2$$XMMRegister, ExternalAddress(vector_byte_perm_mask()), vector_len, $scratch$$Register); + __ vpermq($dst$$XMMRegister, $tmp2$$XMMRegister, $dst$$XMMRegister, vector_len); + + %} + ins_pipe( pipe_slow ); +%} + // Shorts/Chars vector mul instruct vmul2S(vecS dst, vecS src) %{ predicate(UseAVX == 0 && n->as_Vector()->length() == 2); @@ -8024,20 +8241,6 @@ ins_pipe( pipe_slow ); %} -// ------------------------------ Shift --------------------------------------- - -// Left and right shift count vectors are the same on x86 -// (only lowest bits of xmm reg are used for count). -instruct vshiftcnt(vecS dst, rRegI cnt) %{ - match(Set dst (LShiftCntV cnt)); - match(Set dst (RShiftCntV cnt)); - format %{ "movd $dst,$cnt\t! load shift count" %} - ins_encode %{ - __ movdl($dst$$XMMRegister, $cnt$$Register); - %} - ins_pipe( pipe_slow ); -%} - // --------------------------------- Sqrt -------------------------------------- // Floating point vector sqrt @@ -8195,1092 +8398,478 @@ ins_pipe( pipe_slow ); %} -// ------------------------------ LeftShift ----------------------------------- - -// Shorts/Chars vector left shift -instruct vsll2S(vecS dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVS dst shift)); - format %{ "psllw $dst,$shift\t! left shift packed2S" %} - ins_encode %{ - __ psllw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2S_imm(vecS dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVS dst shift)); - format %{ "psllw $dst,$shift\t! left shift packed2S" %} - ins_encode %{ - __ psllw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2S_reg(vecS dst, vecS src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed2S" %} - ins_encode %{ - int vector_len = 0; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2S_reg_imm(vecS dst, vecS src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed2S" %} - ins_encode %{ - int vector_len = 0; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4S(vecD dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVS dst shift)); - format %{ "psllw $dst,$shift\t! left shift packed4S" %} - ins_encode %{ - __ psllw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4S_imm(vecD dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVS dst shift)); - format %{ "psllw $dst,$shift\t! left shift packed4S" %} - ins_encode %{ - __ psllw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4S_reg(vecD dst, vecD src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed4S" %} - ins_encode %{ - int vector_len = 0; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4S_reg_imm(vecD dst, vecD src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed4S" %} - ins_encode %{ - int vector_len = 0; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8S(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVS dst shift)); - format %{ "psllw $dst,$shift\t! left shift packed8S" %} - ins_encode %{ - __ psllw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8S_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVS dst shift)); - format %{ "psllw $dst,$shift\t! left shift packed8S" %} - ins_encode %{ - __ psllw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8S_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed8S" %} - ins_encode %{ - int vector_len = 0; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8S_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed8S" %} - ins_encode %{ - int vector_len = 0; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll16S_reg(vecY dst, vecY src, vecS shift) %{ +// ------------------------------ Shift --------------------------------------- + +// Left and right shift count vectors are the same on x86 +// (only lowest bits of xmm reg are used for count). +instruct vshiftcnt(vecS dst, rRegI cnt) %{ + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "movdl $dst,$cnt\t! load shift count" %} + ins_encode %{ + __ movdl($dst$$XMMRegister, $cnt$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshiftcntimm(vecS dst, immI8 cnt, rRegI tmp) %{ + match(Set dst cnt); + effect(TEMP tmp); + format %{ "movl $tmp,$cnt\t" + "movdl $dst,$tmp\t! load shift count" %} + ins_encode %{ + __ movl($tmp$$Register, $cnt$$constant); + __ movdl($dst$$XMMRegister, $tmp$$Register); + %} + ins_pipe( pipe_slow ); +%} + +// Byte vector shift +instruct vshift4B(vecS dst, vecS src, vecS shift, vecS tmp, rRegI scratch) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + match(Set dst (URShiftVB src shift)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"vextendbw $tmp,$src\n\t" + "vshiftw $tmp,$shift\n\t" + "movdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "pand $dst,$tmp\n\t" + "packuswb $dst,$dst\n\t ! packed4B shift" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + + __ vextendbw(opcode, $tmp$$XMMRegister, $src$$XMMRegister); + __ vshiftw(opcode, $tmp$$XMMRegister, $shift$$XMMRegister); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ pand($dst$$XMMRegister, $tmp$$XMMRegister); + __ packuswb($dst$$XMMRegister, $dst$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift8B(vecD dst, vecD src, vecS shift, vecD tmp, rRegI scratch) %{ + predicate(UseSSE > 3 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + match(Set dst (URShiftVB src shift)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"vextendbw $tmp,$src\n\t" + "vshiftw $tmp,$shift\n\t" + "movdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "pand $dst,$tmp\n\t" + "packuswb $dst,$dst\n\t ! packed8B shift" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + + __ vextendbw(opcode, $tmp$$XMMRegister, $src$$XMMRegister); + __ vshiftw(opcode, $tmp$$XMMRegister, $shift$$XMMRegister); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ pand($dst$$XMMRegister, $tmp$$XMMRegister); + __ packuswb($dst$$XMMRegister, $dst$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift16B(vecX dst, vecX src, vecS shift, vecX tmp1, vecX tmp2, rRegI scratch) %{ + predicate(UseSSE > 3 && UseAVX <= 1 && n->as_Vector()->length() == 16); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + match(Set dst (URShiftVB src shift)); + effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); + format %{"vextendbw $tmp1,$src\n\t" + "vshiftw $tmp1,$shift\n\t" + "pshufd $tmp2,$src\n\t" + "vextendbw $tmp2,$tmp2\n\t" + "vshiftw $tmp2,$shift\n\t" + "movdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "pand $tmp2,$dst\n\t" + "pand $dst,$tmp1\n\t" + "packuswb $dst,$tmp2\n\t! packed16B shift" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + + __ vextendbw(opcode, $tmp1$$XMMRegister, $src$$XMMRegister); + __ vshiftw(opcode, $tmp1$$XMMRegister, $shift$$XMMRegister); + __ pshufd($tmp2$$XMMRegister, $src$$XMMRegister, 0xE); + __ vextendbw(opcode, $tmp2$$XMMRegister, $tmp2$$XMMRegister); + __ vshiftw(opcode, $tmp2$$XMMRegister, $shift$$XMMRegister); + __ movdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ pand($tmp2$$XMMRegister, $dst$$XMMRegister); + __ pand($dst$$XMMRegister, $tmp1$$XMMRegister); + __ packuswb($dst$$XMMRegister, $tmp2$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift16B_avx(vecX dst, vecX src, vecS shift, vecX tmp, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 16); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed16S" %} - ins_encode %{ - int vector_len = 1; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll16S_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 16); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed16S" %} - ins_encode %{ + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + match(Set dst (URShiftVB src shift)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"vextendbw $tmp,$src\n\t" + "vshiftw $tmp,$tmp,$shift\n\t" + "vpand $tmp,$tmp,[0x00ff00ff0x00ff00ff]\n\t" + "vextracti128_high $dst,$tmp\n\t" + "vpackuswb $dst,$tmp,$dst\n\t! packed16B shift" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + int vector_len = 1; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll32S_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed32S" %} - ins_encode %{ - int vector_len = 2; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll32S_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); - match(Set dst (LShiftVS src shift)); - format %{ "vpsllw $dst,$src,$shift\t! left shift packed32S" %} - ins_encode %{ + __ vextendbw(opcode, $tmp$$XMMRegister, $src$$XMMRegister, vector_len); + __ vshiftw(opcode, $tmp$$XMMRegister, $tmp$$XMMRegister, $shift$$XMMRegister, vector_len); + __ vpand($tmp$$XMMRegister, $tmp$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), vector_len, $scratch$$Register); + __ vextracti128_high($dst$$XMMRegister, $tmp$$XMMRegister); + __ vpackuswb($dst$$XMMRegister, $tmp$$XMMRegister, $dst$$XMMRegister, 0); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift32B_avx(vecY dst, vecY src, vecS shift, vecY tmp, rRegI scratch) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + match(Set dst (URShiftVB src shift)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{"vextracti128_high $tmp,$src\n\t" + "vextendbw $tmp,$tmp\n\t" + "vextendbw $dst,$src\n\t" + "vshiftw $tmp,$tmp,$shift\n\t" + "vshiftw $dst,$dst,$shift\n\t" + "vpand $tmp,$tmp,[0x00ff00ff0x00ff00ff]\n\t" + "vpand $dst,$dst,[0x00ff00ff0x00ff00ff]\n\t" + "vpackuswb $dst,$dst,$tmp\n\t" + "vpermq $dst,$dst,0xD8\n\t! packed32B shift" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + + int vector_len = 1; + __ vextracti128_high($tmp$$XMMRegister, $src$$XMMRegister); + __ vextendbw(opcode, $tmp$$XMMRegister, $tmp$$XMMRegister, vector_len); + __ vextendbw(opcode, $dst$$XMMRegister, $src$$XMMRegister, vector_len); + __ vshiftw(opcode, $tmp$$XMMRegister, $tmp$$XMMRegister, $shift$$XMMRegister, vector_len); + __ vshiftw(opcode, $dst$$XMMRegister, $dst$$XMMRegister, $shift$$XMMRegister, vector_len); + __ vpand($tmp$$XMMRegister, $tmp$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), vector_len, $scratch$$Register); + __ vpand($dst$$XMMRegister, $dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), vector_len, $scratch$$Register); + __ vpackuswb($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister, vector_len); + __ vpermq($dst$$XMMRegister, $dst$$XMMRegister, 0xD8, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift64B_avx(vecZ dst, vecZ src, vecS shift, vecZ tmp1, vecZ tmp2, rRegI scratch) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 64); + match(Set dst (LShiftVB src shift)); + match(Set dst (RShiftVB src shift)); + match(Set dst (URShiftVB src shift)); + effect(TEMP dst, TEMP tmp1, TEMP tmp2, TEMP scratch); + format %{"vextracti64x4 $tmp1,$src\n\t" + "vextendbw $tmp1,$tmp1\n\t" + "vextendbw $tmp2,$src\n\t" + "vshiftw $tmp1,$tmp1,$shift\n\t" + "vshiftw $tmp2,$tmp2,$shift\n\t" + "vmovdqu $dst,[0x00ff00ff0x00ff00ff]\n\t" + "vpbroadcastd $dst,$dst\n\t" + "vpand $tmp1,$tmp1,$dst\n\t" + "vpand $tmp2,$tmp2,$dst\n\t" + "vpackuswb $dst,$tmp1,$tmp2\n\t" + "evmovdquq $tmp2, [0x0604020007050301]\n\t" + "vpermq $dst,$tmp2,$dst\n\t! packed64B shift" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + int vector_len = 2; - __ vpsllw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// Integers vector left shift -instruct vsll2I(vecD dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVI dst shift)); - format %{ "pslld $dst,$shift\t! left shift packed2I" %} - ins_encode %{ - __ pslld($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2I_imm(vecD dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVI dst shift)); - format %{ "pslld $dst,$shift\t! left shift packed2I" %} - ins_encode %{ - __ pslld($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2I_reg(vecD dst, vecD src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed2I" %} - ins_encode %{ - int vector_len = 0; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2I_reg_imm(vecD dst, vecD src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed2I" %} - ins_encode %{ - int vector_len = 0; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4I(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVI dst shift)); - format %{ "pslld $dst,$shift\t! left shift packed4I" %} - ins_encode %{ - __ pslld($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4I_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVI dst shift)); - format %{ "pslld $dst,$shift\t! left shift packed4I" %} - ins_encode %{ - __ pslld($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4I_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed4I" %} - ins_encode %{ - int vector_len = 0; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4I_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed4I" %} - ins_encode %{ - int vector_len = 0; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8I_reg(vecY dst, vecY src, vecS shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed8I" %} - ins_encode %{ - int vector_len = 1; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8I_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed8I" %} - ins_encode %{ - int vector_len = 1; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll16I_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 16); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed16I" %} - ins_encode %{ - int vector_len = 2; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll16I_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 16); - match(Set dst (LShiftVI src shift)); - format %{ "vpslld $dst,$src,$shift\t! left shift packed16I" %} - ins_encode %{ - int vector_len = 2; - __ vpslld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// Longs vector left shift -instruct vsll2L(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVL dst shift)); - format %{ "psllq $dst,$shift\t! left shift packed2L" %} - ins_encode %{ - __ psllq($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2L_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVL dst shift)); - format %{ "psllq $dst,$shift\t! left shift packed2L" %} - ins_encode %{ - __ psllq($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2L_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVL src shift)); - format %{ "vpsllq $dst,$src,$shift\t! left shift packed2L" %} - ins_encode %{ - int vector_len = 0; - __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll2L_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (LShiftVL src shift)); - format %{ "vpsllq $dst,$src,$shift\t! left shift packed2L" %} - ins_encode %{ - int vector_len = 0; - __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4L_reg(vecY dst, vecY src, vecS shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVL src shift)); - format %{ "vpsllq $dst,$src,$shift\t! left shift packed4L" %} - ins_encode %{ - int vector_len = 1; - __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll4L_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 4); - match(Set dst (LShiftVL src shift)); - format %{ "vpsllq $dst,$src,$shift\t! left shift packed4L" %} - ins_encode %{ - int vector_len = 1; - __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8L_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVL src shift)); - format %{ "vpsllq $dst,$src,$shift\t! left shift packed8L" %} - ins_encode %{ - int vector_len = 2; - __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsll8L_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 8); - match(Set dst (LShiftVL src shift)); - format %{ "vpsllq $dst,$src,$shift\t! left shift packed8L" %} - ins_encode %{ - int vector_len = 2; - __ vpsllq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// ----------------------- LogicalRightShift ----------------------------------- + __ vextracti64x4($tmp1$$XMMRegister, $src$$XMMRegister, 1); + __ vextendbw(opcode, $tmp1$$XMMRegister, $tmp1$$XMMRegister, vector_len); + __ vextendbw(opcode, $tmp2$$XMMRegister, $src$$XMMRegister, vector_len); + __ vshiftw(opcode, $tmp1$$XMMRegister, $tmp1$$XMMRegister, $shift$$XMMRegister, vector_len); + __ vshiftw(opcode, $tmp2$$XMMRegister, $tmp2$$XMMRegister, $shift$$XMMRegister, vector_len); + __ vmovdqu($dst$$XMMRegister, ExternalAddress(vector_short_to_byte_mask()), $scratch$$Register); + __ vpbroadcastd($dst$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpand($tmp1$$XMMRegister, $tmp1$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpand($tmp2$$XMMRegister, $tmp2$$XMMRegister, $dst$$XMMRegister, vector_len); + __ vpackuswb($dst$$XMMRegister, $tmp1$$XMMRegister, $tmp2$$XMMRegister, vector_len); + __ evmovdquq($tmp2$$XMMRegister, ExternalAddress(vector_byte_perm_mask()), vector_len, $scratch$$Register); + __ vpermq($dst$$XMMRegister, $tmp2$$XMMRegister, $dst$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} // Shorts vector logical right shift produces incorrect Java result // for negative data because java code convert short value into int with // sign extension before a shift. But char vectors are fine since chars are // unsigned values. - -instruct vsrl2S(vecS dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVS dst shift)); - format %{ "psrlw $dst,$shift\t! logical right shift packed2S" %} - ins_encode %{ - __ psrlw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2S_imm(vecS dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVS dst shift)); - format %{ "psrlw $dst,$shift\t! logical right shift packed2S" %} - ins_encode %{ - __ psrlw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2S_reg(vecS dst, vecS src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); +// Shorts/Chars vector left shift +instruct vshist2S(vecS dst, vecS src, vecS shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed2S" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2S_reg_imm(vecS dst, vecS src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed2S" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4S(vecD dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (URShiftVS dst shift)); - format %{ "psrlw $dst,$shift\t! logical right shift packed4S" %} - ins_encode %{ - __ psrlw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4S_imm(vecD dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (URShiftVS dst shift)); - format %{ "psrlw $dst,$shift\t! logical right shift packed4S" %} - ins_encode %{ - __ psrlw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4S_reg(vecD dst, vecD src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + format %{ "vshiftw $dst,$src,$shift\t! shift packed2S" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if (UseAVX == 0) { + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movflt($dst$$XMMRegister, $src$$XMMRegister); + __ vshiftw(opcode, $dst$$XMMRegister, $shift$$XMMRegister); + } else { + int vector_len = 0; + __ vshiftw(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift4S(vecD dst, vecD src, vecS shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed4S" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4S_reg_imm(vecD dst, vecD src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + format %{ "vshiftw $dst,$src,$shift\t! shift packed4S" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if (UseAVX == 0) { + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdbl($dst$$XMMRegister, $src$$XMMRegister); + __ vshiftw(opcode, $dst$$XMMRegister, $shift$$XMMRegister); + + } else { + int vector_len = 0; + __ vshiftw(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift8S(vecX dst, vecX src, vecS shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed4S" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8S(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 8); - match(Set dst (URShiftVS dst shift)); - format %{ "psrlw $dst,$shift\t! logical right shift packed8S" %} - ins_encode %{ - __ psrlw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8S_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 8); - match(Set dst (URShiftVS dst shift)); - format %{ "psrlw $dst,$shift\t! logical right shift packed8S" %} - ins_encode %{ - __ psrlw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8S_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + format %{ "vshiftw $dst,$src,$shift\t! shift packed8S" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if (UseAVX == 0) { + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdqu($dst$$XMMRegister, $src$$XMMRegister); + __ vshiftw(opcode, $dst$$XMMRegister, $shift$$XMMRegister); + } else { + int vector_len = 0; + __ vshiftw(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift16S(vecY dst, vecY src, vecS shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed8S" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8S_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 8); - match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed8S" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl16S_reg(vecY dst, vecY src, vecS shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 16); - match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed16S" %} + format %{ "vshiftw $dst,$src,$shift\t! shift packed16S" %} ins_encode %{ int vector_len = 1; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl16S_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + int opcode = this->as_Mach()->ideal_Opcode(); + __ vshiftw(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift32S(vecZ dst, vecZ src, vecS shift) %{ + predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); + match(Set dst (LShiftVS src shift)); + match(Set dst (RShiftVS src shift)); match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed16S" %} - ins_encode %{ - int vector_len = 1; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl32S_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); - match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed32S" %} - ins_encode %{ - int vector_len = 2; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl32S_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); - match(Set dst (URShiftVS src shift)); - format %{ "vpsrlw $dst,$src,$shift\t! logical right shift packed32S" %} + format %{ "vshiftw $dst,$src,$shift\t! shift packed32S" %} ins_encode %{ int vector_len = 2; - __ vpsrlw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// Integers vector logical right shift -instruct vsrl2I(vecD dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVI dst shift)); - format %{ "psrld $dst,$shift\t! logical right shift packed2I" %} - ins_encode %{ - __ psrld($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2I_imm(vecD dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVI dst shift)); - format %{ "psrld $dst,$shift\t! logical right shift packed2I" %} - ins_encode %{ - __ psrld($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2I_reg(vecD dst, vecD src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed2I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2I_reg_imm(vecD dst, vecD src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); + int opcode = this->as_Mach()->ideal_Opcode(); + __ vshiftw(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// Integers vector left shift +instruct vshift2I(vecD dst, vecD src, vecS shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + match(Set dst (RShiftVI src shift)); match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed2I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4I(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (URShiftVI dst shift)); - format %{ "psrld $dst,$shift\t! logical right shift packed4I" %} - ins_encode %{ - __ psrld($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4I_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (URShiftVI dst shift)); - format %{ "psrld $dst,$shift\t! logical right shift packed4I" %} - ins_encode %{ - __ psrld($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4I_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + format %{ "vshiftd $dst,$src,$shift\t! shift packed2I" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if (UseAVX == 0) { + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdbl($dst$$XMMRegister, $src$$XMMRegister); + __ vshiftd(opcode, $dst$$XMMRegister, $shift$$XMMRegister); + } else { + int vector_len = 0; + __ vshiftd(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift4I(vecX dst, vecX src, vecS shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVI src shift)); + match(Set dst (RShiftVI src shift)); match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed4I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4I_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + format %{ "vshiftd $dst,$src,$shift\t! shift packed4I" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if (UseAVX == 0) { + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdqu($dst$$XMMRegister, $src$$XMMRegister); + __ vshiftd(opcode, $dst$$XMMRegister, $shift$$XMMRegister); + } else { + int vector_len = 0; + __ vshiftd(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift8I(vecY dst, vecY src, vecS shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVI src shift)); + match(Set dst (RShiftVI src shift)); match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed4I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8I_reg(vecY dst, vecY src, vecS shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 8); - match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed8I" %} + format %{ "vshiftd $dst,$src,$shift\t! shift packed8I" %} ins_encode %{ int vector_len = 1; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8I_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 8); + int opcode = this->as_Mach()->ideal_Opcode(); + __ vshiftd(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift16I(vecZ dst, vecZ src, vecS shift) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (LShiftVI src shift)); + match(Set dst (RShiftVI src shift)); match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed8I" %} - ins_encode %{ - int vector_len = 1; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl16I_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 16); - match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed16I" %} - ins_encode %{ - int vector_len = 2; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl16I_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 16); - match(Set dst (URShiftVI src shift)); - format %{ "vpsrld $dst,$src,$shift\t! logical right shift packed16I" %} + format %{ "vshiftd $dst,$src,$shift\t! shift packed16I" %} ins_encode %{ int vector_len = 2; - __ vpsrld($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// Longs vector logical right shift -instruct vsrl2L(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVL dst shift)); - format %{ "psrlq $dst,$shift\t! logical right shift packed2L" %} - ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + __ vshiftd(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// Longs vector shift +instruct vshift2L(vecX dst, vecX src, vecS shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVL src shift)); + match(Set dst (URShiftVL src shift)); + format %{ "vshiftq $dst,$src,$shift\t! shift packed2L" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if (UseAVX == 0) { + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdqu($dst$$XMMRegister, $src$$XMMRegister); + __ vshiftq(opcode, $dst$$XMMRegister, $shift$$XMMRegister); + } else { + int vector_len = 0; + __ vshiftq(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + } + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift4L(vecY dst, vecY src, vecS shift) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 4); + match(Set dst (LShiftVL src shift)); + match(Set dst (URShiftVL src shift)); + format %{ "vshiftq $dst,$src,$shift\t! left shift packed4L" %} + ins_encode %{ + int vector_len = 1; + int opcode = this->as_Mach()->ideal_Opcode(); + __ vshiftq(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vshift8L(vecZ dst, vecZ src, vecS shift) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 8); + match(Set dst (LShiftVL src shift)); + match(Set dst (RShiftVL src shift)); + match(Set dst (URShiftVL src shift)); + format %{ "vshiftq $dst,$src,$shift\t! shift packed8L" %} + ins_encode %{ + int vector_len = 2; + int opcode = this->as_Mach()->ideal_Opcode(); + __ vshiftq(opcode, $dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// -------------------ArithmeticRightShift ----------------------------------- +// Long vector arithmetic right shift +instruct vsra2L_reg(vecX dst, vecX src, vecS shift, vecX tmp, rRegI scratch) %{ + predicate(UseSSE >= 2 && n->as_Vector()->length() == 2); + match(Set dst (RShiftVL src shift)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{ "movdqu $dst,$src\n\t" + "psrlq $dst,$shift\n\t" + "movdqu $tmp,[0x8000000000000000]\n\t" + "psrlq $tmp,$shift\n\t" + "pxor $dst,$tmp\n\t" + "psubq $dst,$tmp\t! arithmetic right shift packed2L" %} + ins_encode %{ + __ movdqu($dst$$XMMRegister, $src$$XMMRegister); __ psrlq($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2L_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVL dst shift)); - format %{ "psrlq $dst,$shift\t! logical right shift packed2L" %} - ins_encode %{ - __ psrlq($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2L_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVL src shift)); - format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed2L" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl2L_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (URShiftVL src shift)); - format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed2L" %} - ins_encode %{ - int vector_len = 0; - __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4L_reg(vecY dst, vecY src, vecS shift) %{ + __ movdqu($tmp$$XMMRegister, ExternalAddress(vector_long_sign_mask()), $scratch$$Register); + __ psrlq($tmp$$XMMRegister, $shift$$XMMRegister); + __ pxor($dst$$XMMRegister, $tmp$$XMMRegister); + __ psubq($dst$$XMMRegister, $tmp$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra2L_reg_evex(vecX dst, vecX src, vecS shift) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 2); + match(Set dst (RShiftVL src shift)); + format %{ "evpsraq $dst,$src,$shift\t! arithmetic right shift packed2L" %} + ins_encode %{ + int vector_len = 0; + __ evpsraq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4L_reg(vecY dst, vecY src, vecS shift, vecY tmp, rRegI scratch) %{ predicate(UseAVX > 1 && n->as_Vector()->length() == 4); - match(Set dst (URShiftVL src shift)); - format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed4L" %} + match(Set dst (RShiftVL src shift)); + effect(TEMP dst, TEMP tmp, TEMP scratch); + format %{ "vpsrlq $dst,$src,$shift\n\t" + "vmovdqu $tmp,[0x8000000000000000]\n\t" + "vpsrlq $tmp,$tmp,$shift\n\t" + "vpxor $dst,$dst,$tmp\n\t" + "vpsubq $dst,$dst,$tmp\t! arithmetic right shift packed4L" %} ins_encode %{ int vector_len = 1; __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl4L_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 4); - match(Set dst (URShiftVL src shift)); - format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed4L" %} + __ vmovdqu($tmp$$XMMRegister, ExternalAddress(vector_long_sign_mask()), $scratch$$Register); + __ vpsrlq($tmp$$XMMRegister, $tmp$$XMMRegister, $shift$$XMMRegister, vector_len); + __ vpxor($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister, vector_len); + __ vpsubq($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vsra4L_reg_evex(vecY dst, vecY src, vecS shift) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 4); + match(Set dst (RShiftVL src shift)); + format %{ "evpsraq $dst,$src,$shift\t! arithmetic right shift packed4L" %} ins_encode %{ int vector_len = 1; - __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8L_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 8); - match(Set dst (URShiftVL src shift)); - format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed8L" %} - ins_encode %{ - int vector_len = 2; - __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsrl8L_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 8); - match(Set dst (URShiftVL src shift)); - format %{ "vpsrlq $dst,$src,$shift\t! logical right shift packed8L" %} - ins_encode %{ - int vector_len = 2; - __ vpsrlq($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// ------------------- ArithmeticRightShift ----------------------------------- - -// Shorts/Chars vector arithmetic right shift -instruct vsra2S(vecS dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVS dst shift)); - format %{ "psraw $dst,$shift\t! arithmetic right shift packed2S" %} - ins_encode %{ - __ psraw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra2S_imm(vecS dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVS dst shift)); - format %{ "psraw $dst,$shift\t! arithmetic right shift packed2S" %} - ins_encode %{ - __ psraw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra2S_reg(vecS dst, vecS src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed2S" %} - ins_encode %{ - int vector_len = 0; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra2S_reg_imm(vecS dst, vecS src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed2S" %} - ins_encode %{ - int vector_len = 0; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4S(vecD dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVS dst shift)); - format %{ "psraw $dst,$shift\t! arithmetic right shift packed4S" %} - ins_encode %{ - __ psraw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4S_imm(vecD dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVS dst shift)); - format %{ "psraw $dst,$shift\t! arithmetic right shift packed4S" %} - ins_encode %{ - __ psraw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4S_reg(vecD dst, vecD src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed4S" %} - ins_encode %{ - int vector_len = 0; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4S_reg_imm(vecD dst, vecD src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed4S" %} - ins_encode %{ - int vector_len = 0; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra8S(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 8); - match(Set dst (RShiftVS dst shift)); - format %{ "psraw $dst,$shift\t! arithmetic right shift packed8S" %} - ins_encode %{ - __ psraw($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra8S_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 8); - match(Set dst (RShiftVS dst shift)); - format %{ "psraw $dst,$shift\t! arithmetic right shift packed8S" %} - ins_encode %{ - __ psraw($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra8S_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 8); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed8S" %} - ins_encode %{ - int vector_len = 0; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra8S_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 8); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed8S" %} - ins_encode %{ - int vector_len = 0; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra16S_reg(vecY dst, vecY src, vecS shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 16); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed16S" %} - ins_encode %{ - int vector_len = 1; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra16S_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 16); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed16S" %} - ins_encode %{ - int vector_len = 1; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra32S_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed32S" %} - ins_encode %{ - int vector_len = 2; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra32S_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && VM_Version::supports_avx512bw() && n->as_Vector()->length() == 32); - match(Set dst (RShiftVS src shift)); - format %{ "vpsraw $dst,$src,$shift\t! arithmetic right shift packed32S" %} - ins_encode %{ - int vector_len = 2; - __ vpsraw($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// Integers vector arithmetic right shift -instruct vsra2I(vecD dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVI dst shift)); - format %{ "psrad $dst,$shift\t! arithmetic right shift packed2I" %} - ins_encode %{ - __ psrad($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra2I_imm(vecD dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVI dst shift)); - format %{ "psrad $dst,$shift\t! arithmetic right shift packed2I" %} - ins_encode %{ - __ psrad($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra2I_reg(vecD dst, vecD src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed2I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra2I_reg_imm(vecD dst, vecD src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 2); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed2I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4I(vecX dst, vecS shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVI dst shift)); - format %{ "psrad $dst,$shift\t! arithmetic right shift packed4I" %} - ins_encode %{ - __ psrad($dst$$XMMRegister, $shift$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4I_imm(vecX dst, immI8 shift) %{ - predicate(UseAVX == 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVI dst shift)); - format %{ "psrad $dst,$shift\t! arithmetic right shift packed4I" %} - ins_encode %{ - __ psrad($dst$$XMMRegister, (int)$shift$$constant); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4I_reg(vecX dst, vecX src, vecS shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed4I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra4I_reg_imm(vecX dst, vecX src, immI8 shift) %{ - predicate(UseAVX > 0 && n->as_Vector()->length() == 4); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed4I" %} - ins_encode %{ - int vector_len = 0; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra8I_reg(vecY dst, vecY src, vecS shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 8); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed8I" %} - ins_encode %{ - int vector_len = 1; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra8I_reg_imm(vecY dst, vecY src, immI8 shift) %{ - predicate(UseAVX > 1 && n->as_Vector()->length() == 8); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed8I" %} - ins_encode %{ - int vector_len = 1; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra16I_reg(vecZ dst, vecZ src, vecS shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 16); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed16I" %} - ins_encode %{ - int vector_len = 2; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -instruct vsra16I_reg_imm(vecZ dst, vecZ src, immI8 shift) %{ - predicate(UseAVX > 2 && n->as_Vector()->length() == 16); - match(Set dst (RShiftVI src shift)); - format %{ "vpsrad $dst,$src,$shift\t! arithmetic right shift packed16I" %} - ins_encode %{ - int vector_len = 2; - __ vpsrad($dst$$XMMRegister, $src$$XMMRegister, (int)$shift$$constant, vector_len); - %} - ins_pipe( pipe_slow ); -%} - -// There are no longs vector arithmetic right shift instructions. - + __ evpsraq($dst$$XMMRegister, $src$$XMMRegister, $shift$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} // --------------------------------- AND -------------------------------------- @@ -9708,6 +9297,291 @@ ins_pipe( pipe_slow ); %} +// --------------------------------- ABS -------------------------------------- +// a = |a| +instruct vabs4B_reg(vecS dst, vecS src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 4); + match(Set dst (AbsVB src)); + format %{ "pabsb $dst,$src\t# $dst = |$src| abs packed4B" %} + ins_encode %{ + __ pabsb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs8B_reg(vecD dst, vecD src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 8); + match(Set dst (AbsVB src)); + format %{ "pabsb $dst,$src\t# $dst = |$src| abs packed8B" %} + ins_encode %{ + __ pabsb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs16B_reg(vecX dst, vecX src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 16); + match(Set dst (AbsVB src)); + format %{ "pabsb $dst,$src\t# $dst = |$src| abs packed16B" %} + ins_encode %{ + __ pabsb($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs32B_reg(vecY dst, vecY src) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 32); + match(Set dst (AbsVB src)); + format %{ "vpabsb $dst,$src\t# $dst = |$src| abs packed32B" %} + ins_encode %{ + int vector_len = 1; + __ vpabsb($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs64B_reg(vecZ dst, vecZ src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 64); + match(Set dst (AbsVB src)); + format %{ "vpabsb $dst,$src\t# $dst = |$src| abs packed64B" %} + ins_encode %{ + int vector_len = 2; + __ vpabsb($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs2S_reg(vecD dst, vecD src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 2); + match(Set dst (AbsVS src)); + format %{ "pabsw $dst,$src\t# $dst = |$src| abs packed2S" %} + ins_encode %{ + __ pabsw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs4S_reg(vecD dst, vecD src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 4); + match(Set dst (AbsVS src)); + format %{ "pabsw $dst,$src\t# $dst = |$src| abs packed4S" %} + ins_encode %{ + __ pabsw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs8S_reg(vecX dst, vecX src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 8); + match(Set dst (AbsVS src)); + format %{ "pabsw $dst,$src\t# $dst = |$src| abs packed8S" %} + ins_encode %{ + __ pabsw($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs16S_reg(vecY dst, vecY src) %{ + predicate(UseAVX > 1 && n->as_Vector()->length() == 16); + match(Set dst (AbsVS src)); + format %{ "vpabsw $dst,$src\t# $dst = |$src| abs packed16S" %} + ins_encode %{ + int vector_len = 1; + __ vpabsw($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs32S_reg(vecZ dst, vecZ src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 32); + match(Set dst (AbsVS src)); + format %{ "vpabsw $dst,$src\t# $dst = |$src| abs packed32S" %} + ins_encode %{ + int vector_len = 2; + __ vpabsw($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs2I_reg(vecD dst, vecD src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 2); + match(Set dst (AbsVI src)); + format %{ "pabsd $dst,$src\t# $dst = |$src| abs packed2I" %} + ins_encode %{ + __ pabsd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs4I_reg(vecX dst, vecX src) %{ + predicate(UseSSE > 2 && n->as_Vector()->length() == 4); + match(Set dst (AbsVI src)); + format %{ "pabsd $dst,$src\t# $dst = |$src| abs packed4I" %} + ins_encode %{ + __ pabsd($dst$$XMMRegister, $src$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs8I_reg(vecY dst, vecY src) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AbsVI src)); + format %{ "vpabsd $dst,$src\t# $dst = |$src| abs packed8I" %} + ins_encode %{ + int vector_len = 1; + __ vpabsd($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs16I_reg(vecZ dst, vecZ src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (AbsVI src)); + format %{ "vpabsd $dst,$src\t# $dst = |$src| abs packed16I" %} + ins_encode %{ + int vector_len = 2; + __ vpabsd($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs2L_reg(vecX dst, vecX src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 2); + match(Set dst (AbsVL src)); + format %{ "evpabsq $dst,$src\t# $dst = |$src| abs packed2L" %} + ins_encode %{ + int vector_len = 0; + __ evpabsq($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs4L_reg(vecY dst, vecY src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 4); + match(Set dst (AbsVL src)); + format %{ "evpabsq $dst,$src\t# $dst = |$src| abs packed4L" %} + ins_encode %{ + int vector_len = 1; + __ evpabsq($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabs8L_reg(vecZ dst, vecZ src) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 8); + match(Set dst (AbsVL src)); + format %{ "evpabsq $dst,$src\t# $dst = |$src| abs packed8L" %} + ins_encode %{ + int vector_len = 2; + __ evpabsq($dst$$XMMRegister, $src$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// --------------------------------- ABSNEG -------------------------------------- + +instruct vabsneg2D(vecX dst, vecX src, rRegI scratch) %{ + predicate(UseSSE >= 2 && n->as_Vector()->length() == 2); + match(Set dst (AbsVD src)); + match(Set dst (NegVD src)); + effect(TEMP scratch); + format %{ "vabsnegd $dst,$src,[mask]\t# absneg packed2D" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdqu($dst$$XMMRegister, $src$$XMMRegister); + __ vabsnegd(opcode, $dst$$XMMRegister, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabsneg4D(vecY dst, vecY src, rRegI scratch) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 4); + match(Set dst (AbsVD src)); + match(Set dst (NegVD src)); + effect(TEMP scratch); + format %{ "vabsnegd $dst,$src,[mask]\t# absneg packed4D" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + int vector_len = 1; + __ vabsnegd(opcode, $dst$$XMMRegister, $src$$XMMRegister, vector_len, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabsneg8D(vecZ dst, vecZ src, rRegI scratch) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 8); + match(Set dst (AbsVD src)); + match(Set dst (NegVD src)); + effect(TEMP scratch); + format %{ "vabsnegd $dst,$src,[mask]\t# absneg packed8D" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + int vector_len = 2; + __ vabsnegd(opcode, $dst$$XMMRegister, $src$$XMMRegister, vector_len, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabsneg2F(vecD dst, vecD src, rRegI scratch) %{ + predicate(UseSSE > 0 && n->as_Vector()->length() == 2); + match(Set dst (AbsVF src)); + match(Set dst (NegVF src)); + effect(TEMP scratch); + format %{ "vabsnegf $dst,$src,[mask]\t# absneg packed2F" %} + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + if ($dst$$XMMRegister != $src$$XMMRegister) + __ movdqu($dst$$XMMRegister, $src$$XMMRegister); + __ vabsnegf(opcode, $dst$$XMMRegister, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabsneg4F(vecX dst, rRegI scratch) %{ + predicate(UseSSE > 0 && n->as_Vector()->length() == 4); + match(Set dst (AbsVF dst)); + match(Set dst (NegVF dst)); + effect(TEMP scratch); + format %{ "vabsnegf $dst,[mask]\t# absneg packed4F" %} + ins_cost(150); + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + __ vabsnegf(opcode, $dst$$XMMRegister, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabsneg8F(vecY dst, vecY src, rRegI scratch) %{ + predicate(UseAVX > 0 && n->as_Vector()->length() == 8); + match(Set dst (AbsVF src)); + match(Set dst (NegVF src)); + effect(TEMP scratch); + format %{ "vabsnegf $dst,$src,[mask]\t# absneg packed8F" %} + ins_cost(150); + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + int vector_len = 1; + __ vabsnegf(opcode, $dst$$XMMRegister, $src$$XMMRegister, vector_len, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + +instruct vabsneg16F(vecZ dst, vecZ src, rRegI scratch) %{ + predicate(UseAVX > 2 && n->as_Vector()->length() == 16); + match(Set dst (AbsVF src)); + match(Set dst (NegVF src)); + effect(TEMP scratch); + format %{ "vabsnegf $dst,$src,[mask]\t# absneg packed16F" %} + ins_cost(150); + ins_encode %{ + int opcode = this->as_Mach()->ideal_Opcode(); + int vector_len = 2; + __ vabsnegf(opcode, $dst$$XMMRegister, $src$$XMMRegister, vector_len, $scratch$$Register); + %} + ins_pipe( pipe_slow ); +%} + // --------------------------------- FMA -------------------------------------- // a * b + c diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/x86_32.ad --- a/src/hotspot/cpu/x86/x86_32.ad Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/x86_32.ad Tue May 07 17:30:14 2019 -0400 @@ -8949,6 +8949,28 @@ ins_pipe(ialu_reg_reg_alu0); %} +// Integer Absolute Instructions +instruct absI_rReg(rRegI dst, rRegI src, rRegI tmp, eFlagsReg cr) +%{ + match(Set dst (AbsI src)); + effect(TEMP dst, TEMP tmp, KILL cr); + format %{ "movl $tmp, $src\n\t" + "sarl $tmp, 31\n\t" + "movl $dst, $src\n\t" + "xorl $dst, $tmp\n\t" + "subl $dst, $tmp\n" + %} + ins_encode %{ + __ movl($tmp$$Register, $src$$Register); + __ sarl($tmp$$Register, 31); + __ movl($dst$$Register, $src$$Register); + __ xorl($dst$$Register, $tmp$$Register); + __ subl($dst$$Register, $tmp$$Register); + %} + + ins_pipe(ialu_reg_reg); +%} + //----------Long Instructions------------------------------------------------ // Add Long Register with Register instruct addL_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{ diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/cpu/x86/x86_64.ad --- a/src/hotspot/cpu/x86/x86_64.ad Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/cpu/x86/x86_64.ad Tue May 07 17:30:14 2019 -0400 @@ -8181,6 +8181,52 @@ ins_pipe( pipe_cmpxchg ); %} +//----------Abs Instructions------------------------------------------- + +// Integer Absolute Instructions +instruct absI_rReg(rRegI dst, rRegI src, rRegI tmp, rFlagsReg cr) +%{ + match(Set dst (AbsI src)); + effect(TEMP dst, TEMP tmp, KILL cr); + format %{ "movl $tmp, $src\n\t" + "sarl $tmp, 31\n\t" + "movl $dst, $src\n\t" + "xorl $dst, $tmp\n\t" + "subl $dst, $tmp\n" + %} + ins_encode %{ + __ movl($tmp$$Register, $src$$Register); + __ sarl($tmp$$Register, 31); + __ movl($dst$$Register, $src$$Register); + __ xorl($dst$$Register, $tmp$$Register); + __ subl($dst$$Register, $tmp$$Register); + %} + + ins_pipe(ialu_reg_reg); +%} + +// Long Absolute Instructions +instruct absL_rReg(rRegL dst, rRegL src, rRegL tmp, rFlagsReg cr) +%{ + match(Set dst (AbsL src)); + effect(TEMP dst, TEMP tmp, KILL cr); + format %{ "movq $tmp, $src\n\t" + "sarq $tmp, 63\n\t" + "movq $dst, $src\n\t" + "xorq $dst, $tmp\n\t" + "subq $dst, $tmp\n" + %} + ins_encode %{ + __ movq($tmp$$Register, $src$$Register); + __ sarq($tmp$$Register, 63); + __ movq($dst$$Register, $src$$Register); + __ xorq($dst$$Register, $tmp$$Register); + __ subq($dst$$Register, $tmp$$Register); + %} + + ins_pipe(ialu_reg_reg); +%} + //----------Subtraction Instructions------------------------------------------- // Integer Subtraction Instructions diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2018 SAP SE. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -302,7 +302,6 @@ address stub = NULL; address pc = NULL; - //%note os_trap_1 if (info != NULL && uc != NULL && thread != NULL) { pc = (address) os::Linux::ucontext_get_pc(uc); @@ -311,17 +310,17 @@ // si_addr may not be valid due to a bug in the linux-ppc64 kernel (see // comment below). Use get_stack_bang_address instead of si_addr. // If SIGSEGV is caused due to a branch to an invalid address an - // "Instruction Storage" interruption is generated and 'pc' (NIP) already + // "Instruction Storage Interrupt" is generated and 'pc' (NIP) already // contains the invalid address. Otherwise, the SIGSEGV is caused due to // load/store instruction trying to load/store from/to an invalid address - // and causing a "Data Storage" interruption, so we inspect the intruction + // and causing a "Data Storage Interrupt", so we inspect the intruction // in order to extract the faulty data addresss. address addr; if ((ucontext_get_trap(uc) & 0x0F00 /* no IRQ reply bits */) == 0x0400) { - // Instruction interruption + // Instruction Storage Interrupt (ISI) addr = pc; } else { - // Data interruption (0x0300): extract faulty data address + // Data Storage Interrupt (DSI), i.e. 0x0300: extract faulty data address addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/adlc/formssel.cpp --- a/src/hotspot/share/adlc/formssel.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/adlc/formssel.cpp Tue May 07 17:30:14 2019 -0400 @@ -3808,7 +3808,7 @@ "MaxI","MinI","MaxF","MinF","MaxD","MinD", "MaxV", "MinV", "MulI","MulL","MulF","MulD", - "MulVS","MulVI","MulVL","MulVF","MulVD", + "MulVB","MulVS","MulVI","MulVL","MulVF","MulVD", "OrI","OrL", "OrV", "XorI","XorL", @@ -4175,10 +4175,10 @@ static const char *vector_list[] = { "AddVB","AddVS","AddVI","AddVL","AddVF","AddVD", "SubVB","SubVS","SubVI","SubVL","SubVF","SubVD", - "MulVS","MulVI","MulVL","MulVF","MulVD", + "MulVB","MulVS","MulVI","MulVL","MulVF","MulVD", "CMoveVD", "CMoveVF", "DivVF","DivVD", - "AbsVF","AbsVD", + "AbsVB","AbsVS","AbsVI","AbsVL","AbsVF","AbsVD", "NegVF","NegVD", "SqrtVD","SqrtVF", "AndV" ,"XorV" ,"OrV", diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/c1/c1_GraphBuilder.cpp --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp Tue May 07 17:30:14 2019 -0400 @@ -1988,8 +1988,9 @@ } if (cha_monomorphic_target != NULL) { + assert(!target->can_be_statically_bound() || target == cha_monomorphic_target, ""); assert(!cha_monomorphic_target->is_abstract(), ""); - if (!target->is_final_method() && !target->is_private()) { + if (!cha_monomorphic_target->can_be_statically_bound(actual_recv)) { // If we inlined because CHA revealed only a single target method, // then we are dependent on that target method not getting overridden // by dynamic class loading. Be sure to test the "static" receiver diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/ci/ciMethod.cpp --- a/src/hotspot/share/ci/ciMethod.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/ci/ciMethod.cpp Tue May 07 17:30:14 2019 -0400 @@ -765,6 +765,14 @@ } // ------------------------------------------------------------------ +// ciMethod::can_be_statically_bound +// +// Tries to determine whether a method can be statically bound in some context. +bool ciMethod::can_be_statically_bound(ciInstanceKlass* context) const { + return (holder() == context) && can_be_statically_bound(); +} + +// ------------------------------------------------------------------ // ciMethod::resolve_invoke // // Given a known receiver klass, find the target for the call. diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/ci/ciMethod.hpp --- a/src/hotspot/share/ci/ciMethod.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/ci/ciMethod.hpp Tue May 07 17:30:14 2019 -0400 @@ -352,6 +352,8 @@ bool is_unboxing_method() const; bool is_object_initializer() const; + bool can_be_statically_bound(ciInstanceKlass* context) const; + // Replay data methods void dump_name_as_ascii(outputStream* st); void dump_replay_data(outputStream* st); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/classfile/vmSymbols.cpp --- a/src/hotspot/share/classfile/vmSymbols.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/classfile/vmSymbols.cpp Tue May 07 17:30:14 2019 -0400 @@ -363,6 +363,9 @@ case vmIntrinsics::_isInstance: case vmIntrinsics::_currentThread: case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: @@ -404,6 +407,9 @@ case vmIntrinsics::_longBitsToDouble: case vmIntrinsics::_currentThread: case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: @@ -567,6 +573,9 @@ case vmIntrinsics::_doubleToRawLongBits: case vmIntrinsics::_longBitsToDouble: case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/classfile/vmSymbols.hpp --- a/src/hotspot/share/classfile/vmSymbols.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/classfile/vmSymbols.hpp Tue May 07 17:30:14 2019 -0400 @@ -472,6 +472,7 @@ template(float_int_signature, "(F)I") \ template(double_long_signature, "(D)J") \ template(double_double_signature, "(D)D") \ + template(float_float_signature, "(F)F") \ template(int_float_signature, "(I)F") \ template(long_int_signature, "(J)I") \ template(long_long_signature, "(J)J") \ @@ -771,6 +772,9 @@ do_name(fma_name, "fma") \ \ do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \ + do_intrinsic(_fabs, java_lang_Math, abs_name, float_float_signature, F_S) \ + do_intrinsic(_iabs, java_lang_Math, abs_name, int_int_signature, F_S) \ + do_intrinsic(_labs, java_lang_Math, abs_name, long_long_signature, F_S) \ do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \ do_intrinsic(_dcos, java_lang_Math, cos_name, double_double_signature, F_S) \ do_intrinsic(_dtan, java_lang_Math, tan_name, double_double_signature, F_S) \ diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/code/dependencies.cpp --- a/src/hotspot/share/code/dependencies.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/code/dependencies.cpp Tue May 07 17:30:14 2019 -0400 @@ -108,6 +108,7 @@ void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) { check_ctxk(ctxk); + check_unique_method(ctxk, uniqm); assert_common_2(unique_concrete_method, ctxk, uniqm); } @@ -180,6 +181,7 @@ void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) { check_ctxk(ctxk); + check_unique_method(ctxk, uniqm); assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm)); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/code/dependencies.hpp --- a/src/hotspot/share/code/dependencies.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/code/dependencies.hpp Tue May 07 17:30:14 2019 -0400 @@ -27,6 +27,7 @@ #include "ci/ciCallSite.hpp" #include "ci/ciKlass.hpp" +#include "ci/ciMethod.hpp" #include "ci/ciMethodHandle.hpp" #include "classfile/systemDictionary.hpp" #include "code/compressedStream.hpp" @@ -341,6 +342,9 @@ check_ctxk(ctxk); assert(!is_concrete_klass(ctxk->as_instance_klass()), "must be abstract"); } + static void check_unique_method(ciKlass* ctxk, ciMethod* m) { + assert(!m->can_be_statically_bound(ctxk->as_instance_klass()), "redundant"); + } void assert_common_1(DepType dept, ciBaseObject* x); void assert_common_2(DepType dept, ciBaseObject* x0, ciBaseObject* x1); @@ -368,6 +372,11 @@ check_ctxk(ctxk); assert(ctxk->is_abstract(), "must be abstract"); } + static void check_unique_method(Klass* ctxk, Method* m) { + // Graal can register redundant dependencies + assert(UseJVMCICompiler || !m->can_be_statically_bound(InstanceKlass::cast(ctxk)), "redundant"); + } + void assert_common_1(DepType dept, DepValue x); void assert_common_2(DepType dept, DepValue x0, DepValue x1); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/compiler/compileBroker.cpp --- a/src/hotspot/share/compiler/compileBroker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/compiler/compileBroker.cpp Tue May 07 17:30:14 2019 -0400 @@ -70,7 +70,6 @@ #if INCLUDE_JVMCI #include "jvmci/jvmciEnv.hpp" #include "jvmci/jvmciRuntime.hpp" -#include "runtime/vframe.hpp" #endif #ifdef COMPILER2 #include "opto/c2compiler.hpp" @@ -1063,20 +1062,22 @@ } #if INCLUDE_JVMCI - if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) { + if (UseJVMCICompiler && blocking) { // Don't allow blocking compiles for requests triggered by JVMCI. if (thread->is_Compiler_thread()) { blocking = false; } - // Don't allow blocking compiles if inside a class initializer or while performing class loading - vframeStream vfst((JavaThread*) thread); - for (; !vfst.at_end(); vfst.next()) { - if (vfst.method()->is_static_initializer() || - (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) && - vfst.method()->name() == vmSymbols::loadClass_name())) { - blocking = false; - break; + if (!UseJVMCINativeLibrary) { + // Don't allow blocking compiles if inside a class initializer or while performing class loading + vframeStream vfst((JavaThread*) thread); + for (; !vfst.at_end(); vfst.next()) { + if (vfst.method()->is_static_initializer() || + (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) && + vfst.method()->name() == vmSymbols::loadClass_name())) { + blocking = false; + break; + } } } @@ -2063,7 +2064,7 @@ compilable = ciEnv::MethodCompilable_never; } else { JVMCICompileState compile_state(task, system_dictionary_modification_counter); - JVMCIEnv env(&compile_state, __FILE__, __LINE__); + JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__); methodHandle method(thread, target_handle); env.runtime()->compile_method(&env, jvmci, method, osr_bci); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/compiler/compileBroker.hpp --- a/src/hotspot/share/compiler/compileBroker.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/compiler/compileBroker.hpp Tue May 07 17:30:14 2019 -0400 @@ -229,7 +229,6 @@ static JavaThread* make_thread(jobject thread_oop, CompileQueue* queue, AbstractCompiler* comp, TRAPS); static void init_compiler_sweeper_threads(); static void possibly_add_compiler_threads(); - static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level); static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded); static void preload_classes (const methodHandle& method, TRAPS); @@ -285,6 +284,7 @@ return NULL; } + static bool compilation_is_complete(const methodHandle& method, int osr_bci, int comp_level); static bool compilation_is_in_queue(const methodHandle& method); static void print_compile_queues(outputStream* st); static void print_directives(outputStream* st); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1CollectedHeap.cpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp Tue May 07 17:30:14 2019 -0400 @@ -1036,7 +1036,7 @@ void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) { assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant"); - assert(used() == recalculate_used(), "Should be equal"); + assert_used_and_recalculate_used_equal(this); _verifier->verify_region_sets_optional(); _verifier->verify_before_gc(G1HeapVerifier::G1VerifyFull); _verifier->check_bitmaps("Full GC Start"); @@ -1092,7 +1092,7 @@ // the full GC has compacted objects and updated TAMS but not updated // the prev bitmap. if (G1VerifyBitmaps) { - GCTraceTime(Debug, gc)("Clear Prev Bitmap for Verification"); + GCTraceTime(Debug, gc) tm("Clear Prev Bitmap for Verification"); _cm->clear_prev_bitmap(workers()); } // This call implicitly verifies that the next bitmap is clear after Full GC. @@ -4539,9 +4539,7 @@ _archive_allocator->clear_used(); } } - assert(used() == recalculate_used(), - "inconsistent used(), value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT, - used(), recalculate_used()); + assert_used_and_recalculate_used_equal(this); } // Methods for the mutator alloc region diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1CollectedHeap.hpp --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp Tue May 07 17:30:14 2019 -0400 @@ -354,6 +354,15 @@ assert(Thread::current()->is_VM_thread(), "current thread is not VM thread"); \ } while (0) +#define assert_used_and_recalculate_used_equal(g1h) \ + do { \ + size_t cur_used_bytes = g1h->used(); \ + size_t recal_used_bytes = g1h->recalculate_used(); \ + assert(cur_used_bytes == recal_used_bytes, "Used(" SIZE_FORMAT ") is not" \ + " same as recalculated used(" SIZE_FORMAT ").", \ + cur_used_bytes, recal_used_bytes); \ + } while (0) + const char* young_gc_name() const; // The young region list. diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1FullCollector.cpp --- a/src/hotspot/share/gc/g1/g1FullCollector.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp Tue May 07 17:30:14 2019 -0400 @@ -289,6 +289,6 @@ // fail. At the end of the GC, the original mark word values // (including hash values) are restored to the appropriate // objects. - GCTraceTime(Info, gc, verify)("Verifying During GC (full)"); + GCTraceTime(Info, gc, verify) tm("Verifying During GC (full)"); _heap->verify(VerifyOption_G1UseFullMarking); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp Tue May 07 17:30:14 2019 -0400 @@ -65,7 +65,6 @@ _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):"); _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):"); _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):"); - _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms):"); _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms):"); if (G1HotCardCache::default_use_cache()) { @@ -406,7 +405,7 @@ trace_phase(_gc_par_phases[GCWorkerStart], false); debug_phase(_gc_par_phases[ExtRootScan]); - for (int i = ExtRootScanSubPhasesStart; i <= ExtRootScanSubPhasesEnd; i++) { + for (int i = ExtRootScanSubPhasesFirst; i <= ExtRootScanSubPhasesLast; i++) { trace_phase(_gc_par_phases[i]); } if (G1HotCardCache::default_use_cache()) { @@ -531,7 +530,6 @@ "CMRefRoots", "WaitForStrongCLD", "WeakCLDRoots", - "SATBFiltering", "UpdateRS", "ScanHCC", "ScanRS", diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp Tue May 07 17:30:14 2019 -0400 @@ -60,7 +60,6 @@ CMRefRoots, WaitForStrongCLD, WeakCLDRoots, - SATBFiltering, UpdateRS, ScanHCC, ScanRS, @@ -82,8 +81,8 @@ GCParPhasesSentinel }; - static const GCParPhases ExtRootScanSubPhasesStart = ThreadRoots; - static const GCParPhases ExtRootScanSubPhasesEnd = SATBFiltering; + static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots; + static const GCParPhases ExtRootScanSubPhasesLast = WeakCLDRoots; enum GCScanRSWorkItems { ScanRSScannedCards, diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1Policy.cpp --- a/src/hotspot/share/gc/g1/g1Policy.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1Policy.cpp Tue May 07 17:30:14 2019 -0400 @@ -487,10 +487,7 @@ assert(max_survivor_regions() + _g1h->num_used_regions() <= _g1h->max_regions(), "Maximum survivor regions %u plus used regions %u exceeds max regions %u", max_survivor_regions(), _g1h->num_used_regions(), _g1h->max_regions()); - - assert(_g1h->used() == _g1h->recalculate_used(), - "sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT, - _g1h->used(), _g1h->recalculate_used()); + assert_used_and_recalculate_used_equal(_g1h); phase_times()->record_cur_collection_start_sec(start_time_sec); _pending_cards = _g1h->pending_card_num(); @@ -581,8 +578,8 @@ void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc) { double end_time_sec = os::elapsedTime(); + assert_used_and_recalculate_used_equal(_g1h); size_t cur_used_bytes = _g1h->used(); - assert(cur_used_bytes == _g1h->recalculate_used(), "It should!"); bool this_pause_included_initial_mark = false; bool this_pause_was_young_only = collector_state()->in_young_only_phase(); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1RootProcessor.cpp --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp Tue May 07 17:30:14 2019 -0400 @@ -122,16 +122,6 @@ assert(closures->second_pass_weak_clds() == NULL, "Should be null if not tracing metadata."); } - // During conc marking we have to filter the per-thread SATB buffers - // to make sure we remove any oops into the CSet (which will show up - // as implicitly live). - { - G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i); - if (_process_strong_tasks.try_claim_task(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_or_rebuild_in_progress()) { - G1BarrierSet::satb_mark_queue_set().filter_thread_buffers(); - } - } - _process_strong_tasks.all_tasks_completed(n_workers()); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/g1/g1RootProcessor.hpp --- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp Tue May 07 17:30:14 2019 -0400 @@ -65,7 +65,6 @@ G1RP_PS_CodeCache_oops_do, AOT_ONLY(G1RP_PS_aot_oops_do COMMA) JVMCI_ONLY(G1RP_PS_JVMCI_oops_do COMMA) - G1RP_PS_filter_satb_buffers, G1RP_PS_refProcessor_oops_do, // Leave this one last. G1RP_PS_NumElements diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/shared/satbMarkQueue.cpp --- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp Tue May 07 17:30:14 2019 -0400 @@ -189,18 +189,6 @@ Threads::threads_do(&closure); } -void SATBMarkQueueSet::filter_thread_buffers() { - class FilterThreadBufferClosure : public ThreadClosure { - SATBMarkQueueSet* _qset; - public: - FilterThreadBufferClosure(SATBMarkQueueSet* qset) : _qset(qset) {} - virtual void do_thread(Thread* t) { - _qset->satb_queue_for_thread(t).filter(); - } - } closure(this); - Threads::threads_do(&closure); -} - bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) { BufferNode* nd = get_completed_buffer(); if (nd != NULL) { diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/shared/satbMarkQueue.hpp --- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp Tue May 07 17:30:14 2019 -0400 @@ -125,9 +125,6 @@ size_t buffer_enqueue_threshold() const { return _buffer_enqueue_threshold; } virtual void filter(SATBMarkQueue* queue) = 0; - // Filter all the currently-active SATB buffers. - void filter_thread_buffers(); - // If there exists some completed buffer, pop and process it, and // return true. Otherwise return false. Processing a buffer // consists of applying the closure to the active range of the diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Tue May 07 17:30:14 2019 -0400 @@ -1333,8 +1333,8 @@ } } } - if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) { - CallNode* call = ctrl->in(0)->as_CallJava(); + if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) { + CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava(); CallProjections projs; call->extract_projections(&projs, false, false); @@ -1362,7 +1362,7 @@ if (idx < n->outcnt()) { Node* u = n->raw_out(idx); Node* c = phase->ctrl_or_self(u); - if (c == ctrl) { + if (phase->is_dominator(call, c) && phase->is_dominator(c, projs.fallthrough_proj)) { stack.set_index(idx+1); assert(!u->is_CFG(), ""); stack.push(u, 0); @@ -1404,14 +1404,11 @@ } } } else { - // assert(n_clone->outcnt() > 0, ""); - // assert(n->outcnt() > 0, ""); stack.pop(); clones.pop(); } } while (stack.size() > 0); assert(stack.size() == 0 && clones.size() == 0, ""); - ctrl = projs.fallthrough_catchproj; } } @@ -1950,6 +1947,9 @@ head->verify_strip_mined(0); } move_heap_stable_test_out_of_loop(iff, phase); + + AutoNodeBudget node_budget(phase); + if (loop->policy_unswitching(phase)) { if (head->is_strip_mined()) { OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop(); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Tue May 07 17:30:14 2019 -0400 @@ -45,10 +45,13 @@ FLAG_SET_DEFAULT(ShenandoahGCHeuristics, "passive"); FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false); + FLAG_SET_DEFAULT(ShenandoahLoadRefBarrier, false); FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier, false); FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, false); FLAG_SET_DEFAULT(ShenandoahCASBarrier, false); FLAG_SET_DEFAULT(ShenandoahCloneBarrier, false); + + FLAG_SET_DEFAULT(ShenandoahVerifyOptoBarriers, false); #endif #ifdef _LP64 @@ -106,6 +109,7 @@ // C2 barrier verification is only reliable when all default barriers are enabled if (ShenandoahVerifyOptoBarriers && (!FLAG_IS_DEFAULT(ShenandoahSATBBarrier) || + !FLAG_IS_DEFAULT(ShenandoahLoadRefBarrier) || !FLAG_IS_DEFAULT(ShenandoahKeepAliveBarrier) || !FLAG_IS_DEFAULT(ShenandoahStoreValEnqueueBarrier) || !FLAG_IS_DEFAULT(ShenandoahCASBarrier) || diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp Tue May 07 17:30:14 2019 -0400 @@ -619,6 +619,7 @@ guarantee(HumongousThresholdWords == 0, "we should only set it once"); HumongousThresholdWords = RegionSizeWords * ShenandoahHumongousThreshold / 100; + HumongousThresholdWords = align_down(HumongousThresholdWords, MinObjAlignment); assert (HumongousThresholdWords <= RegionSizeWords, "sanity"); guarantee(HumongousThresholdBytes == 0, "we should only set it once"); @@ -643,13 +644,14 @@ // // The whole thing is mitigated if Elastic TLABs are enabled. // + guarantee(MaxTLABSizeWords == 0, "we should only set it once"); + MaxTLABSizeWords = MIN2(ShenandoahElasticTLAB ? RegionSizeWords : (RegionSizeWords / 8), HumongousThresholdWords); + MaxTLABSizeWords = align_down(MaxTLABSizeWords, MinObjAlignment); + guarantee(MaxTLABSizeBytes == 0, "we should only set it once"); - MaxTLABSizeBytes = MIN2(ShenandoahElasticTLAB ? RegionSizeBytes : (RegionSizeBytes / 8), HumongousThresholdBytes); + MaxTLABSizeBytes = MaxTLABSizeWords * HeapWordSize; assert (MaxTLABSizeBytes > MinTLABSize, "should be larger"); - guarantee(MaxTLABSizeWords == 0, "we should only set it once"); - MaxTLABSizeWords = MaxTLABSizeBytes / HeapWordSize; - log_info(gc, init)("Regions: " SIZE_FORMAT " x " SIZE_FORMAT "%s", RegionCount, byte_size_in_proper_unit(RegionSizeBytes), proper_unit_for_byte_size(RegionSizeBytes)); log_info(gc, init)("Humongous object threshold: " SIZE_FORMAT "%s", diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp Tue May 07 17:30:14 2019 -0400 @@ -32,6 +32,8 @@ HeapWord* ShenandoahHeapRegion::allocate(size_t size, ShenandoahAllocRequest::Type type) { _heap->assert_heaplock_or_safepoint(); + assert(is_object_aligned(size), "alloc size breaks alignment: " SIZE_FORMAT, size); + HeapWord* obj = top(); if (pointer_delta(end(), obj) >= size) { make_regular_allocation(); @@ -39,7 +41,9 @@ HeapWord* new_top = obj + size; set_top(new_top); - assert(is_aligned(obj) && is_aligned(new_top), "checking alignment"); + + assert(is_object_aligned(new_top), "new top breaks alignment: " PTR_FORMAT, p2i(new_top)); + assert(is_object_aligned(obj), "obj is not aligned: " PTR_FORMAT, p2i(obj)); return obj; } else { diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/z/zGranuleMap.hpp --- a/src/hotspot/share/gc/z/zGranuleMap.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/z/zGranuleMap.hpp Tue May 07 17:30:14 2019 -0400 @@ -35,10 +35,10 @@ friend class ZGranuleMapIterator<T>; private: - T* const _map; + const size_t _size; + T* const _map; size_t index_for_addr(uintptr_t addr) const; - size_t size() const; public: ZGranuleMap(); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/gc/z/zGranuleMap.inline.hpp --- a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp Tue May 07 17:30:14 2019 -0400 @@ -31,11 +31,12 @@ template <typename T> inline ZGranuleMap<T>::ZGranuleMap() : - _map(MmapArrayAllocator<T>::allocate(size(), mtGC)) {} + _size(ZAddressOffsetMax >> ZGranuleSizeShift), + _map(MmapArrayAllocator<T>::allocate(_size, mtGC)) {} template <typename T> inline ZGranuleMap<T>::~ZGranuleMap() { - MmapArrayAllocator<T>::free(_map, size()); + MmapArrayAllocator<T>::free(_map, _size); } template <typename T> @@ -43,17 +44,12 @@ assert(!ZAddress::is_null(addr), "Invalid address"); const size_t index = ZAddress::offset(addr) >> ZGranuleSizeShift; - assert(index < size(), "Invalid index"); + assert(index < _size, "Invalid index"); return index; } template <typename T> -inline size_t ZGranuleMap<T>::size() const { - return ZAddressOffsetMax >> ZGranuleSizeShift; -} - -template <typename T> inline T ZGranuleMap<T>::get(uintptr_t addr) const { const size_t index = index_for_addr(addr); return _map[index]; @@ -83,7 +79,7 @@ template <typename T> inline bool ZGranuleMapIterator<T>::next(T* value) { - if (_next < _map->size()) { + if (_next < _map->_size) { *value = _map->_map[_next++]; return true; } @@ -94,7 +90,7 @@ template <typename T> inline bool ZGranuleMapIterator<T>::next(T** value) { - if (_next < _map->size()) { + if (_next < _map->_size) { *value = _map->_map + _next++; return true; } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/interpreter/abstractInterpreter.cpp --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp Tue May 07 17:30:14 2019 -0400 @@ -28,6 +28,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/bytecodeInterpreter.hpp" +#include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/interp_masm.hpp" @@ -36,6 +37,8 @@ #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/arrayOop.hpp" +#include "oops/constantPool.hpp" +#include "oops/cpCache.inline.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" #include "oops/oop.inline.hpp" @@ -240,9 +243,36 @@ // Return true if the interpreter can prove that the given bytecode has // not yet been executed (in Java semantics, not in actual operation). bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) { - Bytecodes::Code code = method()->code_at(bci); + BytecodeStream s(method, bci); + Bytecodes::Code code = s.next(); + + if (Bytecodes::is_invoke(code)) { + assert(!Bytecodes::must_rewrite(code), "invokes aren't rewritten"); + ConstantPool* cpool = method()->constants(); + + Bytecode invoke_bc(s.bytecode()); - if (!Bytecodes::must_rewrite(code)) { + switch (code) { + case Bytecodes::_invokedynamic: { + assert(invoke_bc.has_index_u4(code), "sanity"); + int method_index = invoke_bc.get_index_u4(code); + return cpool->invokedynamic_cp_cache_entry_at(method_index)->is_f1_null(); + } + case Bytecodes::_invokevirtual: // fall-through + case Bytecodes::_invokeinterface: // fall-through + case Bytecodes::_invokespecial: // fall-through + case Bytecodes::_invokestatic: { + if (cpool->has_preresolution()) { + return false; // might have been reached + } + assert(!invoke_bc.has_index_u4(code), "sanity"); + int method_index = invoke_bc.get_index_u2_cpcache(code); + Method* resolved_method = ConstantPool::method_at_if_loaded(cpool, method_index); + return (resolved_method == NULL); + } + default: ShouldNotReachHere(); + } + } else if (!Bytecodes::must_rewrite(code)) { // might have been reached return false; } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/interpreter/bytecodeStream.hpp --- a/src/hotspot/share/interpreter/bytecodeStream.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/interpreter/bytecodeStream.hpp Tue May 07 17:30:14 2019 -0400 @@ -170,6 +170,10 @@ // Construction BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { } + BytecodeStream(const methodHandle& method, int bci) : BaseBytecodeStream(method) { + set_start(bci); + } + // Iteration Bytecodes::Code next() { Bytecodes::Code raw_code, code; diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciCompilerToVM.cpp --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp Tue May 07 17:30:14 2019 -0400 @@ -62,12 +62,17 @@ return *this; } -void JNIHandleMark::push_jni_handle_block() { - JavaThread* thread = JavaThread::current(); +static void requireInHotSpot(const char* caller, JVMCI_TRAPS) { + if (!JVMCIENV->is_hotspot()) { + JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot call %s from JVMCI shared library", caller)); + } +} + +void JNIHandleMark::push_jni_handle_block(JavaThread* thread) { if (thread != NULL) { // Allocate a new block for JNI handles. // Inlined code from jni_PushLocalFrame() - JNIHandleBlock* java_handles = ((JavaThread*)thread)->active_handles(); + JNIHandleBlock* java_handles = thread->active_handles(); JNIHandleBlock* compile_handles = JNIHandleBlock::allocate_block(thread); assert(compile_handles != NULL && java_handles != NULL, "should not be NULL"); compile_handles->set_pop_frame_link(java_handles); @@ -75,8 +80,7 @@ } } -void JNIHandleMark::pop_jni_handle_block() { - JavaThread* thread = JavaThread::current(); +void JNIHandleMark::pop_jni_handle_block(JavaThread* thread) { if (thread != NULL) { // Release our JNI handle block JNIHandleBlock* compile_handles = thread->active_handles(); @@ -111,25 +115,88 @@ return Handle(Thread::current(), arg); } -// Entry to native method implementation that transitions current thread to '_thread_in_vm'. +// Bring the JVMCI compiler thread into the VM state. +#define JVMCI_VM_ENTRY_MARK \ + ThreadInVMfromNative __tiv(thread); \ + ResetNoHandleMark rnhm; \ + HandleMarkCleaner __hm(thread); \ + Thread* THREAD = thread; \ + debug_only(VMNativeEntryWrapper __vew;) + +// Native method block that transitions current thread to '_thread_in_vm'. +#define C2V_BLOCK(result_type, name, signature) \ + TRACE_CALL(result_type, jvmci_ ## name signature) \ + JVMCI_VM_ENTRY_MARK; \ + ResourceMark rm; \ + JNI_JVMCIENV(thread, env); + +static Thread* get_current_thread() { + return Thread::current_or_null_safe(); +} + +// Entry to native method implementation that transitions +// current thread to '_thread_in_vm'. #define C2V_VMENTRY(result_type, name, signature) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + Thread* base_thread = get_current_thread(); \ + if (base_thread == NULL) { \ + env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ + err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ + return; \ + } \ + assert(base_thread->is_Java_thread(), "just checking");\ + JavaThread* thread = (JavaThread*) base_thread; \ JVMCITraceMark jtm("CompilerToVM::" #name); \ - TRACE_CALL(result_type, jvmci_ ## name signature) \ - JVMCI_VM_ENTRY_MARK; \ - ResourceMark rm; \ - JNI_JVMCIENV(env); + C2V_BLOCK(result_type, name, signature) + +#define C2V_VMENTRY_(result_type, name, signature, result) \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + Thread* base_thread = get_current_thread(); \ + if (base_thread == NULL) { \ + env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ + err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ + return result; \ + } \ + assert(base_thread->is_Java_thread(), "just checking");\ + JavaThread* thread = (JavaThread*) base_thread; \ + JVMCITraceMark jtm("CompilerToVM::" #name); \ + C2V_BLOCK(result_type, name, signature) + +#define C2V_VMENTRY_NULL(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, NULL) +#define C2V_VMENTRY_0(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, 0) + +// Entry to native method implementation that does not transition +// current thread to '_thread_in_vm'. +#define C2V_VMENTRY_PREFIX(result_type, name, signature) \ + JNIEXPORT result_type JNICALL c2v_ ## name signature { \ + Thread* base_thread = get_current_thread(); #define C2V_END } +#define JNI_THROW(caller, name, msg) do { \ + jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ + if (__throw_res != JNI_OK) { \ + tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ + } \ + return; \ + } while (0); + +#define JNI_THROW_(caller, name, msg, result) do { \ + jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ + if (__throw_res != JNI_OK) { \ + tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ + } \ + return result; \ + } while (0) + jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS); -C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv* env)) +C2V_VMENTRY_NULL(jobjectArray, readConfiguration, (JNIEnv* env)) jobjectArray config = readConfiguration0(env, JVMCI_CHECK_NULL); return config; } -C2V_VMENTRY(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle)) +C2V_VMENTRY_NULL(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle)) #define RETURN_BOXED_LONG(value) jvalue p; p.j = (jlong) (value); JVMCIObject box = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); return box.as_jobject(); #define RETURN_BOXED_DOUBLE(value) jvalue p; p.d = (jdouble) (value); JVMCIObject box = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL); return box.as_jobject(); JVMCIObject name = JVMCIENV->wrap(name_handle); @@ -170,10 +237,8 @@ #undef RETURN_BOXED_DOUBLE C2V_END -C2V_VMENTRY(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address)) - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot"); - } +C2V_VMENTRY_NULL(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address)) + requireInHotSpot("getObjectAtAddress", JVMCI_CHECK_NULL); if (oop_address == 0) { JVMCI_THROW_MSG_NULL(InternalError, "Handle must be non-zero"); } @@ -184,7 +249,7 @@ return JNIHandles::make_local(obj); C2V_END -C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); int code_size = method->code_size(); @@ -262,12 +327,12 @@ return JVMCIENV->get_jbyteArray(result); C2V_END -C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jint, getExceptionTableLength, (JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); return method->exception_table_length(); C2V_END -C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jlong, getExceptionTableStart, (JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); if (method->exception_table_length() == 0) { return 0L; @@ -275,11 +340,8 @@ return (jlong) (address) method->exception_table_start(); C2V_END -C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle)) - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot"); - } - +C2V_VMENTRY_NULL(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle)) + requireInHotSpot("asResolvedJavaMethod", JVMCI_CHECK_NULL); oop executable = JNIHandles::resolve(executable_handle); oop mirror = NULL; int slot = 0; @@ -298,7 +360,7 @@ return JVMCIENV->get_jobject(result); } -C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset)) +C2V_VMENTRY_NULL(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset)) methodHandle method; JVMCIObject base_object = JVMCIENV->wrap(base); if (base_object.is_null()) { @@ -321,7 +383,7 @@ return JVMCIENV->get_jobject(result); } -C2V_VMENTRY(jobject, getConstantPool, (JNIEnv* env, jobject, jobject object_handle)) +C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, jobject object_handle)) constantPoolHandle cp; JVMCIObject object = JVMCIENV->wrap(object_handle); if (object.is_null()) { @@ -341,7 +403,7 @@ return JVMCIENV->get_jobject(result); } -C2V_VMENTRY(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed)) +C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed)) JVMCIKlassHandle klass(THREAD); JVMCIObject base_object = JVMCIENV->wrap(base); jlong base_address = 0; @@ -384,7 +446,7 @@ return JVMCIENV->get_jobject(result); } -C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method)) +C2V_VMENTRY_NULL(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); Klass* holder = JVMCIENV->asKlass(jvmci_type); if (holder->is_interface()) { @@ -400,7 +462,7 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jobject, getImplementor, (JNIEnv* env, jobject, jobject jvmci_type)) +C2V_VMENTRY_NULL(jobject, getImplementor, (JNIEnv* env, jobject, jobject jvmci_type)) Klass* klass = JVMCIENV->asKlass(jvmci_type); if (!klass->is_interface()) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), @@ -417,12 +479,12 @@ return JVMCIENV->get_jobject(implementor); C2V_END -C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); return method->is_ignored_by_security_stack_walk(); C2V_END -C2V_VMENTRY(jboolean, isCompilable,(JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jboolean, isCompilable,(JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); constantPoolHandle cp = method->constMethod()->constants(); assert(!cp.is_null(), "npe"); @@ -430,17 +492,17 @@ return !method->is_not_compilable(CompLevel_full_optimization) && !cp->has_dynamic_constant(); C2V_END -C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline(); C2V_END -C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); return CompilerOracle::should_inline(method) || method->force_inline(); C2V_END -C2V_VMENTRY(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jclass accessing_class, jboolean resolve)) +C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jclass accessing_class, jboolean resolve)) JVMCIObject name = JVMCIENV->wrap(jname); const char* str = JVMCIENV->as_utf8_string(name); TempNewSymbol class_name = SymbolTable::new_symbol(str, CHECK_NULL); @@ -465,6 +527,9 @@ if (resolve) { resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0); + if (resolved_klass == NULL) { + JVMCI_THROW_MSG_NULL(ClassNotFoundException, str); + } } else { if (class_name->char_at(0) == 'L' && class_name->char_at(class_name->utf8_length()-1) == ';') { @@ -483,7 +548,6 @@ TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(), class_name->utf8_length()-2-fd.dimension(), CHECK_0); - // naked oop "k" is OK here -- we assign back into it resolved_klass = SystemDictionary::find(strippedsym, class_loader, protection_domain, @@ -502,10 +566,8 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror)) - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot"); - } +C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror)) + requireInHotSpot("lookupClass", JVMCI_CHECK_NULL); if (mirror == NULL) { return NULL; } @@ -518,55 +580,56 @@ return JVMCIENV->get_jobject(result); } -C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_NULL(jobject, resolveConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); oop result = cp->resolve_constant_at(index, CHECK_NULL); return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result)); C2V_END -C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_NULL(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL); return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result)); C2V_END -C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_0(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); return cp->name_and_type_ref_index_at(index); C2V_END -C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which)) +C2V_VMENTRY_NULL(jobject, lookupNameInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); JVMCIObject sym = JVMCIENV->create_string(cp->name_ref_at(which), JVMCI_CHECK_NULL); return JVMCIENV->get_jobject(sym); C2V_END -C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which)) +C2V_VMENTRY_NULL(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); JVMCIObject sym = JVMCIENV->create_string(cp->signature_ref_at(which), JVMCI_CHECK_NULL); return JVMCIENV->get_jobject(sym); C2V_END -C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_0(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); return cp->klass_ref_index_at(index); C2V_END -C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_NULL(jobject, resolveTypeInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); Klass* klass = cp->klass_at(index, CHECK_NULL); JVMCIKlassHandle resolved_klass(THREAD, klass); if (resolved_klass->is_instance_klass()) { - bool linked = InstanceKlass::cast(resolved_klass())->link_class_or_fail(CHECK_NULL); - if (!linked) { - return NULL; + InstanceKlass::cast(resolved_klass())->link_class(CHECK_NULL); + if (!InstanceKlass::cast(resolved_klass())->is_linked()) { + // link_class() should not return here if there is an issue. + JVMCI_THROW_MSG_NULL(InternalError, err_msg("Class %s must be linked", resolved_klass()->external_name())); } } JVMCIObject klassObject = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL); return JVMCIENV->get_jobject(klassObject); C2V_END -C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) +C2V_VMENTRY_NULL(jobject, lookupKlassInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); Klass* loading_klass = cp->pool_holder(); bool is_accessible = false; @@ -594,13 +657,13 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_NULL(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index); return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(appendix_oop)); C2V_END -C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) +C2V_VMENTRY_NULL(jobject, lookupMethodInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); InstanceKlass* pool_holder = cp->pool_holder(); Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF); @@ -609,12 +672,12 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_0(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); return cp->remap_instruction_operand_from_cache(index); C2V_END -C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle)) +C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF); fieldDescriptor fd; @@ -632,7 +695,7 @@ return JVMCIENV->get_jobject(field_holder); C2V_END -C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method)) +C2V_VMENTRY_0(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method)) Klass* klass = JVMCIENV->asKlass(jvmci_type); Method* method = JVMCIENV->asMethod(jvmci_method); if (klass->is_interface()) { @@ -650,7 +713,7 @@ return LinkResolver::vtable_index_of_interface_method(klass, method); C2V_END -C2V_VMENTRY(jobject, resolveMethod, (JNIEnv* env, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type)) +C2V_VMENTRY_NULL(jobject, resolveMethod, (JNIEnv* env, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type)) Klass* recv_klass = JVMCIENV->asKlass(receiver_jvmci_type); Klass* caller_klass = JVMCIENV->asKlass(caller_jvmci_type); methodHandle method = JVMCIENV->asMethod(jvmci_method); @@ -697,13 +760,13 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type)) +C2V_VMENTRY_0(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type)) Klass* klass = JVMCIENV->asKlass(jvmci_type); assert(klass != NULL, "method must not be called for primitive types"); return Dependencies::find_finalizable_subclass(klass) != NULL; C2V_END -C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type)) +C2V_VMENTRY_NULL(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type)) Klass* klass = JVMCIENV->asKlass(jvmci_type); if (!klass->is_instance_klass()) { return NULL; @@ -713,7 +776,7 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr)) +C2V_VMENTRY_0(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr)) address target_addr = (address) addr; if (target_addr != 0x0) { int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); @@ -730,10 +793,10 @@ method->set_dont_inline(true); C2V_END -C2V_VMENTRY(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject compiled_code, +C2V_VMENTRY_0(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject installed_code, jlong failed_speculations_address, jbyteArray speculations_obj)) HandleMark hm; - JNIHandleMark jni_hm; + JNIHandleMark jni_hm(thread); JVMCIObject target_handle = JVMCIENV->wrap(target); JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code); @@ -791,7 +854,7 @@ return result; C2V_END -C2V_VMENTRY(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata)) +C2V_VMENTRY_0(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata)) #if INCLUDE_AOT HandleMark hm; assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode"); @@ -872,7 +935,7 @@ stats->_osr.reset(); C2V_END -C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode)) +C2V_VMENTRY_NULL(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode)) HandleMark hm; if (installedCode == NULL) { @@ -909,7 +972,7 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv* env, jobject, jobject jvmci_method, int bci)) +C2V_VMENTRY_NULL(jobject, getStackTraceElement, (JNIEnv* env, jobject, jobject jvmci_method, int bci)) HandleMark hm; methodHandle method = JVMCIENV->asMethod(jvmci_method); @@ -917,12 +980,10 @@ return JVMCIENV->get_jobject(element); C2V_END -C2V_VMENTRY(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod)) - if (env != JavaThread::current()->jni_environment()) { - // The incoming arguments array would have to contain JavaConstants instead of regular objects - // and the return value would have to be wrapped as a JavaConstant. - JVMCI_THROW_MSG_NULL(InternalError, "Wrapping of arguments is currently unsupported"); - } +C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod)) + // The incoming arguments array would have to contain JavaConstants instead of regular objects + // and the return value would have to be wrapped as a JavaConstant. + requireInHotSpot("executeHotSpotNmethod", JVMCI_CHECK_NULL); HandleMark hm; @@ -968,7 +1029,7 @@ } C2V_END -C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_NULL(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, jobject jvmci_method)) Method* method = JVMCIENV->asMethod(jvmci_method); if (!method->has_linenumber_table()) { return NULL; @@ -995,7 +1056,7 @@ return (jlongArray) JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, jobject jvmci_method)) Method* method = JVMCIENV->asMethod(jvmci_method); if (!method->has_localvariable_table()) { return 0; @@ -1003,7 +1064,7 @@ return (jlong) (address) method->localvariable_table_start(); C2V_END -C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, jobject jvmci_method)) Method* method = JVMCIENV->asMethod(jvmci_method); return method->localvariable_table_length(); C2V_END @@ -1037,18 +1098,23 @@ JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK); C2V_END -C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr)) +C2V_VMENTRY_NULL(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr)) oop ret = RawAccess<>::oop_load((oop*)(address)addr); return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(ret)); C2V_END -C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv* env, jobject)) +C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject)) + // Returns a zero length array if counters aren't enabled JVMCIPrimitiveArray array = JVMCIENV->new_longArray(JVMCICounterSize, JVMCI_CHECK_NULL); - JavaThread::collect_counters(JVMCIENV, array); + if (JVMCICounterSize > 0) { + jlong* temp_array = NEW_RESOURCE_ARRAY(jlong, JVMCICounterSize); + JavaThread::collect_counters(temp_array, JVMCICounterSize); + JVMCIENV->copy_longs_from(temp_array, array, 0, JVMCICounterSize); + } return (jlongArray) JVMCIENV->get_jobject(array); C2V_END -C2V_VMENTRY(int, allocateCompileId, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci)) +C2V_VMENTRY_0(int, allocateCompileId, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci)) HandleMark hm; if (jvmci_method == NULL) { JVMCI_THROW_0(NullPointerException); @@ -1061,17 +1127,17 @@ C2V_END -C2V_VMENTRY(jboolean, isMature, (JNIEnv* env, jobject, jlong metaspace_method_data)) +C2V_VMENTRY_0(jboolean, isMature, (JNIEnv* env, jobject, jlong metaspace_method_data)) MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data); return mdo != NULL && mdo->is_mature(); C2V_END -C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci, int comp_level)) +C2V_VMENTRY_0(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci, int comp_level)) Method* method = JVMCIENV->asMethod(jvmci_method); return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL; C2V_END -C2V_VMENTRY(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol)) +C2V_VMENTRY_NULL(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol)) JVMCIObject sym = JVMCIENV->create_string((Symbol*)(address)symbol, JVMCI_CHECK_NULL); return JVMCIENV->get_jobject(sym); C2V_END @@ -1102,16 +1168,14 @@ JavaCalls::call(result, method, args, CHECK); } -C2V_VMENTRY(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle)) +C2V_VMENTRY_NULL(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle)) if (!thread->has_last_Java_frame()) { return NULL; } Handle visitor(THREAD, JNIHandles::resolve_non_null(visitor_handle)); - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG_NULL(InternalError, "getNextStackFrame is only supported for HotSpot stack walking"); - } + requireInHotSpot("iterateFrames", JVMCI_CHECK_NULL); HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL); Handle frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL); @@ -1283,7 +1347,7 @@ } C2V_END -C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) +C2V_VMENTRY_0(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index)) constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool); ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index)); if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) { @@ -1324,7 +1388,7 @@ C2V_END -C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject)) +C2V_VMENTRY_NULL(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject)) JVMCIObjectArray holders = JVMCIENV->new_String_array(2, JVMCI_CHECK_NULL); JVMCIObject mh = JVMCIENV->create_string("Ljava/lang/invoke/MethodHandle;", JVMCI_CHECK_NULL); JVMCIObject vh = JVMCIENV->create_string("Ljava/lang/invoke/VarHandle;", JVMCI_CHECK_NULL); @@ -1333,7 +1397,7 @@ return JVMCIENV->get_jobject(holders); C2V_END -C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv* env, jobject)) +C2V_VMENTRY_0(jboolean, shouldDebugNonSafepoints, (JNIEnv* env, jobject)) //see compute_recording_non_safepoints in debugInfroRec.cpp if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) { return true; @@ -1348,9 +1412,7 @@ JVMCI_THROW_MSG(NullPointerException, "stack frame is null"); } - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG(InternalError, "getNextStackFrame is only supported for HotSpot stack walking"); - } + requireInHotSpot("materializeVirtualObjects", JVMCI_CHECK); JVMCIENV->HotSpotStackFrameReference_initialize(JVMCI_CHECK); @@ -1465,20 +1527,76 @@ HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE); C2V_END -C2V_VMENTRY(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length)) +// Creates a scope where the current thread is attached and detached +// from HotSpot if it wasn't already attached when entering the scope. +extern "C" void jio_printf(const char *fmt, ...); +class AttachDetach : public StackObj { + public: + bool _attached; + AttachDetach(JNIEnv* env, Thread* current_thread) { + if (current_thread == NULL) { + extern struct JavaVM_ main_vm; + JNIEnv* hotspotEnv; + jint res = main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL); + _attached = res == JNI_OK; + static volatile int report_attach_error = 0; + if (res != JNI_OK && report_attach_error == 0 && Atomic::cmpxchg(1, &report_attach_error, 0) == 0) { + // Only report an attach error once + jio_printf("Warning: attaching current thread to VM failed with %d (future attach errors are suppressed)\n", res); + } + } else { + _attached = false; + } + } + ~AttachDetach() { + if (_attached && get_current_thread() != NULL) { + extern struct JavaVM_ main_vm; + jint res = main_vm.DetachCurrentThread(); + static volatile int report_detach_error = 0; + if (res != JNI_OK && report_detach_error == 0 && Atomic::cmpxchg(1, &report_detach_error, 0) == 0) { + // Only report an attach error once + jio_printf("Warning: detaching current thread from VM failed with %d (future attach errors are suppressed)\n", res); + } + } + } +}; + +C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw)) + AttachDetach ad(env, base_thread); + bool use_tty = true; + if (base_thread == NULL) { + if (!ad._attached) { + // Can only use tty if the current thread is attached + return 0; + } + base_thread = get_current_thread(); + } + JVMCITraceMark jtm("writeDebugOutput"); + assert(base_thread->is_Java_thread(), "just checking"); + JavaThread* thread = (JavaThread*) base_thread; + C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length)) if (bytes == NULL) { - JVMCI_THROW(NullPointerException); + if (can_throw) { + JVMCI_THROW_0(NullPointerException); + } + return -1; } JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes); // Check if offset and length are non negative. if (offset < 0 || length < 0) { - JVMCI_THROW(ArrayIndexOutOfBoundsException); + if (can_throw) { + JVMCI_THROW_0(ArrayIndexOutOfBoundsException); + } + return -2; } // Check if the range is valid. int array_length = JVMCIENV->get_length(array); if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) { - JVMCI_THROW(ArrayIndexOutOfBoundsException); + if (can_throw) { + JVMCI_THROW_0(ArrayIndexOutOfBoundsException); + } + return -2; } jbyte buffer[O_BUFLEN]; while (length > 0) { @@ -1488,13 +1606,17 @@ length -= O_BUFLEN; offset += O_BUFLEN; } + if (flush) { + tty->flush(); + } + return 0; C2V_END C2V_VMENTRY(void, flushDebugOutput, (JNIEnv* env, jobject)) tty->flush(); C2V_END -C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong metaspace_method_data, jint position)) +C2V_VMENTRY_0(int, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong metaspace_method_data, jint position)) MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data); ProfileData* profile_data = mdo->data_at(position); if (mdo->is_valid(profile_data)) { @@ -1512,7 +1634,7 @@ JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Invalid profile data position %d", position)); C2V_END -C2V_VMENTRY(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass)) +C2V_VMENTRY_0(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass)) #if INCLUDE_AOT Klass *k = (Klass*) (address) metaspace_klass; if (k->is_instance_klass()) { @@ -1525,7 +1647,7 @@ #endif C2V_END -C2V_VMENTRY(jobject, getHostClass, (JNIEnv* env, jobject, jobject jvmci_type)) +C2V_VMENTRY_NULL(jobject, getHostClass, (JNIEnv* env, jobject, jobject jvmci_type)) InstanceKlass* k = InstanceKlass::cast(JVMCIENV->asKlass(jvmci_type)); InstanceKlass* host = k->unsafe_anonymous_host(); JVMCIKlassHandle handle(THREAD, host); @@ -1533,7 +1655,7 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type)) +C2V_VMENTRY_NULL(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type)) if (jvmci_type == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1560,7 +1682,7 @@ return JVMCIENV->get_jobject(interfaces); C2V_END -C2V_VMENTRY(jobject, getComponentType, (JNIEnv* env, jobject, jobject jvmci_type)) +C2V_VMENTRY_NULL(jobject, getComponentType, (JNIEnv* env, jobject, jobject jvmci_type)) if (jvmci_type == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1600,7 +1722,7 @@ } C2V_END -C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle)) +C2V_VMENTRY_0(int, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle)) if (bytecode_frame_handle == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1648,12 +1770,12 @@ } C2V_END -C2V_VMENTRY(int, getIdentityHashCode, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_0(int, getIdentityHashCode, (JNIEnv* env, jobject, jobject object)) Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0); return obj->identity_hash(); C2V_END -C2V_VMENTRY(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_0(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object)) Handle str = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0); if (!java_lang_String::is_instance(str())) { return false; @@ -1664,7 +1786,7 @@ C2V_END -C2V_VMENTRY(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_NULL(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object)) if (object == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1678,7 +1800,7 @@ return JVMCIENV->get_jobject(boxResult); C2V_END -C2V_VMENTRY(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_NULL(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object)) if (object == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1722,7 +1844,7 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, jobject holder)) +C2V_VMENTRY_NULL(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, jobject holder)) if (holder == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1751,7 +1873,7 @@ return JVMCIENV->get_jobjectArray(methods); C2V_END -C2V_VMENTRY(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobject holder)) +C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobject holder)) if (holder == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1780,7 +1902,7 @@ return JVMCIENV->get_jobjectArray(methods); C2V_END -C2V_VMENTRY(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile)) +C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile)) if (object == NULL || field == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1848,7 +1970,7 @@ return JVMCIENV->get_jobject(result); C2V_END -C2V_VMENTRY(jboolean, isInstance, (JNIEnv* env, jobject, jobject holder, jobject object)) +C2V_VMENTRY_0(jboolean, isInstance, (JNIEnv* env, jobject, jobject holder, jobject object)) if (object == NULL || holder == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1857,7 +1979,7 @@ return obj->is_a(klass); C2V_END -C2V_VMENTRY(jboolean, isAssignableFrom, (JNIEnv* env, jobject, jobject holder, jobject otherHolder)) +C2V_VMENTRY_0(jboolean, isAssignableFrom, (JNIEnv* env, jobject, jobject holder, jobject otherHolder)) if (holder == NULL || otherHolder == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1866,7 +1988,7 @@ return otherKlass->is_subtype_of(klass); C2V_END -C2V_VMENTRY(jboolean, isTrustedForIntrinsics, (JNIEnv* env, jobject, jobject holder)) +C2V_VMENTRY_0(jboolean, isTrustedForIntrinsics, (JNIEnv* env, jobject, jobject holder)) if (holder == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1877,7 +1999,7 @@ return false; C2V_END -C2V_VMENTRY(jobject, asJavaType, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_NULL(jobject, asJavaType, (JNIEnv* env, jobject, jobject object)) if (object == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1897,7 +2019,7 @@ C2V_END -C2V_VMENTRY(jobject, asString, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_NULL(jobject, asString, (JNIEnv* env, jobject, jobject object)) if (object == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1908,14 +2030,14 @@ C2V_END -C2V_VMENTRY(jboolean, equals, (JNIEnv* env, jobject, jobject x, jlong xHandle, jobject y, jlong yHandle)) +C2V_VMENTRY_0(jboolean, equals, (JNIEnv* env, jobject, jobject x, jlong xHandle, jobject y, jlong yHandle)) if (x == NULL || y == NULL) { JVMCI_THROW_0(NullPointerException); } return JVMCIENV->resolve_handle(xHandle) == JVMCIENV->resolve_handle(yHandle); C2V_END -C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv* env, jobject, jobject object)) +C2V_VMENTRY_NULL(jobject, getJavaMirror, (JNIEnv* env, jobject, jobject object)) if (object == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1934,7 +2056,7 @@ C2V_END -C2V_VMENTRY(jint, getArrayLength, (JNIEnv* env, jobject, jobject x)) +C2V_VMENTRY_0(jint, getArrayLength, (JNIEnv* env, jobject, jobject x)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1946,7 +2068,7 @@ C2V_END -C2V_VMENTRY(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index)) +C2V_VMENTRY_NULL(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1986,7 +2108,7 @@ C2V_END -C2V_VMENTRY(jint, arrayBaseOffset, (JNIEnv* env, jobject, jobject kind)) +C2V_VMENTRY_0(jint, arrayBaseOffset, (JNIEnv* env, jobject, jobject kind)) if (kind == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -1994,7 +2116,7 @@ return arrayOopDesc::header_size(type) * HeapWordSize; C2V_END -C2V_VMENTRY(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind)) +C2V_VMENTRY_0(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind)) if (kind == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -2002,7 +2124,7 @@ return type2aelembytes(type); C2V_END -C2V_VMENTRY(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement)) +C2V_VMENTRY_0(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -2010,7 +2132,7 @@ return xobj->byte_field(displacement); } -C2V_VMENTRY(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement)) +C2V_VMENTRY_0(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -2018,7 +2140,7 @@ return xobj->short_field(displacement); } -C2V_VMENTRY(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement)) +C2V_VMENTRY_0(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -2026,7 +2148,7 @@ return xobj->int_field(displacement); } -C2V_VMENTRY(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement)) +C2V_VMENTRY_0(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -2034,7 +2156,7 @@ return xobj->long_field(displacement); } -C2V_VMENTRY(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement)) +C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement)) if (x == NULL) { JVMCI_THROW_0(NullPointerException); } @@ -2052,30 +2174,38 @@ } } -C2V_VMENTRY(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror)) +static void requireJVMCINativeLibrary(JVMCI_TRAPS) { if (!UseJVMCINativeLibrary) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)"); + JVMCI_THROW_MSG(UnsupportedOperationException, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)"); } - if (!JVMCIENV->is_hotspot()) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "Cannot call registerNativeMethods from JVMCI shared library"); +} + +static JavaVM* requireNativeLibraryJavaVM(const char* caller, JVMCI_TRAPS) { + JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm(); + if (javaVM == NULL) { + JVMCI_THROW_MSG_NULL(IllegalStateException, err_msg("Require JVMCI shared library to be initialized in %s", caller)); } + return javaVM; +} + +C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror)) + requireJVMCINativeLibrary(JVMCI_CHECK_NULL); + requireInHotSpot("registerNativeMethods", JVMCI_CHECK_NULL); void* shared_library = JVMCIEnv::get_shared_library_handle(); if (shared_library == NULL) { // Ensure the JVMCI shared library runtime is initialized. - JVMCIEnv __peer_jvmci_env__(false, __FILE__, __LINE__); + JVMCIEnv __peer_jvmci_env__(thread, false, __FILE__, __LINE__); JVMCIEnv* peerEnv = &__peer_jvmci_env__; HandleMark hm; JVMCIRuntime* runtime = JVMCI::compiler_runtime(); JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv); if (peerEnv->has_pending_exception()) { peerEnv->describe_pending_exception(true); - JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime"); } shared_library = JVMCIEnv::get_shared_library_handle(); - } - - if (shared_library == NULL) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is unavailable"); + if (shared_library == NULL) { + JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime"); + } } if (mirror == NULL) { @@ -2113,15 +2243,18 @@ st.print_raw(pure_name); st.print_raw(long_name); os::print_jni_name_suffix_on(&st, args_size); - jni_name = st.as_string(); - entry = (address) os::dll_lookup(shared_library, jni_name); + char* jni_long_name = st.as_string(); + entry = (address) os::dll_lookup(shared_library, jni_long_name); + if (entry == NULL) { + JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]", + method->name_and_sig_as_C_string(), + jni_name, jni_long_name, JVMCIEnv::get_shared_library_path())); + } } - if (entry == NULL) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, method->name_and_sig_as_C_string()); - } + if (method->has_native_function() && entry != method->native_function()) { - JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("Cannot overwrite existing native implementation for %s", - method->name_and_sig_as_C_string())); + JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [cannot re-link from " PTR_FORMAT " to " PTR_FORMAT "]", + method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry))); } method->set_native_function(entry, Method::native_bind_event_is_interesting); if (PrintJNIResolving) { @@ -2141,11 +2274,102 @@ return (jlongArray) JVMCIENV->get_jobject(result); } -C2V_VMENTRY(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) +C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm)) + if (base_thread == NULL) { + // Called from unattached JVMCI shared library thread + return false; + } + JVMCITraceMark jtm("isCurrentThreadAttached"); + assert(base_thread->is_Java_thread(), "just checking"); + JavaThread* thread = (JavaThread*) base_thread; + if (thread->jni_environment() == env) { + C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject)) + requireJVMCINativeLibrary(JVMCI_CHECK_0); + JavaVM* javaVM = requireNativeLibraryJavaVM("isCurrentThreadAttached", JVMCI_CHECK_0); + JNIEnv* peerEnv; + return javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK; + } + return true; +C2V_END + +C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon)) + if (base_thread == NULL) { + // Called from unattached JVMCI shared library thread + extern struct JavaVM_ main_vm; + JNIEnv* hotspotEnv; + jint res = as_daemon ? main_vm.AttachCurrentThreadAsDaemon((void**)&hotspotEnv, NULL) : + main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL); + if (res != JNI_OK) { + JNI_THROW_("attachCurrentThread", InternalError, err_msg("Trying to attach thread returned %d", res), false); + } + return true; + } + JVMCITraceMark jtm("attachCurrentThread"); + assert(base_thread->is_Java_thread(), "just checking");\ + JavaThread* thread = (JavaThread*) base_thread; + if (thread->jni_environment() == env) { + // Called from HotSpot + C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean)) + requireJVMCINativeLibrary(JVMCI_CHECK_0); + JavaVM* javaVM = requireNativeLibraryJavaVM("attachCurrentThread", JVMCI_CHECK_0); + JavaVMAttachArgs attach_args; + attach_args.version = JNI_VERSION_1_2; + attach_args.name = thread->name(); + attach_args.group = NULL; + JNIEnv* peerEnv; + if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK) { + return false; + } + jint res = as_daemon ? javaVM->AttachCurrentThreadAsDaemon((void**)&peerEnv, &attach_args) : + javaVM->AttachCurrentThread((void**)&peerEnv, &attach_args); + if (res == JNI_OK) { + guarantee(peerEnv != NULL, "must be"); + return true; + } + JVMCI_THROW_MSG_0(InternalError, err_msg("Error %d while attaching %s", res, attach_args.name)); + } + // Called from JVMCI shared library + return false; +C2V_END + +C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm)) + if (base_thread == NULL) { + // Called from unattached JVMCI shared library thread + JNI_THROW("detachCurrentThread", IllegalStateException, err_msg("Cannot detach non-attached thread")); + } + JVMCITraceMark jtm("detachCurrentThread"); + assert(base_thread->is_Java_thread(), "just checking");\ + JavaThread* thread = (JavaThread*) base_thread; + if (thread->jni_environment() == env) { + // Called from HotSpot + C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject)) + requireJVMCINativeLibrary(JVMCI_CHECK); + requireInHotSpot("detachCurrentThread", JVMCI_CHECK); + JavaVM* javaVM = requireNativeLibraryJavaVM("detachCurrentThread", JVMCI_CHECK); + JNIEnv* peerEnv; + if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) != JNI_OK) { + JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot detach non-attached thread: %s", thread->name())); + } + jint res = javaVM->DetachCurrentThread(); + if (res != JNI_OK) { + JVMCI_THROW_MSG(InternalError, err_msg("Error %d while attaching %s", res, thread->name())); + } + } else { + // Called from attached JVMCI shared library thread + extern struct JavaVM_ main_vm; + jint res = main_vm.DetachCurrentThread(); + if (res != JNI_OK) { + JNI_THROW("detachCurrentThread", InternalError, err_msg("Cannot detach non-attached thread")); + } + } +C2V_END + +C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) + requireJVMCINativeLibrary(JVMCI_CHECK_0); if (obj_handle == NULL) { return 0L; } - JVMCIEnv __peer_jvmci_env__(!JVMCIENV->is_hotspot(), __FILE__, __LINE__); + JVMCIEnv __peer_jvmci_env__(thread, !JVMCIENV->is_hotspot(), __FILE__, __LINE__); JVMCIEnv* peerEnv = &__peer_jvmci_env__; JVMCIEnv* thisEnv = JVMCIENV; @@ -2216,7 +2440,8 @@ return (jlong) peerEnv->make_global(result).as_jobject(); } -C2V_VMENTRY(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle)) +C2V_VMENTRY_NULL(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle)) + requireJVMCINativeLibrary(JVMCI_CHECK_NULL); if (obj_handle == 0L) { return NULL; } @@ -2234,7 +2459,7 @@ JVMCIENV->asNmethod(code); } -C2V_VMENTRY(jbyteArray, getCode, (JNIEnv* env, jobject, jobject code_handle)) +C2V_VMENTRY_NULL(jbyteArray, getCode, (JNIEnv* env, jobject, jobject code_handle)) JVMCIObject code = JVMCIENV->wrap(code_handle); CodeBlob* cb = JVMCIENV->asCodeBlob(code); if (cb == NULL) { @@ -2246,10 +2471,8 @@ return JVMCIENV->get_jbyteArray(result); } -C2V_VMENTRY(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method)) - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot"); - } +C2V_VMENTRY_NULL(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method)) + requireInHotSpot("asReflectionExecutable", JVMCI_CHECK_NULL); methodHandle m = JVMCIENV->asMethod(jvmci_method); oop executable; if (m->is_initializer()) { @@ -2264,10 +2487,8 @@ return JNIHandles::make_local(THREAD, executable); } -C2V_VMENTRY(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index)) - if (env != JavaThread::current()->jni_environment()) { - JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot"); - } +C2V_VMENTRY_NULL(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index)) + requireInHotSpot("asReflectionField", JVMCI_CHECK_NULL); Klass* klass = JVMCIENV->asKlass(jvmci_type); if (!klass->is_instance_klass()) { JVMCI_THROW_MSG_NULL(IllegalArgumentException, @@ -2284,7 +2505,7 @@ return JNIHandles::make_local(env, reflected); } -C2V_VMENTRY(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current)) +C2V_VMENTRY_NULL(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current)) FailedSpeculation* head = *((FailedSpeculation**)(address) failed_speculations_address); int result_length = 0; for (FailedSpeculation* fs = head; fs != NULL; fs = fs->next()) { @@ -2316,7 +2537,7 @@ return JVMCIENV->get_jobjectArray(result); } -C2V_VMENTRY(jlong, getFailedSpeculationsAddress, (JNIEnv* env, jobject, jobject jvmci_method)) +C2V_VMENTRY_0(jlong, getFailedSpeculationsAddress, (JNIEnv* env, jobject, jobject jvmci_method)) methodHandle method = JVMCIENV->asMethod(jvmci_method); MethodData* method_data = method->method_data(); if (method_data == NULL) { @@ -2331,7 +2552,7 @@ FailedSpeculation::free_failed_speculations((FailedSpeculation**)(address) failed_speculations_address); } -C2V_VMENTRY(bool, addFailedSpeculation, (JNIEnv* env, jobject, jlong failed_speculations_address, jbyteArray speculation_obj)) +C2V_VMENTRY_0(bool, addFailedSpeculation, (JNIEnv* env, jobject, jlong failed_speculations_address, jbyteArray speculation_obj)) JVMCIPrimitiveArray speculation_handle = JVMCIENV->wrap(speculation_obj); int speculation_len = JVMCIENV->get_length(speculation_handle); char* speculation = NEW_RESOURCE_ARRAY(char, speculation_len); @@ -2431,7 +2652,7 @@ {CC "iterateFrames", CC "([" RESOLVED_METHOD "[" RESOLVED_METHOD "I" INSPECTED_FRAME_VISITOR ")" OBJECT, FN_PTR(iterateFrames)}, {CC "materializeVirtualObjects", CC "(" HS_STACK_FRAME_REF "Z)V", FN_PTR(materializeVirtualObjects)}, {CC "shouldDebugNonSafepoints", CC "()Z", FN_PTR(shouldDebugNonSafepoints)}, - {CC "writeDebugOutput", CC "([BII)V", FN_PTR(writeDebugOutput)}, + {CC "writeDebugOutput", CC "([BIIZZ)I", FN_PTR(writeDebugOutput)}, {CC "flushDebugOutput", CC "()V", FN_PTR(flushDebugOutput)}, {CC "methodDataProfileDataSize", CC "(JI)I", FN_PTR(methodDataProfileDataSize)}, {CC "getFingerprint", CC "(J)J", FN_PTR(getFingerprint)}, @@ -2469,6 +2690,9 @@ {CC "getObject", CC "(" OBJECTCONSTANT "J)" OBJECTCONSTANT, FN_PTR(getObject)}, {CC "deleteGlobalHandle", CC "(J)V", FN_PTR(deleteGlobalHandle)}, {CC "registerNativeMethods", CC "(" CLASS ")[J", FN_PTR(registerNativeMethods)}, + {CC "isCurrentThreadAttached", CC "()Z", FN_PTR(isCurrentThreadAttached)}, + {CC "attachCurrentThread", CC "(Z)Z", FN_PTR(attachCurrentThread)}, + {CC "detachCurrentThread", CC "()V", FN_PTR(detachCurrentThread)}, {CC "translate", CC "(" OBJECT ")J", FN_PTR(translate)}, {CC "unhand", CC "(J)" OBJECT, FN_PTR(unhand)}, {CC "updateHotSpotNmethod", CC "(" HS_NMETHOD ")V", FN_PTR(updateHotSpotNmethod)}, diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciCompilerToVM.hpp --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp Tue May 07 17:30:14 2019 -0400 @@ -160,13 +160,14 @@ }; class JNIHandleMark : public StackObj { + JavaThread* _thread; public: - JNIHandleMark() { push_jni_handle_block(); } - ~JNIHandleMark() { pop_jni_handle_block(); } + JNIHandleMark(JavaThread* thread) : _thread(thread) { push_jni_handle_block(thread); } + ~JNIHandleMark() { pop_jni_handle_block(_thread); } private: - static void push_jni_handle_block(); - static void pop_jni_handle_block(); + static void push_jni_handle_block(JavaThread* thread); + static void pop_jni_handle_block(JavaThread* thread); }; #endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciEnv.cpp --- a/src/hotspot/share/jvmci/jvmciEnv.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp Tue May 07 17:30:14 2019 -0400 @@ -129,11 +129,10 @@ } } -JNIEnv* JVMCIEnv::attach_shared_library() { +JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) { if (_shared_library_javavm == NULL) { MutexLocker locker(JVMCI_lock); if (_shared_library_javavm == NULL) { - char path[JVM_MAXPATHLEN]; char ebuf[1024]; if (JVMCILibPath != NULL) { @@ -179,85 +178,107 @@ } } } - JNIEnv* env; - if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) { - guarantee(env != NULL, "missing env"); - return env; - } - fatal("Error attaching current thread to JVMCI shared library JNI interface"); return NULL; } -void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) { +void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) { + assert(thread != NULL, "npe"); // By default there is only one runtime which is the compiler runtime. _runtime = JVMCI::compiler_runtime(); + _env = NULL; + _pop_frame_on_close = false; + _detach_on_close = false; if (!UseJVMCINativeLibrary) { // In HotSpot mode, JNI isn't used at all. _is_hotspot = true; - _env = NULL; return; } if (parent_env != NULL) { // If the parent JNI environment is non-null then figure out whether it // is a HotSpot or shared library JNIEnv and set the state appropriately. - JavaThread* thread = JavaThread::current(); - if (thread->jni_environment() == parent_env) { + _is_hotspot = thread->jni_environment() == parent_env; + if (_is_hotspot) { // Select the Java runtime _runtime = JVMCI::java_runtime(); - _is_hotspot = true; - _env = NULL; return; } + _env = parent_env; + return; + } + + // Running in JVMCI shared library mode so ensure the shared library + // is loaded and initialized and get a shared library JNIEnv + _is_hotspot = false; + _env = init_shared_library(thread); + + if (_env != NULL) { + // Creating the JVMCI shared library VM also attaches the current thread + _detach_on_close = true; + } else { + _shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2); + if (parent_env != NULL) { + // Even though there's a parent JNI env, there's no guarantee + // it was opened by a JVMCIEnv scope and thus may not have + // pushed a local JNI frame. As such, we use a new JNI local + // frame in this scope to ensure local JNI refs are collected + // in a timely manner after leaving this scope. + _env = parent_env; + } else { + ResourceMark rm; // Thread name is resource allocated + JavaVMAttachArgs attach_args; + attach_args.version = JNI_VERSION_1_2; + attach_args.name = thread->name(); + attach_args.group = NULL; + if (_shared_library_javavm->AttachCurrentThread((void**)&_env, &attach_args) != JNI_OK) { + fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name); + } + _detach_on_close = true; + } } - // Running in JVMCI shared library mode so get a shared library JNIEnv - _is_hotspot = false; - _env = attach_shared_library(); - assert(parent_env == NULL || _env == parent_env, "must be"); + assert(_env != NULL, "missing env"); + assert(_throw_to_caller == false, "must be"); - if (parent_env == NULL) { - // There is no parent shared library JNI env so push - // a JNI local frame to release all local handles in - // this JVMCIEnv scope when it's closed. - assert(_throw_to_caller == false, "must be"); - JNIAccessMark jni(this); - jint result = _env->PushLocalFrame(32); - if (result != JNI_OK) { - char message[256]; - jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line); - JVMCIRuntime::exit_on_pending_exception(this, message); - } + JNIAccessMark jni(this); + jint result = _env->PushLocalFrame(32); + if (result != JNI_OK) { + char message[256]; + jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line); + JVMCIRuntime::exit_on_pending_exception(this, message); } + _pop_frame_on_close = true; } -JVMCIEnv::JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line): +JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line): _throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) { - init_env_mode_runtime(NULL); + init_env_mode_runtime(thread, NULL); } JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line): _throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) { - init_env_mode_runtime(NULL); + init_env_mode_runtime(thread, NULL); } -JVMCIEnv::JVMCIEnv(JNIEnv* parent_env, const char* file, int line): +JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line): _throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) { - init_env_mode_runtime(parent_env); + init_env_mode_runtime(thread, parent_env); assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment"); } -void JVMCIEnv::init(bool is_hotspot, const char* file, int line) { +void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) { _compile_state = NULL; _throw_to_caller = false; _file = file; _line = line; if (is_hotspot) { _env = NULL; + _pop_frame_on_close = false; + _detach_on_close = false; _is_hotspot = true; _runtime = JVMCI::java_runtime(); } else { - init_env_mode_runtime(NULL); + init_env_mode_runtime(thread, NULL); } } @@ -324,7 +345,7 @@ } } } else { - if (!is_hotspot()) { + if (_pop_frame_on_close) { // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope. JNIAccessMark jni(this); jni()->PopLocalFrame(NULL); @@ -335,6 +356,10 @@ jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line); JVMCIRuntime::exit_on_pending_exception(this, message); } + + if (_detach_on_close) { + get_shared_library_javavm()->DetachCurrentThread(); + } } } @@ -463,26 +488,38 @@ } } -void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes) { - if (size_in_bytes == 0) { +void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) { + if (length == 0) { + return; + } + if (is_hotspot()) { + memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length); + } else { + JNIAccessMark jni(this); + jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest); + } +} +void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) { + if (length == 0) { return; } if (is_hotspot()) { - memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), size_in_bytes); + memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length); } else { JNIAccessMark jni(this); - jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, size_in_bytes, dest); + jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src); } } -void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes) { - if (size_in_bytes == 0) { + +void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) { + if (length == 0) { return; } if (is_hotspot()) { - memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, size_in_bytes); + memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong)); } else { JNIAccessMark jni(this); - jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, size_in_bytes, src); + jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src); } } @@ -612,6 +649,8 @@ DO_THROW(IllegalArgumentException) DO_THROW(InvalidInstalledCodeException) DO_THROW(UnsatisfiedLinkError) +DO_THROW(UnsupportedOperationException) +DO_THROW(ClassNotFoundException) #undef DO_THROW @@ -888,7 +927,7 @@ return JVMCIObject(); } jobject file_name = NULL; - if (file_name != NULL) { + if (file_name_sym != NULL) { file_name = jni()->NewStringUTF(file_name_sym->as_C_string()); if (jni()->ExceptionCheck()) { return JVMCIObject(); @@ -1323,14 +1362,15 @@ assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type"); oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant)); return Handle(THREAD, obj); - } else { - assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type"); + } else if (isa_IndirectHotSpotObjectConstantImpl(constant)) { jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant); oop result = resolve_handle(object_handle); if (result == NULL) { JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle()); } return Handle(THREAD, result); + } else { + JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle()); } } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciEnv.hpp --- a/src/hotspot/share/jvmci/jvmciEnv.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp Tue May 07 17:30:14 2019 -0400 @@ -36,15 +36,6 @@ class JVMCICompiler; class JVMCIRuntime; -// Bring the JVMCI compiler thread into the VM state. -#define JVMCI_VM_ENTRY_MARK \ - JavaThread* thread = JavaThread::current(); \ - ThreadInVMfromNative __tiv(thread); \ - ResetNoHandleMark rnhm; \ - HandleMarkCleaner __hm(thread); \ - Thread* THREAD = thread; \ - debug_only(VMNativeEntryWrapper __vew;) - #define JVMCI_EXCEPTION_CONTEXT \ JavaThread* thread=JavaThread::current(); \ Thread* THREAD = thread; @@ -154,24 +145,25 @@ static void* _shared_library_handle; // result of os::dll_load static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library - // Attaches the current thread to the JavaVM in the shared library, - // initializing the shared library VM first if necessary. - // Returns the JNI interface pointer of the current thread. - // The _shared_library_* fields are initialized by the first - // call to this method. - static JNIEnv* attach_shared_library(); + // Initializes the shared library JavaVM if not already initialized. + // Returns the JNI interface pointer for the current thread + // if initialization was performed by this call, NULL if + // initialization was performed by a previous call. + static JNIEnv* init_shared_library(JavaThread* thread); // Initializes the _env, _mode and _runtime fields. - void init_env_mode_runtime(JNIEnv* parent_env); + void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env); - void init(bool is_hotspot, const char* file, int line); + void init(JavaThread* thread, bool is_hotspot, const char* file, int line); - JNIEnv* _env; // JNI env for calling into shared library - JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime - bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in - bool _throw_to_caller; // Propagate an exception raised in this env to the caller? - const char* _file; // The file and ... - int _line; // ... line where this JNIEnv was created + JNIEnv* _env; // JNI env for calling into shared library + bool _pop_frame_on_close; // Must pop frame on close? + bool _detach_on_close; // Must detach on close? + JVMCIRuntime* _runtime; // Access to a HotSpotJVMCIRuntime + bool _is_hotspot; // Which heap is the HotSpotJVMCIRuntime in + bool _throw_to_caller; // Propagate an exception raised in this env to the caller? + const char* _file; // The file and ... + int _line; // ... line where this JNIEnv was created // Translates an exception on the HotSpot heap to an exception on // the shared library heap. The translation includes the stack and @@ -185,12 +177,12 @@ // scope closes so that it will be propagated back to Java. // The JVMCIEnv destructor translates the exception object for the // Java runtime if necessary. - JVMCIEnv(JNIEnv* env, const char* file, int line); + JVMCIEnv(JavaThread* thread, JNIEnv* env, const char* file, int line); // Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker. // An exception occurring within the scope must not be propagated back to // the CompileBroker. - JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line); + JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line); // Opens a JNIEnv scope for a call from within the VM. An exception occurring // within the scope must not be propagated back to the caller. @@ -198,20 +190,20 @@ // Opens a JNIEnv scope for accessing `for_object`. An exception occurring // within the scope must not be propagated back to the caller. - JVMCIEnv(JVMCIObject for_object, const char* file, int line) { + JVMCIEnv(JavaThread* thread, JVMCIObject for_object, const char* file, int line) { // A JNI call to access an object in the shared library heap // can block or take a long time so do not allow such access // on the VM thread. assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(), "cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object"); - init(for_object.is_hotspot(), file, line); + init(thread, for_object.is_hotspot(), file, line); } // Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true // otherwise for the shared library runtime. An exception occurring // within the scope must not be propagated back to the caller. - JVMCIEnv(bool is_hotspot, const char* file, int line) { - init(is_hotspot, file, line); + JVMCIEnv(JavaThread* thread, bool is_hotspot, const char* file, int line) { + init(thread, is_hotspot, file, line); } ~JVMCIEnv(); @@ -247,8 +239,10 @@ long get_long_at(JVMCIPrimitiveArray array, int index); void put_long_at(JVMCIPrimitiveArray array, int index, jlong value); - void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes); - void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes); + void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length); + void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length); + + void copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length); JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS); @@ -323,6 +317,8 @@ DO_THROW(IllegalArgumentException) DO_THROW(InvalidInstalledCodeException) DO_THROW(UnsatisfiedLinkError) + DO_THROW(UnsupportedOperationException) + DO_THROW(ClassNotFoundException) #undef DO_THROW diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciExceptions.hpp --- a/src/hotspot/share/jvmci/jvmciExceptions.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciExceptions.hpp Tue May 07 17:30:14 2019 -0400 @@ -32,8 +32,8 @@ #define JVMCIENV __jvmci_env__ #define JVMCI_TRAPS JVMCIEnv* JVMCIENV -#define JNI_JVMCIENV(env) \ - JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__); \ +#define JNI_JVMCIENV(thread, env) \ + JVMCIEnv __stack_jvmci_env__(thread, env, __FILE__, __LINE__); \ JVMCIEnv* JVMCIENV = &__stack_jvmci_env__ #define THREAD_JVMCIENV(thread) \ diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciJavaClasses.cpp --- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp Tue May 07 17:30:14 2019 -0400 @@ -356,6 +356,43 @@ jobject JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c); } +// Dumps symbols for public <init>() and <init>(String) methods of +// non-abstract Throwable subtypes known by the VM. This is to +// support the use of reflection in jdk.vm.ci.hotspot.TranslatedException.create(). +class ThrowableInitDumper : public SymbolClosure { + private: + fileStream* _st; + public: + ThrowableInitDumper(fileStream* st) { _st = st; } + void do_symbol(Symbol** p) { + Thread* THREAD = Thread::current(); + Symbol* name = *p; + if (name == NULL) { + return; + } + Klass* k = SystemDictionary::resolve_or_null(name, CHECK_EXIT); + if (k != NULL && k->is_instance_klass()) { + InstanceKlass* iklass = InstanceKlass::cast(k); + if (iklass->is_subclass_of(SystemDictionary::Throwable_klass()) && iklass->is_public() && !iklass->is_abstract()) { + const char* class_name = NULL; + Array<Method*>* methods = iklass->methods(); + for (int i = 0; i < methods->length(); i++) { + Method* m = methods->at(i); + if (m->name() == vmSymbols::object_initializer_name() && + m->is_public() && + (m->signature() == vmSymbols::void_method_signature() || m->signature() == vmSymbols::string_void_signature())) { + if (class_name == NULL) { + class_name = name->as_C_string(); + _st->print_cr("class %s", class_name); + } + _st->print_cr("method %s %s %s", class_name, m->name()->as_C_string(), m->signature()->as_C_string()); + } + } + } + } + } +}; + #define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string() /** * Initializes the JNI method and field ids used in JNIJVMCI. @@ -441,6 +478,8 @@ fileStream* st = JVMCIGlobals::get_jni_config_file(); DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM()); + ThrowableInitDumper dumper(st); + vmSymbols::symbols_do(&dumper); st->flush(); tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciJavaClasses.hpp --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp Tue May 07 17:30:14 2019 -0400 @@ -381,12 +381,18 @@ start_class(InternalError, java_lang_InternalError) \ jvmci_constructor(InternalError, "(Ljava/lang/String;)V") \ end_class \ + start_class(ClassNotFoundException, java_lang_ClassNotFoundException) \ + jvmci_constructor(ClassNotFoundException, "(Ljava/lang/String;)V") \ + end_class \ start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException) \ jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V") \ end_class \ start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError) \ jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V") \ end_class \ + start_class(UnsupportedOperationException, java_lang_UnsupportedOperationException) \ + jvmci_constructor(UnsupportedOperationException, "(Ljava/lang/String;)V") \ + end_class \ start_class(StackTraceElement, java_lang_StackTraceElement) \ object_field(StackTraceElement, declaringClass, "Ljava/lang/String;") \ object_field(StackTraceElement, methodName, "Ljava/lang/String;") \ diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmciRuntime.cpp --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp Tue May 07 17:30:14 2019 -0400 @@ -655,7 +655,7 @@ // private static JVMCIRuntime JVMCI.initializeRuntime() JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c)) - JNI_JVMCIENV(env); + JNI_JVMCIENV(thread, env); if (!EnableJVMCI) { JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled"); } @@ -877,7 +877,7 @@ fatal("check TLAB allocation code for address space conflicts"); #endif - JNI_JVMCIENV(env); + JNI_JVMCIENV(thread, env); if (!EnableJVMCI) { JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled"); @@ -1353,6 +1353,10 @@ compile_state->set_failure(true, "No OSR during boostrap"); return; } + if (JVMCI::shutdown_called()) { + compile_state->set_failure(false, "Avoiding compilation during shutdown"); + return; + } HandleMark hm; JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmci_globals.cpp --- a/src/hotspot/share/jvmci/jvmci_globals.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmci_globals.cpp Tue May 07 17:30:14 2019 -0400 @@ -83,7 +83,7 @@ } FLAG_SET_DEFAULT(EnableJVMCI, true); if (BootstrapJVMCI && UseJVMCINativeLibrary) { - jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary"); + jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary\n"); return false; } } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/jvmci_globals.hpp --- a/src/hotspot/share/jvmci/jvmci_globals.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/jvmci_globals.hpp Tue May 07 17:30:14 2019 -0400 @@ -53,7 +53,10 @@ "Prints properties used by the JVMCI compiler and exits") \ \ experimental(bool, BootstrapJVMCI, false, \ - "Bootstrap JVMCI before running Java main method") \ + "Bootstrap JVMCI before running Java main method. This " \ + "initializes the compile queue with a small set of methods " \ + "and processes the queue until it is empty. Combining this with " \ + "-XX:-TieredCompilation makes JVMCI compile more of itself.") \ \ experimental(bool, EagerJVMCI, false, \ "Force eager JVMCI initialization") \ diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/jvmci/vmStructs_jvmci.cpp --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp Tue May 07 17:30:14 2019 -0400 @@ -246,6 +246,10 @@ \ nonstatic_field(ObjArrayKlass, _element_klass, Klass*) \ \ + volatile_nonstatic_field(ObjectMonitor, _cxq, ObjectWaiter*) \ + volatile_nonstatic_field(ObjectMonitor, _EntryList, ObjectWaiter*) \ + volatile_nonstatic_field(ObjectMonitor, _succ, Thread*) \ + \ volatile_nonstatic_field(oopDesc, _mark, markOop) \ volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \ \ @@ -347,6 +351,7 @@ declare_toplevel_type(JVMCIEnv) \ declare_toplevel_type(LocalVariableTableElement) \ declare_toplevel_type(narrowKlass) \ + declare_toplevel_type(ObjectWaiter) \ declare_toplevel_type(Symbol*) \ declare_toplevel_type(vtableEntry) \ \ diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/oops/cpCache.cpp --- a/src/hotspot/share/oops/cpCache.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/oops/cpCache.cpp Tue May 07 17:30:14 2019 -0400 @@ -506,7 +506,7 @@ switch (invoke_code) { case Bytecodes::_invokeinterface: assert(f1->is_klass(), ""); - return klassItable::method_for_itable_index((InstanceKlass*)f1, f2_as_index()); + return f2_as_interface_method(); case Bytecodes::_invokestatic: case Bytecodes::_invokespecial: assert(!has_appendix(), ""); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/oops/instanceKlass.cpp --- a/src/hotspot/share/oops/instanceKlass.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/oops/instanceKlass.cpp Tue May 07 17:30:14 2019 -0400 @@ -2965,6 +2965,13 @@ // On-stack replacement stuff void InstanceKlass::add_osr_nmethod(nmethod* n) { +#ifndef PRODUCT + if (TieredCompilation) { + nmethod * prev = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), n->comp_level(), true); + assert(prev == NULL || !prev->is_in_use(), + "redundunt OSR recompilation detected. memory leak in CodeCache!"); + } +#endif // only one compilation can be active { // This is a short non-blocking critical region, so the no safepoint check is ok. @@ -3083,7 +3090,9 @@ } osr = osr->osr_link(); } - if (best != NULL && best->comp_level() >= comp_level && match_level == false) { + + assert(match_level == false || best == NULL, "shouldn't pick up anything if match_level is set"); + if (best != NULL && best->comp_level() >= comp_level) { return best; } return NULL; diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/oops/klass.cpp --- a/src/hotspot/share/oops/klass.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/oops/klass.cpp Tue May 07 17:30:14 2019 -0400 @@ -733,8 +733,9 @@ st->cr(); } +#define BULLET " - " + void Klass::oop_print_on(oop obj, outputStream* st) { - ResourceMark rm; // print title st->print_cr("%s ", internal_name()); obj->print_address_on(st); @@ -742,10 +743,13 @@ if (WizardMode) { // print header obj->mark()->print_on(st); + st->cr(); + st->print(BULLET"prototype_header: " INTPTR_FORMAT, p2i(_prototype_header)); + st->cr(); } // print class - st->print(" - klass: "); + st->print(BULLET"klass: "); obj->klass()->print_value_on(st); st->cr(); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/oops/markOop.cpp --- a/src/hotspot/share/oops/markOop.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/oops/markOop.cpp Tue May 07 17:30:14 2019 -0400 @@ -25,45 +25,40 @@ #include "precompiled.hpp" #include "oops/markOop.hpp" #include "runtime/thread.inline.hpp" -#include "runtime/objectMonitor.inline.hpp" +#include "runtime/objectMonitor.hpp" void markOopDesc::print_on(outputStream* st) const { - if (is_marked()) { + if (is_marked()) { // last bits = 11 st->print(" marked(" INTPTR_FORMAT ")", value()); - } else if (has_monitor()) { + } else if (has_monitor()) { // last bits = 10 // have to check has_monitor() before is_locked() st->print(" monitor(" INTPTR_FORMAT ")=", value()); ObjectMonitor* mon = monitor(); if (mon == NULL) { st->print("NULL (this should never be seen!)"); } else { - st->print("{contentions=0x%08x,waiters=0x%08x" - ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", - mon->contentions(), mon->waiters(), mon->recursions(), - p2i(mon->owner())); + mon->print_on(st); } - } else if (is_locked()) { - st->print(" locked(" INTPTR_FORMAT ")->", value()); - if (is_neutral()) { + } else if (is_locked()) { // last bits != 01 => 00 + // thin locked + st->print(" locked(" INTPTR_FORMAT ")", value()); + } else { + st->print(" mark("); + // Biased bit is 3rd rightmost bit + if (is_neutral()) { // last bits = 001 st->print("is_neutral"); if (has_no_hash()) { st->print(" no_hash"); } else { st->print(" hash=" INTPTR_FORMAT, hash()); } - st->print(" age=%d", age()); - } else if (has_bias_pattern()) { + } else if (has_bias_pattern()) { // last bits = 101 st->print("is_biased"); JavaThread* jt = biased_locker(); - st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt)); + st->print(" biased_locker=" INTPTR_FORMAT " epoch=%d", p2i(jt), bias_epoch()); } else { st->print("??"); } - } else { - assert(is_unlocked() || has_bias_pattern(), "just checking"); - st->print("mark("); - if (has_bias_pattern()) st->print("biased,"); - st->print("hash " INTPTR_FORMAT ",", hash()); - st->print("age %d)", age()); + st->print(" age=%d)", age()); } } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/oops/method.cpp --- a/src/hotspot/share/oops/method.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/oops/method.cpp Tue May 07 17:30:14 2019 -0400 @@ -624,6 +624,10 @@ return can_be_statically_bound(method_holder()->access_flags()); } +bool Method::can_be_statically_bound(InstanceKlass* context) const { + return (method_holder() == context) && can_be_statically_bound(); +} + bool Method::is_accessor() const { return is_getter() || is_setter(); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/oops/method.hpp --- a/src/hotspot/share/oops/method.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/oops/method.hpp Tue May 07 17:30:14 2019 -0400 @@ -619,6 +619,7 @@ // true if method needs no dynamic dispatch (final and/or no vtable entry) bool can_be_statically_bound() const; + bool can_be_statically_bound(InstanceKlass* context) const; bool can_be_statically_bound(AccessFlags class_access_flags) const; // returns true if the method has any backward branches. diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/bytecodeInfo.cpp --- a/src/hotspot/share/opto/bytecodeInfo.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/bytecodeInfo.cpp Tue May 07 17:30:14 2019 -0400 @@ -321,6 +321,35 @@ return false; } +bool InlineTree::is_not_reached(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile) { + if (!UseInterpreter) { + return false; // -Xcomp + } + if (profile.count() > 0) { + return false; // reachable according to profile + } + if (!callee_method->was_executed_more_than(0)) { + return true; // callee was never executed + } + if (caller_method->is_not_reached(caller_bci)) { + return true; // call site not resolved + } + if (profile.count() == -1) { + return false; // immature profile; optimistically treat as reached + } + assert(profile.count() == 0, "sanity"); + + // Profile info is scarce. + // Try to guess: check if the call site belongs to a start block. + // Call sites in a start block should be reachable if no exception is thrown earlier. + ciMethodBlocks* caller_blocks = caller_method->get_method_blocks(); + bool is_start_block = caller_blocks->block_containing(caller_bci)->start_bci() == 0; + if (is_start_block) { + return false; // treat the call reached as part of start block + } + return true; // give up and treat the call site as not reached +} + //-----------------------------try_to_inline----------------------------------- // return true if ok // Relocated from "InliningClosure::try_to_inline" @@ -372,7 +401,7 @@ // inline constructors even if they are not reached. } else if (forced_inline()) { // Inlining was forced by CompilerOracle, ciReplay or annotation - } else if (profile.count() == 0) { + } else if (is_not_reached(callee_method, caller_method, caller_bci, profile)) { // don't inline unreached call sites set_msg("call site not reached"); return false; diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/c2compiler.cpp --- a/src/hotspot/share/opto/c2compiler.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/c2compiler.cpp Tue May 07 17:30:14 2019 -0400 @@ -460,6 +460,9 @@ case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: case vmIntrinsics::_datan2: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dexp: diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/classes.hpp --- a/src/hotspot/share/opto/classes.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/classes.hpp Tue May 07 17:30:14 2019 -0400 @@ -30,6 +30,7 @@ macro(AbsD) macro(AbsF) macro(AbsI) +macro(AbsL) macro(AddD) macro(AddF) macro(AddI) @@ -335,6 +336,7 @@ macro(SubVL) macro(SubVF) macro(SubVD) +macro(MulVB) macro(MulVS) macro(MulVI) macro(MulReductionVI) @@ -349,6 +351,10 @@ macro(FmaVF) macro(DivVF) macro(DivVD) +macro(AbsVB) +macro(AbsVS) +macro(AbsVI) +macro(AbsVL) macro(AbsVF) macro(AbsVD) macro(NegVF) diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/doCall.cpp --- a/src/hotspot/share/opto/doCall.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/doCall.cpp Tue May 07 17:30:14 2019 -0400 @@ -1152,14 +1152,19 @@ cha_monomorphic_target = NULL; } } + if (cha_monomorphic_target != NULL) { // Hardwiring a virtual. - // If we inlined because CHA revealed only a single target method, - // then we are dependent on that target method not getting overridden - // by dynamic class loading. Be sure to test the "static" receiver - // dest_method here, as opposed to the actual receiver, which may - // falsely lead us to believe that the receiver is final or private. - dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target); + assert(!callee->can_be_statically_bound(), "should have been handled earlier"); + assert(!cha_monomorphic_target->is_abstract(), ""); + if (!cha_monomorphic_target->can_be_statically_bound(actual_receiver)) { + // If we inlined because CHA revealed only a single target method, + // then we are dependent on that target method not getting overridden + // by dynamic class loading. Be sure to test the "static" receiver + // dest_method here, as opposed to the actual receiver, which may + // falsely lead us to believe that the receiver is final or private. + dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target); + } return cha_monomorphic_target; } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/library_call.cpp --- a/src/hotspot/share/opto/library_call.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/library_call.cpp Tue May 07 17:30:14 2019 -0400 @@ -227,6 +227,7 @@ bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); bool inline_math_native(vmIntrinsics::ID id); bool inline_math(vmIntrinsics::ID id); + bool inline_double_math(vmIntrinsics::ID id); template <typename OverflowOp> bool inline_math_overflow(Node* arg1, Node* arg2); void inline_math_mathExact(Node* math, Node* test); @@ -533,6 +534,9 @@ case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: case vmIntrinsics::_dabs: + case vmIntrinsics::_fabs: + case vmIntrinsics::_iabs: + case vmIntrinsics::_labs: case vmIntrinsics::_datan2: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dexp: @@ -1793,7 +1797,7 @@ // public static double Math.sqrt(double) // public static double Math.log(double) // public static double Math.log10(double) -bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { +bool LibraryCallKit::inline_double_math(vmIntrinsics::ID id) { Node* arg = round_double_node(argument(0)); Node* n = NULL; switch (id) { @@ -1805,6 +1809,23 @@ return true; } +//------------------------------inline_math----------------------------------- +// public static float Math.abs(float) +// public static int Math.abs(int) +// public static long Math.abs(long) +bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { + Node* arg = argument(0); + Node* n = NULL; + switch (id) { + case vmIntrinsics::_fabs: n = new AbsFNode( arg); break; + case vmIntrinsics::_iabs: n = new AbsINode( arg); break; + case vmIntrinsics::_labs: n = new AbsLNode( arg); break; + default: fatal_unexpected_iid(id); break; + } + set_result(_gvn.transform(n)); + return true; +} + //------------------------------runtime_math----------------------------- bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) { assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(), @@ -1855,8 +1876,11 @@ runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); // These intrinsics are supported on all hardware - case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false; - case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_math(id) : false; + case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_double_math(id) : false; + case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_double_math(id) : false; + case vmIntrinsics::_fabs: return Matcher::match_rule_supported(Op_AbsF) ? inline_math(id) : false; + case vmIntrinsics::_iabs: return Matcher::match_rule_supported(Op_AbsI) ? inline_math(id) : false; + case vmIntrinsics::_labs: return Matcher::match_rule_supported(Op_AbsL) ? inline_math(id) : false; case vmIntrinsics::_dexp: return StubRoutines::dexp() != NULL ? diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/memnode.cpp --- a/src/hotspot/share/opto/memnode.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/memnode.cpp Tue May 07 17:30:14 2019 -0400 @@ -1047,11 +1047,11 @@ // Try harder before giving up. Unify base pointers with casts (e.g., raw/non-raw pointers). intptr_t st_off = 0; Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_off); - if (ld_base == NULL) return NULL; - if (st_base == NULL) return NULL; - if (ld_base->uncast() != st_base->uncast()) return NULL; - if (ld_off != st_off) return NULL; - if (ld_off == Type::OffsetBot) return NULL; + if (ld_base == NULL) return NULL; + if (st_base == NULL) return NULL; + if (!ld_base->eqv_uncast(st_base, /*keep_deps=*/true)) return NULL; + if (ld_off != st_off) return NULL; + if (ld_off == Type::OffsetBot) return NULL; // Same base, same offset. // Possible improvement for arrays: check index value instead of absolute offset. @@ -1062,6 +1062,7 @@ // (Actually, we haven't yet proven the Q's are the same.) // In other words, we are loading from a casted version of // the same pointer-and-offset that we stored to. + // Casted version may carry a dependency and it is respected. // Thus, we are able to replace L by V. } // Now prove that we have a LoadQ matched to a StoreQ, for some Q. diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/node.cpp --- a/src/hotspot/share/opto/node.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/node.cpp Tue May 07 17:30:14 2019 -0400 @@ -891,13 +891,15 @@ //-----------------------------uncast--------------------------------------- // %%% Temporary, until we sort out CheckCastPP vs. CastPP. // Strip away casting. (It is depth-limited.) -Node* Node::uncast() const { +// Optionally, keep casts with dependencies. +Node* Node::uncast(bool keep_deps) const { // Should be inline: //return is_ConstraintCast() ? uncast_helper(this) : (Node*) this; - if (is_ConstraintCast()) - return uncast_helper(this); - else + if (is_ConstraintCast()) { + return uncast_helper(this, keep_deps); + } else { return (Node*) this; + } } // Find out of current node that matches opcode. @@ -929,7 +931,7 @@ //---------------------------uncast_helper------------------------------------- -Node* Node::uncast_helper(const Node* p) { +Node* Node::uncast_helper(const Node* p, bool keep_deps) { #ifdef ASSERT uint depth_count = 0; const Node* orig_p = p; @@ -947,6 +949,9 @@ if (p == NULL || p->req() != 2) { break; } else if (p->is_ConstraintCast()) { + if (keep_deps && p->as_ConstraintCast()->carry_dependency()) { + break; // stop at casts with dependencies + } p = p->in(1); } else { break; diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/node.hpp --- a/src/hotspot/share/opto/node.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/node.hpp Tue May 07 17:30:14 2019 -0400 @@ -456,10 +456,10 @@ void setup_is_top(); // Strip away casting. (It is depth-limited.) - Node* uncast() const; + Node* uncast(bool keep_deps = false) const; // Return whether two Nodes are equivalent, after stripping casting. - bool eqv_uncast(const Node* n) const { - return (this->uncast() == n->uncast()); + bool eqv_uncast(const Node* n, bool keep_deps = false) const { + return (this->uncast(keep_deps) == n->uncast(keep_deps)); } // Find out of current node that matches opcode. @@ -470,7 +470,7 @@ bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4); private: - static Node* uncast_helper(const Node* n); + static Node* uncast_helper(const Node* n, bool keep_deps); // Add an output edge to the end of the list void add_out( Node *n ) { diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/parse.hpp --- a/src/hotspot/share/opto/parse.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/parse.hpp Tue May 07 17:30:14 2019 -0400 @@ -88,6 +88,10 @@ ciMethod* caller_method, JVMState* jvms, WarmCallInfo* wci_result); + bool is_not_reached(ciMethod* callee_method, + ciMethod* caller_method, + int caller_bci, + ciCallProfile& profile); void print_inlining(ciMethod* callee_method, int caller_bci, ciMethod* caller_method, bool success) const; diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/subnode.hpp --- a/src/hotspot/share/opto/subnode.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/subnode.hpp Tue May 07 17:30:14 2019 -0400 @@ -350,6 +350,17 @@ virtual uint ideal_reg() const { return Op_RegI; } }; +//------------------------------AbsLNode--------------------------------------- +// Absolute value a long. Since a naive graph involves control flow, we +// "match" it in the ideal world (so the control flow can be removed). +class AbsLNode : public AbsNode { +public: + AbsLNode( Node *in1 ) : AbsNode(in1) {} + virtual int Opcode() const; + const Type *bottom_type() const { return TypeLong::LONG; } + virtual uint ideal_reg() const { return Op_RegL; } +}; + //------------------------------AbsFNode--------------------------------------- // Absolute value a float, a common float-point idiom with a cheap hardware // implemention on most chips. Since a naive graph involves control flow, we diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/superword.cpp --- a/src/hotspot/share/opto/superword.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/superword.cpp Tue May 07 17:30:14 2019 -0400 @@ -2453,6 +2453,7 @@ } } else if (opc == Op_SqrtF || opc == Op_SqrtD || opc == Op_AbsF || opc == Op_AbsD || + opc == Op_AbsI || opc == Op_AbsL || opc == Op_NegF || opc == Op_NegD || opc == Op_PopCountI) { assert(n->req() == 2, "only one input expected"); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/vectornode.cpp --- a/src/hotspot/share/opto/vectornode.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/vectornode.cpp Tue May 07 17:30:14 2019 -0400 @@ -70,8 +70,8 @@ return Op_SubVD; case Op_MulI: switch (bt) { - case T_BOOLEAN: - case T_BYTE: return 0; // Unimplemented + case T_BOOLEAN:return 0; + case T_BYTE: return Op_MulVB; case T_CHAR: case T_SHORT: return Op_MulVS; case T_INT: return Op_MulVI; @@ -104,6 +104,18 @@ case Op_DivD: assert(bt == T_DOUBLE, "must be"); return Op_DivVD; + case Op_AbsI: + switch (bt) { + case T_BOOLEAN: + case T_CHAR: return 0; // abs does not make sense for unsigned + case T_BYTE: return Op_AbsVB; + case T_SHORT: return Op_AbsVS; + case T_INT: return Op_AbsVI; + default: ShouldNotReachHere(); return 0; + } + case Op_AbsL: + assert(bt == T_LONG, "must be"); + return Op_AbsVL; case Op_AbsF: assert(bt == T_FLOAT, "must be"); return Op_AbsVF; @@ -350,6 +362,7 @@ case Op_SubVF: return new SubVFNode(n1, n2, vt); case Op_SubVD: return new SubVDNode(n1, n2, vt); + case Op_MulVB: return new MulVBNode(n1, n2, vt); case Op_MulVS: return new MulVSNode(n1, n2, vt); case Op_MulVI: return new MulVINode(n1, n2, vt); case Op_MulVL: return new MulVLNode(n1, n2, vt); @@ -359,6 +372,10 @@ case Op_DivVF: return new DivVFNode(n1, n2, vt); case Op_DivVD: return new DivVDNode(n1, n2, vt); + case Op_AbsVB: return new AbsVBNode(n1, vt); + case Op_AbsVS: return new AbsVSNode(n1, vt); + case Op_AbsVI: return new AbsVINode(n1, vt); + case Op_AbsVL: return new AbsVLNode(n1, vt); case Op_AbsVF: return new AbsVFNode(n1, vt); case Op_AbsVD: return new AbsVDNode(n1, vt); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/opto/vectornode.hpp --- a/src/hotspot/share/opto/vectornode.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/opto/vectornode.hpp Tue May 07 17:30:14 2019 -0400 @@ -224,6 +224,14 @@ virtual int Opcode() const; }; +//------------------------------MulVBNode-------------------------------------- +// Vector multiply byte +class MulVBNode : public VectorNode { + public: + MulVBNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1, in2, vt) {} + virtual int Opcode() const; +}; + //------------------------------MulVSNode-------------------------------------- // Vector multiply short class MulVSNode : public VectorNode { @@ -360,6 +368,38 @@ virtual int Opcode() const; }; +//------------------------------AbsVBNode-------------------------------------- +// Vector Abs byte +class AbsVBNode : public VectorNode { +public: + AbsVBNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + virtual int Opcode() const; +}; + +//------------------------------AbsVSNode-------------------------------------- +// Vector Abs short +class AbsVSNode : public VectorNode { +public: + AbsVSNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + virtual int Opcode() const; +}; + +//------------------------------AbsVINode-------------------------------------- +// Vector Abs int +class AbsVINode : public VectorNode { +public: + AbsVINode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + virtual int Opcode() const; +}; + +//------------------------------AbsVLNode-------------------------------------- +// Vector Abs long +class AbsVLNode : public VectorNode { +public: + AbsVLNode(Node* in, const TypeVect* vt) : VectorNode(in, vt) {} + virtual int Opcode() const; +}; + //------------------------------AbsVFNode-------------------------------------- // Vector Abs float class AbsVFNode : public VectorNode { diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/prims/jvmti.xml --- a/src/hotspot/share/prims/jvmti.xml Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/prims/jvmti.xml Tue May 07 17:30:14 2019 -0400 @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="jvmti.xsl"?> <!-- - Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 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 @@ -24,7 +24,7 @@ --> <!DOCTYPE specification [ - <!ELEMENT specification (title, copyright, intro*, functionsection, errorsection, + <!ELEMENT specification (title, intro*, functionsection, errorsection, eventsection, datasection, issuessection, changehistory)> <!ATTLIST specification label CDATA #REQUIRED majorversion CDATA #REQUIRED @@ -34,8 +34,6 @@ <!ELEMENT title (#PCDATA|jvmti|tm)*> <!ATTLIST title subtitle CDATA #REQUIRED> - <!ELEMENT copyright ANY> - <!ELEMENT intro ANY> <!ATTLIST intro id CDATA #IMPLIED label CDATA ""> @@ -367,10 +365,6 @@ <tm>JVM</tm> Tool Interface </title> - <copyright> - Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. - </copyright> - <intro id="whatIs" label="What is the JVM Tool Interface?"> The <tm>JVM</tm> Tool Interface (<jvmti/>) is a programming interface used by development and monitoring tools. diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/prims/jvmti.xsl --- a/src/hotspot/share/prims/jvmti.xsl Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/prims/jvmti.xsl Tue May 07 17:30:14 2019 -0400 @@ -1,6 +1,6 @@ -<?xml version="1.0"?> +<?xml version="1.0"?> <!-- - Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2002, 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 @@ -20,14 +20,14 @@ 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. - + --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:import href="jvmtiLib.xsl"/> -<xsl:output method="html" indent="yes" +<xsl:output method="html" indent="yes" doctype-system="about:legacy-compat"/> <xsl:param name="development"></xsl:param> @@ -119,7 +119,7 @@ <li> <a href="#DataSection"><b>Data Types</b></a> <ul> - <xsl:for-each select="//basetypes"> + <xsl:for-each select="//basetypes"> <li> <a> <xsl:attribute name="href">#<xsl:value-of select="@id"/></xsl:attribute> @@ -204,7 +204,6 @@ <p id="ChangeHistory"/> <xsl:apply-templates select="changehistory"/> </div> - <xsl:apply-templates select="copyright"/> </body> </html> </xsl:template> @@ -220,12 +219,6 @@ </h3> </xsl:template> -<xsl:template match="copyright"> - <p> - <xsl:apply-templates/> - </p> -</xsl:template> - <xsl:template match="functionsection"> <div class="sep"/> <hr class="thick"/> @@ -286,7 +279,7 @@ <xsl:apply-templates select="$calltypes" mode="index"/> </ul> </xsl:if> - <xsl:variable name="cattypes" + <xsl:variable name="cattypes" select="(descendant::typedef|descendant::uniontypedef|descendant::capabilitiestypedef|descendant::constants[@kind='enum'])"/> <xsl:if test="count($cattypes)!=0"> <xsl:value-of select="@label"/> types: @@ -304,9 +297,9 @@ <xsl:value-of select="@label"/> </li> </xsl:for-each> - </ul> + </ul> </xsl:if> - <xsl:variable name="catconst" + <xsl:variable name="catconst" select="(descendant::constants[@kind!='enum'])"/> <xsl:if test="count($catconst)!=0"> <xsl:value-of select="@label"/> flags and constants: @@ -322,7 +315,7 @@ </a> </li> </xsl:for-each> - </ul> + </ul> </xsl:if> <xsl:apply-templates select="intro|typedef|uniontypedef|capabilitiestypedef"/> <div class="sep"/> @@ -334,7 +327,7 @@ <xsl:attribute name="id"> <xsl:value-of select="@id"/> </xsl:attribute> - + </hr> <xsl:apply-templates select="synopsis" mode="body"/> <blockquote> @@ -505,7 +498,7 @@ <xsl:when test="contains(@callbacksafe,'safe')"> This function may be called from the callbacks to the <a href="#Heap">Heap</a> iteration functions, or from the - event handlers for the + event handlers for the <a href="#GarbageCollectionStart"><code>GarbageCollectionStart</code></a>, <a href="#GarbageCollectionFinish"><code>GarbageCollectionFinish</code></a>, and <a href="#ObjectFree"><code>ObjectFree</code></a> events. @@ -536,7 +529,7 @@ <xsl:for-each select="parameters"> <xsl:apply-templates select="param[position()=1]" mode="signature"/> <xsl:for-each select="param[position()>1]"> - <xsl:text>, + <xsl:text>, </xsl:text> <xsl:apply-templates select="." mode="signature"/> </xsl:for-each> @@ -932,7 +925,7 @@ </a> <xsl:apply-templates select="description" mode="brief"/> </td> - </tr> + </tr> </xsl:when> <xsl:otherwise> <tr> @@ -949,12 +942,12 @@ </a> <xsl:apply-templates select="description" mode="brief"/> </td> - </tr> + </tr> <tr> <td> <pre> <xsl:apply-templates select="definition"/> - </pre> + </pre> </td> </tr> </xsl:otherwise> @@ -977,7 +970,7 @@ <xsl:when test=".=''"> <code> <xsl:value-of select="@id"/> - </code> + </code> </xsl:when> <xsl:otherwise> <xsl:apply-templates/> @@ -994,7 +987,7 @@ <xsl:when test=".=''"> <code> <xsl:value-of select="@id"/> - </code> + </code> </xsl:when> <xsl:otherwise> <xsl:apply-templates/> @@ -1010,7 +1003,7 @@ <xsl:when test=".=''"> <code> <xsl:value-of select="@id"/> - </code> + </code> </xsl:when> <xsl:otherwise> <xsl:apply-templates/> @@ -1038,7 +1031,7 @@ <xsl:template match="eventphaselist"> <xsl:variable name="phase" select="@phase"/> <ul> - <xsl:for-each select="//eventsection/event[@phase=$phase]"> + <xsl:for-each select="//eventsection/event[@phase=$phase]"> <li> <a> <xsl:attribute name="href">#<xsl:value-of select="@id"/></xsl:attribute> @@ -1064,7 +1057,7 @@ <cite> <xsl:text>The Java™ Virtual Machine Specification</xsl:text> <xsl:if test="count(@chapter)=1"> - <xsl:text>, Chapter </xsl:text> + <xsl:text>, Chapter </xsl:text> <xsl:value-of select="@chapter"/> </xsl:if> </cite> @@ -1155,18 +1148,18 @@ <tr> <td colspan="2"> <b>Optional Functionality:</b> might not be implemented for all - virtual machines. + virtual machines. <xsl:choose> <xsl:when test="count(required)=1"> - The following capability + The following capability </xsl:when> <xsl:otherwise> One of the following capabilities </xsl:otherwise> </xsl:choose> - (as returned by + (as returned by <a href="#GetCapabilities"><code>GetCapabilities</code></a>) - must be true to use this + must be true to use this <xsl:choose> <xsl:when test="ancestor::function"> function. @@ -1322,8 +1315,8 @@ <xsl:when test="contains($haserrors,'yes')"> <tr> <td colspan="2"> - This function returns either a - <a href="#universal-error">universal error</a> + This function returns either a + <a href="#universal-error">universal error</a> or one of the following errors </td> </tr> @@ -1342,7 +1335,7 @@ <xsl:otherwise> <tr> <td colspan="{$fullRowColspan}"> - This function returns a + This function returns a <a href="#universal-error">universal error</a> </td> </tr> @@ -1370,7 +1363,7 @@ <xsl:attribute name="href">#jvmtiCapabilities.<xsl:value-of select="@id"/></xsl:attribute> <code> <xsl:value-of select="@id"/> - </code> + </code> </a>. Use <a href="#AddCapabilities"><code>AddCapabilities</code></a>. </td> @@ -1412,7 +1405,7 @@ </tr> </xsl:if> </xsl:template> - + <xsl:template match="param" mode="errors2"> <xsl:variable name="haserrors2"> <xsl:apply-templates mode="haserrors2"/> @@ -1439,7 +1432,7 @@ </tr> </xsl:if> </xsl:template> - + <xsl:template match="description" mode="haserrors"> </xsl:template> @@ -1684,7 +1677,7 @@ </xsl:attribute> <code> <xsl:value-of select="ancestor::param/@id"/> - </code> + </code> </a> </xsl:template> @@ -1858,7 +1851,7 @@ </td> <td> <pre> - <xsl:text>void *reserved</xsl:text> + <xsl:text>void *reserved</xsl:text> <xsl:value-of select="$index"/> <xsl:text>;</xsl:text> </pre> diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/prims/whitebox.cpp --- a/src/hotspot/share/prims/whitebox.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/prims/whitebox.cpp Tue May 07 17:30:14 2019 -0400 @@ -1080,6 +1080,24 @@ return result; WB_END +WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION(env); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + + MethodData* mdo = mh->method_data(); + if (mdo == NULL) { + Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR); + mdo = mh->method_data(); + } + mdo->init(); + InvocationCounter* icnt = mdo->invocation_counter(); + InvocationCounter* bcnt = mdo->backedge_counter(); + // set i-counter according to TieredThresholdPolicy::is_method_profiled + icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold); + bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold); +WB_END + WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION(env); @@ -2209,6 +2227,8 @@ CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation}, {CC"enqueueInitializerForCompilation0", CC"(Ljava/lang/Class;I)Z", (void*)&WB_EnqueueInitializerForCompilation}, + {CC"markMethodProfiled", + CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_MarkMethodProfiled}, {CC"clearMethodState0", CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState}, {CC"lockCompilation", CC"()V", (void*)&WB_LockCompilation}, diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/deoptimization.cpp --- a/src/hotspot/share/runtime/deoptimization.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/deoptimization.cpp Tue May 07 17:30:14 2019 -0400 @@ -674,8 +674,7 @@ int top_frame_expression_stack_adjustment = 0; methodHandle mh(thread, iframe->interpreter_frame_method()); OopMapCache::compute_one_oop_map(mh, iframe->interpreter_frame_bci(), &mask); - BytecodeStream str(mh); - str.set_start(iframe->interpreter_frame_bci()); + BytecodeStream str(mh, iframe->interpreter_frame_bci()); int max_bci = mh->code_size(); // Get to the next bytecode if possible assert(str.bci() < max_bci, "bci in interpreter frame out of bounds"); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/java.cpp --- a/src/hotspot/share/runtime/java.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/java.cpp Tue May 07 17:30:14 2019 -0400 @@ -526,11 +526,31 @@ vm_direct_exit(code); } + // We'd like to add an entry to the XML log to show that the VM is + // terminating, but we can't safely do that here. The logic to make + // XML termination logging safe is tied to the termination of the + // VMThread, and it doesn't terminate on this exit path. See 8222534. + if (VMThread::vm_thread() != NULL) { + if (thread->is_Java_thread()) { + // We must be "in_vm" for the code below to work correctly. + // Historically there must have been some exit path for which + // that was not the case and so we set it explicitly - even + // though we no longer know what that path may be. + ((JavaThread*)thread)->set_thread_state(_thread_in_vm); + } + // Fire off a VM_Exit operation to bring VM to a safepoint and exit VM_Exit op(code); - if (thread->is_Java_thread()) - ((JavaThread*)thread)->set_thread_state(_thread_in_vm); + + // 4945125 The vm thread comes to a safepoint during exit. + // GC vm_operations can get caught at the safepoint, and the + // heap is unparseable if they are caught. Grab the Heap_lock + // to prevent this. The GC vm_operations will not be able to + // queue until after we release it, but we never do that as we + // are terminating the VM process. + MutexLocker ml(Heap_lock); + VMThread::execute(&op); // should never reach here; but in case something wrong with VM Thread. vm_direct_exit(code); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/objectMonitor.cpp --- a/src/hotspot/share/runtime/objectMonitor.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/objectMonitor.cpp Tue May 07 17:30:14 2019 -0400 @@ -1926,3 +1926,11 @@ DEBUG_ONLY(InitDone = true;) } + +void ObjectMonitor::print_on(outputStream* st) const { + // The minimal things to print for markOop printing, more can be added for debugging and logging. + st->print("{contentions=0x%08x,waiters=0x%08x" + ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", + contentions(), waiters(), recursions(), + p2i(owner())); +} diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/objectMonitor.hpp --- a/src/hotspot/share/runtime/objectMonitor.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/objectMonitor.hpp Tue May 07 17:30:14 2019 -0400 @@ -139,6 +139,7 @@ friend class ObjectSynchronizer; friend class ObjectWaiter; friend class VMStructs; + JVMCI_ONLY(friend class JVMCIVMStructs;) volatile markOop _header; // displaced object header word - mark void* volatile _object; // backward object pointer - strong root @@ -291,6 +292,9 @@ void notify(TRAPS); void notifyAll(TRAPS); + void print() const { print_on(tty); } + void print_on(outputStream* st) const; + // Use the following at your own risk intptr_t complete_exit(TRAPS); void reenter(intptr_t recursions, TRAPS); diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/thread.cpp Tue May 07 17:30:14 2019 -0400 @@ -1575,18 +1575,15 @@ return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread(); } -void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) { - if (JVMCICounterSize > 0) { - JavaThreadIteratorWithHandle jtiwh; - int len = jvmci_env->get_length(array); - for (int i = 0; i < len; i++) { - jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]); - } - for (; JavaThread *tp = jtiwh.next(); ) { - if (jvmci_counters_include(tp)) { - for (int i = 0; i < len; i++) { - jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]); - } +void JavaThread::collect_counters(jlong* array, int length) { + assert(length == JVMCICounterSize, "wrong value"); + for (int i = 0; i < length; i++) { + array[i] = _jvmci_old_thread_counters[i]; + } + for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) { + if (jvmci_counters_include(tp)) { + for (int i = 0; i < length; i++) { + array[i] += tp->_jvmci_counters[i]; } } } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/thread.hpp --- a/src/hotspot/share/runtime/thread.hpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/thread.hpp Tue May 07 17:30:14 2019 -0400 @@ -1152,7 +1152,7 @@ public: static jlong* _jvmci_old_thread_counters; - static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array); + static void collect_counters(jlong* array, int length); private: #endif // INCLUDE_JVMCI diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/tieredThresholdPolicy.cpp --- a/src/hotspot/share/runtime/tieredThresholdPolicy.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp Tue May 07 17:30:14 2019 -0400 @@ -353,6 +353,16 @@ TieredStopAtLevel > CompLevel_full_profile && max_method != NULL && is_method_profiled(max_method)) { max_task->set_comp_level(CompLevel_limited_profile); + + if (CompileBroker::compilation_is_complete(max_method, max_task->osr_bci(), CompLevel_limited_profile)) { + if (PrintTieredEvents) { + print_event(REMOVE_FROM_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level()); + } + compile_queue->remove_and_mark_stale(max_task); + max_method->clear_queued_for_compilation(); + return NULL; + } + if (PrintTieredEvents) { print_event(UPDATE_IN_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level()); } diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/vmOperations.cpp --- a/src/hotspot/share/runtime/vmOperations.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/vmOperations.cpp Tue May 07 17:30:14 2019 -0400 @@ -30,6 +30,7 @@ #include "gc/shared/isGCActiveMark.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "logging/logConfiguration.hpp" #include "memory/heapInspection.hpp" #include "memory/resourceArea.hpp" #include "oops/symbol.hpp" @@ -437,14 +438,14 @@ if (thr->is_Compiler_thread()) { #if INCLUDE_JVMCI CompilerThread* ct = (CompilerThread*) thr; - if (ct->compiler() == NULL || !ct->compiler()->is_jvmci() || !UseJVMCINativeLibrary) { + if (ct->compiler() == NULL || !ct->compiler()->is_jvmci()) { num_active_compiler_thread++; } else { - // When using a compiler in a JVMCI shared library, it's possible - // for one compiler thread to grab a lock in the shared library, - // enter HotSpot and go to sleep on the shutdown safepoint. Another - // JVMCI shared library compiler thread can then attempt to grab the - // lock and thus never make progress. + // A JVMCI compiler thread never accesses VM data structures + // while in _thread_in_native state so there's no need to wait + // for it and potentially add a 300 millisecond delay to VM + // shutdown. + num_active--; } #else num_active_compiler_thread++; @@ -469,6 +470,16 @@ } void VM_Exit::doit() { + + if (VerifyBeforeExit) { + HandleMark hm(VMThread::vm_thread()); + // Among other things, this ensures that Eden top is correct. + Universe::heap()->prepare_for_verify(); + // Silent verification so as not to pollute normal output, + // unless we really asked for it. + Universe::verify(); + } + CompileBroker::set_should_block(); // Wait for a short period for threads in native to block. Any thread @@ -480,10 +491,17 @@ set_vm_exited(); + // We'd like to call IdealGraphPrinter::clean_up() to finalize the + // XML logging, but we can't safely do that here. The logic to make + // XML termination logging safe is tied to the termination of the + // VMThread, and it doesn't terminate on this exit path. See 8222534. + // cleanup globals resources before exiting. exit_globals() currently // cleans up outputStream resources and PerfMemory resources. exit_globals(); + LogConfiguration::finalize(); + // Check for exit hook exit_hook_t exit_hook = Arguments::exit_hook(); if (exit_hook != NULL) { diff -r bf3d37105ef9 -r 51709d9aab69 src/hotspot/share/runtime/vmStructs.cpp --- a/src/hotspot/share/runtime/vmStructs.cpp Fri May 03 14:59:32 2019 -0400 +++ b/src/hotspot/share/runtime/vmStructs.cpp Tue May 07 17:30:14 2019 -0400 @@ -1758,6 +1758,10 @@ declare_c2_type(ReverseBytesLNode, Node) \ declare_c2_type(ReductionNode, Node) \ declare_c2_type(VectorNode, Node) \ + declare_c2_type(AbsVBNode, VectorNode) \ + declare_c2_type(AbsVSNode, VectorNode) \ + declare_c2_type(AbsVINode, VectorNode) \ + declare_c2_type(AbsVLNode, VectorNode) \ declare_c2_type(AddVBNode, VectorNode) \ declare_c2_type(AddVSNode, VectorNode) \ declare_c2_type(AddVINode, VectorNode) \ @@ -1774,6 +1778,7 @@ declare_c2_type(SubVLNode, VectorNode) \ declare_c2_type(SubVFNode, VectorNode) \ declare_c2_type(SubVDNode, VectorNode) \ + declare_c2_type(MulVBNode, VectorNode) \ declare_c2_type(MulVSNode, VectorNode) \ declare_c2_type(MulVLNode, VectorNode) \ declare_c2_type(MulReductionVLNode, ReductionNode) \ @@ -1782,6 +1787,8 @@ declare_c2_type(MulVFNode, VectorNode) \ declare_c2_type(MulReductionVFNode, ReductionNode) \ declare_c2_type(MulVDNode, VectorNode) \ + declare_c2_type(NegVFNode, VectorNode) \ + declare_c2_type(NegVDNode, VectorNode) \ declare_c2_type(FmaVDNode, VectorNode) \ declare_c2_type(FmaVFNode, VectorNode) \ declare_c2_type(CMoveVFNode, VectorNode) \ diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/lang/Math.java --- a/src/java.base/share/classes/java/lang/Math.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/lang/Math.java Tue May 07 17:30:14 2019 -0400 @@ -1353,6 +1353,7 @@ * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. */ + @HotSpotIntrinsicCandidate public static int abs(int a) { return (a < 0) ? -a : a; } @@ -1370,6 +1371,7 @@ * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. */ + @HotSpotIntrinsicCandidate public static long abs(long a) { return (a < 0) ? -a : a; } @@ -1394,6 +1396,7 @@ * @param a the argument whose absolute value is to be determined * @return the absolute value of the argument. */ + @HotSpotIntrinsicCandidate public static float abs(float a) { return (a <= 0.0F) ? 0.0F - a : a; } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/lang/String.java --- a/src/java.base/share/classes/java/lang/String.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/lang/String.java Tue May 07 17:30:14 2019 -0400 @@ -75,7 +75,7 @@ * System.out.println("abc"); * String cde = "cde"; * System.out.println("abc" + cde); - * String c = "abc".substring(2,3); + * String c = "abc".substring(2, 3); * String d = cde.substring(1, 2); * </pre></blockquote> * <p> @@ -2160,27 +2160,48 @@ * @since 1.5 */ public String replace(CharSequence target, CharSequence replacement) { - String tgtStr = target.toString(); + String trgtStr = target.toString(); String replStr = replacement.toString(); - int j = indexOf(tgtStr); - if (j < 0) { - return this; - } - int tgtLen = tgtStr.length(); - int tgtLen1 = Math.max(tgtLen, 1); int thisLen = length(); + int trgtLen = trgtStr.length(); + int replLen = replStr.length(); + + if (trgtLen > 0) { + if (trgtLen == 1 && replLen == 1) { + return replace(trgtStr.charAt(0), replStr.charAt(0)); + } - int newLenHint = thisLen - tgtLen + replStr.length(); - if (newLenHint < 0) { - throw new OutOfMemoryError(); + boolean thisIsLatin1 = this.isLatin1(); + boolean trgtIsLatin1 = trgtStr.isLatin1(); + boolean replIsLatin1 = replStr.isLatin1(); + String ret = (thisIsLatin1 && trgtIsLatin1 && replIsLatin1) + ? StringLatin1.replace(value, thisLen, + trgtStr.value, trgtLen, + replStr.value, replLen) + : StringUTF16.replace(value, thisLen, thisIsLatin1, + trgtStr.value, trgtLen, trgtIsLatin1, + replStr.value, replLen, replIsLatin1); + if (ret != null) { + return ret; + } + return this; + + } else { // trgtLen == 0 + int resultLen; + try { + resultLen = Math.addExact(thisLen, Math.multiplyExact( + Math.addExact(thisLen, 1), replLen)); + } catch (ArithmeticException ignored) { + throw new OutOfMemoryError(); + } + + StringBuilder sb = new StringBuilder(resultLen); + sb.append(replStr); + for (int i = 0; i < thisLen; ++i) { + sb.append(charAt(i)).append(replStr); + } + return sb.toString(); } - StringBuilder sb = new StringBuilder(newLenHint); - int i = 0; - do { - sb.append(this, i, j).append(replStr); - i = j + tgtLen; - } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0); - return sb.append(this, i, thisLen).toString(); } /** diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/lang/StringLatin1.java --- a/src/java.base/share/classes/java/lang/StringLatin1.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/lang/StringLatin1.java Tue May 07 17:30:14 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 @@ -42,6 +42,14 @@ final class StringLatin1 { + /** + * The maximum size of array to allocate (unless necessary). + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + public static char charAt(byte[] value, int index) { if (index < 0 || index >= value.length) { throw new StringIndexOutOfBoundsException(index); @@ -304,7 +312,7 @@ } if (i < len) { if (canEncode(newChar)) { - byte buf[] = new byte[len]; + byte[] buf = StringConcatHelper.newArray(len); for (int j = 0; j < i; j++) { // TBD arraycopy? buf[j] = value[j]; } @@ -330,6 +338,64 @@ return null; // for string to return this; } + public static String replace(byte[] value, int valLen, byte[] targ, + int targLen, byte[] repl, int replLen) + { + assert targLen > 0; + int i, j, p = 0; + if (valLen == 0 || (i = indexOf(value, valLen, targ, targLen, 0)) < 0) { + return null; // for string to return this; + } + + // find and store indices of substrings to replace + int[] pos = new int[16]; + pos[0] = i; + i += targLen; + while ((j = indexOf(value, valLen, targ, targLen, i)) > 0) { + if (++p == pos.length) { + int cap = p + (p >> 1); + // overflow-conscious code + if (cap - MAX_ARRAY_SIZE > 0) { + if (p == MAX_ARRAY_SIZE) { + throw new OutOfMemoryError(); + } + cap = MAX_ARRAY_SIZE; + } + pos = Arrays.copyOf(pos, cap); + } + pos[p] = j; + i = j + targLen; + } + + int resultLen; + try { + resultLen = Math.addExact(valLen, + Math.multiplyExact(++p, replLen - targLen)); + } catch (ArithmeticException ignored) { + throw new OutOfMemoryError(); + } + if (resultLen == 0) { + return ""; + } + + byte[] result = StringConcatHelper.newArray(resultLen); + int posFrom = 0, posTo = 0; + for (int q = 0; q < p; ++q) { + int nextPos = pos[q]; + while (posFrom < nextPos) { + result[posTo++] = value[posFrom++]; + } + posFrom += targLen; + for (int k = 0; k < replLen; ++k) { + result[posTo++] = repl[k]; + } + } + while (posFrom < valLen) { + result[posTo++] = value[posFrom++]; + } + return new String(result, LATIN1); + } + // case insensitive public static boolean regionMatchesCI(byte[] value, int toffset, byte[] other, int ooffset, int len) { diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/lang/StringUTF16.java --- a/src/java.base/share/classes/java/lang/StringUTF16.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/lang/StringUTF16.java Tue May 07 17:30:14 2019 -0400 @@ -574,7 +574,7 @@ } } if (i < len) { - byte buf[] = new byte[value.length]; + byte[] buf = new byte[value.length]; for (int j = 0; j < i; j++) { putChar(buf, j, getChar(value, j)); // TBD:arraycopy? } @@ -582,21 +582,145 @@ char c = getChar(value, i); putChar(buf, i, c == oldChar ? newChar : c); i++; - } - // Check if we should try to compress to latin1 - if (String.COMPACT_STRINGS && - !StringLatin1.canEncode(oldChar) && - StringLatin1.canEncode(newChar)) { - byte[] val = compress(buf, 0, len); - if (val != null) { - return new String(val, LATIN1); - } - } - return new String(buf, UTF16); + } + // Check if we should try to compress to latin1 + if (String.COMPACT_STRINGS && + !StringLatin1.canEncode(oldChar) && + StringLatin1.canEncode(newChar)) { + byte[] val = compress(buf, 0, len); + if (val != null) { + return new String(val, LATIN1); + } + } + return new String(buf, UTF16); } return null; } + public static String replace(byte[] value, int valLen, boolean valLat1, + byte[] targ, int targLen, boolean targLat1, + byte[] repl, int replLen, boolean replLat1) + { + assert targLen > 0; + assert !valLat1 || !targLat1 || !replLat1; + + // Possible combinations of the arguments/result encodings: + // +---+--------+--------+--------+-----------------------+ + // | # | VALUE | TARGET | REPL | RESULT | + // +===+========+========+========+=======================+ + // | 1 | Latin1 | Latin1 | UTF16 | null or UTF16 | + // +---+--------+--------+--------+-----------------------+ + // | 2 | Latin1 | UTF16 | Latin1 | null | + // +---+--------+--------+--------+-----------------------+ + // | 3 | Latin1 | UTF16 | UTF16 | null | + // +---+--------+--------+--------+-----------------------+ + // | 4 | UTF16 | Latin1 | Latin1 | null or UTF16 | + // +---+--------+--------+--------+-----------------------+ + // | 5 | UTF16 | Latin1 | UTF16 | null or UTF16 | + // +---+--------+--------+--------+-----------------------+ + // | 6 | UTF16 | UTF16 | Latin1 | null, Latin1 or UTF16 | + // +---+--------+--------+--------+-----------------------+ + // | 7 | UTF16 | UTF16 | UTF16 | null or UTF16 | + // +---+--------+--------+--------+-----------------------+ + + if (String.COMPACT_STRINGS && valLat1 && !targLat1) { + // combinations 2 or 3 + return null; // for string to return this; + } + + int i = (String.COMPACT_STRINGS && valLat1) + ? StringLatin1.indexOf(value, targ) : + (String.COMPACT_STRINGS && targLat1) + ? indexOfLatin1(value, targ) + : indexOf(value, targ); + if (i < 0) { + return null; // for string to return this; + } + + // find and store indices of substrings to replace + int j, p = 0; + int[] pos = new int[16]; + pos[0] = i; + i += targLen; + while ((j = ((String.COMPACT_STRINGS && valLat1) + ? StringLatin1.indexOf(value, valLen, targ, targLen, i) : + (String.COMPACT_STRINGS && targLat1) + ? indexOfLatin1(value, valLen, targ, targLen, i) + : indexOf(value, valLen, targ, targLen, i))) > 0) + { + if (++p == pos.length) { + int cap = p + (p >> 1); + // overflow-conscious code + if (cap - MAX_ARRAY_SIZE > 0) { + if (p == MAX_ARRAY_SIZE) { + throw new OutOfMemoryError(); + } + cap = MAX_ARRAY_SIZE; + } + pos = Arrays.copyOf(pos, cap); + } + pos[p] = j; + i = j + targLen; + } + + int resultLen; + try { + resultLen = Math.addExact(valLen, + Math.multiplyExact(++p, replLen - targLen)); + } catch (ArithmeticException ignored) { + throw new OutOfMemoryError(); + } + if (resultLen == 0) { + return ""; + } + + byte[] result = newBytesFor(resultLen); + int posFrom = 0, posTo = 0; + for (int q = 0; q < p; ++q) { + int nextPos = pos[q]; + if (String.COMPACT_STRINGS && valLat1) { + while (posFrom < nextPos) { + char c = (char)(value[posFrom++] & 0xff); + putChar(result, posTo++, c); + } + } else { + while (posFrom < nextPos) { + putChar(result, posTo++, getChar(value, posFrom++)); + } + } + posFrom += targLen; + if (String.COMPACT_STRINGS && replLat1) { + for (int k = 0; k < replLen; ++k) { + char c = (char)(repl[k] & 0xff); + putChar(result, posTo++, c); + } + } else { + for (int k = 0; k < replLen; ++k) { + putChar(result, posTo++, getChar(repl, k)); + } + } + } + if (String.COMPACT_STRINGS && valLat1) { + while (posFrom < valLen) { + char c = (char)(value[posFrom++] & 0xff); + putChar(result, posTo++, c); + } + } else { + while (posFrom < valLen) { + putChar(result, posTo++, getChar(value, posFrom++)); + } + } + + if (String.COMPACT_STRINGS && replLat1 && !targLat1) { + // combination 6 + byte[] lat1Result = compress(result, 0, resultLen); + if (lat1Result != null) { + return new String(lat1Result, LATIN1); + } + } + return new String(result, UTF16); + } + public static boolean regionMatchesCI(byte[] value, int toffset, byte[] other, int ooffset, int len) { int last = toffset + len; @@ -1430,6 +1554,15 @@ static final int MAX_LENGTH = Integer.MAX_VALUE >> 1; + + /** + * The maximum size of array to allocate (unless necessary). + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + // Used by trusted callers. Assumes all necessary bounds checks have // been done by the caller. diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/lang/constant/ClassDesc.java --- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java Tue May 07 17:30:14 2019 -0400 @@ -213,7 +213,7 @@ * @param moreNestedNames the unqualified name(s) of the remaining levels of * nested class * @return a {@linkplain ClassDesc} describing the nested class - * @throws NullPointerException if any argument is {@code null} + * @throws NullPointerException if any argument or its contents is {@code null} * @throws IllegalStateException if this {@linkplain ClassDesc} does not * describe a class or interface type * @throws IllegalArgumentException if the nested class name is invalid @@ -221,6 +221,11 @@ default ClassDesc nested(String firstNestedName, String... moreNestedNames) { if (!isClassOrInterface()) throw new IllegalStateException("Outer class is not a class or interface type"); + validateMemberName(firstNestedName, false); + requireNonNull(moreNestedNames); + for (String addNestedNames : moreNestedNames) { + validateMemberName(addNestedNames, false); + } return moreNestedNames.length == 0 ? nested(firstNestedName) : nested(firstNestedName + Stream.of(moreNestedNames).collect(joining("$", "$", ""))); diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/net/ServerSocket.java --- a/src/java.base/share/classes/java/net/ServerSocket.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/net/ServerSocket.java Tue May 07 17:30:14 2019 -0400 @@ -32,6 +32,7 @@ import java.nio.channels.ServerSocketChannel; import java.security.AccessController; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.Set; import java.util.Collections; @@ -81,6 +82,7 @@ * @since 12 */ protected ServerSocket(SocketImpl impl) { + Objects.requireNonNull(impl); this.impl = impl; } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/nio/file/FileSystems.java --- a/src/java.base/share/classes/java/nio/file/FileSystems.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/nio/file/FileSystems.java Tue May 07 17:30:14 2019 -0400 @@ -252,10 +252,8 @@ * Suppose there is a provider identified by the scheme {@code "memory"} * installed: * <pre> - * Map<String,String> env = new HashMap<>(); - * env.put("capacity", "16G"); - * env.put("blockSize", "4k"); - * FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env); + * FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), + * Map.of("capacity", "16G", "blockSize", "4k")); * </pre> * * @param uri diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/java/util/regex/Pattern.java --- a/src/java.base/share/classes/java/util/regex/Pattern.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/java/util/regex/Pattern.java Tue May 07 17:30:14 2019 -0400 @@ -1678,7 +1678,13 @@ return; int j = i; i += 2; - int[] newtemp = new int[j + 3*(pLen-i) + 2]; + int newTempLen; + try { + newTempLen = Math.addExact(j + 2, Math.multiplyExact(3, pLen - i)); + } catch (ArithmeticException ae) { + throw new OutOfMemoryError(); + } + int[] newtemp = new int[newTempLen]; System.arraycopy(temp, 0, newtemp, 0, j); boolean inQuote = true; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Tue May 07 17:30:14 2019 -0400 @@ -826,6 +826,10 @@ // reading lock private final ReentrantLock readLock = new ReentrantLock(); + // closing status + private volatile boolean isClosing; + private volatile boolean hasDepleted; + AppInputStream() { this.appDataIsAvailable = false; this.buffer = ByteBuffer.allocate(4096); @@ -871,8 +875,7 @@ * and returning "-1" on non-fault EOF status. */ @Override - public int read(byte[] b, int off, int len) - throws IOException { + public int read(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException("the target buffer is null"); } else if (off < 0 || len < 0 || len > b.length - off) { @@ -900,12 +903,40 @@ throw new SocketException("Connection or inbound has closed"); } + // Check if the input stream has been depleted. + // + // Note that the "hasDepleted" rather than the isClosing + // filed is checked here, in case the closing process is + // still in progress. + if (hasDepleted) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.fine("The input stream has been depleted"); + } + + return -1; + } + // Read the available bytes at first. // // Note that the receiving and processing of post-handshake message // are also synchronized with the read lock. readLock.lock(); try { + // Double check if the Socket is invalid (error or closed). + if (conContext.isBroken || conContext.isInboundClosed()) { + throw new SocketException( + "Connection or inbound has closed"); + } + + // Double check if the input stream has been depleted. + if (hasDepleted) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.fine("The input stream is closing"); + } + + return -1; + } + int remains = available(); if (remains > 0) { int howmany = Math.min(remains, len); @@ -938,7 +969,17 @@ return -1; } } finally { - readLock.unlock(); + // Check if the input stream is closing. + // + // If the deplete() did not hold the lock, clean up the + // input stream here. + try { + if (isClosing) { + readLockedDeplete(); + } + } finally { + readLock.unlock(); + } } } @@ -1016,34 +1057,48 @@ * socket gracefully, without impact the performance too much. */ private void deplete() { - if (conContext.isInboundClosed()) { + if (conContext.isInboundClosed() || isClosing) { return; } - readLock.lock(); - try { - // double check - if (conContext.isInboundClosed()) { - return; + isClosing = true; + if (readLock.tryLock()) { + try { + readLockedDeplete(); + } finally { + readLock.unlock(); } - - if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) { - return; - } + } + } - SSLSocketInputRecord socketInputRecord = - (SSLSocketInputRecord)conContext.inputRecord; - try { - socketInputRecord.deplete( - conContext.isNegotiated && (getSoTimeout() > 0)); - } catch (IOException ioe) { - if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.warning( - "input stream close depletion failed", ioe); - } + /** + * Try to use up the input records. + * + * Please don't call this method unless the readLock is held by + * the current thread. + */ + private void readLockedDeplete() { + // double check + if (hasDepleted || conContext.isInboundClosed()) { + return; + } + + if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) { + return; + } + + SSLSocketInputRecord socketInputRecord = + (SSLSocketInputRecord)conContext.inputRecord; + try { + socketInputRecord.deplete( + conContext.isNegotiated && (getSoTimeout() > 0)); + } catch (Exception ex) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.warning( + "input stream close depletion failed", ex); } } finally { - readLock.unlock(); + hasDepleted = true; } } } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java Tue May 07 17:30:14 2019 -0400 @@ -40,6 +40,7 @@ import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; import org.w3c.dom.Text; public abstract class IntegrityHmac extends SignatureAlgorithmSpi { @@ -325,12 +326,13 @@ throw new IllegalArgumentException("element null"); } - Text hmaclength = - XMLUtils.selectDsNodeText(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0); - - if (hmaclength != null) { - this.HMACOutputLength = Integer.parseInt(hmaclength.getData()); - this.HMACOutputLengthSet = true; + Node n = XMLUtils.selectDsNode(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0); + if (n != null) { + String hmacLength = XMLUtils.getFullTextChildrenFromNode(n); + if (hmacLength != null && !"".equals(hmacLength)) { + this.HMACOutputLength = Integer.parseInt(hmacLength); + this.HMACOutputLengthSet = true; + } } } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java Tue May 07 17:30:14 2019 -0400 @@ -33,7 +33,6 @@ import java.security.SignatureException; import java.security.interfaces.DSAKey; import java.security.spec.AlgorithmParameterSpec; -import java.util.Base64; import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi; @@ -41,6 +40,7 @@ import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.JavaUtils; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; public class SignatureDSA extends SignatureAlgorithmSpi { @@ -109,7 +109,7 @@ throws XMLSignatureException { try { if (LOG.isDebugEnabled()) { - LOG.debug("Called DSA.verify() on " + Base64.getMimeEncoder().encodeToString(signature)); + LOG.debug("Called DSA.verify() on " + XMLUtils.encodeToString(signature)); } byte[] jcebytes = JavaUtils.convertDsaXMLDSIGtoASN1(signature, diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java Tue May 07 17:30:14 2019 -0400 @@ -33,12 +33,12 @@ import java.security.Signature; import java.security.SignatureException; import java.security.spec.AlgorithmParameterSpec; -import java.util.Base64; import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi; import com.sun.org.apache.xml.internal.security.signature.XMLSignature; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; /** * @@ -132,7 +132,7 @@ byte[] jcebytes = SignatureECDSA.convertXMLDSIGtoASN1(signature); if (LOG.isDebugEnabled()) { - LOG.debug("Called ECDSA.verify() on " + Base64.getMimeEncoder().encodeToString(signature)); + LOG.debug("Called ECDSA.verify() on " + XMLUtils.encodeToString(signature)); } return this.signatureAlgorithm.verify(jcebytes); diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java Tue May 07 17:30:14 2019 -0400 @@ -331,7 +331,7 @@ ns.addMapping(NName, NValue, attribute); } } else if (XML_LANG_URI.equals(attribute.getNamespaceURI()) - && (!c14n11 || c14n11 && !"id".equals(NName))) { + && (!c14n11 || !"id".equals(NName))) { xmlattrStack.addXmlnsAttr(attribute); } } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java Tue May 07 17:30:14 2019 -0400 @@ -342,7 +342,7 @@ protected void circumventBugIfNeeded(XMLSignatureInput input) throws CanonicalizationException, ParserConfigurationException, IOException, SAXException { - if (!input.isNeedsToBeExpanded() || inclusiveNSSet.isEmpty() || inclusiveNSSet.isEmpty()) { + if (!input.isNeedsToBeExpanded() || inclusiveNSSet.isEmpty()) { return; } Document doc = null; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java Tue May 07 17:30:14 2019 -0400 @@ -50,7 +50,6 @@ import com.sun.org.apache.xml.internal.security.transforms.Transforms; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.ElementProxy; -import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants; import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Attr; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java Tue May 07 17:30:14 2019 -0400 @@ -26,6 +26,7 @@ import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.DSAKeyValue; +import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.ECKeyValue; import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.RSAKeyValue; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; @@ -107,9 +108,14 @@ appendSelf(rsa); addReturnToSelf(); + } else if (pk instanceof java.security.interfaces.ECPublicKey) { + ECKeyValue ec = new ECKeyValue(getDocument(), pk); + + appendSelf(ec); + addReturnToSelf(); } else { String error = "The given PublicKey type " + pk + " is not supported. Only DSAPublicKey and " - + "RSAPublicKey types are currently supported"; + + "RSAPublicKey and ECPublicKey types are currently supported"; throw new IllegalArgumentException(error); } } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,366 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.sun.org.apache.xml.internal.security.keys.content.keyvalues; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.interfaces.ECPublicKey; +import java.security.spec.ECField; +import java.security.spec.ECFieldFp; +import java.security.spec.ECParameterSpec; +import java.security.spec.ECPoint; +import java.security.spec.ECPublicKeySpec; +import java.security.spec.EllipticCurve; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; + +import javax.xml.crypto.MarshalException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Text; + +import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; +import com.sun.org.apache.xml.internal.security.utils.Constants; +import com.sun.org.apache.xml.internal.security.utils.I18n; +import com.sun.org.apache.xml.internal.security.utils.Signature11ElementProxy; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; + +public class ECKeyValue extends Signature11ElementProxy implements KeyValueContent { + + /* Supported curve, secp256r1 */ + private static final Curve SECP256R1 = initializeCurve( + "secp256r1 [NIST P-256, X9.62 prime256v1]", + "1.2.840.10045.3.1.7", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 1 + ); + + /* Supported curve secp384r1 */ + private static final Curve SECP384R1 = initializeCurve( + "secp384r1 [NIST P-384]", + "1.3.132.0.34", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 1 + ); + + /* Supported curve secp521r1 */ + private static final Curve SECP521R1 = initializeCurve( + "secp521r1 [NIST P-521]", + "1.3.132.0.35", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 1 + ); + + private static Curve initializeCurve(String name, String oid, + String sfield, String a, String b, + String x, String y, String n, int h) { + BigInteger p = bigInt(sfield); + ECField field = new ECFieldFp(p); + EllipticCurve curve = new EllipticCurve(field, bigInt(a), + bigInt(b)); + ECPoint g = new ECPoint(bigInt(x), bigInt(y)); + return new Curve(name, oid, curve, g, bigInt(n), h); + } + + + /** + * Constructor DSAKeyValue + * + * @param element + * @param baseURI + * @throws XMLSecurityException + */ + public ECKeyValue(Element element, String baseURI) throws XMLSecurityException { + super(element, baseURI); + } + + /** + * Constructor DSAKeyValue + * + * @param doc + * @param key + * @throws IllegalArgumentException + */ + public ECKeyValue(Document doc, Key key) throws IllegalArgumentException { + super(doc); + + addReturnToSelf(); + + if (key instanceof ECPublicKey) { + ECParameterSpec ecParams = ((ECPublicKey)key).getParams(); + + // NamedCurve + String oid = getCurveOid(ecParams); + if (oid == null) { + throw new IllegalArgumentException("Invalid ECParameterSpec"); + } + + Element namedCurveElement = XMLUtils.createElementInSignature11Space(getDocument(), "NamedCurve"); + namedCurveElement.setAttributeNS(null, "URI", "urn:oid:" + oid); + appendSelf(namedCurveElement); + addReturnToSelf(); + + // PublicKey + ECPoint ecPoint = ((ECPublicKey)key).getW(); + byte[] secPublicKey = encodePoint(ecPoint, ecParams.getCurve()); + String encoded = XMLUtils.encodeToString(secPublicKey); + Element publicKeyElement = XMLUtils.createElementInSignature11Space(getDocument(), "PublicKey"); + Text text = getDocument().createTextNode(encoded); + + publicKeyElement.appendChild(text); + + appendSelf(publicKeyElement); + addReturnToSelf(); + + } else { + Object[] exArgs = { Constants._TAG_ECKEYVALUE, key.getClass().getName() }; + + throw new IllegalArgumentException(I18n.translate("KeyValue.IllegalArgument", exArgs)); + } + } + + /** {@inheritDoc} */ + public PublicKey getPublicKey() throws XMLSecurityException { + try { + ECParameterSpec ecParams = null; + Element curElem = getFirstChildElement(getElement()); + if (curElem == null) { + throw new MarshalException("KeyValue must contain at least one type"); + } + + if ("ECParameters".equals(curElem.getLocalName()) + && Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) { + throw new UnsupportedOperationException + ("ECParameters not supported"); + } else if ("NamedCurve".equals(curElem.getLocalName()) + && Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) { + String uri = null; + if (curElem.hasAttributeNS(null, "URI")) { + uri = curElem.getAttributeNS(null, "URI"); + } + // strip off "urn:oid" + if (uri.startsWith("urn:oid:")) { + String oid = uri.substring("urn:oid:".length()); + ecParams = getECParameterSpec(oid); + if (ecParams == null) { + throw new MarshalException("Invalid curve OID"); + } + } else { + throw new MarshalException("Invalid NamedCurve URI"); + } + } else { + throw new MarshalException("Invalid ECKeyValue"); + } + curElem = getNextSiblingElement(curElem, "PublicKey", Constants.SignatureSpec11NS); + ECPoint ecPoint = null; + + try { + String content = XMLUtils.getFullTextChildrenFromNode(curElem); + ecPoint = decodePoint(XMLUtils.decode(content), ecParams.getCurve()); + } catch (IOException ioe) { + throw new MarshalException("Invalid EC Point", ioe); + } + + ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams); + return KeyFactory.getInstance("EC").generatePublic(spec); + } catch (NoSuchAlgorithmException ex) { + throw new XMLSecurityException(ex); + } catch (InvalidKeySpecException ex) { + throw new XMLSecurityException(ex); + } catch (MarshalException ex) { + throw new XMLSecurityException(ex); + } + } + + /** {@inheritDoc} */ + public String getBaseLocalName() { + return Constants._TAG_ECKEYVALUE; + } + + private static Element getFirstChildElement(Node node) { + Node child = node.getFirstChild(); + while (child != null && child.getNodeType() != Node.ELEMENT_NODE) { + child = child.getNextSibling(); + } + return (Element)child; + } + + private static Element getNextSiblingElement(Node node, String localName, String namespaceURI) + throws MarshalException + { + return verifyElement(getNextSiblingElement(node), localName, namespaceURI); + } + + private static Element getNextSiblingElement(Node node) { + Node sibling = node.getNextSibling(); + while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE) { + sibling = sibling.getNextSibling(); + } + return (Element)sibling; + } + + private static Element verifyElement(Element elem, String localName, String namespaceURI) + throws MarshalException + { + if (elem == null) { + throw new MarshalException("Missing " + localName + " element"); + } + String name = elem.getLocalName(); + String namespace = elem.getNamespaceURI(); + if (!name.equals(localName) || namespace == null && namespaceURI != null + || namespace != null && !namespace.equals(namespaceURI)) { + throw new MarshalException("Invalid element name: " + + namespace + ":" + name + ", expected " + namespaceURI + ":" + localName); + } + return elem; + } + + private static String getCurveOid(ECParameterSpec params) { + // Check that the params represent one of the supported + // curves. If there is a match, return the object identifier + // of the curve. + Curve match; + if (matchCurve(params, SECP256R1)) { + match = SECP256R1; + } else if (matchCurve(params, SECP384R1)) { + match = SECP384R1; + } else if (matchCurve(params, SECP521R1)) { + match = SECP521R1; + } else { + return null; + } + return match.getObjectId(); + } + + private static boolean matchCurve(ECParameterSpec params, Curve curve) { + int fieldSize = params.getCurve().getField().getFieldSize(); + return curve.getCurve().getField().getFieldSize() == fieldSize + && curve.getCurve().equals(params.getCurve()) + && curve.getGenerator().equals(params.getGenerator()) + && curve.getOrder().equals(params.getOrder()) + && curve.getCofactor() == params.getCofactor(); + } + + private static ECPoint decodePoint(byte[] data, EllipticCurve curve) + throws IOException { + if (data.length == 0 || data[0] != 4) { + throw new IOException("Only uncompressed point format " + + "supported"); + } + // Per ANSI X9.62, an encoded point is a 1 byte type followed by + // ceiling(LOG base 2 field-size / 8) bytes of x and the same of y. + int n = (data.length - 1) / 2; + if (n != (curve.getField().getFieldSize() + 7) >> 3) { + throw new IOException("Point does not match field size"); + } + + byte[] xb = Arrays.copyOfRange(data, 1, 1 + n); + byte[] yb = Arrays.copyOfRange(data, n + 1, n + 1 + n); + + return new ECPoint(new BigInteger(1, xb), new BigInteger(1, yb)); + } + + private static byte[] encodePoint(ECPoint point, EllipticCurve curve) { + // get field size in bytes (rounding up) + int n = (curve.getField().getFieldSize() + 7) >> 3; + byte[] xb = trimZeroes(point.getAffineX().toByteArray()); + byte[] yb = trimZeroes(point.getAffineY().toByteArray()); + if (xb.length > n || yb.length > n) { + throw new RuntimeException("Point coordinates do not " + + "match field size"); + } + byte[] b = new byte[1 + (n << 1)]; + b[0] = 4; // uncompressed + System.arraycopy(xb, 0, b, n - xb.length + 1, xb.length); + System.arraycopy(yb, 0, b, b.length - yb.length, yb.length); + return b; + } + + private static byte[] trimZeroes(byte[] b) { + int i = 0; + while (i < b.length - 1 && b[i] == 0) { + i++; + } + if (i == 0) { + return b; + } + return Arrays.copyOfRange(b, i, b.length); + } + + private static ECParameterSpec getECParameterSpec(String oid) { + if (oid.equals(SECP256R1.getObjectId())) { + return SECP256R1; + } else if (oid.equals(SECP384R1.getObjectId())) { + return SECP384R1; + } else if (oid.equals(SECP521R1.getObjectId())) { + return SECP521R1; + } else { + return null; + } + } + + static final class Curve extends ECParameterSpec { + private final String name; + private final String oid; + + Curve(String name, String oid, EllipticCurve curve, + ECPoint g, BigInteger n, int h) { + super(curve, g, n, h); + this.name = name; + this.oid = oid; + } + + private String getName() { + return name; + } + + private String getObjectId() { + return oid; + } + } + + private static BigInteger bigInt(String s) { + return new BigInteger(s, 16); + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SKI.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SKI.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SKI.java Tue May 07 17:30:14 2019 -0400 @@ -24,18 +24,18 @@ import java.security.cert.X509Certificate; import java.util.Arrays; -import java.util.Base64; import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Handles SubjectKeyIdentifier (SKI) for X.509v3. * - * @see <A HREF="http://docs.oracle.com/javase/1.5.0/docs/api/java/security/cert/X509Extension.html"> + * @see <A HREF="http://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Extension.html"> * Interface X509Extension</A> */ public class XMLX509SKI extends SignatureElementProxy implements XMLX509DataContent { @@ -138,7 +138,7 @@ System.arraycopy(extensionValue, 4, skidValue, 0, skidValue.length); if (LOG.isDebugEnabled()) { - LOG.debug("Base64 of SKI is " + Base64.getMimeEncoder().encodeToString(skidValue)); + LOG.debug("Base64 of SKI is " + XMLUtils.encodeToString(skidValue)); } return skidValue; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java Tue May 07 17:30:14 2019 -0400 @@ -33,6 +33,7 @@ import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DEREncodedKeyValueResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DSAKeyValueResolver; +import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.ECKeyValueResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.KeyInfoReferenceResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RSAKeyValueResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RetrievalMethodResolver; @@ -295,6 +296,7 @@ keyResolverList.add(new KeyResolver(new DEREncodedKeyValueResolver())); keyResolverList.add(new KeyResolver(new KeyInfoReferenceResolver())); keyResolverList.add(new KeyResolver(new X509DigestResolver())); + keyResolverList.add(new KeyResolver(new ECKeyValueResolver())); resolverVector.addAll(keyResolverList); } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/ECKeyValueResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/ECKeyValueResolver.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,97 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations; + +import java.security.PublicKey; +import java.security.cert.X509Certificate; + +import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; +import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.ECKeyValue; +import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi; +import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; +import com.sun.org.apache.xml.internal.security.utils.Constants; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; +import org.w3c.dom.Element; + +public class ECKeyValueResolver extends KeyResolverSpi { + + private static final com.sun.org.slf4j.internal.Logger LOG = + com.sun.org.slf4j.internal.LoggerFactory.getLogger(ECKeyValueResolver.class); + + + /** + * Method engineResolvePublicKey + * + * @param element + * @param baseURI + * @param storage + * @return null if no {@link PublicKey} could be obtained + */ + public PublicKey engineLookupAndResolvePublicKey( + Element element, String baseURI, StorageResolver storage + ) { + if (element == null) { + return null; + } + Element ecKeyElement = null; + boolean isKeyValue = + XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE); + if (isKeyValue) { + ecKeyElement = + XMLUtils.selectDs11Node(element.getFirstChild(), Constants._TAG_ECKEYVALUE, 0); + } else if (XMLUtils.elementIsInSignature11Space(element, Constants._TAG_ECKEYVALUE)) { + // this trick is needed to allow the RetrievalMethodResolver to eat a + // ds:ECKeyValue directly (without KeyValue) + ecKeyElement = element; + } + + if (ecKeyElement == null) { + return null; + } + + try { + ECKeyValue ecKeyValue = new ECKeyValue(ecKeyElement, baseURI); + return ecKeyValue.getPublicKey(); + } catch (XMLSecurityException ex) { + LOG.debug(ex.getMessage(), ex); + //do nothing + } + + return null; + } + + + /** {@inheritDoc} */ + public X509Certificate engineLookupResolveX509Certificate( + Element element, String baseURI, StorageResolver storage + ) { + return null; + } + + /** {@inheritDoc} */ + public javax.crypto.SecretKey engineLookupAndResolveSecretKey( + Element element, String baseURI, StorageResolver storage + ) { + return null; + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java Tue May 07 17:30:14 2019 -0400 @@ -44,11 +44,12 @@ public PublicKey engineLookupAndResolvePublicKey( Element element, String baseURI, StorageResolver storage ) { - LOG.debug("Can I resolve {}", element.getTagName()); if (element == null) { return null; } + LOG.debug("Can I resolve {}", element.getTagName()); + boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE); Element rsaKeyElement = null; if (isKeyValue) { diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/CertsInFilesystemDirectoryResolver.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/CertsInFilesystemDirectoryResolver.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/CertsInFilesystemDirectoryResolver.java Tue May 07 17:30:14 2019 -0400 @@ -35,12 +35,12 @@ import java.security.cert.CertificateNotYetValidException; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Base64; import java.util.Iterator; import java.util.List; import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolverException; import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolverSpi; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; /** * This {@link StorageResolverSpi} makes all raw (binary) {@link X509Certificate}s @@ -207,7 +207,7 @@ System.out.println(); System.out.println("Base64(SKI())= \"" - + Base64.getMimeEncoder().encodeToString(ski) + "\""); + + XMLUtils.encodeToString(ski) + "\""); System.out.println("cert.getSerialNumber()= \"" + cert.getSerialNumber().toString() + "\""); System.out.println("cert.getSubjectX500Principal().getName()= \"" diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml Tue May 07 17:30:14 2019 -0400 @@ -643,6 +643,8 @@ DESCRIPTION="Uses an X509 SubjectName to retrieve a certificate from the storages" /> <Resolver JAVACLASS="com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509IssuerSerialResolver" DESCRIPTION="Uses an X509 IssuerName and IssuerSerial to retrieve a certificate from the storages" /> + <Resolver JAVACLASS="com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.ECKeyValueResolver" + DESCRIPTION="Can extract EC public keys" /> </KeyResolver> <PrefixMappings> @@ -665,5 +667,7 @@ prefix="ec" /> <PrefixMapping namespace="http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/#xpathFilter" prefix="xx" /> + <PrefixMapping namespace="http://www.w3.org/2009/xmldsig11#" + prefix="dsig11" /> </PrefixMappings> </Configuration> diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java Tue May 07 17:30:14 2019 -0400 @@ -23,7 +23,10 @@ package com.sun.org.apache.xml.internal.security.signature; import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -56,19 +59,24 @@ public class Manifest extends SignatureElementProxy { /** - * The maximum number of references per Manifest, if secure validation is enabled. + * The default maximum number of references per Manifest, if secure validation is enabled. */ public static final int MAXIMUM_REFERENCE_COUNT = 30; private static final com.sun.org.slf4j.internal.Logger LOG = com.sun.org.slf4j.internal.LoggerFactory.getLogger(Manifest.class); + private static Integer referenceCount = + AccessController.doPrivileged( + (PrivilegedAction<Integer>) () -> Integer.parseInt(System.getProperty("com.sun.org.apache.xml.internal.security.maxReferences", + Integer.toString(MAXIMUM_REFERENCE_COUNT)))); + /** Field references */ private List<Reference> references; private Element[] referencesEl; /** Field verificationResults[] */ - private boolean[] verificationResults; + private List<VerifiedReference> verificationResults; /** Field resolverProperties */ private Map<String, String> resolverProperties; @@ -135,8 +143,8 @@ I18n.translate("xml.WrongContent", exArgs)); } - if (secureValidation && le > MAXIMUM_REFERENCE_COUNT) { - Object exArgs[] = { le, MAXIMUM_REFERENCE_COUNT }; + if (secureValidation && le > referenceCount) { + Object exArgs[] = { le, referenceCount }; throw new XMLSecurityException("signature.tooManyReferences", exArgs); } @@ -317,13 +325,13 @@ if (referencesEl.length == 0) { throw new XMLSecurityException("empty", new Object[]{"References are empty"}); } - if (secureValidation && referencesEl.length > MAXIMUM_REFERENCE_COUNT) { - Object exArgs[] = { referencesEl.length, MAXIMUM_REFERENCE_COUNT }; + if (secureValidation && referencesEl.length > referenceCount) { + Object exArgs[] = { referencesEl.length, referenceCount }; throw new XMLSecurityException("signature.tooManyReferences", exArgs); } - this.verificationResults = new boolean[referencesEl.length]; + this.verificationResults = new ArrayList<>(referencesEl.length); boolean verify = true; for (int i = 0; i < this.referencesEl.length; i++) { Reference currentRef = @@ -335,13 +343,13 @@ try { boolean currentRefVerified = currentRef.verify(); - this.setVerificationResult(i, currentRefVerified); - if (!currentRefVerified) { verify = false; } LOG.debug("The Reference has Type {}", currentRef.getType()); + List<VerifiedReference> manifestReferences = Collections.emptyList(); + // was verification successful till now and do we want to verify the Manifest? if (verify && followManifests && currentRef.typeIsReferenceToManifest()) { LOG.debug("We have to follow a nested Manifest"); @@ -393,6 +401,8 @@ } else { LOG.debug("The nested Manifest was valid (good)"); } + + manifestReferences = referencedManifest.getVerificationResults(); } catch (IOException ex) { throw new ReferenceNotInitializedException(ex); } catch (ParserConfigurationException ex) { @@ -401,6 +411,8 @@ throw new ReferenceNotInitializedException(ex); } } + + verificationResults.add(new VerifiedReference(currentRefVerified, currentRef.getURI(), manifestReferences)); } catch (ReferenceNotInitializedException ex) { Object exArgs[] = { currentRef.getURI() }; @@ -414,20 +426,6 @@ } /** - * Method setVerificationResult - * - * @param index - * @param verify - */ - private void setVerificationResult(int index, boolean verify) { - if (this.verificationResults == null) { - this.verificationResults = new boolean[this.getLength()]; - } - - this.verificationResults[index] = verify; - } - - /** * After verifying a {@link Manifest} or a {@link SignedInfo} using the * {@link Manifest#verifyReferences()} or {@link SignedInfo#verify()} methods, * the individual results can be retrieved with this method. @@ -455,14 +453,24 @@ } } - return this.verificationResults[index]; + return ((ArrayList<VerifiedReference>)verificationResults).get(index).isValid(); + } + + /** + * Get the list of verification result objects + */ + public List<VerifiedReference> getVerificationResults() { + if (verificationResults == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(verificationResults); } /** * Adds Resource Resolver for retrieving resources at specified {@code URI} attribute * in {@code reference} element * - * @param resolver {@link ResourceResolver} can provide the implemenatin subclass of + * @param resolver {@link ResourceResolver} can provide the implementation subclass of * {@link ResourceResolverSpi} for retrieving resource. */ public void addResourceResolver(ResourceResolver resolver) { diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java Tue May 07 17:30:14 2019 -0400 @@ -26,7 +26,6 @@ import java.io.OutputStream; import java.security.AccessController; import java.security.PrivilegedAction; -import java.util.Base64; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -396,7 +395,7 @@ n = n.getNextSibling(); } - String base64codedValue = Base64.getMimeEncoder().encodeToString(digestValue); + String base64codedValue = XMLUtils.encodeToString(digestValue); Text t = createText(base64codedValue); digestValueElement.appendChild(t); @@ -723,12 +722,17 @@ return getPreCalculatedDigest(input); } + cacheDereferencedElement(input); + MessageDigestAlgorithm mda = this.getMessageDigestAlgorithm(); mda.reset(); try (DigesterOutputStream diOs = new DigesterOutputStream(mda); OutputStream os = new UnsyncBufferedOutputStream(diOs)) { - XMLSignatureInput output = this.dereferenceURIandPerformTransforms(os); + + XMLSignatureInput output = this.getContentsAfterTransformation(input, os); + this.transformsOutput = output; + // if signing and c14n11 property == true explicitly add // C14N11 transform if needed if (Reference.useC14N11 && !validating && !output.isOutputStreamSet() @@ -772,7 +776,7 @@ throws ReferenceNotInitializedException { LOG.debug("Verifying element with pre-calculated digest"); String preCalculatedDigest = input.getPreCalculatedDigest(); - return Base64.getMimeDecoder().decode(preCalculatedDigest); + return XMLUtils.decode(preCalculatedDigest); } /** @@ -789,8 +793,8 @@ "signature.Verification.NoSignatureElement", exArgs ); } - String content = XMLUtils.getFullTextChildrenFromElement(digestValueElement); - return Base64.getMimeDecoder().decode(content); + String content = XMLUtils.getFullTextChildrenFromNode(digestValueElement); + return XMLUtils.decode(content); } @@ -809,8 +813,8 @@ if (!equal) { LOG.warn("Verification failed for URI \"" + this.getURI() + "\""); - LOG.warn("Expected Digest: " + Base64.getMimeEncoder().encodeToString(elemDig)); - LOG.warn("Actual Digest: " + Base64.getMimeEncoder().encodeToString(calcDig)); + LOG.warn("Expected Digest: " + XMLUtils.encodeToString(elemDig)); + LOG.warn("Actual Digest: " + XMLUtils.encodeToString(calcDig)); } else { LOG.debug("Verification successful for URI \"{}\"", this.getURI()); } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,64 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package com.sun.org.apache.xml.internal.security.signature; + +import java.util.Collections; +import java.util.List; + +/** + * Holds the result of a Reference validation. + */ +public class VerifiedReference { + + private final boolean valid; + private final String uri; + private final List<VerifiedReference> manifestReferences; + + /** + * @param valid Whether this Reference was successfully validated or not + * @param uri The URI of this Reference + * @param manifestReferences If this reference is a reference to a Manifest, this holds the list + * of verified referenes associated with this Manifest + */ + public VerifiedReference(boolean valid, String uri, List<VerifiedReference> manifestReferences) { + this.valid = valid; + this.uri = uri; + if (manifestReferences != null) { + this.manifestReferences = manifestReferences; + } else { + this.manifestReferences = Collections.emptyList(); + } + } + + public boolean isValid() { + return valid; + } + + public String getUri() { + return uri; + } + + public List<VerifiedReference> getManifestReferences() { + return Collections.unmodifiableList(manifestReferences); + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java Tue May 07 17:30:14 2019 -0400 @@ -27,7 +27,6 @@ import java.security.Key; import java.security.PublicKey; import java.security.cert.X509Certificate; -import java.util.Base64; import javax.crypto.SecretKey; @@ -504,8 +503,8 @@ * @throws XMLSignatureException If there is no content */ public byte[] getSignatureValue() throws XMLSignatureException { - String content = XMLUtils.getFullTextChildrenFromElement(signatureValueElement); - return Base64.getMimeDecoder().decode(content); + String content = XMLUtils.getFullTextChildrenFromNode(signatureValueElement); + return XMLUtils.decode(content); } /** @@ -520,7 +519,7 @@ signatureValueElement.removeChild(signatureValueElement.getFirstChild()); } - String base64codedValue = Base64.getMimeEncoder().encodeToString(bytes); + String base64codedValue = XMLUtils.encodeToString(bytes); if (base64codedValue.length() > 76 && !XMLUtils.ignoreLineBreaks()) { base64codedValue = "\n" + base64codedValue + "\n"; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformBase64Decode.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformBase64Decode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformBase64Decode.java Tue May 07 17:30:14 2019 -0400 @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.OutputStream; -import java.util.Base64; import javax.xml.parsers.ParserConfigurationException; @@ -109,12 +108,12 @@ StringBuilder sb = new StringBuilder(); traverseElement((Element)el, sb); if (os == null) { - byte[] decodedBytes = Base64.getMimeDecoder().decode(sb.toString()); + byte[] decodedBytes = XMLUtils.decode(sb.toString()); XMLSignatureInput output = new XMLSignatureInput(decodedBytes); output.setSecureValidation(secureValidation); return output; } - byte[] bytes = Base64.getMimeDecoder().decode(sb.toString()); + byte[] bytes = XMLUtils.decode(sb.toString()); os.write(bytes); XMLSignatureInput output = new XMLSignatureInput((byte[])null); output.setSecureValidation(secureValidation); @@ -125,17 +124,17 @@ if (input.isOctetStream() || input.isNodeSet()) { if (os == null) { byte[] base64Bytes = input.getBytes(); - byte[] decodedBytes = Base64.getMimeDecoder().decode(base64Bytes); + byte[] decodedBytes = XMLUtils.decode(base64Bytes); XMLSignatureInput output = new XMLSignatureInput(decodedBytes); output.setSecureValidation(secureValidation); return output; } if (input.isByteArray() || input.isNodeSet()) { - byte[] bytes = Base64.getMimeDecoder().decode(input.getBytes()); + byte[] bytes = XMLUtils.decode(input.getBytes()); os.write(bytes); } else { byte[] inputBytes = JavaUtils.getBytesFromStream(input.getOctetStreamReal()); - byte[] bytes = Base64.getMimeDecoder().decode(inputBytes); + byte[] bytes = XMLUtils.decode(inputBytes); os.write(bytes); } XMLSignatureInput output = new XMLSignatureInput((byte[])null); @@ -153,7 +152,7 @@ Element rootNode = doc.getDocumentElement(); StringBuilder sb = new StringBuilder(); traverseElement(rootNode, sb); - byte[] decodedBytes = Base64.getMimeDecoder().decode(sb.toString()); + byte[] decodedBytes = XMLUtils.decode(sb.toString()); XMLSignatureInput output = new XMLSignatureInput(decodedBytes); output.setSecureValidation(secureValidation); return output; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXSLT.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXSLT.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXSLT.java Tue May 07 17:30:14 2019 -0400 @@ -84,7 +84,10 @@ Element xsltElement = XMLUtils.selectNode(transformElement.getFirstChild(), XSLTSpecNS, "stylesheet", 0); - + if (xsltElement == null) { + xsltElement = + XMLUtils.selectNode(transformElement.getFirstChild(), XSLTSpecNS, "transform", 0); + } if (xsltElement == null) { Object exArgs[] = { "xslt:stylesheet", "Transform" }; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathFilterCHGPContainer.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathFilterCHGPContainer.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathFilterCHGPContainer.java Tue May 07 17:30:14 2019 -0400 @@ -30,6 +30,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.w3c.dom.Text; /** * Implements the parameters for a custom Transform which has a better performance @@ -204,7 +205,7 @@ getElement().getFirstChild(), this.getBaseNamespace(), type, 0 ); - return XMLUtils.getFullTextChildrenFromElement(xElem); + return XMLUtils.getFullTextChildrenFromNode(xElem); } /** @@ -258,11 +259,23 @@ return null; } - return XMLUtils.selectNodeText( + return selectNodeText( getFirstChild(), this.getBaseNamespace(), type, 0 ); } + private static Text selectNodeText(Node sibling, String uri, String nodeName, int number) { + Node n = XMLUtils.selectNode(sibling, uri, nodeName, number); + if (n == null) { + return null; + } + n = n.getFirstChild(); + while (n != null && n.getNodeType() != Node.TEXT_NODE) { + n = n.getNextSibling(); + } + return (Text)n; + } + /** * Method getHereContextNodeIncludeButSearch * diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java Tue May 07 17:30:14 2019 -0400 @@ -210,6 +210,9 @@ /** Tag of Element J **/ public static final String _TAG_J = "J"; + /** Tag of Element ECKeyValue **/ + public static final String _TAG_ECKEYVALUE = "ECKeyValue"; + /** Tag of Element Seed **/ public static final String _TAG_SEED = "Seed"; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java Tue May 07 17:30:14 2019 -0400 @@ -24,7 +24,6 @@ import java.math.BigInteger; import java.util.concurrent.ConcurrentHashMap; -import java.util.Base64; import java.util.Map; import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; @@ -267,7 +266,7 @@ Element e = XMLUtils.createElementInSignatureSpace(getDocument(), localname); byte[] bytes = XMLUtils.getBytes(bi, bi.bitLength()); - String encodedInt = Base64.getMimeEncoder().encodeToString(bytes); + String encodedInt = XMLUtils.encodeToString(bytes); Document doc = e.getOwnerDocument(); Text text = doc.createTextNode(encodedInt); @@ -292,7 +291,7 @@ public void addBase64Element(byte[] bytes, String localname) { if (bytes != null) { Element el = XMLUtils.createElementInSignatureSpace(getDocument(), localname); - Text text = getDocument().createTextNode(Base64.getMimeEncoder().encodeToString(bytes)); + Text text = getDocument().createTextNode(XMLUtils.encodeToString(bytes)); el.appendChild(text); @@ -326,8 +325,8 @@ public void addBase64Text(byte[] bytes) { if (bytes != null) { Text t = XMLUtils.ignoreLineBreaks() - ? createText(Base64.getMimeEncoder().encodeToString(bytes)) - : createText("\n" + Base64.getMimeEncoder().encodeToString(bytes) + "\n"); + ? createText(XMLUtils.encodeToString(bytes)) + : createText("\n" + XMLUtils.encodeToString(bytes) + "\n"); appendSelf(t); } } @@ -367,11 +366,11 @@ public BigInteger getBigIntegerFromChildElement( String localname, String namespace ) { - return new BigInteger(1, Base64.getMimeDecoder().decode( - XMLUtils.selectNodeText( - getFirstChild(), namespace, localname, 0 - ).getNodeValue() - )); + Node n = XMLUtils.selectNode(getFirstChild(), namespace, localname, 0); + if (n != null) { + return new BigInteger(1, XMLUtils.decode(XMLUtils.getFullTextChildrenFromNode(n))); + } + return null; } /** @@ -396,7 +395,7 @@ * @throws XMLSecurityException */ public byte[] getBytesFromTextChild() throws XMLSecurityException { - return Base64.getMimeDecoder().decode(getTextFromTextChild()); + return XMLUtils.decode(getTextFromTextChild()); } /** @@ -406,7 +405,7 @@ * element */ public String getTextFromTextChild() { - return XMLUtils.getFullTextChildrenFromElement(getElement()); + return XMLUtils.getFullTextChildrenFromNode(getElement()); } /** @@ -498,8 +497,9 @@ if (Constants.SignatureSpecNS.equals(namespace)) { XMLUtils.setDsPrefix(prefix); - } - if (EncryptionConstants.EncryptionSpecNS.equals(namespace)) { + } else if (Constants.SignatureSpec11NS.equals(namespace)) { + XMLUtils.setDs11Prefix(prefix); + } else if (EncryptionConstants.EncryptionSpecNS.equals(namespace)) { XMLUtils.setXencPrefix(prefix); } prefixMappings.put(namespace, prefix); @@ -519,6 +519,7 @@ setNamespacePrefix( "http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/#xpathFilter", "xx" ); + setNamespacePrefix("http://www.w3.org/2009/xmldsig11#", "dsig11"); } /** diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Signature11ElementProxy.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Signature11ElementProxy.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Signature11ElementProxy.java Tue May 07 17:30:14 2019 -0400 @@ -47,6 +47,13 @@ setDocument(doc); setElement(XMLUtils.createElementInSignature11Space(doc, this.getBaseLocalName())); + + String prefix = ElementProxy.getDefaultPrefix(getBaseNamespace()); + if (prefix == null || prefix.length() == 0) { + getElement().setAttributeNS(Constants.NamespaceSpecNS, "xmlns", getBaseNamespace()); + } else { + getElement().setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + prefix, getBaseNamespace()); + } } /** diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java Tue May 07 17:30:14 2019 -0400 @@ -254,16 +254,21 @@ } } + @Deprecated + public static String getFullTextChildrenFromElement(Element element) { + return getFullTextChildrenFromNode(element); + } + /** - * Method getFullTextChildrenFromElement + * Method getFullTextChildrenFromNode * - * @param element + * @param node * @return the string of children */ - public static String getFullTextChildrenFromElement(Element element) { + public static String getFullTextChildrenFromNode(Node node) { StringBuilder sb = new StringBuilder(); - Node child = element.getFirstChild(); + Node child = node.getFirstChild(); while (child != null) { if (child.getNodeType() == Node.TEXT_NODE) { sb.append(((Text)child).getData()); @@ -682,7 +687,7 @@ while (sibling != null) { if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri) && sibling.getLocalName().equals(nodeName)) { - if (number == 0){ + if (number == 0) { return (Element)sibling; } number--; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java Tue May 07 17:30:14 2019 -0400 @@ -97,7 +97,7 @@ LOG.debug("check resolvability by class {}", resolverTmp.getClass().getName()); - if (resolverTmp != null && resolverTmp.canResolve(context)) { + if (resolverTmp.canResolve(context)) { // Check to see whether the Resolver is allowed if (context.secureValidation && (resolverTmp.resolverSpi instanceof ResolverLocalFilesystem diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java Tue May 07 17:30:14 2019 -0400 @@ -33,9 +33,9 @@ import java.net.URL; import java.net.URLConnection; import java.nio.charset.StandardCharsets; -import java.util.Base64; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverContext; import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException; import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi; @@ -57,7 +57,7 @@ * </PRE> * * @see <A HREF="http://www.javaworld.com/javaworld/javatips/jw-javatip42_p.html">Java Tip 42: Write Java apps that work with proxy-based firewalls</A> - * @see <A HREF="http://docs.oracle.com/javase/1.4.2/docs/guide/net/properties.html">SUN J2SE docs for network properties</A> + * @see <A HREF="https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html">JDK docs for network properties</A> * @see <A HREF="http://metalab.unc.edu/javafaq/javafaq.html#proxy">The JAVA FAQ Question 9.5: How do I make Java work with a proxy server?</A> */ public class ResolverDirectHTTP extends ResourceResolverSpi { @@ -122,7 +122,7 @@ urlConnection = openConnection(url); String password = user + ":" + pass; - String encodedPassword = Base64.getMimeEncoder().encodeToString(password.getBytes(StandardCharsets.ISO_8859_1)); + String encodedPassword = XMLUtils.encodeToString(password.getBytes(StandardCharsets.ISO_8859_1)); // set authentication property in the http header urlConnection.setRequestProperty("Authorization", @@ -187,7 +187,7 @@ if (proxyUser != null && proxyPass != null) { String password = proxyUser + ":" + proxyPass; - String authString = "Basic " + Base64.getMimeEncoder().encodeToString(password.getBytes(StandardCharsets.ISO_8859_1)); + String authString = "Basic " + XMLUtils.encodeToString(password.getBytes(StandardCharsets.ISO_8859_1)); urlConnection.setRequestProperty("Proxy-Authorization", authString); } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: ApacheCanonicalizer.java 1785016 2017-03-01 18:23:48Z coheigea $ + * $Id: ApacheCanonicalizer.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheOctetStreamData.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheOctetStreamData.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheOctetStreamData.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: ApacheOctetStreamData.java 1667527 2015-03-18 12:54:20Z mullan $ + * $Id: ApacheOctetStreamData.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: ApacheTransform.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: ApacheTransform.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14NMethod.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14NMethod.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14NMethod.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMCanonicalXMLC14NMethod.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMCanonicalXMLC14NMethod.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCryptoBinary.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCryptoBinary.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCryptoBinary.java Tue May 07 17:30:14 2019 -0400 @@ -1,3 +1,7 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -17,7 +21,7 @@ * under the License. */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * $Id$ @@ -33,16 +37,16 @@ import org.w3c.dom.Text; /** - * A DOM-based representation of the XML <code>CryptoBinary</code> simple type + * A DOM-based representation of the XML {@code CryptoBinary} simple type * as defined in the W3C specification for XML-Signature Syntax and Processing. * The XML Schema Definition is defined as: * - * <xmp> + * <pre>{@code * <simpleType name="CryptoBinary"> * <restriction base = "base64Binary"> * </restriction> * </simpleType> - * </xmp> + * }</pre> * * @author Sean Mullan */ @@ -52,11 +56,11 @@ private final String value; /** - * Create a <code>DOMCryptoBinary</code> instance from the specified - * <code>BigInteger</code> + * Create a {@code DOMCryptoBinary} instance from the specified + * {@code BigInteger} * * @param bigNum the arbitrary-length integer - * @throws NullPointerException if <code>bigNum</code> is <code>null</code> + * @throws NullPointerException if {@code bigNum} is {@code null} */ public DOMCryptoBinary(BigInteger bigNum) { if (bigNum == null) { @@ -69,7 +73,7 @@ } /** - * Creates a <code>DOMCryptoBinary</code> from a node. + * Creates a {@code DOMCryptoBinary} from a node. * * @param cbNode a CryptoBinary text node * @throws MarshalException if value cannot be decoded (invalid format) @@ -84,9 +88,9 @@ } /** - * Returns the <code>BigInteger</code> that this object contains. + * Returns the {@code BigInteger} that this object contains. * - * @return the <code>BigInteger</code> that this object contains + * @return the {@code BigInteger} that this object contains */ public BigInteger getBigNum() { return bigNum; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMDigestMethod.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMDigestMethod.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMDigestMethod.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMDigestMethod.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMDigestMethod.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMEnvelopedTransform.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMEnvelopedTransform.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMEnvelopedTransform.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMEnvelopedTransform.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMEnvelopedTransform.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMExcC14NMethod.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMExcC14NMethod.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMExcC14NMethod.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMExcC14NMethod.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMExcC14NMethod.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMHMACSignatureMethod.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMHMACSignatureMethod.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfo.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfo.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfo.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMKeyInfo.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMKeyInfo.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMKeyInfoFactory.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMKeyInfoFactory.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyName.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyName.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyName.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMKeyName.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMKeyName.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java Tue May 07 17:30:14 2019 -0400 @@ -21,18 +21,13 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMKeyValue.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMKeyValue.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; -import javax.xml.crypto.*; -import javax.xml.crypto.dom.DOMCryptoContext; -import javax.xml.crypto.dsig.*; -import javax.xml.crypto.dsig.keyinfo.KeyValue; - import java.io.IOException; import java.math.BigInteger; import java.security.KeyException; @@ -55,6 +50,11 @@ import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dom.DOMCryptoContext; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.crypto.dsig.keyinfo.KeyValue; + import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -500,7 +500,7 @@ throw new MarshalException("Invalid ECParameterSpec"); } DOMUtils.setAttribute(namedCurveElem, "URI", "urn:oid:" + oid); - String qname = (prefix == null || prefix.length() == 0) + String qname = prefix == null || prefix.length() == 0 ? "xmlns" : "xmlns:" + prefix; namedCurveElem.setAttributeNS("http://www.w3.org/2000/xmlns/", qname, XMLDSIG_11_XMLNS); @@ -554,7 +554,7 @@ ECPoint ecPoint = null; try { - String content = XMLUtils.getFullTextChildrenFromElement(curElem); + String content = XMLUtils.getFullTextChildrenFromNode(curElem); ecPoint = decodePoint(XMLUtils.decode(content), ecParams.getCurve()); } catch (IOException ioe) { diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMManifest.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMManifest.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMPGPData.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMPGPData.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMPGPData.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMPGPData.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMPGPData.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -56,7 +56,7 @@ * and optional list of external elements. * * @param keyPacket a PGP Key Material Packet as defined in section 5.5 of - * <a href="http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The + * <a href="https://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The * array is cloned to prevent subsequent modification. * @param other a list of {@link XMLStructure}s representing elements from * an external namespace. The list is defensively copied to prevent @@ -94,10 +94,10 @@ * optional key packet and list of external elements. * * @param keyId a PGP public key id as defined in section 11.2 of - * <a href="http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The + * <a href="https://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The * array is cloned to prevent subsequent modification. * @param keyPacket a PGP Key Material Packet as defined in section 5.5 of - * <a href="http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a> (may + * <a href="https://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a> (may * be {@code null}). The array is cloned to prevent subsequent * modification. * @param other a list of {@link XMLStructure}s representing elements from @@ -157,10 +157,10 @@ String localName = childElem.getLocalName(); String namespace = childElem.getNamespaceURI(); if ("PGPKeyID".equals(localName) && XMLSignature.XMLNS.equals(namespace)) { - String content = XMLUtils.getFullTextChildrenFromElement(childElem); + String content = XMLUtils.getFullTextChildrenFromNode(childElem); pgpKeyId = XMLUtils.decode(content); } else if ("PGPKeyPacket".equals(localName) && XMLSignature.XMLNS.equals(namespace)) { - String content = XMLUtils.getFullTextChildrenFromElement(childElem); + String content = XMLUtils.getFullTextChildrenFromNode(childElem); pgpKeyPacket = XMLUtils.decode(content); } else { other.add diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java Tue May 07 17:30:14 2019 -0400 @@ -21,7 +21,7 @@ * under the License. */ /* - * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -31,7 +31,7 @@ * =========================================================================== */ /* - * $Id: DOMReference.java 1803518 2017-07-31 11:02:52Z coheigea $ + * $Id: DOMReference.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -56,7 +56,6 @@ import org.jcp.xml.dsig.internal.DigesterOutputStream; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream; -import com.sun.org.apache.xml.internal.security.utils.XMLUtils; /** * DOM-based implementation of Reference. @@ -244,7 +243,7 @@ // unmarshal DigestValue Element dvElem = DOMUtils.getNextSiblingElement(dmElem, "DigestValue", XMLSignature.XMLNS); - String content = XMLUtils.getFullTextChildrenFromElement(dvElem); + String content = XMLUtils.getFullTextChildrenFromNode(dvElem); this.digestValue = XMLUtils.decode(content); // check for extra elements @@ -311,6 +310,7 @@ refElem = DOMUtils.createElement(ownerDoc, "Reference", XMLSignature.XMLNS, dsPrefix); + // set attributes DOMUtils.setAttributeID(refElem, "Id", id); DOMUtils.setAttribute(refElem, "URI", uri); @@ -341,7 +341,6 @@ if (digestValue != null) { digestValueElem.appendChild (ownerDoc.createTextNode(XMLUtils.encodeToString(digestValue))); - } refElem.appendChild(digestValueElem); diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Tue May 07 17:30:14 2019 -0400 @@ -21,7 +21,7 @@ * under the License. */ /* - * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -31,7 +31,7 @@ * =========================================================================== */ /* - * $Id: DOMRetrievalMethod.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMRetrievalMethod.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMSignatureMethod.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMSignatureMethod.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperties.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperties.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperties.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMSignatureProperties.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMSignatureProperties.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperty.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperty.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperty.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMSignatureProperty.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMSignatureProperty.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMSignedInfo.java 1820179 2018-01-04 19:09:52Z mullan $ + * $Id: DOMSignedInfo.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMStructure.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMStructure.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMStructure.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMStructure.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMStructure.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMTransform.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMTransform.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMURIDereferencer.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMURIDereferencer.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMUtils.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMUtils.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMUtils.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMUtils.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMUtils.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -92,7 +92,7 @@ public static Element createElement(Document doc, String tag, String nsURI, String prefix) { - String qName = (prefix == null || prefix.length() == 0) + String qName = prefix == null || prefix.length() == 0 ? tag : prefix + ":" + tag; return doc.createElementNS(nsURI, qName); } diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509Data.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509Data.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509Data.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMX509Data.java 1789702 2017-03-31 15:15:04Z coheigea $ + * $Id: DOMX509Data.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -33,12 +33,13 @@ import java.security.cert.*; import java.util.*; -import javax.xml.crypto.*; +import javax.security.auth.x500.X500Principal; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.XMLStructure; import javax.xml.crypto.dom.DOMCryptoContext; -import javax.xml.crypto.dsig.*; +import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.keyinfo.X509Data; import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial; -import javax.security.auth.x500.X500Principal; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -115,7 +116,7 @@ } else if ("X509SubjectName".equals(localName) && XMLSignature.XMLNS.equals(namespace)) { newContent.add(childElem.getFirstChild().getNodeValue()); } else if ("X509SKI".equals(localName) && XMLSignature.XMLNS.equals(namespace)) { - String content = XMLUtils.getFullTextChildrenFromElement(childElem); + String content = XMLUtils.getFullTextChildrenFromNode(childElem); newContent.add(XMLUtils.decode(content)); } else if ("X509CRL".equals(localName) && XMLSignature.XMLNS.equals(namespace)) { newContent.add(unmarshalX509CRL(childElem)); @@ -132,6 +133,7 @@ return content; } + @Override public void marshal(Node parent, String dsPrefix, DOMCryptoContext context) throws MarshalException { @@ -241,7 +243,7 @@ if (cf == null) { cf = CertificateFactory.getInstance("X.509"); } - String content = XMLUtils.getFullTextChildrenFromElement(elem); + String content = XMLUtils.getFullTextChildrenFromNode(elem); return new ByteArrayInputStream(XMLUtils.decode(content)); } catch (CertificateException e) { throw new MarshalException("Cannot create CertificateFactory", e); diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509IssuerSerial.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509IssuerSerial.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509IssuerSerial.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMX509IssuerSerial.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMX509IssuerSerial.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLObject.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLObject.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLObject.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMXMLObject.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMXMLObject.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java Tue May 07 17:30:14 2019 -0400 @@ -21,7 +21,7 @@ * under the License. */ /* - * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -31,7 +31,7 @@ * =========================================================================== */ /* - * $Id: DOMXMLSignature.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMXMLSignature.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -508,7 +508,7 @@ throws MarshalException { // base64 decode signatureValue - String content = XMLUtils.getFullTextChildrenFromElement(sigValueElem); + String content = XMLUtils.getFullTextChildrenFromNode(sigValueElem); value = XMLUtils.decode(content); Attr attr = sigValueElem.getAttributeNodeNS(null, "Id"); @@ -612,6 +612,7 @@ DOMCryptoContext context) throws MarshalException { + // create SignatureValue element sigValueElem = DOMUtils.createElement(ownerDoc, "SignatureValue", XMLSignature.XMLNS, dsPrefix); if (valueBase64 != null) { diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMXMLSignatureFactory.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMXMLSignatureFactory.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; @@ -255,8 +255,6 @@ return new DOMSignatureMethod.SHA384withRSA(params); } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA512)) { return new DOMSignatureMethod.SHA512withRSA(params); - } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA512)) { - return new DOMSignatureMethod.SHA512withRSA(params); } else if (algorithm.equals(DOMSignatureMethod.RSA_RIPEMD160)) { return new DOMSignatureMethod.RIPEMD160withRSA(params); } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA1_MGF1)) { diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java Tue May 07 17:30:14 2019 -0400 @@ -28,10 +28,10 @@ * =========================================================================== */ /* - * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMXPathFilter2Transform.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMXPathFilter2Transform.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathTransform.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathTransform.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathTransform.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMXPathTransform.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMXPathTransform.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXSLTTransform.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXSLTTransform.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXSLTTransform.java Tue May 07 17:30:14 2019 -0400 @@ -21,10 +21,10 @@ * under the License. */ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: DOMXSLTTransform.java 1788465 2017-03-24 15:10:51Z coheigea $ + * $Id: DOMXSLTTransform.java 1854026 2019-02-21 09:30:01Z coheigea $ */ package org.jcp.xml.dsig.internal.dom; diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java Tue May 07 17:30:14 2019 -0400 @@ -28,10 +28,10 @@ * =========================================================================== */ /* - * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. */ /* - * $Id: XMLDSigRI.java 1804972 2017-08-14 09:59:23Z coheigea $ + * $Id: XMLDSigRI.java 1833618 2018-06-15 17:36:20Z mullan $ */ package org.jcp.xml.dsig.internal.dom; @@ -123,7 +123,7 @@ } else if (algo.equals(Transform.XSLT)) { return new DOMXSLTTransform(); } - } + } } catch (Exception ex) { throw new NoSuchAlgorithmException("Error constructing " + type + " for " + algo + " using XMLDSig", ex); diff -r bf3d37105ef9 -r 51709d9aab69 src/java.xml.crypto/share/legal/santuario.md --- a/src/java.xml.crypto/share/legal/santuario.md Fri May 03 14:59:32 2019 -0400 +++ b/src/java.xml.crypto/share/legal/santuario.md Tue May 07 17:30:14 2019 -0400 @@ -1,10 +1,10 @@ -## Apache Santuario v2.1.1 +## Apache Santuario v2.1.3 ### Apache Santuario Notice <pre> Apache Santuario - XML Security for Java - Copyright 1999-2018 The Apache Software Foundation + Copyright 1999-2019 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Tue May 07 17:30:14 2019 -0400 @@ -612,10 +612,15 @@ * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's * log stream. * + * @param flush specifies if the log stream should be flushed after writing + * @param canThrow specifies if an error in the {@code bytes}, {@code offset} or {@code length} + * arguments should result in an exception or a negative return value + * @return 0 on success, -1 if {@code bytes == null && !canThrow}, -2 if {@code !canThrow} and + * copying would cause access of data outside array bounds * @throws NullPointerException if {@code bytes == null} * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds */ - native void writeDebugOutput(byte[] bytes, int offset, int length); + native int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow); /** * Flush HotSpot's log stream. @@ -947,4 +952,18 @@ */ native boolean addFailedSpeculation(long failedSpeculationsAddress, byte[] speculation); + /** + * @see HotSpotJVMCIRuntime#isCurrentThreadAttached() + */ + native boolean isCurrentThreadAttached(); + + /** + * @see HotSpotJVMCIRuntime#attachCurrentThread + */ + native boolean attachCurrentThread(boolean asDaemon); + + /** + * @see HotSpotJVMCIRuntime#detachCurrentThread() + */ + native void detachCurrentThread(); } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Tue May 07 17:30:14 2019 -0400 @@ -46,7 +46,6 @@ import java.util.Map; import java.util.Objects; import java.util.ServiceLoader; -import java.util.TreeMap; import java.util.function.Predicate; import jdk.internal.misc.Unsafe; @@ -180,8 +179,8 @@ // Can only do eager initialization of the JVMCI compiler // once the singleton instance is available. - if (instance.config.getFlag("EagerJVMCI", Boolean.class)) { - instance.getCompiler(); + if (result.config.getFlag("EagerJVMCI", Boolean.class)) { + result.getCompiler(); } } // Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is @@ -384,7 +383,25 @@ /** * Cache for speeding up {@link #fromClass(Class)}. */ - @NativeImageReinitialize private volatile ClassValue<WeakReference<HotSpotResolvedJavaType>> resolvedJavaType; + @NativeImageReinitialize private volatile ClassValue<WeakReferenceHolder<HotSpotResolvedJavaType>> resolvedJavaType; + + /** + * To avoid calling ClassValue.remove to refresh the weak reference, which + * under certain circumstances can lead to an infinite loop, we use a + * permanent holder with a mutable field that we refresh. + */ + private static class WeakReferenceHolder<T> { + private volatile WeakReference<T> ref; + WeakReferenceHolder(T value) { + set(value); + } + void set(T value) { + ref = new WeakReference<T>(value); + } + T get() { + return ref.get(); + } + }; @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes; @@ -464,7 +481,7 @@ } if (Option.PrintConfig.getBoolean()) { - printConfig(configStore, compilerToVm); + configStore.printConfig(); } } @@ -486,27 +503,25 @@ if (resolvedJavaType == null) { synchronized (this) { if (resolvedJavaType == null) { - resolvedJavaType = new ClassValue<WeakReference<HotSpotResolvedJavaType>>() { + resolvedJavaType = new ClassValue<WeakReferenceHolder<HotSpotResolvedJavaType>>() { @Override - protected WeakReference<HotSpotResolvedJavaType> computeValue(Class<?> type) { - return new WeakReference<>(createClass(type)); + protected WeakReferenceHolder<HotSpotResolvedJavaType> computeValue(Class<?> type) { + return new WeakReferenceHolder<>(createClass(type)); } }; } } } - HotSpotResolvedJavaType javaType = null; - while (javaType == null) { - WeakReference<HotSpotResolvedJavaType> type = resolvedJavaType.get(javaClass); - javaType = type.get(); - if (javaType == null) { - /* - * If the referent has become null, clear out the current value and let computeValue - * above create a new value. Reload the value in a loop because in theory the - * WeakReference referent can be reclaimed at any point. - */ - resolvedJavaType.remove(javaClass); - } + + WeakReferenceHolder<HotSpotResolvedJavaType> ref = resolvedJavaType.get(javaClass); + HotSpotResolvedJavaType javaType = ref.get(); + if (javaType == null) { + /* + * If the referent has become null, create a new value and + * update cached weak reference. + */ + javaType = createClass(javaClass); + ref.set(javaType); } return javaType; } @@ -727,39 +742,21 @@ } } - @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!") - private static void printConfigLine(CompilerToVM vm, String format, Object... args) { - String line = String.format(format, args); - byte[] lineBytes = line.getBytes(); - vm.writeDebugOutput(lineBytes, 0, lineBytes.length); - vm.flushDebugOutput(); - } - - private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) { - TreeMap<String, VMField> fields = new TreeMap<>(store.getFields()); - for (VMField field : fields.values()) { - if (!field.isStatic()) { - printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset); - } else { - String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value); - printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address); - } - } - TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags()); - for (VMFlag flag : flags.values()) { - printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value); - } - TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses()); - for (Map.Entry<String, Long> e : addresses.entrySet()) { - printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue()); - } - TreeMap<String, Long> constants = new TreeMap<>(store.getConstants()); - for (Map.Entry<String, Long> e : constants.entrySet()) { - printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue()); - } - for (VMIntrinsicMethod e : store.getIntrinsics()) { - printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor); - } + /** + * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's + * log stream. + * + * @param flush specifies if the log stream should be flushed after writing + * @param canThrow specifies if an error in the {@code bytes}, {@code offset} or {@code length} + * arguments should result in an exception or a negative return value. If + * {@code false}, this call will not perform any heap allocation + * @return 0 on success, -1 if {@code bytes == null && !canThrow}, -2 if {@code !canThrow} and + * copying would cause access of data outside array bounds + * @throws NullPointerException if {@code bytes == null} + * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds + */ + public int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow) { + return compilerToVm.writeDebugOutput(bytes, offset, length, flush, canThrow); } /** @@ -777,7 +774,7 @@ } else if (len == 0) { return; } - compilerToVm.writeDebugOutput(b, off, len); + compilerToVm.writeDebugOutput(b, off, len, false, true); } @Override @@ -907,11 +904,13 @@ * the Java VM in the JVMCI shared library, and the remaining values are the first 3 * pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface}) * @throws NullPointerException if {@code clazz == null} - * @throws IllegalArgumentException if the current execution context is the JVMCI shared library - * or if {@code clazz} is {@link Class#isPrimitive()} - * @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in - * {@code clazz} is already linked or the JVMCI shared library does not contain a - * JNI-compatible symbol for a native method in {@code clazz} + * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. + * {@code -XX:-UseJVMCINativeLibrary}) + * @throws IllegalStateException if the current execution context is the JVMCI shared library + * @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()} + * @throws UnsatisfiedLinkError if there's a problem linking a native method in {@code clazz} + * (no matching JNI symbol or the native method is already linked to a different + * address) */ public long[] registerNativeMethods(Class<?> clazz) { return compilerToVm.registerNativeMethods(clazz); @@ -935,6 +934,8 @@ * * @param obj an object for which an equivalent instance in the peer runtime is requested * @return a JNI global reference to the mirror of {@code obj} in the peer runtime + * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. + * {@code -XX:-UseJVMCINativeLibrary}) * @throws IllegalArgumentException if {@code obj} is not of a translatable type * * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references" @@ -950,7 +951,9 @@ * * @param handle a JNI global reference to an object in the current runtime * @return the object referred to by {@code handle} - * @throws ClassCastException if the returned object cannot be case to {@code type} + * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. + * {@code -XX:-UseJVMCINativeLibrary}) + * @throws ClassCastException if the returned object cannot be cast to {@code type} * * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references" * @@ -960,6 +963,44 @@ } /** + * Determines if the current thread is attached to the peer runtime. + * + * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. + * {@code -XX:-UseJVMCINativeLibrary}) + * @throws IllegalStateException if the peer runtime has not been initialized + */ + public boolean isCurrentThreadAttached() { + return compilerToVm.isCurrentThreadAttached(); + } + + /** + * Ensures the current thread is attached to the peer runtime. + * + * @param asDaemon if the thread is not yet attached, should it be attached as a daemon + * @return {@code true} if this call attached the current thread, {@code false} if the current + * thread was already attached + * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. + * {@code -XX:-UseJVMCINativeLibrary}) + * @throws IllegalStateException if the peer runtime has not been initialized or there is an + * error while trying to attach the thread + */ + public boolean attachCurrentThread(boolean asDaemon) { + return compilerToVm.attachCurrentThread(asDaemon); + } + + /** + * Detaches the current thread from the peer runtime. + * + * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. + * {@code -XX:-UseJVMCINativeLibrary}) + * @throws IllegalStateException if the peer runtime has not been initialized or if the current + * thread is not attached or if there is an error while trying to detach the thread + */ + public void detachCurrentThread() { + compilerToVm.detachCurrentThread(); + } + + /** * Informs HotSpot that no method whose module is in {@code modules} is to be compiled * with {@link #compileMethod}. * diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java Tue May 07 17:30:14 2019 -0400 @@ -193,8 +193,7 @@ private static void printConfigLine(CompilerToVM vm, String format, Object... args) { String line = String.format(format, args); byte[] lineBytes = line.getBytes(); - vm.writeDebugOutput(lineBytes, 0, lineBytes.length); - vm.flushDebugOutput(); + vm.writeDebugOutput(lineBytes, 0, lineBytes.length, true, true); } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java Tue May 07 17:30:14 2019 -0400 @@ -49,16 +49,23 @@ return this; } - @Override - public String toString() { - return getMessage(); - } + private static Throwable create(String className, String message) { + // Try create with reflection first. + try { + Class<?> cls = Class.forName(className); + if (message == null) { + return (Throwable) cls.getConstructor().newInstance(); + } + cls.getDeclaredConstructor(String.class); + return (Throwable) cls.getConstructor(String.class).newInstance(message); + } catch (Throwable ignore) { + } - private static TranslatedException create(String className, String message) { if (className.equals(TranslatedException.class.getName())) { // Chop the class name when boxing another TranslatedException return new TranslatedException(message); } + if (message == null) { return new TranslatedException(className); } @@ -147,7 +154,7 @@ Throwable throwable = create(exceptionClassName, exceptionMessage); int stackTraceDepth = Integer.parseInt(parts[i++]); - StackTraceElement[] suffix = parent == null ? new StackTraceElement[0] : getStackTraceSuffix(); + StackTraceElement[] suffix = getStackTraceSuffix(); StackTraceElement[] stackTrace = new StackTraceElement[stackTraceDepth + suffix.length]; for (int j = 0; j < stackTraceDepth; j++) { String className = parts[i++]; diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -38,13 +38,13 @@ * @return the simple name */ public static String getSimpleName(Class<?> clazz, boolean withEnclosingClass) { - final String simpleName = clazz.getSimpleName(); + final String simpleName = safeSimpleName(clazz); if (simpleName.length() != 0) { if (withEnclosingClass) { String prefix = ""; Class<?> enclosingClass = clazz; while ((enclosingClass = enclosingClass.getEnclosingClass()) != null) { - prefix = enclosingClass.getSimpleName() + "." + prefix; + prefix = safeSimpleName(enclosingClass) + "." + prefix; } return prefix + simpleName; } @@ -63,6 +63,29 @@ return name.substring(index + 1); } + private static String safeSimpleName(Class<?> clazz) { + try { + return clazz.getSimpleName(); + } catch (InternalError e) { + // Scala inner class names do not always start with '$', + // causing Class.getSimpleName to throw an InternalError + Class<?> enclosingClass = clazz.getEnclosingClass(); + String fqn = clazz.getName(); + if (enclosingClass == null) { + // Should never happen given logic in + // Class.getSimpleName but best be safe + return fqn; + } + String enclosingFQN = enclosingClass.getName(); + int length = fqn.length(); + if (enclosingFQN.length() >= length) { + // Should also never happen + return fqn; + } + return fqn.substring(enclosingFQN.length()); + } + } + /** * Converts a type name in internal form to an external form. * diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java Tue May 07 17:30:14 2019 -0400 @@ -283,6 +283,17 @@ } /** + * A Java {@code char} has a maximal UTF8 length of 3. + */ + private static final int MAX_UNICODE_IN_UTF8_LENGTH = 3; + + /** + * {@link DataOutputStream#writeUTF(String)} only supports values whose UTF8 encoding length is + * less than 65535. + */ + private static final int MAX_UTF8_PROPERTY_STRING_LENGTH = 65535 / MAX_UNICODE_IN_UTF8_LENGTH; + + /** * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial * properties in the JVMCI shared library. @@ -292,25 +303,48 @@ if (IS_IN_NATIVE_IMAGE) { throw new InternalError("Can only serialize saved properties in HotSpot runtime"); } - Map<String, String> props = Services.getSavedProperties(); + return serializeProperties(Services.getSavedProperties()); + } + private static byte[] serializeProperties(Map<String, String> props) throws IOException { // Compute size of output on the assumption that // all system properties have ASCII names and values - int estimate = 4; + int estimate = 4 + 4; + int nonUtf8Props = 0; for (Map.Entry<String, String> e : props.entrySet()) { String name = e.getKey(); String value = e.getValue(); estimate += (2 + (name.length())) + (2 + (value.length())); + if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) { + nonUtf8Props++; + } } ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate); DataOutputStream out = new DataOutputStream(baos); - out.writeInt(props.size()); + out.writeInt(props.size() - nonUtf8Props); + out.writeInt(nonUtf8Props); for (Map.Entry<String, String> e : props.entrySet()) { String name = e.getKey(); String value = e.getValue(); - out.writeUTF(name); - out.writeUTF(value); + if (name.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH && value.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH) { + out.writeUTF(name); + out.writeUTF(value); + } + } + if (nonUtf8Props != 0) { + for (Map.Entry<String, String> e : props.entrySet()) { + String name = e.getKey(); + String value = e.getValue(); + if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) { + byte[] utf8Name = name.getBytes("UTF-8"); + byte[] utf8Value = value.getBytes("UTF-8"); + out.writeInt(utf8Name.length); + out.write(utf8Name); + out.writeInt(utf8Value.length); + out.write(utf8Value); + } + } } return baos.toByteArray(); } @@ -325,13 +359,33 @@ if (!IS_IN_NATIVE_IMAGE) { throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime"); } + savedProperties = Collections.unmodifiableMap(deserializeProperties(serializedProperties)); + } + + private static Map<String, String> deserializeProperties(byte[] serializedProperties) throws IOException { DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties)); - Map<String, String> props = new HashMap<>(in.readInt()); + int utf8Props = in.readInt(); + int nonUtf8Props = in.readInt(); + Map<String, String> props = new HashMap<>(utf8Props + nonUtf8Props); + int index = 0; while (in.available() != 0) { - String name = in.readUTF(); - String value = in.readUTF(); - props.put(name, value); + if (index < utf8Props) { + String name = in.readUTF(); + String value = in.readUTF(); + props.put(name, value); + } else { + int nameLen = in.readInt(); + byte[] nameBytes = new byte[nameLen]; + in.read(nameBytes); + int valueLen = in.readInt(); + byte[] valueBytes = new byte[valueLen]; + in.read(valueBytes); + String name = new String(nameBytes, "UTF-8"); + String value = new String(valueBytes, "UTF-8"); + props.put(name, value); + } + index++; } - savedProperties = Collections.unmodifiableMap(props); + return props; } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/SuppressFBWarnings.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/SuppressFBWarnings.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,42 @@ +/* + * 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.vm.ci.services; + +/** + * Used to suppress <a href="http://findbugs.sourceforge.net">FindBugs</a> warnings. + */ +@interface SuppressFBWarnings { + /** + * The set of FindBugs + * <a href="http://findbugs.sourceforge.net/bugDescriptions.html">warnings</a> that are to be + * suppressed in annotated element. The value can be a bug category, kind or pattern. + */ + String[] value(); + + /** + * Reason why the warning is suppressed. + */ + String justification(); +} diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.ci/share/classes/module-info.java --- a/src/jdk.internal.vm.ci/share/classes/module-info.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.ci/share/classes/module-info.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -30,6 +30,9 @@ exports jdk.vm.ci.runtime to jdk.internal.vm.compiler, jdk.internal.vm.compiler.management; + exports jdk.vm.ci.meta to jdk.internal.vm.compiler; + exports jdk.vm.ci.code to jdk.internal.vm.compiler; + exports jdk.vm.ci.hotspot to jdk.internal.vm.compiler; uses jdk.vm.ci.services.JVMCIServiceLocator; uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory; diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java --- a/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java Tue May 07 17:30:14 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 @@ -35,7 +35,7 @@ import com.sun.management.ThreadMXBean; /** - * Implementation of {@link JMXService} for JDK 11 and later. + * Implementation of {@link JMXService} for JDK 13 and later. */ @ServiceProvider(JMXService.class) public class JMXServiceProvider extends JMXService { diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java Tue May 07 17:30:14 2019 -0400 @@ -3003,6 +3003,18 @@ emitByte(0x99); } + public final void repStosb() { + emitByte(0xf3); + rexw(); + emitByte(0xaa); + } + + public final void repStosq() { + emitByte(0xf3); + rexw(); + emitByte(0xab); + } + public final void cmovq(ConditionFlag cc, Register dst, Register src) { prefixq(dst, src); emitByte(0x0F); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java Tue May 07 17:30:14 2019 -0400 @@ -121,6 +121,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ShiftOp; import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp; import org.graalvm.compiler.lir.amd64.AMD64Unary; +import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary; @@ -1102,6 +1103,12 @@ return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y); } + @Override + public void emitZeroMemory(Value address, Value length) { + RegisterValue lengthReg = moveToReg(AMD64.rcx, length); + getLIRGen().append(new AMD64ZeroMemoryOp(getAMD64LIRGen().asAddressValue(address), lengthReg)); + } + protected AMD64LIRGenerator getAMD64LIRGen() { return (AMD64LIRGenerator) getLIRGen(); } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java Tue May 07 17:30:14 2019 -0400 @@ -279,9 +279,13 @@ @Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug) public static final OptionKey<Boolean> TraceInliningForStubsAndSnippets = new OptionKey<>(false); - @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.") + @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.", type = OptionType.Expert) public static final OptionKey<Boolean> UseGraalStubs = new OptionKey<>(true); @Option(help = "Encode and decode snippets and substitutions before parsing to test libgraal code path. This option is ignored in the context of libgraal.") public static final OptionKey<Boolean> UseEncodedGraphs = new OptionKey<>(false); + + @Option(help = "If applicable, use bulk zeroing instructions when the zeroing size in bytes exceeds this threshold.", type = OptionType.Expert) + public static final OptionKey<Integer> MinimalBulkZeroingSize = new OptionKey<>(2048); + } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java Tue May 07 17:30:14 2019 -0400 @@ -318,8 +318,10 @@ /* * There are many forms of NaNs and any operations on them can silently convert them into * the canonical NaN. + * + * We need to exclude 0 here since it can contain -0.0 && 0.0 . */ - return (Double.compare(lowerBound, upperBound) == 0 && nonNaN); + return (Double.compare(lowerBound, upperBound) == 0 && nonNaN) && lowerBound != 0; } private static FloatStamp stampForConstant(Constant constant) { diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BciBlockMappingTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BciBlockMappingTest.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,1416 @@ +/* + * 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. + */ + + +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.java.BciBlockMapping; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Test; + +/** + * Tests that the {@link BciBlockMapping} can handle code with a lot of blocks. The test code is + * derived from the {@code ImplicitStringConcatShapes} test in OpenJDK. + */ +public class BciBlockMappingTest extends GraalCompilerTest { + + @Test + public void test() { + parseEager("run", AllowAssumptions.NO); + } + + @SuppressWarnings("unused") + public static void blackhole(String expected, String actual) { + } + + static double aDouble = -96.0d; + + public void run() { + blackhole("-96.0", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("\u045176", "" + aDouble); + blackhole("92", "" + aDouble); + blackhole("51", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("-54", "" + aDouble); + blackhole("-87.0", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("19", "" + aDouble); + blackhole("-41", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("T", "" + aDouble); + blackhole("-42.0", "" + aDouble); + blackhole("25", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("-1410065408", "" + aDouble); + blackhole("8.0", "" + aDouble); + blackhole("55.0", "" + aDouble); + blackhole("97000000", "" + aDouble); + blackhole("-9900", "" + aDouble); + blackhole("935228928", "" + aDouble); + blackhole("-8400", "" + aDouble); + blackhole("C(82)", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("true", "" + aDouble); + blackhole("3900", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("94000000", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("true", "" + aDouble); + blackhole("5500", "" + aDouble); + blackhole("-2900", "" + aDouble); + blackhole("-194313216", "" + aDouble); + blackhole("12", "" + aDouble); + blackhole("C(87)", "" + aDouble); + blackhole("91", "" + aDouble); + blackhole("21", "" + aDouble); + blackhole("18", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("\u045180", "" + aDouble); + blackhole("C", "" + aDouble); + blackhole("75", "" + aDouble); + blackhole("-43", "" + aDouble); + blackhole("80", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("-52.0", "" + aDouble); + blackhole("75000000", "" + aDouble); + blackhole("44", "" + aDouble); + blackhole("-1705032704", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("83.0", "" + aDouble); + blackhole("I", "" + aDouble); + blackhole("94.0", "" + aDouble); + blackhole("12.0", "" + aDouble); + blackhole("-99.0", "" + aDouble); + blackhole("17.0", "" + aDouble); + blackhole("-84.0", "" + aDouble); + blackhole("58000000", "" + aDouble); + blackhole("-55000000", "" + aDouble); + blackhole("1460392448", "" + aDouble); + blackhole("C(70)", "" + aDouble); + blackhole("\u04511", "" + aDouble); + blackhole("8000", "" + aDouble); + blackhole("18", "" + aDouble); + blackhole("-1000000", "" + aDouble); + blackhole("1000000", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("false", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("-2000000", "" + aDouble); + blackhole("-820130816", "" + aDouble); + blackhole("null", "" + aDouble); + blackhole("25000000", "" + aDouble); + blackhole("-96.0-96.0", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0\u045176", "" + aDouble); + blackhole("-96.092", "" + aDouble); + blackhole("-96.051", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0-54", "" + aDouble); + blackhole("-96.0-87.0", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.019", "" + aDouble); + blackhole("-96.0-41", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0T", "" + aDouble); + blackhole("-96.0-42.0", "" + aDouble); + blackhole("-96.025", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0-1410065408", "" + aDouble); + blackhole("-96.08.0", "" + aDouble); + blackhole("-96.055.0", "" + aDouble); + blackhole("-96.097000000", "" + aDouble); + blackhole("-96.0-9900", "" + aDouble); + blackhole("-96.0935228928", "" + aDouble); + blackhole("-96.0-8400", "" + aDouble); + blackhole("-96.0C(82)", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0true", "" + aDouble); + blackhole("-96.03900", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.094000000", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0true", "" + aDouble); + blackhole("-96.05500", "" + aDouble); + blackhole("-96.0-2900", "" + aDouble); + blackhole("-96.0-194313216", "" + aDouble); + blackhole("-96.012", "" + aDouble); + blackhole("-96.0C(87)", "" + aDouble); + blackhole("-96.091", "" + aDouble); + blackhole("-96.021", "" + aDouble); + blackhole("-96.018", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0\u045180", "" + aDouble); + blackhole("-96.0C", "" + aDouble); + blackhole("-96.075", "" + aDouble); + blackhole("-96.0-43", "" + aDouble); + blackhole("-96.080", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0-52.0", "" + aDouble); + blackhole("-96.075000000", "" + aDouble); + blackhole("-96.044", "" + aDouble); + blackhole("-96.0-1705032704", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.083.0", "" + aDouble); + blackhole("-96.0I", "" + aDouble); + blackhole("-96.094.0", "" + aDouble); + blackhole("-96.012.0", "" + aDouble); + blackhole("-96.0-99.0", "" + aDouble); + blackhole("-96.017.0", "" + aDouble); + blackhole("-96.0-84.0", "" + aDouble); + blackhole("-96.058000000", "" + aDouble); + blackhole("-96.0-55000000", "" + aDouble); + blackhole("-96.01460392448", "" + aDouble); + blackhole("-96.0C(70)", "" + aDouble); + blackhole("-96.0\u04511", "" + aDouble); + blackhole("-96.08000", "" + aDouble); + blackhole("-96.018", "" + aDouble); + blackhole("-96.0-1000000", "" + aDouble); + blackhole("-96.01000000", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0false", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.0-2000000", "" + aDouble); + blackhole("-96.0-820130816", "" + aDouble); + blackhole("-96.0null", "" + aDouble); + blackhole("-96.025000000", "" + aDouble); + blackhole("null-96.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045176", "" + aDouble); + blackhole("null92", "" + aDouble); + blackhole("null51", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-54", "" + aDouble); + blackhole("null-87.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null19", "" + aDouble); + blackhole("null-41", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullT", "" + aDouble); + blackhole("null-42.0", "" + aDouble); + blackhole("null25", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-1410065408", "" + aDouble); + blackhole("null8.0", "" + aDouble); + blackhole("null55.0", "" + aDouble); + blackhole("null97000000", "" + aDouble); + blackhole("null-9900", "" + aDouble); + blackhole("null935228928", "" + aDouble); + blackhole("null-8400", "" + aDouble); + blackhole("nullC(82)", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null3900", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null94000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null5500", "" + aDouble); + blackhole("null-2900", "" + aDouble); + blackhole("null-194313216", "" + aDouble); + blackhole("null12", "" + aDouble); + blackhole("nullC(87)", "" + aDouble); + blackhole("null91", "" + aDouble); + blackhole("null21", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045180", "" + aDouble); + blackhole("nullC", "" + aDouble); + blackhole("null75", "" + aDouble); + blackhole("null-43", "" + aDouble); + blackhole("null80", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-52.0", "" + aDouble); + blackhole("null75000000", "" + aDouble); + blackhole("null44", "" + aDouble); + blackhole("null-1705032704", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null83.0", "" + aDouble); + blackhole("nullI", "" + aDouble); + blackhole("null94.0", "" + aDouble); + blackhole("null12.0", "" + aDouble); + blackhole("null-99.0", "" + aDouble); + blackhole("null17.0", "" + aDouble); + blackhole("null-84.0", "" + aDouble); + blackhole("null58000000", "" + aDouble); + blackhole("null-55000000", "" + aDouble); + blackhole("null1460392448", "" + aDouble); + blackhole("nullC(70)", "" + aDouble); + blackhole("null\u04511", "" + aDouble); + blackhole("null8000", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("null-1000000", "" + aDouble); + blackhole("null1000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullfalse", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-2000000", "" + aDouble); + blackhole("null-820130816", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null25000000", "" + aDouble); + blackhole("\u045176-96.0", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176\u045176", "" + aDouble); + blackhole("\u04517692", "" + aDouble); + blackhole("\u04517651", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176-54", "" + aDouble); + blackhole("\u045176-87.0", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u04517619", "" + aDouble); + blackhole("\u045176-41", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176T", "" + aDouble); + blackhole("\u045176-42.0", "" + aDouble); + blackhole("\u04517625", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176-1410065408", "" + aDouble); + blackhole("\u0451768.0", "" + aDouble); + blackhole("\u04517655.0", "" + aDouble); + blackhole("\u04517697000000", "" + aDouble); + blackhole("\u045176-9900", "" + aDouble); + blackhole("\u045176935228928", "" + aDouble); + blackhole("\u045176-8400", "" + aDouble); + blackhole("\u045176C(82)", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176true", "" + aDouble); + blackhole("\u0451763900", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u04517694000000", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176true", "" + aDouble); + blackhole("\u0451765500", "" + aDouble); + blackhole("\u045176-2900", "" + aDouble); + blackhole("\u045176-194313216", "" + aDouble); + blackhole("\u04517612", "" + aDouble); + blackhole("\u045176C(87)", "" + aDouble); + blackhole("\u04517691", "" + aDouble); + blackhole("\u04517621", "" + aDouble); + blackhole("\u04517618", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176\u045180", "" + aDouble); + blackhole("\u045176C", "" + aDouble); + blackhole("\u04517675", "" + aDouble); + blackhole("\u045176-43", "" + aDouble); + blackhole("\u04517680", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176-52.0", "" + aDouble); + blackhole("\u04517675000000", "" + aDouble); + blackhole("\u04517644", "" + aDouble); + blackhole("\u045176-1705032704", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u04517683.0", "" + aDouble); + blackhole("\u045176I", "" + aDouble); + blackhole("\u04517694.0", "" + aDouble); + blackhole("\u04517612.0", "" + aDouble); + blackhole("\u045176-99.0", "" + aDouble); + blackhole("\u04517617.0", "" + aDouble); + blackhole("\u045176-84.0", "" + aDouble); + blackhole("\u04517658000000", "" + aDouble); + blackhole("\u045176-55000000", "" + aDouble); + blackhole("\u0451761460392448", "" + aDouble); + blackhole("\u045176C(70)", "" + aDouble); + blackhole("\u045176\u04511", "" + aDouble); + blackhole("\u0451768000", "" + aDouble); + blackhole("\u04517618", "" + aDouble); + blackhole("\u045176-1000000", "" + aDouble); + blackhole("\u0451761000000", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176false", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u045176-2000000", "" + aDouble); + blackhole("\u045176-820130816", "" + aDouble); + blackhole("\u045176null", "" + aDouble); + blackhole("\u04517625000000", "" + aDouble); + blackhole("92-96.0", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92\u045176", "" + aDouble); + blackhole("9292", "" + aDouble); + blackhole("9251", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92-54", "" + aDouble); + blackhole("92-87.0", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("9219", "" + aDouble); + blackhole("92-41", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92T", "" + aDouble); + blackhole("92-42.0", "" + aDouble); + blackhole("9225", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92-1410065408", "" + aDouble); + blackhole("928.0", "" + aDouble); + blackhole("9255.0", "" + aDouble); + blackhole("9297000000", "" + aDouble); + blackhole("92-9900", "" + aDouble); + blackhole("92935228928", "" + aDouble); + blackhole("92-8400", "" + aDouble); + blackhole("92C(82)", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92true", "" + aDouble); + blackhole("923900", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("9294000000", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92true", "" + aDouble); + blackhole("925500", "" + aDouble); + blackhole("92-2900", "" + aDouble); + blackhole("92-194313216", "" + aDouble); + blackhole("9212", "" + aDouble); + blackhole("92C(87)", "" + aDouble); + blackhole("9291", "" + aDouble); + blackhole("9221", "" + aDouble); + blackhole("9218", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92\u045180", "" + aDouble); + blackhole("92C", "" + aDouble); + blackhole("9275", "" + aDouble); + blackhole("92-43", "" + aDouble); + blackhole("9280", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92-52.0", "" + aDouble); + blackhole("9275000000", "" + aDouble); + blackhole("9244", "" + aDouble); + blackhole("92-1705032704", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("9283.0", "" + aDouble); + blackhole("92I", "" + aDouble); + blackhole("9294.0", "" + aDouble); + blackhole("9212.0", "" + aDouble); + blackhole("92-99.0", "" + aDouble); + blackhole("9217.0", "" + aDouble); + blackhole("92-84.0", "" + aDouble); + blackhole("9258000000", "" + aDouble); + blackhole("92-55000000", "" + aDouble); + blackhole("921460392448", "" + aDouble); + blackhole("92C(70)", "" + aDouble); + blackhole("92\u04511", "" + aDouble); + blackhole("928000", "" + aDouble); + blackhole("9218", "" + aDouble); + blackhole("92-1000000", "" + aDouble); + blackhole("921000000", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92false", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("92-2000000", "" + aDouble); + blackhole("92-820130816", "" + aDouble); + blackhole("92null", "" + aDouble); + blackhole("9225000000", "" + aDouble); + blackhole("51-96.0", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51\u045176", "" + aDouble); + blackhole("5192", "" + aDouble); + blackhole("5151", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51-54", "" + aDouble); + blackhole("51-87.0", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("5119", "" + aDouble); + blackhole("51-41", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51T", "" + aDouble); + blackhole("51-42.0", "" + aDouble); + blackhole("5125", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51-1410065408", "" + aDouble); + blackhole("518.0", "" + aDouble); + blackhole("5155.0", "" + aDouble); + blackhole("5197000000", "" + aDouble); + blackhole("51-9900", "" + aDouble); + blackhole("51935228928", "" + aDouble); + blackhole("51-8400", "" + aDouble); + blackhole("51C(82)", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51true", "" + aDouble); + blackhole("513900", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("5194000000", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51true", "" + aDouble); + blackhole("515500", "" + aDouble); + blackhole("51-2900", "" + aDouble); + blackhole("51-194313216", "" + aDouble); + blackhole("5112", "" + aDouble); + blackhole("51C(87)", "" + aDouble); + blackhole("5191", "" + aDouble); + blackhole("5121", "" + aDouble); + blackhole("5118", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51\u045180", "" + aDouble); + blackhole("51C", "" + aDouble); + blackhole("5175", "" + aDouble); + blackhole("51-43", "" + aDouble); + blackhole("5180", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51-52.0", "" + aDouble); + blackhole("5175000000", "" + aDouble); + blackhole("5144", "" + aDouble); + blackhole("51-1705032704", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("5183.0", "" + aDouble); + blackhole("51I", "" + aDouble); + blackhole("5194.0", "" + aDouble); + blackhole("5112.0", "" + aDouble); + blackhole("51-99.0", "" + aDouble); + blackhole("5117.0", "" + aDouble); + blackhole("51-84.0", "" + aDouble); + blackhole("5158000000", "" + aDouble); + blackhole("51-55000000", "" + aDouble); + blackhole("511460392448", "" + aDouble); + blackhole("51C(70)", "" + aDouble); + blackhole("51\u04511", "" + aDouble); + blackhole("518000", "" + aDouble); + blackhole("5118", "" + aDouble); + blackhole("51-1000000", "" + aDouble); + blackhole("511000000", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51false", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("51-2000000", "" + aDouble); + blackhole("51-820130816", "" + aDouble); + blackhole("51null", "" + aDouble); + blackhole("5125000000", "" + aDouble); + blackhole("null-96.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045176", "" + aDouble); + blackhole("null92", "" + aDouble); + blackhole("null51", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-54", "" + aDouble); + blackhole("null-87.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null19", "" + aDouble); + blackhole("null-41", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullT", "" + aDouble); + blackhole("null-42.0", "" + aDouble); + blackhole("null25", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-1410065408", "" + aDouble); + blackhole("null8.0", "" + aDouble); + blackhole("null55.0", "" + aDouble); + blackhole("null97000000", "" + aDouble); + blackhole("null-9900", "" + aDouble); + blackhole("null935228928", "" + aDouble); + blackhole("null-8400", "" + aDouble); + blackhole("nullC(82)", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null3900", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null94000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null5500", "" + aDouble); + blackhole("null-2900", "" + aDouble); + blackhole("null-194313216", "" + aDouble); + blackhole("null12", "" + aDouble); + blackhole("nullC(87)", "" + aDouble); + blackhole("null91", "" + aDouble); + blackhole("null21", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045180", "" + aDouble); + blackhole("nullC", "" + aDouble); + blackhole("null75", "" + aDouble); + blackhole("null-43", "" + aDouble); + blackhole("null80", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-52.0", "" + aDouble); + blackhole("null75000000", "" + aDouble); + blackhole("null44", "" + aDouble); + blackhole("null-1705032704", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null83.0", "" + aDouble); + blackhole("nullI", "" + aDouble); + blackhole("null94.0", "" + aDouble); + blackhole("null12.0", "" + aDouble); + blackhole("null-99.0", "" + aDouble); + blackhole("null17.0", "" + aDouble); + blackhole("null-84.0", "" + aDouble); + blackhole("null58000000", "" + aDouble); + blackhole("null-55000000", "" + aDouble); + blackhole("null1460392448", "" + aDouble); + blackhole("nullC(70)", "" + aDouble); + blackhole("null\u04511", "" + aDouble); + blackhole("null8000", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("null-1000000", "" + aDouble); + blackhole("null1000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullfalse", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-2000000", "" + aDouble); + blackhole("null-820130816", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null25000000", "" + aDouble); + blackhole("-54-96.0", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54\u045176", "" + aDouble); + blackhole("-5492", "" + aDouble); + blackhole("-5451", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54-54", "" + aDouble); + blackhole("-54-87.0", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-5419", "" + aDouble); + blackhole("-54-41", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54T", "" + aDouble); + blackhole("-54-42.0", "" + aDouble); + blackhole("-5425", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54-1410065408", "" + aDouble); + blackhole("-548.0", "" + aDouble); + blackhole("-5455.0", "" + aDouble); + blackhole("-5497000000", "" + aDouble); + blackhole("-54-9900", "" + aDouble); + blackhole("-54935228928", "" + aDouble); + blackhole("-54-8400", "" + aDouble); + blackhole("-54C(82)", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54true", "" + aDouble); + blackhole("-543900", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-5494000000", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54true", "" + aDouble); + blackhole("-545500", "" + aDouble); + blackhole("-54-2900", "" + aDouble); + blackhole("-54-194313216", "" + aDouble); + blackhole("-5412", "" + aDouble); + blackhole("-54C(87)", "" + aDouble); + blackhole("-5491", "" + aDouble); + blackhole("-5421", "" + aDouble); + blackhole("-5418", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54\u045180", "" + aDouble); + blackhole("-54C", "" + aDouble); + blackhole("-5475", "" + aDouble); + blackhole("-54-43", "" + aDouble); + blackhole("-5480", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54-52.0", "" + aDouble); + blackhole("-5475000000", "" + aDouble); + blackhole("-5444", "" + aDouble); + blackhole("-54-1705032704", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-5483.0", "" + aDouble); + blackhole("-54I", "" + aDouble); + blackhole("-5494.0", "" + aDouble); + blackhole("-5412.0", "" + aDouble); + blackhole("-54-99.0", "" + aDouble); + blackhole("-5417.0", "" + aDouble); + blackhole("-54-84.0", "" + aDouble); + blackhole("-5458000000", "" + aDouble); + blackhole("-54-55000000", "" + aDouble); + blackhole("-541460392448", "" + aDouble); + blackhole("-54C(70)", "" + aDouble); + blackhole("-54\u04511", "" + aDouble); + blackhole("-548000", "" + aDouble); + blackhole("-5418", "" + aDouble); + blackhole("-54-1000000", "" + aDouble); + blackhole("-541000000", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54false", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-54-2000000", "" + aDouble); + blackhole("-54-820130816", "" + aDouble); + blackhole("-54null", "" + aDouble); + blackhole("-5425000000", "" + aDouble); + blackhole("-87.0-96.0", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0\u045176", "" + aDouble); + blackhole("-87.092", "" + aDouble); + blackhole("-87.051", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0-54", "" + aDouble); + blackhole("-87.0-87.0", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.019", "" + aDouble); + blackhole("-87.0-41", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0T", "" + aDouble); + blackhole("-87.0-42.0", "" + aDouble); + blackhole("-87.025", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0-1410065408", "" + aDouble); + blackhole("-87.08.0", "" + aDouble); + blackhole("-87.055.0", "" + aDouble); + blackhole("-87.097000000", "" + aDouble); + blackhole("-87.0-9900", "" + aDouble); + blackhole("-87.0935228928", "" + aDouble); + blackhole("-87.0-8400", "" + aDouble); + blackhole("-87.0C(82)", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0true", "" + aDouble); + blackhole("-87.03900", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.094000000", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0true", "" + aDouble); + blackhole("-87.05500", "" + aDouble); + blackhole("-87.0-2900", "" + aDouble); + blackhole("-87.0-194313216", "" + aDouble); + blackhole("-87.012", "" + aDouble); + blackhole("-87.0C(87)", "" + aDouble); + blackhole("-87.091", "" + aDouble); + blackhole("-87.021", "" + aDouble); + blackhole("-87.018", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0\u045180", "" + aDouble); + blackhole("-87.0C", "" + aDouble); + blackhole("-87.075", "" + aDouble); + blackhole("-87.0-43", "" + aDouble); + blackhole("-87.080", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0-52.0", "" + aDouble); + blackhole("-87.075000000", "" + aDouble); + blackhole("-87.044", "" + aDouble); + blackhole("-87.0-1705032704", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.083.0", "" + aDouble); + blackhole("-87.0I", "" + aDouble); + blackhole("-87.094.0", "" + aDouble); + blackhole("-87.012.0", "" + aDouble); + blackhole("-87.0-99.0", "" + aDouble); + blackhole("-87.017.0", "" + aDouble); + blackhole("-87.0-84.0", "" + aDouble); + blackhole("-87.058000000", "" + aDouble); + blackhole("-87.0-55000000", "" + aDouble); + blackhole("-87.01460392448", "" + aDouble); + blackhole("-87.0C(70)", "" + aDouble); + blackhole("-87.0\u04511", "" + aDouble); + blackhole("-87.08000", "" + aDouble); + blackhole("-87.018", "" + aDouble); + blackhole("-87.0-1000000", "" + aDouble); + blackhole("-87.01000000", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0false", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.0-2000000", "" + aDouble); + blackhole("-87.0-820130816", "" + aDouble); + blackhole("-87.0null", "" + aDouble); + blackhole("-87.025000000", "" + aDouble); + blackhole("null-96.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045176", "" + aDouble); + blackhole("null92", "" + aDouble); + blackhole("null51", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-54", "" + aDouble); + blackhole("null-87.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null19", "" + aDouble); + blackhole("null-41", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullT", "" + aDouble); + blackhole("null-42.0", "" + aDouble); + blackhole("null25", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-1410065408", "" + aDouble); + blackhole("null8.0", "" + aDouble); + blackhole("null55.0", "" + aDouble); + blackhole("null97000000", "" + aDouble); + blackhole("null-9900", "" + aDouble); + blackhole("null935228928", "" + aDouble); + blackhole("null-8400", "" + aDouble); + blackhole("nullC(82)", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null3900", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null94000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null5500", "" + aDouble); + blackhole("null-2900", "" + aDouble); + blackhole("null-194313216", "" + aDouble); + blackhole("null12", "" + aDouble); + blackhole("nullC(87)", "" + aDouble); + blackhole("null91", "" + aDouble); + blackhole("null21", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045180", "" + aDouble); + blackhole("nullC", "" + aDouble); + blackhole("null75", "" + aDouble); + blackhole("null-43", "" + aDouble); + blackhole("null80", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-52.0", "" + aDouble); + blackhole("null75000000", "" + aDouble); + blackhole("null44", "" + aDouble); + blackhole("null-1705032704", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null83.0", "" + aDouble); + blackhole("nullI", "" + aDouble); + blackhole("null94.0", "" + aDouble); + blackhole("null12.0", "" + aDouble); + blackhole("null-99.0", "" + aDouble); + blackhole("null17.0", "" + aDouble); + blackhole("null-84.0", "" + aDouble); + blackhole("null58000000", "" + aDouble); + blackhole("null-55000000", "" + aDouble); + blackhole("null1460392448", "" + aDouble); + blackhole("nullC(70)", "" + aDouble); + blackhole("null\u04511", "" + aDouble); + blackhole("null8000", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("null-1000000", "" + aDouble); + blackhole("null1000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullfalse", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-2000000", "" + aDouble); + blackhole("null-820130816", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null25000000", "" + aDouble); + blackhole("19-96.0", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19\u045176", "" + aDouble); + blackhole("1992", "" + aDouble); + blackhole("1951", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19-54", "" + aDouble); + blackhole("19-87.0", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("1919", "" + aDouble); + blackhole("19-41", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19T", "" + aDouble); + blackhole("19-42.0", "" + aDouble); + blackhole("1925", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19-1410065408", "" + aDouble); + blackhole("198.0", "" + aDouble); + blackhole("1955.0", "" + aDouble); + blackhole("1997000000", "" + aDouble); + blackhole("19-9900", "" + aDouble); + blackhole("19935228928", "" + aDouble); + blackhole("19-8400", "" + aDouble); + blackhole("19C(82)", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19true", "" + aDouble); + blackhole("193900", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("1994000000", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19true", "" + aDouble); + blackhole("195500", "" + aDouble); + blackhole("19-2900", "" + aDouble); + blackhole("19-194313216", "" + aDouble); + blackhole("1912", "" + aDouble); + blackhole("19C(87)", "" + aDouble); + blackhole("1991", "" + aDouble); + blackhole("1921", "" + aDouble); + blackhole("1918", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19\u045180", "" + aDouble); + blackhole("19C", "" + aDouble); + blackhole("1975", "" + aDouble); + blackhole("19-43", "" + aDouble); + blackhole("1980", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19-52.0", "" + aDouble); + blackhole("1975000000", "" + aDouble); + blackhole("1944", "" + aDouble); + blackhole("19-1705032704", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("1983.0", "" + aDouble); + blackhole("19I", "" + aDouble); + blackhole("1994.0", "" + aDouble); + blackhole("1912.0", "" + aDouble); + blackhole("19-99.0", "" + aDouble); + blackhole("1917.0", "" + aDouble); + blackhole("19-84.0", "" + aDouble); + blackhole("1958000000", "" + aDouble); + blackhole("19-55000000", "" + aDouble); + blackhole("191460392448", "" + aDouble); + blackhole("19C(70)", "" + aDouble); + blackhole("19\u04511", "" + aDouble); + blackhole("198000", "" + aDouble); + blackhole("1918", "" + aDouble); + blackhole("19-1000000", "" + aDouble); + blackhole("191000000", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19false", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("19-2000000", "" + aDouble); + blackhole("19-820130816", "" + aDouble); + blackhole("19null", "" + aDouble); + blackhole("1925000000", "" + aDouble); + blackhole("-41-96.0", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41\u045176", "" + aDouble); + blackhole("-4192", "" + aDouble); + blackhole("-4151", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41-54", "" + aDouble); + blackhole("-41-87.0", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-4119", "" + aDouble); + blackhole("-41-41", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41T", "" + aDouble); + blackhole("-41-42.0", "" + aDouble); + blackhole("-4125", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41-1410065408", "" + aDouble); + blackhole("-418.0", "" + aDouble); + blackhole("-4155.0", "" + aDouble); + blackhole("-4197000000", "" + aDouble); + blackhole("-41-9900", "" + aDouble); + blackhole("-41935228928", "" + aDouble); + blackhole("-41-8400", "" + aDouble); + blackhole("-41C(82)", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41true", "" + aDouble); + blackhole("-413900", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-4194000000", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41true", "" + aDouble); + blackhole("-415500", "" + aDouble); + blackhole("-41-2900", "" + aDouble); + blackhole("-41-194313216", "" + aDouble); + blackhole("-4112", "" + aDouble); + blackhole("-41C(87)", "" + aDouble); + blackhole("-4191", "" + aDouble); + blackhole("-4121", "" + aDouble); + blackhole("-4118", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41\u045180", "" + aDouble); + blackhole("-41C", "" + aDouble); + blackhole("-4175", "" + aDouble); + blackhole("-41-43", "" + aDouble); + blackhole("-4180", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41-52.0", "" + aDouble); + blackhole("-4175000000", "" + aDouble); + blackhole("-4144", "" + aDouble); + blackhole("-41-1705032704", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-4183.0", "" + aDouble); + blackhole("-41I", "" + aDouble); + blackhole("-4194.0", "" + aDouble); + blackhole("-4112.0", "" + aDouble); + blackhole("-41-99.0", "" + aDouble); + blackhole("-4117.0", "" + aDouble); + blackhole("-41-84.0", "" + aDouble); + blackhole("-4158000000", "" + aDouble); + blackhole("-41-55000000", "" + aDouble); + blackhole("-411460392448", "" + aDouble); + blackhole("-41C(70)", "" + aDouble); + blackhole("-41\u04511", "" + aDouble); + blackhole("-418000", "" + aDouble); + blackhole("-4118", "" + aDouble); + blackhole("-41-1000000", "" + aDouble); + blackhole("-411000000", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41false", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-41-2000000", "" + aDouble); + blackhole("-41-820130816", "" + aDouble); + blackhole("-41null", "" + aDouble); + blackhole("-4125000000", "" + aDouble); + blackhole("null-96.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045176", "" + aDouble); + blackhole("null92", "" + aDouble); + blackhole("null51", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-54", "" + aDouble); + blackhole("null-87.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null19", "" + aDouble); + blackhole("null-41", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullT", "" + aDouble); + blackhole("null-42.0", "" + aDouble); + blackhole("null25", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-1410065408", "" + aDouble); + blackhole("null8.0", "" + aDouble); + blackhole("null55.0", "" + aDouble); + blackhole("null97000000", "" + aDouble); + blackhole("null-9900", "" + aDouble); + blackhole("null935228928", "" + aDouble); + blackhole("null-8400", "" + aDouble); + blackhole("nullC(82)", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null3900", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null94000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null5500", "" + aDouble); + blackhole("null-2900", "" + aDouble); + blackhole("null-194313216", "" + aDouble); + blackhole("null12", "" + aDouble); + blackhole("nullC(87)", "" + aDouble); + blackhole("null91", "" + aDouble); + blackhole("null21", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045180", "" + aDouble); + blackhole("nullC", "" + aDouble); + blackhole("null75", "" + aDouble); + blackhole("null-43", "" + aDouble); + blackhole("null80", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-52.0", "" + aDouble); + blackhole("null75000000", "" + aDouble); + blackhole("null44", "" + aDouble); + blackhole("null-1705032704", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null83.0", "" + aDouble); + blackhole("nullI", "" + aDouble); + blackhole("null94.0", "" + aDouble); + blackhole("null12.0", "" + aDouble); + blackhole("null-99.0", "" + aDouble); + blackhole("null17.0", "" + aDouble); + blackhole("null-84.0", "" + aDouble); + blackhole("null58000000", "" + aDouble); + blackhole("null-55000000", "" + aDouble); + blackhole("null1460392448", "" + aDouble); + blackhole("nullC(70)", "" + aDouble); + blackhole("null\u04511", "" + aDouble); + blackhole("null8000", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("null-1000000", "" + aDouble); + blackhole("null1000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullfalse", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-2000000", "" + aDouble); + blackhole("null-820130816", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null25000000", "" + aDouble); + blackhole("T-96.0", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T\u045176", "" + aDouble); + blackhole("T92", "" + aDouble); + blackhole("T51", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T-54", "" + aDouble); + blackhole("T-87.0", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T19", "" + aDouble); + blackhole("T-41", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("TT", "" + aDouble); + blackhole("T-42.0", "" + aDouble); + blackhole("T25", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T-1410065408", "" + aDouble); + blackhole("T8.0", "" + aDouble); + blackhole("T55.0", "" + aDouble); + blackhole("T97000000", "" + aDouble); + blackhole("T-9900", "" + aDouble); + blackhole("T935228928", "" + aDouble); + blackhole("T-8400", "" + aDouble); + blackhole("TC(82)", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("Ttrue", "" + aDouble); + blackhole("T3900", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T94000000", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("Ttrue", "" + aDouble); + blackhole("T5500", "" + aDouble); + blackhole("T-2900", "" + aDouble); + blackhole("T-194313216", "" + aDouble); + blackhole("T12", "" + aDouble); + blackhole("TC(87)", "" + aDouble); + blackhole("T91", "" + aDouble); + blackhole("T21", "" + aDouble); + blackhole("T18", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T\u045180", "" + aDouble); + blackhole("TC", "" + aDouble); + blackhole("T75", "" + aDouble); + blackhole("T-43", "" + aDouble); + blackhole("T80", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T-52.0", "" + aDouble); + blackhole("T75000000", "" + aDouble); + blackhole("T44", "" + aDouble); + blackhole("T-1705032704", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T83.0", "" + aDouble); + blackhole("TI", "" + aDouble); + blackhole("T94.0", "" + aDouble); + blackhole("T12.0", "" + aDouble); + blackhole("T-99.0", "" + aDouble); + blackhole("T17.0", "" + aDouble); + blackhole("T-84.0", "" + aDouble); + blackhole("T58000000", "" + aDouble); + blackhole("T-55000000", "" + aDouble); + blackhole("T1460392448", "" + aDouble); + blackhole("TC(70)", "" + aDouble); + blackhole("T\u04511", "" + aDouble); + blackhole("T8000", "" + aDouble); + blackhole("T18", "" + aDouble); + blackhole("T-1000000", "" + aDouble); + blackhole("T1000000", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("Tfalse", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T-2000000", "" + aDouble); + blackhole("T-820130816", "" + aDouble); + blackhole("Tnull", "" + aDouble); + blackhole("T25000000", "" + aDouble); + blackhole("-42.0-96.0", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0\u045176", "" + aDouble); + blackhole("-42.092", "" + aDouble); + blackhole("-42.051", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0-54", "" + aDouble); + blackhole("-42.0-87.0", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.019", "" + aDouble); + blackhole("-42.0-41", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0T", "" + aDouble); + blackhole("-42.0-42.0", "" + aDouble); + blackhole("-42.025", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0-1410065408", "" + aDouble); + blackhole("-42.08.0", "" + aDouble); + blackhole("-42.055.0", "" + aDouble); + blackhole("-42.097000000", "" + aDouble); + blackhole("-42.0-9900", "" + aDouble); + blackhole("-42.0935228928", "" + aDouble); + blackhole("-42.0-8400", "" + aDouble); + blackhole("-42.0C(82)", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0true", "" + aDouble); + blackhole("-42.03900", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.094000000", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0true", "" + aDouble); + blackhole("-42.05500", "" + aDouble); + blackhole("-42.0-2900", "" + aDouble); + blackhole("-42.0-194313216", "" + aDouble); + blackhole("-42.012", "" + aDouble); + blackhole("-42.0C(87)", "" + aDouble); + blackhole("-42.091", "" + aDouble); + blackhole("-42.021", "" + aDouble); + blackhole("-42.018", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0\u045180", "" + aDouble); + blackhole("-42.0C", "" + aDouble); + blackhole("-42.075", "" + aDouble); + blackhole("-42.0-43", "" + aDouble); + blackhole("-42.080", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0-52.0", "" + aDouble); + blackhole("-42.075000000", "" + aDouble); + blackhole("-42.044", "" + aDouble); + blackhole("-42.0-1705032704", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.083.0", "" + aDouble); + blackhole("-42.0I", "" + aDouble); + blackhole("-42.094.0", "" + aDouble); + blackhole("-42.012.0", "" + aDouble); + blackhole("-42.0-99.0", "" + aDouble); + blackhole("-42.017.0", "" + aDouble); + blackhole("-42.0-84.0", "" + aDouble); + blackhole("-42.058000000", "" + aDouble); + blackhole("-42.0-55000000", "" + aDouble); + blackhole("-42.01460392448", "" + aDouble); + blackhole("-42.0C(70)", "" + aDouble); + blackhole("-42.0\u04511", "" + aDouble); + blackhole("-42.08000", "" + aDouble); + blackhole("-42.018", "" + aDouble); + blackhole("-42.0-1000000", "" + aDouble); + blackhole("-42.01000000", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0false", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.0-2000000", "" + aDouble); + blackhole("-42.0-820130816", "" + aDouble); + blackhole("-42.0null", "" + aDouble); + blackhole("-42.025000000", "" + aDouble); + blackhole("25-96.0", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25\u045176", "" + aDouble); + blackhole("2592", "" + aDouble); + blackhole("2551", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25-54", "" + aDouble); + blackhole("25-87.0", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("2519", "" + aDouble); + blackhole("25-41", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25T", "" + aDouble); + blackhole("25-42.0", "" + aDouble); + blackhole("2525", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25-1410065408", "" + aDouble); + blackhole("258.0", "" + aDouble); + blackhole("2555.0", "" + aDouble); + blackhole("2597000000", "" + aDouble); + blackhole("25-9900", "" + aDouble); + blackhole("25935228928", "" + aDouble); + blackhole("25-8400", "" + aDouble); + blackhole("25C(82)", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25true", "" + aDouble); + blackhole("253900", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("2594000000", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25true", "" + aDouble); + blackhole("255500", "" + aDouble); + blackhole("25-2900", "" + aDouble); + blackhole("25-194313216", "" + aDouble); + blackhole("2512", "" + aDouble); + blackhole("25C(87)", "" + aDouble); + blackhole("2591", "" + aDouble); + blackhole("2521", "" + aDouble); + blackhole("2518", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25\u045180", "" + aDouble); + blackhole("25C", "" + aDouble); + blackhole("2575", "" + aDouble); + blackhole("25-43", "" + aDouble); + blackhole("2580", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25-52.0", "" + aDouble); + blackhole("2575000000", "" + aDouble); + blackhole("2544", "" + aDouble); + blackhole("25-1705032704", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("2583.0", "" + aDouble); + blackhole("25I", "" + aDouble); + blackhole("2594.0", "" + aDouble); + blackhole("2512.0", "" + aDouble); + blackhole("25-99.0", "" + aDouble); + blackhole("2517.0", "" + aDouble); + blackhole("25-84.0", "" + aDouble); + blackhole("2558000000", "" + aDouble); + blackhole("25-55000000", "" + aDouble); + blackhole("251460392448", "" + aDouble); + blackhole("25C(70)", "" + aDouble); + blackhole("25\u04511", "" + aDouble); + blackhole("258000", "" + aDouble); + blackhole("2518", "" + aDouble); + blackhole("25-1000000", "" + aDouble); + blackhole("251000000", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25false", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("25-2000000", "" + aDouble); + blackhole("25-820130816", "" + aDouble); + blackhole("25null", "" + aDouble); + blackhole("2525000000", "" + aDouble); + blackhole("null-96.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045176", "" + aDouble); + blackhole("null92", "" + aDouble); + blackhole("null51", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-54", "" + aDouble); + blackhole("null-87.0", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null19", "" + aDouble); + blackhole("null-41", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullT", "" + aDouble); + blackhole("null-42.0", "" + aDouble); + blackhole("null25", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-1410065408", "" + aDouble); + blackhole("null8.0", "" + aDouble); + blackhole("null55.0", "" + aDouble); + blackhole("null97000000", "" + aDouble); + blackhole("null-9900", "" + aDouble); + blackhole("null935228928", "" + aDouble); + blackhole("null-8400", "" + aDouble); + blackhole("nullC(82)", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null3900", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null94000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nulltrue", "" + aDouble); + blackhole("null5500", "" + aDouble); + blackhole("null-2900", "" + aDouble); + blackhole("null-194313216", "" + aDouble); + blackhole("null12", "" + aDouble); + blackhole("nullC(87)", "" + aDouble); + blackhole("null91", "" + aDouble); + blackhole("null21", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null\u045180", "" + aDouble); + blackhole("nullC", "" + aDouble); + blackhole("null75", "" + aDouble); + blackhole("null-43", "" + aDouble); + blackhole("null80", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-52.0", "" + aDouble); + blackhole("null75000000", "" + aDouble); + blackhole("null44", "" + aDouble); + blackhole("null-1705032704", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null83.0", "" + aDouble); + blackhole("nullI", "" + aDouble); + blackhole("null94.0", "" + aDouble); + blackhole("null12.0", "" + aDouble); + blackhole("null-99.0", "" + aDouble); + blackhole("null17.0", "" + aDouble); + blackhole("null-84.0", "" + aDouble); + blackhole("null58000000", "" + aDouble); + blackhole("null-55000000", "" + aDouble); + blackhole("null1460392448", "" + aDouble); + blackhole("nullC(70)", "" + aDouble); + blackhole("null\u04511", "" + aDouble); + blackhole("null8000", "" + aDouble); + blackhole("null18", "" + aDouble); + blackhole("null-1000000", "" + aDouble); + blackhole("null1000000", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("nullfalse", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null-2000000", "" + aDouble); + blackhole("null-820130816", "" + aDouble); + blackhole("nullnull", "" + aDouble); + blackhole("null25000000", "" + aDouble); + blackhole("-1410065408-96.0", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408\u045176", "" + aDouble); + blackhole("-141006540892", "" + aDouble); + blackhole("-141006540851", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408-54", "" + aDouble); + blackhole("-1410065408-87.0", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-141006540819", "" + aDouble); + blackhole("-1410065408-41", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408T", "" + aDouble); + blackhole("-1410065408-42.0", "" + aDouble); + blackhole("-141006540825", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408-1410065408", "" + aDouble); + blackhole("-14100654088.0", "" + aDouble); + blackhole("-141006540855.0", "" + aDouble); + blackhole("-141006540897000000", "" + aDouble); + blackhole("-1410065408-9900", "" + aDouble); + blackhole("-1410065408935228928", "" + aDouble); + blackhole("-1410065408-8400", "" + aDouble); + blackhole("-1410065408C(82)", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408true", "" + aDouble); + blackhole("-14100654083900", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-141006540894000000", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408true", "" + aDouble); + blackhole("-14100654085500", "" + aDouble); + blackhole("-1410065408-2900", "" + aDouble); + blackhole("-1410065408-194313216", "" + aDouble); + blackhole("-141006540812", "" + aDouble); + blackhole("-1410065408C(87)", "" + aDouble); + blackhole("-141006540891", "" + aDouble); + blackhole("-141006540821", "" + aDouble); + blackhole("-141006540818", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408\u045180", "" + aDouble); + blackhole("-1410065408C", "" + aDouble); + blackhole("-141006540875", "" + aDouble); + blackhole("-1410065408-43", "" + aDouble); + blackhole("-141006540880", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408-52.0", "" + aDouble); + blackhole("-141006540875000000", "" + aDouble); + blackhole("-141006540844", "" + aDouble); + blackhole("-1410065408-1705032704", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-141006540883.0", "" + aDouble); + blackhole("-1410065408I", "" + aDouble); + blackhole("-141006540894.0", "" + aDouble); + blackhole("-141006540812.0", "" + aDouble); + blackhole("-1410065408-99.0", "" + aDouble); + blackhole("-141006540817.0", "" + aDouble); + blackhole("-1410065408-84.0", "" + aDouble); + blackhole("-141006540858000000", "" + aDouble); + blackhole("-1410065408-55000000", "" + aDouble); + blackhole("-14100654081460392448", "" + aDouble); + blackhole("-1410065408C(70)", "" + aDouble); + blackhole("-1410065408\u04511", "" + aDouble); + blackhole("-14100654088000", "" + aDouble); + blackhole("-141006540818", "" + aDouble); + blackhole("-1410065408-1000000", "" + aDouble); + blackhole("-14100654081000000", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408false", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-1410065408-2000000", "" + aDouble); + blackhole("-1410065408-820130816", "" + aDouble); + blackhole("-1410065408null", "" + aDouble); + blackhole("-141006540825000000", "" + aDouble); + blackhole("8.0-96.0", "" + aDouble); + blackhole("8.0null", "" + aDouble); + blackhole("8.0\u045176", "" + aDouble); + blackhole("8.092", "" + aDouble); + blackhole("8.051", "" + aDouble); + blackhole("8.0null", "" + aDouble); + blackhole("8.0-54", "" + aDouble); + blackhole("8.0-87.0", "" + aDouble); + blackhole("8.0null", "" + aDouble); + blackhole("8.019", "" + aDouble); + blackhole("8.0-41", "" + aDouble); + blackhole("8.0null", "" + aDouble); + blackhole("8.0T", "" + aDouble); + blackhole("8.0-42.0", "" + aDouble); + blackhole("8.025", "" + aDouble); + blackhole("C(87)-96.0", "" + aDouble); + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationPiTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationPiTest.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,66 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.core.test; + +import org.junit.Test; + +public class ConditionalEliminationPiTest extends ConditionalEliminationTestBase { + + static int SideEffect; + + static double oracleValue1 = -0.0; + static double oracleValue2; + + public static double testSnippet1(int a) { + double phi; + if (a > 0) { + double oracle = oracleValue1; + if (oracle == 0.0) { + SideEffect = 1; + } else { + return 123; + } + phi = oracle; + } else { + double oracle = oracleValue2; + if (oracle == 0.0) { + SideEffect = 1; + phi = oracle; + } else { + return 0; + } + } + if (Double.doubleToRawLongBits(phi) == Double.doubleToRawLongBits(-0.0)) { + return 12; + } + return 2; + } + + @Test + public void test1() { + test("testSnippet1", 1); + } +} + diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest16.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,84 @@ +/* + * 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. + */ + + +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Check that multiple bounds checks are correctly grouped together. + */ +public class ConditionalEliminationTest16 extends ConditionalEliminationTestBase { + + public static int testCastExactInstance(Object object) { + if (object.getClass() == Integer.class) { + return ((Integer) object).intValue(); + } + GraalDirectives.deoptimizeAndInvalidate(); + return -1; + } + + @Override + protected boolean checkHighTierGraph(StructuredGraph graph) { + for (ParameterNode param : graph.getNodes().filter(ParameterNode.class)) { + if (param.index() == 0) { + ParameterNode newParam = new ParameterNode(0, StampPair.createSingle(StampFactory.object(TypeReference.createExactTrusted(getMetaAccess().lookupJavaType(Integer.class))))); + graph.addWithoutUnique(newParam); + param.replaceAtUsages(newParam); + param.safeDelete(); + break; + } + } + new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); + return super.checkHighTierGraph(graph); + } + + @Override + protected boolean checkMidTierGraph(StructuredGraph graph) { + int count = 0; + for (PiNode node : graph.getNodes().filter(PiNode.class)) { + assertTrue(node.getGuard() != null, "must have guarding node"); + count++; + } + assertTrue(count > 0, "expected at least one Pi"); + return super.checkMidTierGraph(graph); + } + + @Test + public void test1() { + ResolvedJavaMethod method = getResolvedJavaMethod("testCastExactInstance"); + StructuredGraph graph = parseForCompile(method); + compile(method, graph); + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java Tue May 07 17:30:14 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 @@ -129,4 +129,9 @@ public Integer smallestCompareWidth() { return 8; } + + @Override + public boolean supportBulkZeroing() { + return true; + } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java Tue May 07 17:30:14 2019 -0400 @@ -398,6 +398,9 @@ if (isJDK13OrHigher()) { add(toBeInvestigated, + "java/lang/Math.abs(F)F", + "java/lang/Math.abs(I)I", + "java/lang/Math.abs(J)J", "java/lang/Math.max(DD)D", "java/lang/Math.max(FF)F", "java/lang/Math.min(DD)D", diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIVersionCheckTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIVersionCheckTest.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,83 @@ +/* + * 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. + */ + + +package org.graalvm.compiler.hotspot.test; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.hotspot.JVMCIVersionCheck; +import org.junit.Assert; +import org.junit.Test; + +public class JVMCIVersionCheckTest extends GraalCompilerTest { + + @Test + public void test01() { + Properties sprops = System.getProperties(); + Map<String, String> props = new HashMap<>(sprops.size()); + for (String name : sprops.stringPropertyNames()) { + props.put(name, sprops.getProperty(name)); + } + + for (int i = 0; i < 100; i++) { + int minMajor = i; + int minMinor = 100 - i; + for (int j = 0; j < 100; j++) { + int major = j; + int minor = 100 - j; + + boolean ok = (major > minMajor) || (major == minMajor && minor >= minMinor); + for (String sep : new String[]{".", "-b"}) { + String javaVmVersion = String.format("prefix-jvmci-%03d%s%03d-suffix", major, sep, minor); + if (ok) { + JVMCIVersionCheck.check(props, minMajor, minMinor, "1.8", javaVmVersion, false); + } else { + try { + JVMCIVersionCheck.check(props, minMajor, minMinor, "1.8", javaVmVersion, false); + Assert.fail("expected to fail checking " + javaVmVersion + " against " + minMajor + "." + minMinor); + } catch (InternalError e) { + // pass + } + } + } + } + } + + // Test handling of version components bigger than Integer.MAX_VALUE + for (String sep : new String[]{".", "-b"}) { + for (String version : new String[]{"0" + sep + Long.MAX_VALUE, Long.MAX_VALUE + sep + 0}) { + String javaVmVersion = String.format("prefix-jvmci-%s-suffix", version); + try { + JVMCIVersionCheck.check(props, 0, 59, "1.8", javaVmVersion, false); + Assert.fail("expected to fail checking " + javaVmVersion + " against 0.59"); + } catch (InternalError e) { + // pass + } + } + } + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java Tue May 07 17:30:14 2019 -0400 @@ -32,7 +32,6 @@ import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; import java.io.PrintStream; -import java.util.List; import jdk.internal.vm.compiler.collections.EconomicMap; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; @@ -44,7 +43,6 @@ import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionValues; @@ -52,7 +50,6 @@ import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; -import jdk.vm.ci.hotspot.EventProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -60,23 +57,9 @@ import jdk.vm.ci.hotspot.HotSpotNmethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCICompiler; -import jdk.vm.ci.services.JVMCIServiceLocator; public class CompilationTask { - private static final EventProvider eventProvider; - - static { - List<EventProvider> providers = JVMCIServiceLocator.getProviders(EventProvider.class); - if (providers.size() > 1) { - throw new GraalError("Multiple %s providers found: %s", EventProvider.class.getName(), providers); - } else if (providers.isEmpty()) { - eventProvider = EventProvider.createEmptyEventProvider(); - } else { - eventProvider = providers.get(0); - } - } - private final HotSpotJVMCIRuntime jvmciRuntime; private final HotSpotGraalCompiler compiler; @@ -94,12 +77,10 @@ private final boolean shouldRetainLocalVariables; final class HotSpotCompilationWrapper extends CompilationWrapper<HotSpotCompilationRequestResult> { - private final EventProvider.CompilationEvent compilationEvent; CompilationResult result; - HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) { + HotSpotCompilationWrapper() { super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction()); - this.compilationEvent = compilationEvent; } @Override @@ -125,13 +106,6 @@ */ return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !bailout.isPermanent()); } - // Log a failure event. - EventProvider.CompilerFailureEvent event = eventProvider.newCompilerFailureEvent(); - if (event.shouldWrite()) { - event.setCompileId(getId()); - event.setMessage(t.getMessage()); - event.commit(); - } /* * Treat random exceptions from the compiler as indicating a problem compiling this @@ -181,14 +155,9 @@ final CompilationPrinter printer = CompilationPrinter.begin(debug.getOptions(), compilationId, method, entryBCI); try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { - // Begin the compilation event. - compilationEvent.begin(); result = compiler.compile(method, entryBCI, useProfilingInfo, shouldRetainLocalVariables, compilationId, debug); } catch (Throwable e) { throw debug.handle(e); - } finally { - // End the compilation event. - compilationEvent.end(); } if (result != null) { @@ -322,9 +291,6 @@ boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotResolvedJavaMethod method = getMethod(); - // Log a compilation event. - EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); - if (installAsDefault || isOSR) { // If there is already compiled code for this method on our level we simply return. // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we @@ -337,7 +303,7 @@ } } - HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper(compilationEvent); + HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper(); try (DebugCloseable a = CompilationTime.start(debug)) { return compilation.run(debug); } finally { @@ -354,18 +320,6 @@ InstalledCodeSize.add(debug, codeSize); } } - - // Log a compilation event. - if (compilationEvent.shouldWrite()) { - compilationEvent.setMethod(method.format("%H.%n(%p)")); - compilationEvent.setCompileId(getId()); - compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); - compilationEvent.setSucceeded(compilation.result != null && installedCode != null); - compilationEvent.setIsOsr(isOSR); - compilationEvent.setCodeSize(codeSize); - compilationEvent.setInlinedBytes(compiledBytecodes); - compilationEvent.commit(); - } } catch (Throwable t) { return compilation.handleException(t); } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Tue May 07 17:30:14 2019 -0400 @@ -460,6 +460,7 @@ public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t", -1); public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*", -1); public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*", -1); + public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, "Thread*", -1); public final int markWordNoHashInPlace = getConstant("markOopDesc::no_hash_in_place", Integer.class); public final int markWordNoLockInPlace = getConstant("markOopDesc::no_lock_in_place", Integer.class); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java Tue May 07 17:30:14 2019 -0400 @@ -39,7 +39,7 @@ * * This class only depends on the JDK so that it can be used without building Graal. */ -class JVMCIVersionCheck { +public final class JVMCIVersionCheck { // 0.57 introduces HotSpotJVMCIRuntime.excludeFromJVMCICompilation private static final int JVMCI8_MIN_MAJOR_VERSION = 0; @@ -73,42 +73,115 @@ } } + private final String javaSpecVersion; + private final String vmVersion; + private int cursor; + private final Map<String, String> props; + + private JVMCIVersionCheck(Map<String, String> props, String javaSpecVersion, String vmVersion) { + this.props = props; + this.javaSpecVersion = javaSpecVersion; + this.vmVersion = vmVersion; + } + static void check(Map<String, String> props, boolean exitOnFailure) { + JVMCIVersionCheck checker = new JVMCIVersionCheck(props, props.get("java.specification.version"), props.get("java.vm.version")); + checker.run(exitOnFailure, JVMCI8_MIN_MAJOR_VERSION, JVMCI8_MIN_MINOR_VERSION); + } + + /** + * Entry point for testing. + */ + public static void check(Map<String, String> props, + int jvmci8MinMajorVersion, + int jvmci8MinMinorVersion, + String javaSpecVersion, + String javaVmVersion, + boolean exitOnFailure) { + JVMCIVersionCheck checker = new JVMCIVersionCheck(props, javaSpecVersion, javaVmVersion); + checker.run(exitOnFailure, jvmci8MinMajorVersion, jvmci8MinMinorVersion); + } + + /** + * Parses a positive decimal number at {@link #cursor}. + * + * @return -1 if there is no positive decimal number at {@link #cursor} + */ + private int parseNumber() { + int result = -1; + while (cursor < vmVersion.length()) { + int digit = vmVersion.charAt(cursor) - '0'; + if (digit >= 0 && digit <= 9) { + if (result == -1) { + result = digit; + } else { + long r = (long) result * (long) 10; + if ((int) r != r) { + // Overflow + return -1; + } + result = (int) r + digit; + } + cursor++; + } else { + break; + } + } + return result; + } + + /** + * Parse {@code "."} or {@code "-b"} at {@link #cursor}. + * + * @return {@code true} iff there was an expected separator at {@link #cursor} + */ + private boolean parseSeparator() { + if (cursor < vmVersion.length()) { + char ch = vmVersion.charAt(cursor); + if (ch == '.') { + cursor++; + return true; + } + if (ch == '-') { + cursor++; + if (cursor < vmVersion.length()) { + if (vmVersion.charAt(cursor) == 'b') { + cursor++; + return true; + } + } + return false; + } + } + return false; + } + + private void run(boolean exitOnFailure, int jvmci8MinMajorVersion, int jvmci8MinMinorVersion) { // Don't use regular expressions to minimize Graal startup time - String javaSpecVersion = props.get("java.specification.version"); - String vmVersion = props.get("java.vm.version"); if (javaSpecVersion.compareTo("1.9") < 0) { - int start = vmVersion.indexOf("-jvmci-"); - if (start >= 0) { - start += "-jvmci-".length(); - int end = vmVersion.indexOf('.', start); - if (end > 0) { - int major; - try { - major = Integer.parseInt(vmVersion.substring(start, end)); - } catch (NumberFormatException e) { - failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + - "Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion); - return; - } - start = end + 1; - end = start; - while (end < vmVersion.length() && Character.isDigit(vmVersion.charAt(end))) { - end++; - } - int minor; - try { - minor = Integer.parseInt(vmVersion.substring(start, end)); - } catch (NumberFormatException e) { + cursor = vmVersion.indexOf("-jvmci-"); + if (cursor >= 0) { + cursor += "-jvmci-".length(); + int major = parseNumber(); + if (major == -1) { + failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + + "Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion); + return; + } + + if (parseSeparator()) { + int minor = parseNumber(); + if (minor == -1) { failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" + "Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion); return; } - if (major >= JVMCI8_MIN_MAJOR_VERSION && minor >= JVMCI8_MIN_MINOR_VERSION) { + + if (major > jvmci8MinMajorVersion || (major >= jvmci8MinMajorVersion && minor >= jvmci8MinMinorVersion)) { return; } failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %d.%d < %d.%d.%n", - major, minor, JVMCI8_MIN_MAJOR_VERSION, JVMCI8_MIN_MINOR_VERSION); + major, minor, jvmci8MinMajorVersion, jvmci8MinMinorVersion); return; } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java Tue May 07 17:30:14 2019 -0400 @@ -571,7 +571,7 @@ try { replacement = ((SymbolicJVMCIReference<?>) o).resolve(type); break; - } catch (NoClassDefFoundError | AssertionError e) { + } catch (NoClassDefFoundError e) { } } } else if (o instanceof UnresolvedJavaType) { @@ -579,7 +579,7 @@ try { replacement = ((UnresolvedJavaType) o).resolve(type); break; - } catch (NoClassDefFoundError | AssertionError e) { + } catch (NoClassDefFoundError e) { } } } else if (o instanceof UnresolvedJavaMethod) { @@ -589,7 +589,7 @@ try { replacement = ((UnresolvedJavaField) o).resolve(type); break; - } catch (NoClassDefFoundError | AssertionError e) { + } catch (NoClassDefFoundError e) { } } } else if (o instanceof GraalCapability) { diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java Tue May 07 17:30:14 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 diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java Tue May 07 17:30:14 2019 -0400 @@ -43,6 +43,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import jdk.vm.ci.hotspot.HotSpotConstantPoolObject; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Constant; @@ -83,7 +84,7 @@ public void generate(NodeLIRBuilderTool gen) { assert constant != null : "Expected the value to fold: " + value; Value result; - if (constant instanceof HotSpotObjectConstant) { + if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) { result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadObjectAddress(constant); } else if (constant instanceof HotSpotMetaspaceConstant) { result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLoadMetaspaceAddress(constant, action); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java Tue May 07 17:30:14 2019 -0400 @@ -45,6 +45,7 @@ import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.word.Word; +import jdk.vm.ci.hotspot.HotSpotConstantPoolObject; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Constant; @@ -100,7 +101,7 @@ Value result; LIRFrameState fs = gen.state(this); assert fs != null : "The stateAfter is null"; - if (constant instanceof HotSpotObjectConstant) { + if (constant instanceof HotSpotObjectConstant || constant instanceof HotSpotConstantPoolObject) { result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitObjectConstantRetrieval(constant, stringValue, fs); } else if (constant instanceof HotSpotMetaspaceConstant) { if (action == HotSpotConstantLoadAction.RESOLVE) { diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java Tue May 07 17:30:14 2019 -0400 @@ -516,6 +516,11 @@ return config.objectMonitorEntryList; } + @Fold + public static int objectMonitorSuccOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorSucc; + } + /** * Mask for a biasable, locked or unlocked mark word. * @@ -685,6 +690,8 @@ public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList"); + public static final LocationIdentity OBJECT_MONITOR_SUCC_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_succ"); + @Fold public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.basicLockDisplacedHeaderOffset; diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java Tue May 07 17:30:14 2019 -0400 @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.replacements; import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; @@ -38,6 +39,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_SUCC_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace; @@ -51,6 +53,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorOwnerOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorRecursionsOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorSuccOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; @@ -574,6 +577,32 @@ traceObject(trace, "-lock{inflated:simple}", object, false); counters.unlockInflatedSimple.inc(); return true; + } else { + int succOffset = objectMonitorSuccOffset(INJECTED_VMCONFIG); + Word succ = monitor.readWord(succOffset, OBJECT_MONITOR_SUCC_LOCATION); + if (probability(FREQUENT_PROBABILITY, succ.isNonNull())) { + // There may be a thread spinning on this monitor. Temporarily setting + // the monitor owner to null, and hope that the other thread will grab it. + monitor.writeWord(ownerOffset, zero()); + memoryBarrier(STORE_STORE | STORE_LOAD); + succ = monitor.readWord(succOffset, OBJECT_MONITOR_SUCC_LOCATION); + if (probability(NOT_FREQUENT_PROBABILITY, succ.isNonNull())) { + // We manage to release the monitor before the other running thread even + // notices. + traceObject(trace, "-lock{inflated:transfer}", object, false); + counters.unlockInflatedTransfer.inc(); + return true; + } else { + // Either the monitor is grabbed by a spinning thread, or the spinning + // thread parks. Now we attempt to reset the owner of the monitor. + if (probability(FREQUENT_PROBABILITY, !monitor.logicCompareAndSwapWord(ownerOffset, zero(), thread, OBJECT_MONITOR_OWNER_LOCATION))) { + // The monitor is stolen. + traceObject(trace, "-lock{inflated:transfer}", object, false); + counters.unlockInflatedTransfer.inc(); + return true; + } + } + } } } counters.unlockStubInflated.inc(); @@ -692,6 +721,7 @@ public final SnippetCounter unlockStub; public final SnippetCounter unlockStubInflated; public final SnippetCounter unlockInflatedSimple; + public final SnippetCounter unlockInflatedTransfer; public Counters(SnippetCounter.Group.Factory factory) { SnippetCounter.Group enter = factory.createSnippetCounterGroup("MonitorEnters"); @@ -716,6 +746,7 @@ unlockStub = new SnippetCounter(exit, "unlock{stub}", "stub-unlocked an object"); unlockStubInflated = new SnippetCounter(exit, "unlock{stub:inflated}", "stub-unlocked an object with inflated monitor"); unlockInflatedSimple = new SnippetCounter(exit, "unlock{inflated}", "unlocked an object monitor"); + unlockInflatedTransfer = new SnippetCounter(exit, "unlock{inflated:transfer}", "unlocked an object monitor in the presence of ObjectMonitor::_succ"); } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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,7 @@ import static jdk.vm.ci.meta.DeoptimizationAction.None; import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.MinimalBulkZeroingSize; import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_OPTIONVALUES; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG; @@ -130,6 +131,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; +import org.graalvm.compiler.replacements.nodes.ZeroMemoryNode; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.WordFactory; @@ -311,21 +313,39 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + public static Object allocatePrimitiveArrayPIC(KlassPointer hub, + int length, + Word prototypeMarkWord, + @ConstantParameter int headerSize, + @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, + @ConstantParameter boolean maybeUnroll, + @ConstantParameter String typeContext, + @ConstantParameter boolean useBulkZeroing, @ConstantParameter Counters counters) { // Primitive array types are eagerly pre-resolved. We can use a floating load. KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, counters); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, + threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters); } @Snippet - public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + public static Object allocateArrayPIC(KlassPointer hub, + int length, + Word prototypeMarkWord, + @ConstantParameter int headerSize, + @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, + @ConstantParameter boolean maybeUnroll, + @ConstantParameter String typeContext, + @ConstantParameter boolean useBulkZeroing, @ConstantParameter Counters counters) { // Array type would be resolved by dominating resolution. KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, counters); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, + threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters); } @Snippet @@ -338,6 +358,7 @@ @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter boolean useBulkZeroing, @ConstantParameter Counters counters) { Object result = allocateArrayImpl(hub, length, @@ -348,7 +369,7 @@ threadRegister, maybeUnroll, typeContext, - + useBulkZeroing, counters); return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } @@ -363,7 +384,7 @@ } private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister, - boolean maybeUnroll, String typeContext, Counters counters) { + boolean maybeUnroll, String typeContext, boolean useBulkZeroing, Counters counters) { Object result; long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize); Word thread = registerAsWord(threadRegister); @@ -378,7 +399,7 @@ if (theCounters != null && theCounters.arrayLoopInit != null) { theCounters.arrayLoopInit.inc(); } - result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters); + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, useBulkZeroing, counters); } else { result = newArrayStub(hub, length); } @@ -435,15 +456,23 @@ public static native Object dynamicNewInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class<?> elementType); @Snippet - public static Object allocateArrayDynamic(Class<?> elementType, Class<?> voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, + public static Object allocateArrayDynamic(Class<?> elementType, + Class<?> voidClass, + int length, + @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, + @ConstantParameter JavaKind knownElementKind, + @ConstantParameter int knownLayoutHelper, + @ConstantParameter boolean useBulkZeroing, + Word prototypeMarkWord, @ConstantParameter Counters counters) { - Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, counters); + Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, + knownLayoutHelper, useBulkZeroing, prototypeMarkWord, counters); return result; } private static Object allocateArrayDynamicImpl(Class<?> elementType, Class<?> voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind, - int knownLayoutHelper, Word prototypeMarkWord, Counters counters) { + int knownLayoutHelper, boolean useBulkZeroing, Word prototypeMarkWord, Counters counters) { /* * We only need the dynamic check for void when we have no static information from * knownElementKind. @@ -485,7 +514,8 @@ int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); - Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", counters); + Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, + threadRegister, false, "dynamic type", useBulkZeroing, counters); return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } @@ -538,12 +568,15 @@ * @param constantSize is {@code size} known to be constant in the snippet * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing + * @param useBulkZeroing apply bulk zeroing */ - private static void zeroMemory(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { - fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, counters); + private static void zeroMemory(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, + boolean useBulkZeroing, Counters counters) { + fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, useBulkZeroing, counters); } - private static void fillMemory(long value, long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + private static void fillMemory(long value, long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, + boolean useBulkZeroing, Counters counters) { ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size"); int offset = startOffset; if ((offset & 0x7) != 0) { @@ -571,22 +604,35 @@ } else { // Use Word instead of int to avoid extension to long in generated code Word off = WordFactory.signed(offset); - if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { - if (theCounters != null && theCounters.instanceSeqInit != null) { - theCounters.instanceSeqInit.inc(); + if (useBulkZeroing && probability(SLOW_PATH_PROBABILITY, size >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) { + if (theCounters != null && theCounters.instanceBulkInit != null) { + theCounters.instanceBulkInit.inc(); } - explodeLoop(); + ZeroMemoryNode.zero(memory.add(off), size - offset, LocationIdentity.init()); } else { - if (theCounters != null && theCounters.instanceLoopInit != null) { - theCounters.instanceLoopInit.inc(); + if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { + if (theCounters != null && theCounters.instanceSeqInit != null) { + theCounters.instanceSeqInit.inc(); + } + explodeLoop(); + } else { + if (theCounters != null && theCounters.instanceLoopInit != null) { + theCounters.instanceLoopInit.inc(); + } } - } - for (; off.rawValue() < size; off = off.add(8)) { - memory.initializeLong(off, value, LocationIdentity.init()); + for (; off.rawValue() < size; off = off.add(8)) { + memory.initializeLong(off, value, LocationIdentity.init()); + } + } } } + @Fold + static int getMinimalBulkZeroingSize(@InjectedParameter OptionValues optionValues) { + return MinimalBulkZeroingSize.getValue(optionValues); + } + /** * Fill uninitialized memory with garbage value in a newly allocated object, unrolling as * necessary and ensuring that stores are aligned. @@ -598,7 +644,7 @@ * @param manualUnroll maximally unroll zeroing */ private static void fillWithGarbage(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { - fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters); + fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, false, counters); } /** @@ -608,7 +654,7 @@ Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); + zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, false, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } @@ -632,7 +678,7 @@ * Formats some allocated memory with an object header and zeroes out the rest. */ private static Object formatArray(KlassPointer hub, long allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll, - Counters counters) { + boolean useBulkZeroing, Counters counters) { memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init()); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field @@ -640,7 +686,7 @@ */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, counters); + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useBulkZeroing, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters); } @@ -654,12 +700,14 @@ Group newArray = factory.createSnippetCounterGroup("NewArray"); instanceSeqInit = new SnippetCounter(newInstance, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); instanceLoopInit = new SnippetCounter(newInstance, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + instanceBulkInit = new SnippetCounter(newArray, "tlabBulkInit", "TLAB alloc with bulk zeroing"); arrayLoopInit = new SnippetCounter(newArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); stub = new SnippetCounter(newInstance, "stub", "alloc and zeroing via stub"); } final SnippetCounter instanceSeqInit; final SnippetCounter instanceLoopInit; + final SnippetCounter instanceBulkInit; final SnippetCounter arrayLoopInit; final SnippetCounter stub; } @@ -753,6 +801,7 @@ args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("maybeUnroll", length.isConstant()); args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : ""); + args.addConst("useBulkZeroing", tool.getLowerer().supportBulkZeroing()); args.addConst("counters", counters); SnippetTemplate template = template(newArrayNode, args); graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); @@ -775,7 +824,7 @@ public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newArrayNode.graph(); - Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(allocateArrayDynamic, graph.getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); ValueNode voidClass = newArrayNode.getVoidClass(); assert voidClass != null; @@ -794,6 +843,7 @@ } else { args.addConst("knownLayoutHelper", 0); } + args.addConst("useBulkZeroing", tool.getLowerer().supportBulkZeroing()); args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); args.addConst("counters", counters); SnippetTemplate template = template(newArrayNode, args); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java Tue May 07 17:30:14 2019 -0400 @@ -93,6 +93,7 @@ import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH; import static org.graalvm.compiler.core.common.GraalOptions.SupportJsrBytecodes; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -117,7 +118,7 @@ /** * Builds a mapping between bytecodes and basic blocks and builds a conservative control flow graph - * (CFG). It makes one linear passes over the bytecodes to build the CFG where it detects block + * (CFG). It makes one linear pass over the bytecodes to build the CFG where it detects block * headers and connects them. * <p> * It also creates exception dispatch blocks for exception handling. These blocks are between a @@ -477,6 +478,18 @@ } } + private static final class TraversalStep { + private BciBlock block; + private int currentSuccessorIndex; + private long loops; + + private TraversalStep(BciBlock block) { + this.block = block; + this.currentSuccessorIndex = 0; + this.loops = 0; + } + } + /** * The blocks found in this method, in reverse postorder. */ @@ -857,7 +870,7 @@ b.visited = false; } - long loop = fixLoopBits(blockMap, blockMap[0]); + long loop = fixLoopBits(blockMap[0]); if (loop != 0) { // There is a path from a loop end to the method entry that does not pass the loop @@ -1029,78 +1042,107 @@ } /** - * Depth-first traversal of the control flow graph. The flag {@linkplain BciBlock#visited} is - * used to visit every block only once. The flag {@linkplain BciBlock#active} is used to detect - * cycles (backward edges). + * Non-recursive depth-first traversal of the control flow graph. The flag + * {@linkplain BciBlock#visited} is used to visit every block only once. The flag + * {@linkplain BciBlock#active} is used to detect cycles (backward edges) */ - private long computeBlockOrder(BciBlock block) { - if (block.visited) { - if (block.active) { - // Reached block via backward branch. - makeLoopHeader(block); - // Return cached loop information for this block. - return block.loops; - } else if (block.isLoopHeader) { - return block.loops & ~(1L << block.loopId); + private long computeBlockOrder(BciBlock initialBlock) { + ArrayDeque<TraversalStep> workStack = new ArrayDeque<>(); + workStack.push(new TraversalStep(initialBlock)); + while (true) { + TraversalStep step = workStack.peek(); + BciBlock block = step.block; + if (step.currentSuccessorIndex == 0) { + block.visited = true; + block.active = true; } else { - return block.loops; + BciBlock successor = block.getSuccessor(step.currentSuccessorIndex - 1); + if (successor.active) { + // Reached block via backward branch. + step.loops |= (1L << successor.loopId); + } } - } - - block.visited = true; - block.active = true; + if (step.currentSuccessorIndex < block.successors.size()) { + BciBlock successor = block.getSuccessors().get(step.currentSuccessorIndex); + if (successor.visited) { + if (successor.active) { + // Reached block via backward branch. + makeLoopHeader(successor); + step.loops |= successor.loops; + } else if (successor.isLoopHeader) { + step.loops |= successor.loops & ~(1L << successor.loopId); + } else { + step.loops |= successor.loops; + } + } else { + workStack.push(new TraversalStep(successor)); + } + step.currentSuccessorIndex++; + } else { + // We processed all the successors of this block. + block.loops = step.loops; + debug.log("computeBlockOrder(%s) -> %x", block, block.loops); - long loops = 0; - for (BciBlock successor : block.getSuccessors()) { - // Recursively process successors. - loops |= computeBlockOrder(successor); - if (successor.active) { - // Reached block via backward branch. - loops |= (1L << successor.loopId); + if (block.isLoopHeader) { + step.loops &= ~(1L << block.loopId); + } + + block.active = false; + blocksNotYetAssignedId--; + blocks[blocksNotYetAssignedId] = block; + + workStack.pop(); + if (!workStack.isEmpty()) { + workStack.peek().loops |= step.loops; + } else { + return step.loops; + } } } - - block.loops = loops; - debug.log("computeBlockOrder(%s) -> %x", block, block.loops); - - if (block.isLoopHeader) { - loops &= ~(1L << block.loopId); - } - - block.active = false; - blocksNotYetAssignedId--; - blocks[blocksNotYetAssignedId] = block; - - return loops; } - private long fixLoopBits(BciBlock[] blockMap, BciBlock block) { - if (block.visited) { - // Return cached loop information for this block. - if (block.isLoopHeader) { - return block.loops & ~(1L << block.loopId); + private long fixLoopBits(BciBlock initialBlock) { + ArrayDeque<TraversalStep> workStack = new ArrayDeque<>(); + workStack.push(new TraversalStep(initialBlock)); + while (true) { + TraversalStep step = workStack.peek(); + BciBlock block = step.block; + if (step.currentSuccessorIndex == 0) { + block.visited = true; + step.loops = block.loops; + } + if (step.currentSuccessorIndex < block.getSuccessors().size()) { + BciBlock successor = block.getSuccessors().get(step.currentSuccessorIndex); + if (successor.visited) { + // Return cached loop information for this block. + if (successor.isLoopHeader) { + step.loops |= successor.loops & ~(1L << successor.loopId); + } else { + step.loops |= successor.loops; + } + } else { + workStack.push(new TraversalStep(successor)); + } + step.currentSuccessorIndex++; } else { - return block.loops; + if (block.loops != step.loops) { + loopChanges = true; + block.loops = step.loops; + debug.log("fixLoopBits0(%s) -> %x", block, block.loops); + } + + if (block.isLoopHeader) { + step.loops &= ~(1L << block.loopId); + } + + workStack.pop(); + if (!workStack.isEmpty()) { + workStack.peek().loops |= step.loops; + } else { + return step.loops; + } } } - - block.visited = true; - long loops = block.loops; - for (BciBlock successor : block.getSuccessors()) { - // Recursively process successors. - loops |= fixLoopBits(blockMap, successor); - } - if (block.loops != loops) { - loopChanges = true; - block.loops = loops; - debug.log("fixLoopBits0(%s) -> %x", block, block.loops); - } - - if (block.isLoopHeader) { - loops &= ~(1L << block.loopId); - } - - return loops; } public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options, DebugContext debug) { diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java Tue May 07 17:30:14 2019 -0400 @@ -710,4 +710,71 @@ } } + private abstract static class ZeroNullConversionOp extends AArch64LIRInstruction { + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue input; + + protected ZeroNullConversionOp(LIRInstructionClass<? extends ZeroNullConversionOp> type, AllocatableValue result, AllocatableValue input) { + super(type); + this.result = result; + this.input = input; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register nullRegister = crb.nullRegister; + if (!nullRegister.equals(Register.None)) { + emitConversion(asRegister(result), asRegister(input), nullRegister, masm); + } + } + + protected abstract void emitConversion(Register resultRegister, Register inputRegister, Register nullRegister, AArch64MacroAssembler masm); + } + + public static class ConvertNullToZeroOp extends ZeroNullConversionOp { + public static final LIRInstructionClass<ConvertNullToZeroOp> TYPE = LIRInstructionClass.create(ConvertNullToZeroOp.class); + + public ConvertNullToZeroOp(AllocatableValue result, AllocatableValue input) { + super(TYPE, result, input); + } + + @Override + protected final void emitConversion(Register resultRegister, Register inputRegister, Register nullRegister, AArch64MacroAssembler masm) { + if (inputRegister.equals(resultRegister)) { + masm.subs(64, inputRegister, inputRegister, nullRegister); + Label done = new Label(); + masm.branchConditionally(AArch64Assembler.ConditionFlag.EQ, done); + masm.add(64, inputRegister, inputRegister, nullRegister); + masm.bind(done); + } else { + masm.subs(64, resultRegister, resultRegister, resultRegister); + masm.cmp(64, inputRegister, nullRegister); + Label done = new Label(); + masm.branchConditionally(AArch64Assembler.ConditionFlag.EQ, done); + masm.movx(resultRegister, inputRegister); + masm.bind(done); + } + } + } + + public static class ConvertZeroToNullOp extends ZeroNullConversionOp { + public static final LIRInstructionClass<ConvertZeroToNullOp> TYPE = LIRInstructionClass.create(ConvertZeroToNullOp.class); + + public ConvertZeroToNullOp(AllocatableValue result, AllocatableValue input) { + super(TYPE, result, input); + } + + @Override + protected final void emitConversion(Register resultRegister, Register inputRegister, Register nullRegister, AArch64MacroAssembler masm) { + if (!inputRegister.equals(resultRegister)) { + masm.movx(resultRegister, inputRegister); + } + Label done = new Label(); + masm.ands(64, zr, inputRegister, inputRegister); + masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, done); + masm.movx(resultRegister, nullRegister); + masm.bind(done); + } + } + } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZeroMemoryOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZeroMemoryOp.java Tue May 07 17:30:14 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. + */ + + +package org.graalvm.compiler.lir.amd64; + +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64Kind; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.Value; + +/** + * Zeros a chunk of memory using rep stosb. + */ +@Opcode("ZERO_MEMORY") +public final class AMD64ZeroMemoryOp extends AMD64LIRInstruction { + + public static final LIRInstructionClass<AMD64ZeroMemoryOp> TYPE = LIRInstructionClass.create(AMD64ZeroMemoryOp.class); + + @Use({COMPOSITE}) protected AMD64AddressValue pointer; + @Use({REG}) protected RegisterValue length; + + @Temp protected Value pointerTemp; + @Temp protected Value valueTemp; + @Temp protected Value lengthTemp; + + public AMD64ZeroMemoryOp(AMD64AddressValue pointer, RegisterValue length) { + super(TYPE); + this.pointer = pointer; + this.length = length; + + this.pointerTemp = AMD64.rdi.asValue(LIRKind.value(AMD64Kind.QWORD)); + this.valueTemp = AMD64.rax.asValue(LIRKind.value(AMD64Kind.QWORD)); + this.lengthTemp = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.QWORD)); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + assert AMD64.rcx.equals(length.getRegister()); + masm.leaq(AMD64.rdi, pointer.toAddress()); + masm.xorq(AMD64.rax, AMD64.rax); + masm.repStosb(); + } +} diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGeneratorTool.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGeneratorTool.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGeneratorTool.java Tue May 07 17:30:14 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 @@ -132,4 +132,8 @@ throw GraalError.unimplemented("No specialized implementation available"); } + @SuppressWarnings("unused") + default void emitZeroMemory(Value address, Value length) { + throw GraalError.unimplemented("Bulk zeroing is not supported on this platform"); + } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes.test/src/org/graalvm/compiler/nodes/test/PrimitiveStampBoundaryTest.java Tue May 07 17:30:14 2019 -0400 @@ -83,7 +83,7 @@ } static double[] doubleBoundaryValues = {Double.NEGATIVE_INFINITY, Double.MIN_VALUE, Float.NEGATIVE_INFINITY, Float.MIN_VALUE, - Long.MIN_VALUE, Long.MIN_VALUE + 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1, 0, 1, + Long.MIN_VALUE, Long.MIN_VALUE + 1, Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1, -0.0, +0.0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, Long.MAX_VALUE - 1, Long.MAX_VALUE, Float.MAX_VALUE, Float.POSITIVE_INFINITY, Double.MAX_VALUE, Double.POSITIVE_INFINITY}; @@ -171,11 +171,24 @@ checkConvertOperation(op, op.foldStamp(stamp), upper); } } + + } + + static void shouldConstantFold(boolean b, Stamp folded, Object o, Stamp s1) { + assertTrue(b || (folded instanceof FloatStamp && ((FloatStamp) folded).contains(0.0)), "should constant fold %s %s %s", o, s1, folded); + } + + private static boolean constantFloatStampMayIncludeNegativeZero(Stamp s) { + if (s instanceof FloatStamp) { + FloatStamp f = (FloatStamp) s; + return Double.compare(f.lowerBound(), f.upperBound()) == 0 && f.isNonNaN(); + } + return false; } private static void checkConvertOperation(ArithmeticOpTable.FloatConvertOp op, Stamp result, Stamp v1stamp) { Stamp folded = op.foldStamp(v1stamp); - assertTrue(folded.isEmpty() || folded.asConstant() != null, "should constant fold %s %s %s", op, v1stamp, folded); + shouldConstantFold(folded.isEmpty() || folded.asConstant() != null, folded, op, v1stamp); assertTrue(result.meet(folded).equals(result), "result out of range %s %s %s %s %s", op, v1stamp, folded, result, result.meet(folded)); } @@ -216,6 +229,9 @@ } private static void checkBinaryOperation(ArithmeticOpTable.BinaryOp<?> op, Stamp result, Stamp v1stamp, Stamp v2stamp) { + if (constantFloatStampMayIncludeNegativeZero(v1stamp) || constantFloatStampMayIncludeNegativeZero(v2stamp)) { + return; + } Stamp folded = op.foldStamp(v1stamp, v2stamp); if (v1stamp.isEmpty() || v2stamp.isEmpty()) { assertTrue(folded.isEmpty()); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java Tue May 07 17:30:14 2019 -0400 @@ -84,7 +84,7 @@ IntegerStamp yStamp = (IntegerStamp) forY.stamp(view); if (constY < 0 && constY != CodeUtil.minValue(yStamp.getBits())) { Stamp newStamp = IntegerStamp.OPS.getRem().foldStamp(forX.stamp(view), forY.stamp(view)); - return canonical(null, forX, ConstantNode.forIntegerStamp(yStamp, -constY), zeroCheck, newStamp, view, tool); + return canonical(self, forX, ConstantNode.forIntegerStamp(yStamp, -constY), zeroCheck, newStamp, view, tool); } if (constY == 1) { @@ -104,10 +104,19 @@ } } } - return self != null ? self : new SignedRemNode(forX, forY, zeroCheck); + if (self != null && self.x == forX && self.y == forY) { + return self; + } else { + return new SignedRemNode(forX, forY, zeroCheck); + } } private static boolean allUsagesCompareAgainstZero(SignedRemNode self) { + if (self == null) { + // If the node was not yet created, then we do not know its usages yet. + return false; + } + int compareAgainstZero = 0; int usageCount = self.getUsageCount(); for (int i = 0; i < usageCount; i++) { diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ArrayLengthNode.java Tue May 07 17:30:14 2019 -0400 @@ -33,6 +33,7 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; @@ -44,6 +45,8 @@ import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; /** * The {@code ArrayLength} instruction gets the length of an array. @@ -83,6 +86,9 @@ @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isNullConstant()) { + return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); + } ValueNode length = readArrayLength(forValue, tool.getConstantReflection()); if (length != null) { return length; diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java Tue May 07 17:30:14 2019 -0400 @@ -40,6 +40,7 @@ import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FixedGuardNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.LogicNode; @@ -140,6 +141,9 @@ @Override public Node canonical(CanonicalizerTool tool) { + if (array().isNullConstant()) { + return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); + } ValueNode constant = tryConstantFold(array(), index(), tool.getMetaAccess(), tool.getConstantReflection()); if (constant != null) { return constant; diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewInstanceNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewInstanceNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewInstanceNode.java Tue May 07 17:30:14 2019 -0400 @@ -60,7 +60,7 @@ protected NewInstanceNode(NodeClass<? extends NewInstanceNode> c, ResolvedJavaType type, boolean fillContents, FrameState stateBefore) { super(c, StampFactory.objectNonNull(TypeReference.createExactTrusted(type)), fillContents, stateBefore); - assert !type.isArray() && !type.isInterface() && !type.isPrimitive() && !type.isAbstract(); + assert !type.isArray() && !type.isInterface() && !type.isPrimitive() && !type.isAbstract() : type; this.instanceClass = type; } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreFieldNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreFieldNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreFieldNode.java Tue May 07 17:30:14 2019 -0400 @@ -27,10 +27,14 @@ import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; @@ -39,13 +43,15 @@ import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaField; /** * The {@code StoreFieldNode} represents a write to a static or instance field. */ @NodeInfo(nameTemplate = "StoreField#{p#field/s}") -public final class StoreFieldNode extends AccessFieldNode implements StateSplit, Virtualizable { +public final class StoreFieldNode extends AccessFieldNode implements StateSplit, Virtualizable, Canonicalizable { public static final NodeClass<StoreFieldNode> TYPE = NodeClass.create(StoreFieldNode.class); @Input ValueNode value; @@ -111,4 +117,12 @@ } return super.estimatedNodeCycles(); } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (!field.isStatic() && object.isNullConstant()) { + return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); + } + return this; + } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/StoreIndexedNode.java Tue May 07 17:30:14 2019 -0400 @@ -29,9 +29,13 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.ValueNode; @@ -43,6 +47,8 @@ import org.graalvm.compiler.nodes.virtual.VirtualArrayNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; @@ -50,7 +56,7 @@ * The {@code StoreIndexedNode} represents a write to an array element. */ @NodeInfo(cycles = CYCLES_8, size = SIZE_8) -public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable { +public final class StoreIndexedNode extends AccessIndexedNode implements StateSplit, Lowerable, Virtualizable, Canonicalizable { public static final NodeClass<StoreIndexedNode> TYPE = NodeClass.create(StoreIndexedNode.class); @@ -110,4 +116,12 @@ public FrameState getState() { return stateAfter; } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (array().isNullConstant()) { + return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); + } + return this; + } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java Tue May 07 17:30:14 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 @@ -54,4 +54,11 @@ // most platforms only support 32 and 64 bit compares return 32; } + + /** + * Indicates whether the target platform supports bulk zeroing instruction. + */ + default boolean supportBulkZeroing() { + return false; + } } diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java Tue May 07 17:30:14 2019 -0400 @@ -88,6 +88,7 @@ import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; +import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.TypeSwitchNode; import org.graalvm.compiler.nodes.spi.NodeWithState; import org.graalvm.compiler.nodes.spi.StampInverter; @@ -364,7 +365,38 @@ node.setCondition(LogicConstantNode.forBoolean(result, node.graph()), node.isNegated()); // Don't kill this branch immediately, see `processGuard`. } - debug.log("Kill fixed guard guard"); + + if (guard instanceof DeoptimizingGuard && !node.isNegated() && !((DeoptimizingGuard) guard).isNegated()) { + LogicNode newCondition = ((DeoptimizingGuard) guard.asNode()).getCondition(); + if (newCondition instanceof InstanceOfNode) { + InstanceOfNode inst = (InstanceOfNode) newCondition; + ValueNode originalValue = GraphUtil.skipPi(inst.getValue()); + PiNode pi = null; + // Ensure that any Pi that's weaker than what the instanceof proves is + // replaced by one derived from the instanceof itself. + for (PiNode existing : guard.asNode().usages().filter(PiNode.class).snapshot()) { + if (!existing.isAlive()) { + continue; + } + if (originalValue != GraphUtil.skipPi(existing.object())) { + // Somehow these are unrelated values so leave it alone + continue; + } + // If the pi has a weaker stamp or the same stamp but a different input + // then replace it. + boolean strongerStamp = !existing.piStamp().join(inst.getCheckedStamp()).equals(inst.getCheckedStamp()); + boolean differentStamp = !existing.piStamp().equals(inst.getCheckedStamp()); + boolean differentObject = existing.object() != inst.getValue(); + if (!strongerStamp && (differentStamp || differentObject)) { + if (pi == null) { + pi = graph.unique(new PiNode(inst.getValue(), inst.getCheckedStamp(), (ValueNode) guard)); + } + existing.replaceAndDelete(pi); + } + } + } + } + debug.log("Kill fixed guard %s", node); return true; })) { registerNewCondition(node.condition(), node.isNegated(), node); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java Tue May 07 17:30:14 2019 -0400 @@ -91,7 +91,7 @@ public BinaryGraphPrinter(DebugContext ctx, SnippetReflectionProvider snippetReflection) throws IOException { // @formatter:off this.output = ctx.buildOutput(GraphOutput.newBuilder(this). - protocolVersion(6, 0). + protocolVersion(6, 1). blocks(this). elementsAndLocations(this, this). types(this) diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java Tue May 07 17:30:14 2019 -0400 @@ -59,7 +59,13 @@ public class AArch64GraphBuilderPlugins { - public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, boolean registerMathPlugins) { + public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, + boolean registerMathPlugins) { + register(plugins, bytecodeProvider, explicitUnsafeNullChecks, registerMathPlugins, true); + } + + public static void register(Plugins plugins, BytecodeProvider bytecodeProvider, boolean explicitUnsafeNullChecks, + boolean registerMathPlugins, boolean emitJDK9StringSubstitutions) { InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); invocationPlugins.defer(new Runnable() { @Override @@ -69,8 +75,10 @@ if (registerMathPlugins) { registerMathPlugins(invocationPlugins); } - registerStringLatin1Plugins(invocationPlugins, bytecodeProvider); - registerStringUTF16Plugins(invocationPlugins, bytecodeProvider); + if (emitJDK9StringSubstitutions) { + registerStringLatin1Plugins(invocationPlugins, bytecodeProvider); + registerStringUTF16Plugins(invocationPlugins, bytecodeProvider); + } registerUnsafePlugins(invocationPlugins, bytecodeProvider); // This is temporarily disabled until we implement correct emitting of the CAS // instructions of the proper width. diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java Tue May 07 17:30:14 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. + */ + + +package org.graalvm.compiler.replacements.nodes; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; + +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.word.Word; +import jdk.internal.vm.compiler.word.LocationIdentity; + +/** + * Zeros a chunk of memory. + */ +@NodeInfo(nameTemplate = "ZeroMemory#{p#location/s}", allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_8, size = SIZE_8) +public class ZeroMemoryNode extends FixedAccessNode implements LIRLowerable { + public static final NodeClass<ZeroMemoryNode> TYPE = NodeClass.create(ZeroMemoryNode.class); + + @Input ValueNode length; + + public ZeroMemoryNode(ValueNode address, ValueNode length, LocationIdentity locationIdentity) { + this(OffsetAddressNode.create(address), length, locationIdentity, BarrierType.NONE); + } + + public ZeroMemoryNode(AddressNode address, ValueNode length, LocationIdentity locationIdentity, BarrierType type) { + super(TYPE, address, locationIdentity, StampFactory.forVoid(), type); + this.length = length; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + gen.getLIRGeneratorTool().getArithmetic().emitZeroMemory(gen.operand(getAddress()), gen.operand(length)); + } + + @Override + public boolean canNullCheck() { + return false; + } + + @NodeIntrinsic + public static native void zero(Word address, long length, @ConstantNodeParameter LocationIdentity locationIdentity); +} diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/GraphEffectList.java Tue May 07 17:30:14 2019 -0400 @@ -223,7 +223,7 @@ */ public void replaceAtUsages(ValueNode node, ValueNode replacement, FixedNode insertBefore) { assert node != null && replacement != null : node + " " + replacement; - assert node.stamp(NodeView.DEFAULT).isCompatible(replacement.stamp(NodeView.DEFAULT)) : "Replacement node stamp not compatible " + node.stamp(NodeView.DEFAULT) + " vs " + + assert !node.hasUsages() || node.stamp(NodeView.DEFAULT).isCompatible(replacement.stamp(NodeView.DEFAULT)) : "Replacement node stamp not compatible " + node.stamp(NodeView.DEFAULT) + " vs " + replacement.stamp(NodeView.DEFAULT); add("replace at usages", (graph, obsoleteNodes) -> { assert node.isAlive(); @@ -240,7 +240,7 @@ * to improve the stamp information of the read. Such a read might later be replaced * with a read with a less precise stamp. */ - if (!node.stamp(NodeView.DEFAULT).equals(replacementNode.stamp(NodeView.DEFAULT))) { + if (node.hasUsages() && !node.stamp(NodeView.DEFAULT).equals(replacementNode.stamp(NodeView.DEFAULT))) { replacementNode = graph.unique(new PiNode(replacementNode, node.stamp(NodeView.DEFAULT))); } node.replaceAtUsages(replacementNode); diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Fri May 03 14:59:32 2019 -0400 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java Tue May 07 17:30:14 2019 -0400 @@ -75,6 +75,9 @@ private static final byte[] MAGIC_BYTES = {'B', 'I', 'G', 'V'}; + private static final int MAJOR_VERSION = 6; + private static final int MINOR_VERSION = 1; + private final ConstantPool constantPool; private final ByteBuffer buffer; private final WritableByteChannel channel; @@ -84,7 +87,7 @@ private boolean printing; GraphProtocol(WritableByteChannel channel, int major, int minor, boolean embedded) throws IOException { - if (major > 6 || (major == 6 && minor > 0)) { + if (major > MAJOR_VERSION || (major == MAJOR_VERSION && minor > MINOR_VERSION)) { throw new IllegalArgumentException("Unrecognized version " + major + "." + minor); } this.versionMajor = major; diff -r bf3d37105ef9 -r 51709d9aab69 src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayAllocationBenchmark.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayAllocationBenchmark.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,51 @@ +/* + * 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. + */ + + +package micro.benchmarks; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +/** + * Benchmarks cost of ArrayList. + */ +public class ArrayAllocationBenchmark extends BenchmarkBase { + + @State(Scope.Benchmark) + public static class ThreadState { + @Param({"128", "256", "512", "1024", "2048", "4096", "8192", "16384", "32768", "65536", "131072"}) int size; + byte[] result; + } + + @Benchmark + @Threads(8) + @Warmup(iterations = 10) + public void arrayAllocate(ThreadState state) { + state.result = new byte[state.size]; + } +} diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/gtest/oops/test_markOop.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/gtest/oops/test_markOop.cpp Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,140 @@ +/* + * 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. + */ + +#include "precompiled.hpp" +#include "classfile/systemDictionary.hpp" +#include "memory/resourceArea.hpp" +#include "memory/universe.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/atomic.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/orderAccess.hpp" +#include "runtime/os.hpp" +#include "runtime/synchronizer.hpp" +#include "threadHelper.inline.hpp" +#include "unittest.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +// The test doesn't work for PRODUCT because it needs WizardMode +#ifndef PRODUCT +static bool test_pattern(stringStream* st, const char* pattern) { + return (strstr(st->as_string(), pattern) != NULL); +} + +static void assert_test_pattern(Handle object, const char* pattern) { + stringStream st; + object->print_on(&st); + ASSERT_TRUE(test_pattern(&st, pattern)) << pattern << " not in " << st.as_string(); +} + +static void assert_not_test_pattern(Handle object, const char* pattern) { + stringStream st; + object->print_on(&st); + ASSERT_FALSE(test_pattern(&st, pattern)) << pattern << " found in " << st.as_string(); +} + +class LockerThread : public JavaTestThread { + oop _obj; + public: + LockerThread(Semaphore* post, oop obj) : JavaTestThread(post), _obj(obj) {} + virtual ~LockerThread() {} + + void main_run() { + Thread* THREAD = Thread::current(); + HandleMark hm(THREAD); + Handle h_obj(THREAD, _obj); + ResourceMark rm(THREAD); + + // Wait gets the lock inflated. + // The object will stay locked for the context of 'ol' so the lock will + // still be inflated after the notify_all() call. Deflation can't happen + // while an ObjectMonitor is "busy" and being locked is the most "busy" + // state we have... + ObjectLocker ol(h_obj, THREAD); + ol.notify_all(THREAD); + assert_test_pattern(h_obj, "monitor"); + } +}; + + +TEST_VM(markOopDesc, printing) { + JavaThread* THREAD = JavaThread::current(); + ThreadInVMfromNative invm(THREAD); + ResourceMark rm(THREAD); + + oop obj = SystemDictionary::Byte_klass()->allocate_instance(THREAD); + + FlagSetting fs(WizardMode, true); + FlagSetting bf(UseBiasedLocking, true); + + HandleMark hm(THREAD); + Handle h_obj(THREAD, obj); + + // Biased locking is initially enabled for this java.lang.Byte object. + assert_test_pattern(h_obj, "is_biased"); + + // Lock using biased locking. + BasicObjectLock lock; + lock.set_obj(obj); + markOop mark = obj->mark()->incr_bias_epoch(); + obj->set_mark(mark); + ObjectSynchronizer::fast_enter(h_obj, lock.lock(), true, THREAD); +#ifdef _LP64 + // Look for the biased_locker in markOop, not prototype_header. + assert_not_test_pattern(h_obj, "mark(is_biased biased_locker=0x0000000000000000"); +#endif + + // Same thread tries to lock it again. + { + ObjectLocker ol(h_obj, THREAD); + assert_test_pattern(h_obj, "locked"); + } + + // This is no longer biased, because ObjectLocker revokes the bias. + assert_test_pattern(h_obj, "is_neutral no_hash"); + + // Wait gets the lock inflated. + { + ObjectLocker ol(h_obj, THREAD); + + Semaphore done(0); + LockerThread* st; + st = new LockerThread(&done, h_obj()); + st->doit(); + + ol.wait(THREAD); + assert_test_pattern(h_obj, "monitor"); + } + + // Make the object older. Not all GCs use this field. + Universe::heap()->collect(GCCause::_java_lang_system_gc); + if (UseParallelGC) { + assert_test_pattern(h_obj, "is_neutral no_hash age 1"); + } + + // Hash the object then print it. + intx hash = h_obj->identity_hash(); + assert_test_pattern(h_obj, "is_neutral hash=0x"); +} +#endif // PRODUCT diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/ProblemList-graal.txt --- a/test/hotspot/jtreg/ProblemList-graal.txt Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/ProblemList-graal.txt Tue May 07 17:30:14 2019 -0400 @@ -210,8 +210,6 @@ serviceability/tmtools/jstat/GcCapacityTest.java 8196611 generic-all serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorMultiArrayTest.java 8196611 generic-all -vmTestbase/gc/lock/jvmti/alloc/jvmtialloclock02/TestDescription.java 8218700 generic-all - vmTestbase/nsk/jdb/unmonitor/unmonitor001/unmonitor001.java 8218701 generic-all vmTestbase/nsk/jdb/clear/clear003/clear003.java 8218701 generic-all diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/c2/cr6340864/TestDoubleVect.java --- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestDoubleVect.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestDoubleVect.java Tue May 07 17:30:14 2019 -0400 @@ -86,6 +86,7 @@ test_divc_n(a0, a1); test_divv(a0, a1, -VALUE); test_diva(a0, a1, a3); + test_negc(a0, a1); } // Test and verify results System.out.println("Verification"); @@ -339,6 +340,16 @@ for (int i=12; i<ARRLEN; i++) { errn += verify("test_diva_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); } + test_negc(a0, a1); + errn += verify("test_negc: ", 0, a0[0], (Double.NaN)); + errn += verify("test_negc: ", 1, a0[1], (Double.NEGATIVE_INFINITY)); + errn += verify("test_negc: ", 2, a0[2], (Double.POSITIVE_INFINITY)); + errn += verify("test_negc: ", 3, a0[3], (double)(-Double.MAX_VALUE)); + errn += verify("test_negc: ", 4, a0[4], (double)(-Double.MIN_VALUE)); + errn += verify("test_negc: ", 5, a0[5], (double)(-Double.MIN_NORMAL)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_negc: ", i, a0[i], (double)(-((double)(ADD_INIT+i)))); + } } @@ -469,6 +480,13 @@ end = System.currentTimeMillis(); System.out.println("test_diva_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_negc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_negc_n: " + (end - start)); + return errn; } @@ -553,6 +571,11 @@ a0[i] = (a1[i]/a2[i]); } } + static void test_negc(double[] a0, double[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (double)(-((double)a1[i])); + } + } static int verify(String text, int i, double elem, double val) { if (elem != val && !(Double.isNaN(elem) && Double.isNaN(val))) { diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/c2/cr6340864/TestFloatVect.java --- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestFloatVect.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestFloatVect.java Tue May 07 17:30:14 2019 -0400 @@ -86,6 +86,7 @@ test_divc_n(a0, a1); test_divv(a0, a1, -VALUE); test_diva(a0, a1, a3); + test_negc(a0, a1); } // Test and verify results System.out.println("Verification"); @@ -340,6 +341,17 @@ errn += verify("test_diva_n: ", i, a0[i], ((ADD_INIT+i)/(-VALUE))); } + test_negc(a0, a1); + errn += verify("test_negc: ", 0, a0[0], (Float.NaN)); + errn += verify("test_negc: ", 1, a0[1], (Float.NEGATIVE_INFINITY)); + errn += verify("test_negc: ", 2, a0[2], (Float.POSITIVE_INFINITY)); + errn += verify("test_negc: ", 3, a0[3], (float)(-Float.MAX_VALUE)); + errn += verify("test_negc: ", 4, a0[4], (float)(-Float.MIN_VALUE)); + errn += verify("test_negc: ", 5, a0[5], (float)(-Float.MIN_NORMAL)); + for (int i=6; i<ARRLEN; i++) { + errn += verify("test_negc: ", i, a0[i], (float)(-((float)(ADD_INIT+i)))); + } + } if (errn > 0) @@ -469,6 +481,13 @@ end = System.currentTimeMillis(); System.out.println("test_diva_n: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_negc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_negc_n: " + (end - start)); + return errn; } @@ -554,6 +573,12 @@ } } + static void test_negc(float[] a0, float[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (float)(-((float)a1[i])); + } + } + static int verify(String text, int i, float elem, float val) { if (elem != val && !(Float.isNaN(elem) && Float.isNaN(val))) { System.err.println(text + "[" + i + "] = " + elem + " != " + val); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java --- a/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/compiler/c2/cr6340864/TestIntVect.java Tue May 07 17:30:14 2019 -0400 @@ -102,6 +102,10 @@ test_xorv(a0, a1, (int)BIT_MASK); test_xora(a0, a1, a4); + test_absc(a0, a1); + test_negc(a0, a1); + test_notc(a0, a1); + test_sllc(a0, a1); test_sllv(a0, a1, VALUE); test_srlc(a0, a1); @@ -276,6 +280,21 @@ errn += verify("test_xora: ", i, a0[i], (int)((int)(ADD_INIT+i)^BIT_MASK)); } + test_absc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_absc: ", i, a0[i], (int)(Math.abs((int)(ADD_INIT+i)))); + } + + test_negc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_negc: ", i, a0[i], (int)(-(int)(ADD_INIT+i))); + } + + test_notc(a0, a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_notc: ", i, a0[i], (int)(~(int)(ADD_INIT+i))); + } + test_sllc(a0, a1); for (int i=0; i<ARRLEN; i++) { errn += verify("test_sllc: ", i, a0[i], (int)((int)(ADD_INIT+i)<<VALUE)); @@ -650,6 +669,27 @@ start = System.currentTimeMillis(); for (int i=0; i<ITERS; i++) { + test_absc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_absc: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_negc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_negc: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_notc(a0, a1); + } + end = System.currentTimeMillis(); + System.out.println("test_notc: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { test_sllc(a0, a1); } end = System.currentTimeMillis(); @@ -1040,6 +1080,24 @@ } } + static void test_absc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(Math.abs(a1[i])); + } + } + + static void test_negc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(-a1[i]); + } + } + + static void test_notc(int[] a0, int[] a1) { + for (int i = 0; i < a0.length; i+=1) { + a0[i] = (int)(~a1[i]); + } + } + static void test_sllc(int[] a0, int[] a1) { for (int i = 0; i < a0.length; i+=1) { a0[i] = (int)(a1[i]<<VALUE); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java --- a/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/compiler/graalunit/common/GraalUnitTestLauncher.java Tue May 07 17:30:14 2019 -0400 @@ -254,7 +254,11 @@ .collect(Collectors.joining(File.pathSeparator)); javaFlags.add("-cp"); - javaFlags.add(String.join(File.pathSeparator, System.getProperty("java.class.path"), graalJarsCP)); + // Existing classpath returned by System.getProperty("java.class.path") may contain another + // version of junit with which the jtreg tool is built. It may be incompatible with required + // junit version. So we put graalJarsCP before existing classpath when generating a new one + // to avoid incompatibility issues. + javaFlags.add(String.join(File.pathSeparator, graalJarsCP, System.getProperty("java.class.path"))); // javaFlags.add("com.oracle.mxtool.junit.MxJUnitWrapper"); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java --- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Tue May 07 17:30:14 2019 -0400 @@ -301,7 +301,7 @@ } public static void writeDebugOutput(byte[] bytes, int offset, int length) { - CTVM.writeDebugOutput(bytes, offset, length); + CTVM.writeDebugOutput(bytes, offset, length, true, true); } public static void flushDebugOutput() { diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,117 @@ +/* + * 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. + */ +package jdk.vm.ci.hotspot.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; + +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +public class TestHotSpotJVMCIRuntime { + + @Test + public void writeDebugOutputTest() { + HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + + expectWriteDebugOutputFailure(runtime, null, 0, 0, true, true, NullPointerException.class); + expectWriteDebugOutputFailure(runtime, null, 0, 0, true, false, -1); + + byte[] emptyOutput = {}; + byte[] nonEmptyOutput = String.format("non-empty output%n").getBytes(); + + for (boolean canThrow : new boolean[]{true, false}) { + for (byte[] output : new byte[][]{emptyOutput, nonEmptyOutput}) { + for (int offset = 0; offset < output.length; offset++) { + int length = output.length - offset; + runtime.writeDebugOutput(output, offset, length, true, canThrow); + } + + Object expect = canThrow ? IndexOutOfBoundsException.class : -2; + expectWriteDebugOutputFailure(runtime, output, output.length + 1, 0, true, canThrow, expect); + expectWriteDebugOutputFailure(runtime, output, 0, output.length + 1, true, canThrow, expect); + expectWriteDebugOutputFailure(runtime, output, -1, 0, true, canThrow, expect); + expectWriteDebugOutputFailure(runtime, output, 0, -1, true, canThrow, expect); + } + } + } + + private static void expectWriteDebugOutputFailure(HotSpotJVMCIRuntime runtime, byte[] bytes, int offset, int length, boolean flush, boolean canThrow, Object expect) { + try { + int result = runtime.writeDebugOutput(bytes, offset, length, flush, canThrow); + if (expect instanceof Integer) { + Assert.assertEquals((int) expect, result); + } else { + Assert.fail("expected " + expect + ", got " + result + " for bytes == " + Arrays.toString(bytes)); + } + } catch (Exception e) { + if (expect instanceof Integer) { + Assert.fail("expected " + expect + ", got " + e + " for bytes == " + Arrays.toString(bytes)); + } else { + Assert.assertTrue(e.toString(), ((Class<?>) expect).isInstance(e)); + } + } + } + + @Test + public void getIntrinsificationTrustPredicateTest() throws Exception { + HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + MetaAccessProvider metaAccess = runtime.getHostJVMCIBackend().getMetaAccess(); + Predicate<ResolvedJavaType> predicate = runtime.getIntrinsificationTrustPredicate(HotSpotJVMCIRuntime.class); + List<Class<?>> classes = new ArrayList<>(Arrays.asList( + Object.class, + String.class, + Class.class, + HotSpotJVMCIRuntime.class, + VirtualObjectLayoutTest.class, + TestHotSpotJVMCIRuntime.class)); + try { + classes.add(Class.forName("com.sun.crypto.provider.AESCrypt")); + classes.add(Class.forName("com.sun.crypto.provider.CipherBlockChaining")); + } catch (ClassNotFoundException e) { + // Extension classes not available + } + ClassLoader jvmciLoader = HotSpotJVMCIRuntime.class.getClassLoader(); + ClassLoader extLoader = getExtensionLoader(); + for (Class<?> c : classes) { + ClassLoader cl = c.getClassLoader(); + boolean expected = cl == null || cl == jvmciLoader || cl == extLoader; + boolean actual = predicate.test(metaAccess.lookupJavaType(c)); + Assert.assertEquals(c + ": cl=" + cl, expected, actual); + } + } + + private static ClassLoader getExtensionLoader() throws Exception { + Object launcher = Class.forName("sun.misc.Launcher").getMethod("getLauncher").invoke(null); + ClassLoader appLoader = (ClassLoader) launcher.getClass().getMethod("getClassLoader").invoke(launcher); + ClassLoader extLoader = appLoader.getParent(); + assert extLoader.getClass().getName().equals("sun.misc.Launcher$ExtClassLoader") : extLoader; + return extLoader; + } +} diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java Tue May 07 17:30:14 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. + */ +package jdk.vm.ci.hotspot.test; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.services.Services; + +public class TestServices { + + @SuppressWarnings("unchecked") + @Test + public void serializeSavedPropertiesTest() throws Exception { + + Field f = Services.class.getDeclaredField("MAX_UTF8_PROPERTY_STRING_LENGTH"); + f.setAccessible(true); + int maxUtf8PropertyStringLength = (int) f.get(null); + + Method serializeProperties = Services.class.getDeclaredMethod("serializeProperties", Map.class); + Method deserializeProperties = Services.class.getDeclaredMethod("deserializeProperties", byte[].class); + serializeProperties.setAccessible(true); + deserializeProperties.setAccessible(true); + + Map<String, String> props = new HashMap<>(Services.getSavedProperties()); + String[] names = { + new String(new char[maxUtf8PropertyStringLength - 100]).replace('\0', 'x'), + new String(new char[maxUtf8PropertyStringLength - 1]).replace('\0', 'x'), + new String(new char[maxUtf8PropertyStringLength]).replace('\0', 'y'), + new String(new char[maxUtf8PropertyStringLength + 1]).replace('\0', 'z'), + new String(new char[maxUtf8PropertyStringLength + 100]).replace('\0', 'z') + }; + String[] values = { + new String(new char[maxUtf8PropertyStringLength - 100]).replace('\0', '1'), + new String(new char[maxUtf8PropertyStringLength - 1]).replace('\0', '1'), + new String(new char[maxUtf8PropertyStringLength]).replace('\0', '2'), + new String(new char[maxUtf8PropertyStringLength + 1]).replace('\0', '1'), + new String(new char[maxUtf8PropertyStringLength + 100]).replace('\0', '3') + }; + for (String name : names) { + for (String value : values) { + props.put(name, value); + } + } + + byte[] data = (byte[]) serializeProperties.invoke(null, props); + + Map<String, String> newProps = (Map<String, String>) deserializeProperties.invoke(null, data); + + Assert.assertEquals(props.size(), newProps.size()); + for (String name : props.keySet()) { + String expect = props.get(name); + String actual = newProps.get(name); + Assert.assertEquals(expect, actual); + } + } +} diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/compiler/tiered/Level2RecompilationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/tiered/Level2RecompilationTest.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,102 @@ +/* + * 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 Level2RecompilationTest + * @summary Test downgrading mechanism from level 3 to level 2 for those profiled methods. + * @library /test/lib / + * @modules java.base/jdk.internal.misc + * java.management + * + * @build sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCounterDecay + * -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCaseHelper::* + * -XX:CompileCommand=print,compiler.whitebox.SimpleTestCaseHelper::* + * compiler.tiered.Level2RecompilationTest + */ + +package compiler.tiered; + +import compiler.whitebox.CompilerWhiteBoxTest; +import jtreg.SkippedException; + +public class Level2RecompilationTest extends CompLevelsTest { + public static void main(String[] args) throws Throwable { + if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) { + throw new SkippedException("Test isn't applicable for non-tiered mode"); + } + String[] testcases = {"METHOD_TEST", "OSR_STATIC_TEST"}; + CompilerWhiteBoxTest.main(Level2RecompilationTest::new, testcases); + } + + protected Level2RecompilationTest(TestCase testCase) { + super(testCase); + // to prevent inlining of #method + WHITE_BOX.testSetDontInlineMethod(method, true); + } + + @Override + protected void test() throws Exception { + if (skipXcompOSR()) { + return; + } + + checkNotCompiled(); + int bci = WHITE_BOX.getMethodEntryBci(method); + WHITE_BOX.markMethodProfiled(method); + if (testCase.isOsr()) { + // for OSR compilation, it must be the begin of a BB. + // c1_GraphBulider.cpp:153 assert(method()->bci_block_start().at(cur_bci), ... + bci = 0; + } + + WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_FULL_PROFILE, bci); + checkCompiled(); + checkLevel(COMP_LEVEL_LIMITED_PROFILE, getCompLevel()); + + for (int i=0; i<1_000; ++i) { + WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_FULL_PROFILE, bci); + waitBackgroundCompilation(); + checkLevel(COMP_LEVEL_LIMITED_PROFILE, getCompLevel()); + } + } + + @Override + protected void checkLevel(int expected, int actual) { + if (expected == COMP_LEVEL_FULL_PROFILE + && actual == COMP_LEVEL_LIMITED_PROFILE) { + // for simple method full_profile may be replaced by limited_profile + if (IS_VERBOSE) { + System.out.printf("Level check: full profiling was replaced " + + "by limited profiling. Expected: %d, actual:%d\n", + expected, actual); + } + return; + } + super.checkLevel(expected, actual); + } +} + diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/gc/g1/TestGCLogMessages.java --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java Tue May 07 17:30:14 2019 -0400 @@ -119,7 +119,6 @@ new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE), new LogMessageWithLevel("CLDG Roots", Level.TRACE), new LogMessageWithLevel("JVMTI Roots", Level.TRACE), - new LogMessageWithLevel("SATB Filtering", Level.TRACE), new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE), new LogMessageWithLevel("Weak CLD Roots", Level.TRACE), diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/gc/shenandoah/TestHumongousThreshold.java --- a/test/hotspot/jtreg/gc/shenandoah/TestHumongousThreshold.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/gc/shenandoah/TestHumongousThreshold.java Tue May 07 17:30:14 2019 -0400 @@ -26,13 +26,76 @@ * @key gc * @requires vm.gc.Shenandoah * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:+ShenandoahVerify TestHumongousThreshold - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:ShenandoahHumongousThreshold=50 -XX:+ShenandoahVerify TestHumongousThreshold - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:ShenandoahHumongousThreshold=90 -XX:+ShenandoahVerify TestHumongousThreshold - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:ShenandoahHumongousThreshold=99 -XX:+ShenandoahVerify TestHumongousThreshold - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:ShenandoahHumongousThreshold=100 -XX:+ShenandoahVerify TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:+ShenandoahVerify + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=50 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=90 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=99 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=100 + * TestHumongousThreshold + * + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:+ShenandoahVerify + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=50 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=90 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=99 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=100 + * TestHumongousThreshold * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g -XX:ShenandoahHumongousThreshold=90 -XX:ShenandoahGCHeuristics=aggressive TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=50 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=90 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=99 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=100 + * TestHumongousThreshold + * + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=50 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=90 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=99 + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:ObjectAlignmentInBytes=16 -XX:+ShenandoahVerify -XX:ShenandoahHumongousThreshold=100 + * TestHumongousThreshold + * + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:ShenandoahHumongousThreshold=90 -XX:ShenandoahGCHeuristics=aggressive + * TestHumongousThreshold + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xmx1g + * -XX:-UseTLAB -XX:ShenandoahHumongousThreshold=90 -XX:ShenandoahGCHeuristics=aggressive + * TestHumongousThreshold */ import java.util.Random; diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/gc/shenandoah/TestStringDedupStress.java --- a/test/hotspot/jtreg/gc/shenandoah/TestStringDedupStress.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/gc/shenandoah/TestStringDedupStress.java Tue May 07 17:30:14 2019 -0400 @@ -30,60 +30,74 @@ * @modules java.base/jdk.internal.misc:open * @modules java.base/java.lang:open * java.management - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -DtargetStrings=3000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=aggressive -DtargetStrings=2000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=aggressive -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=static -DtargetStrings=4000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=compact + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats - * -XX:ShenandoahGCHeuristics=passive -XX:+ShenandoahDegeneratedGC -DtargetOverwrites=40000000 + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats + * -XX:ShenandoahGCHeuristics=passive -XX:+ShenandoahDegeneratedGC + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats - * -XX:ShenandoahGCHeuristics=passive -XX:-ShenandoahDegeneratedGC -DtargetOverwrites=40000000 + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats + * -XX:ShenandoahGCHeuristics=passive -XX:-ShenandoahDegeneratedGC + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=traversal + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=3000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=compact -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=2000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=aggressive -XX:ShenandoahUpdateRefsEarly=off -DtargetStrings=2000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats - * -XX:ShenandoahGCHeuristics=static -XX:ShenandoahUpdateRefsEarly=off -DtargetOverwrites=4000000 + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats + * -XX:ShenandoahGCHeuristics=static -XX:ShenandoahUpdateRefsEarly=off + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=aggressive -XX:ShenandoahUpdateRefsEarly=off -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000 + * -Xlog:gc * TestStringDedupStress * - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx512M -Xlog:gc+stats + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:+UseStringDeduplication -Xmx1g -Xlog:gc+stats * -XX:ShenandoahGCHeuristics=traversal -XX:+ShenandoahOOMDuringEvacALot -DtargetStrings=2000000 + * -Xlog:gc * TestStringDedupStress */ @@ -97,9 +111,9 @@ private static Field valueField; private static Unsafe unsafe; - private static long TARGET_STRINGS = Long.getLong("targetStrings", 2_500_000); - private static long TARGET_OVERWRITES = Long.getLong("targetOverwrites", 600_000); + private static final int TARGET_STRINGS = Integer.getInteger("targetStrings", 2_500_000); private static final long MAX_REWRITE_GC_CYCLES = 6; + private static final long MAX_REWRITE_TIME = 30*1000; // ms private static final int UNIQUE_STRINGS = 20; @@ -151,8 +165,8 @@ } } - private static int verifyDedepString(ArrayList<StringAndId> strs) { - HashMap<Object, StringAndId> seen = new HashMap<>(); + private static int verifyDedupString(ArrayList<StringAndId> strs) { + Map<Object, StringAndId> seen = new HashMap<>(TARGET_STRINGS*2); int total = 0; int dedup = 0; @@ -195,14 +209,16 @@ } // Generate roughly TARGET_STRINGS strings, only UNIQUE_STRINGS are unique - long genIters = TARGET_STRINGS / UNIQUE_STRINGS; - for (long index = 0; index < genIters; index++) { + int genIters = TARGET_STRINGS / UNIQUE_STRINGS; + for (int index = 0; index < genIters; index++) { generateStrings(astrs, UNIQUE_STRINGS); } long cycleBeforeRewrite = gcCycleMBean.getCollectionCount(); + long timeBeforeRewrite = System.currentTimeMillis(); - for (long loop = 1; loop < TARGET_OVERWRITES; loop++) { + long loop = 1; + while (true) { int arrSize = astrs.size(); int index = rn.nextInt(arrSize); StringAndId item = astrs.get(index); @@ -210,13 +226,18 @@ item.str = "Unique String " + n; item.id = n; - if (loop % 1000 == 0) { + if (loop++ % 1000 == 0) { // enough GC cycles for rewritten strings to be deduplicated if (gcCycleMBean.getCollectionCount() - cycleBeforeRewrite >= MAX_REWRITE_GC_CYCLES) { break; } + + // enough time is spent waiting for GC to happen + if (System.currentTimeMillis() - timeBeforeRewrite >= MAX_REWRITE_TIME) { + break; + } } } - verifyDedepString(astrs); + verifyDedupString(astrs); } } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ThreadStartRequest/addThreadFilter/addthreadfilter002.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, 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 @@ -479,12 +479,25 @@ throws JDITestRuntimeException { log2("breakpointForCommunication"); - getEventSet(); - - if (eventIterator.nextEvent() instanceof BreakpointEvent) - return; - - throw new JDITestRuntimeException("** event IS NOT a breakpoint **"); + while (true) { + getEventSet(); + while (eventIterator.hasNext()) { + Event event = eventIterator.nextEvent(); + if (event instanceof BreakpointEvent) { + return; + } else if (event instanceof ThreadStartEvent) { + // It might be the case that while the thread start request was enabled + // some threads not related to the test ( e.g. JVMCI threads) were started + // and generated thread start events. We ignore these thread start events + // and keep waiting for a breakpoint event. + ThreadStartEvent tse = (ThreadStartEvent) event; + log2("ThreadStartEvent is received while waiting for a breakpoint" + + " event, thread: : " + tse.thread().name()); + continue; + } + throw new JDITestRuntimeException("** event IS NOT a breakpoint or a thread start **"); + } + } } } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach002/attach002Agent00.cpp Tue May 07 17:30:14 2019 -0400 @@ -69,14 +69,14 @@ #define ATTACH002_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach002/attach002Target" void registerNativeMethods(JNIEnv* jni_env) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass appClass; JNINativeMethod nativeMethods[] = { { (char*) "agentGotCapabilities", (char*) "()Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach002_attach002Target_agentGotCapabilities } }; jint nativeMethodsNumber = 1; - appClass = jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); - jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); + appClass = ec_jni->FindClass(ATTACH002_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); + ec_jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); } void JNICALL classLoadHandler( diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach021/attach021Agent00.cpp Tue May 07 17:30:14 2019 -0400 @@ -89,15 +89,15 @@ } void registerNativeMethods(JNIEnv* jni_env) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass appClass; JNINativeMethod nativeMethods[] = { { (char*) "setTagFor", (char*) "(Ljava/lang/Object;)Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach021_attach021Target_setTagFor }, { (char*) "shutdownAgent", (char*) "()V", (void*) Java_nsk_jvmti_AttachOnDemand_attach021_attach021Target_shutdownAgent } }; jint nativeMethodsNumber = 2; - appClass = jni->FindClass(ATTACH021_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); - jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); + appClass = ec_jni->FindClass(ATTACH021_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); + ec_jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); } #ifdef STATIC_BUILD diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach022/attach022Agent00.cpp Tue May 07 17:30:14 2019 -0400 @@ -98,15 +98,15 @@ #define ATTACH022_TARGET_APP_CLASS_NAME "nsk/jvmti/AttachOnDemand/attach022/attach022Target" void registerNativeMethods(JNIEnv* jni_env) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass appClass; JNINativeMethod nativeMethods[] = { { (char*)"shutdownAgent", (char*)"(I)Z", (void*) Java_nsk_jvmti_AttachOnDemand_attach022_attach022Target_shutdownAgent } }; jint nativeMethodsNumber = 1; - appClass = jni->FindClass(ATTACH022_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); - jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); + appClass = ec_jni->FindClass(ATTACH022_TARGET_APP_CLASS_NAME, TRACE_JNI_CALL); + ec_jni->RegisterNatives(appClass, nativeMethods, nativeMethodsNumber, TRACE_JNI_CALL); } void JNICALL vmObjectAllocHandler(jvmtiEnv * jvmti, diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/allocation/AP04/ap04t003/ap04t003.cpp Tue May 07 17:30:14 2019 -0400 @@ -335,13 +335,13 @@ /** Create thread object for new agent thread. */ static jthread newThreadObj(JNIEnv* jni_env) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass thrClass; jmethodID cid; - thrClass = jni->FindClass("java/lang/Thread", TRACE_JNI_CALL); - cid = jni->GetMethodID(thrClass, "<init>", "()V", TRACE_JNI_CALL); - return jni->NewObject(thrClass, cid, TRACE_JNI_CALL); + thrClass = ec_jni->FindClass("java/lang/Thread", TRACE_JNI_CALL); + cid = ec_jni->GetMethodID(thrClass, "<init>", "()V", TRACE_JNI_CALL); + return ec_jni->NewObject(thrClass, cid, TRACE_JNI_CALL); } /***********************************************************************/ @@ -491,12 +491,12 @@ JNIEXPORT void JNICALL Java_nsk_jvmti_scenarios_allocation_AP04_ap04t003_runIterateOverObjectsReachableFromObject(JNIEnv* jni_env, jclass klass) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jobject root = NULL; int modified = 0; int found = 0; - root = jni->GetStaticObjectField(debugeeClass, rootFieldID, TRACE_JNI_CALL); + root = ec_jni->GetStaticObjectField(debugeeClass, rootFieldID, TRACE_JNI_CALL); if (!prepareToIteration(jni_env)) return; @@ -524,7 +524,7 @@ static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* jni_env, void* arg) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); NSK_DISPLAY0("Wait for debugee start\n\n"); if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) return; @@ -536,10 +536,10 @@ return; } - debugeeClass = (jclass) jni->NewGlobalRef(debugeeClass, TRACE_JNI_CALL); + debugeeClass = (jclass) ec_jni->NewGlobalRef(debugeeClass, TRACE_JNI_CALL); NSK_DISPLAY1("Find ID of 'root' field: %s\n", ROOT_SIGNATURE); - rootFieldID = jni->GetStaticFieldID(debugeeClass, "root", + rootFieldID = ec_jni->GetStaticFieldID(debugeeClass, "root", ROOT_SIGNATURE, TRACE_JNI_CALL); NSK_DISPLAY0("Let debugee to run test cases\n"); @@ -550,7 +550,7 @@ if (!NSK_VERIFY(nsk_jvmti_waitForSync(timeout))) return; - jni->DeleteGlobalRef(debugeeClass, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(debugeeClass, TRACE_JNI_CALL); NSK_TRACE(jvmti->DestroyRawMonitor(counterMonitor_ptr)); NSK_TRACE(jvmti->DestroyRawMonitor(startLock)); NSK_TRACE(jvmti->DestroyRawMonitor(runLock)); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t001/bi01t001.cpp Tue May 07 17:30:14 2019 -0400 @@ -50,18 +50,18 @@ Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t001_setNewByteCode(JNIEnv *jni_env, jobject o, jbyteArray byteCode) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jbyte* elements; jboolean isCopy; - newClassSize = jni->GetArrayLength(byteCode, TRACE_JNI_CALL); + newClassSize = ec_jni->GetArrayLength(byteCode, TRACE_JNI_CALL); if (newClassSize <= 0) { nsk_jvmti_setFailStatus(); return NSK_FALSE; } NSK_DISPLAY1("\t... got array size: %d\n", newClassSize); - elements = jni->GetByteArrayElements(byteCode, &isCopy, TRACE_JNI_CALL); + elements = ec_jni->GetByteArrayElements(byteCode, &isCopy, TRACE_JNI_CALL); NSK_DISPLAY1("\t... got elements list: 0x%p\n", (void*)elements); if (!NSK_JVMTI_VERIFY(jvmti->Allocate(newClassSize, &newClassBytes))) { @@ -78,7 +78,7 @@ NSK_DISPLAY1("\t... copied bytecode: %d bytes\n", (int)newClassSize); NSK_DISPLAY1("\t... release elements list: 0x%p\n", (void*)elements); - jni->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT, TRACE_JNI_CALL); + ec_jni->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT, TRACE_JNI_CALL); NSK_DISPLAY0("\t... released\n"); return NSK_TRUE; } @@ -92,8 +92,8 @@ JNIEXPORT void JNICALL Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t001_setClass(JNIEnv *jni_env, jobject o, jclass cls) { - ExceptionCheckingJniEnvPtr jni(jni_env); - oldClassDef.klass = (jclass) jni->NewGlobalRef(cls, TRACE_JNI_CALL); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); + oldClassDef.klass = (jclass) ec_jni->NewGlobalRef(cls, TRACE_JNI_CALL); } /* ============================================================================= */ @@ -149,7 +149,7 @@ /** Agent algorithm. */ static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { - ExceptionCheckingJniEnvPtr jni(agentJNI); + ExceptionCheckingJniEnvPtr ec_jni(agentJNI); /*Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1*/ NSK_DISPLAY0("Wait for debuggee to read new byte codes nsk_jvmti_waitForSync#1\n"); @@ -210,7 +210,7 @@ if (!nsk_jvmti_waitForSync(timeout)) return; - jni->DeleteGlobalRef(oldClassDef.klass, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(oldClassDef.klass, TRACE_JNI_CALL); NSK_DISPLAY0("Let debuggee to finish\n"); if (!nsk_jvmti_resumeSync()) diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t002/bi01t002.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t002/bi01t002.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t002/bi01t002.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" @@ -51,21 +52,18 @@ Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t002_setNewByteCode(JNIEnv *jni_env, jobject o, jint ind, jbyteArray byteCode) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jbyte* elements; jboolean isCopy; - newClassSize[ind] = jni_env->GetArrayLength(byteCode); - if (!NSK_JNI_VERIFY(jni_env, newClassSize[ind] > 0)) { + newClassSize[ind] = ec_jni->GetArrayLength(byteCode, TRACE_JNI_CALL); + if (!NSK_VERIFY(newClassSize[ind] > 0)) { nsk_jvmti_setFailStatus(); return NSK_FALSE; } NSK_DISPLAY1("\t... got array size: %d\n", newClassSize[ind]); - elements = jni_env->GetByteArrayElements(byteCode, &isCopy); - if (!NSK_JNI_VERIFY(jni_env, elements != NULL)) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } + elements = ec_jni->GetByteArrayElements(byteCode, &isCopy, TRACE_JNI_CALL); NSK_DISPLAY1("\t... got elements list: 0x%p\n", (void*)elements); if (!NSK_JVMTI_VERIFY(jvmti->Allocate(newClassSize[ind], &newClassBytes[ind]))) { @@ -82,7 +80,7 @@ NSK_DISPLAY1("\t... copied bytecode: %d bytes\n", (int)newClassSize[ind]); NSK_DISPLAY1("\t... release elements list: 0x%p\n", (void*)elements); - NSK_TRACE(jni_env->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT)); + NSK_TRACE(ec_jni->ReleaseByteArrayElements(byteCode, elements, JNI_ABORT, TRACE_JNI_CALL)); NSK_DISPLAY0("\t... released\n"); return NSK_TRUE; } @@ -97,10 +95,8 @@ Java_nsk_jvmti_scenarios_bcinstr_BI01_bi01t002_setClass(JNIEnv *jni_env, jobject o, jint ind, jclass cls) { - oldClassDef[ind].klass = (jclass) jni_env->NewGlobalRef(cls); - if (!NSK_JNI_VERIFY(jni_env, oldClassDef[ind].klass != NULL)) { - nsk_jvmti_setFailStatus(); - } + ExceptionCheckingJniEnvPtr ec_jni(jni_env); + oldClassDef[ind].klass = (jclass) ec_jni->NewGlobalRef(cls, TRACE_JNI_CALL); } /* ============================================================================= */ diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t002/libbi01t002.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t002/libbi01t002.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI01/bi01t002/libbi01t002.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/bi04t002.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/bi04t002.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/bi04t002.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" @@ -91,23 +92,15 @@ static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { + ExceptionCheckingJniEnvPtr ec_jni(jni); /*Wait for debuggee to set classes to be redefined nsk_jvmti_waitForSync#4*/ NSK_DISPLAY0("Wait for debuggee to set classes to be redefined nsk_jvmti_waitForSync#4\n"); if (!nsk_jvmti_waitForSync(timeout)) return; NSK_DISPLAY1("Find class: %s\n", TESTED_CLASS_NAME); - classDef.klass = jni->FindClass(TESTED_CLASS_NAME); - if (!NSK_JNI_VERIFY(jni, classDef.klass != NULL)) { - nsk_jvmti_setFailStatus(); - return; - } - - classDef.klass = (jclass) jni->NewGlobalRef(classDef.klass); - if (!NSK_JNI_VERIFY(jni, classDef.klass != NULL)) { - nsk_jvmti_setFailStatus(); - return; - } + classDef.klass = ec_jni->FindClass(TESTED_CLASS_NAME, TRACE_JNI_CALL); + classDef.klass = (jclass) ec_jni->NewGlobalRef(classDef.klass, TRACE_JNI_CALL); NSK_DISPLAY0("Redfine class with new byte code\n"); NSK_DISPLAY3("class definition:\n\t0x%p, 0x%p:%d\n", @@ -123,7 +116,7 @@ return; } - jni->DeleteGlobalRef(classDef.klass); + ec_jni->DeleteGlobalRef(classDef.klass, TRACE_JNI_CALL); if (!nsk_jvmti_resumeSync()) return; diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/libbi04t002.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/libbi04t002.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/bcinstr/BI04/bi04t002/libbi04t002.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t001/em01t001.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t001/em01t001.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t001/em01t001.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" #include "JVMTITools.h" @@ -135,17 +136,13 @@ void threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass classObject; char *className; char *generic; jvmtiPhase phase; - - classObject = jni_env->GetObjectClass(thread); - if (!NSK_JNI_VERIFY(jni_env, classObject != NULL)) { - nsk_jvmti_setFailStatus(); - return; - } + classObject = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL); if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) { nsk_jvmti_setFailStatus(); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t001/libem01t001.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t001/libem01t001.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t001/libem01t001.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t002/em01t002.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t002/em01t002.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t002/em01t002.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" #include "JVMTITools.h" @@ -61,28 +62,16 @@ JNIEXPORT jclass JNICALL Java_nsk_jvmti_scenarios_events_EM01_em01t002_loadClass(JNIEnv *jni_env, jobject o, jobject loader, jstring className) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass klass; jmethodID methodID; jclass loadedClass; - klass = jni_env->GetObjectClass(loader); - if (!NSK_JNI_VERIFY(jni_env, klass != NULL)) { - nsk_jvmti_setFailStatus(); - return NULL; - } - - methodID = jni_env->GetMethodID( - klass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); - if (!NSK_JNI_VERIFY(jni_env, methodID != NULL)) { - nsk_jvmti_setFailStatus(); - return NULL; - } - - loadedClass = (jclass) jni_env->CallObjectMethod(loader, methodID, className); - if (!NSK_JNI_VERIFY(jni_env, loadedClass != NULL)) { - nsk_jvmti_setFailStatus(); - return NULL; - } + klass = ec_jni->GetObjectClass(loader, TRACE_JNI_CALL); + methodID = ec_jni->GetMethodID( + klass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;", TRACE_JNI_CALL); + loadedClass = (jclass) ec_jni->CallObjectMethod(loader, methodID, + TRACE_JNI_CALL_VARARGS(className)); return loadedClass; } @@ -93,16 +82,12 @@ * Signature: (Ljava/lang/Class;)Z */ JNIEXPORT jboolean JNICALL -Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv *jni_env, +Java_nsk_jvmti_scenarios_events_EM01_em01t002_prepareClass(JNIEnv *jni, jobject o, jclass klass) { + ExceptionCheckingJniEnvPtr ec_jni(jni); jfieldID fieldID; - fieldID = jni_env->GetStaticFieldID(klass, "toProvokePreparation", "I"); - if (!NSK_JNI_VERIFY(jni_env, fieldID != NULL)) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } - + fieldID = ec_jni->GetStaticFieldID(klass, "toProvokePreparation", "I", TRACE_JNI_CALL); return NSK_TRUE; } @@ -114,26 +99,13 @@ JNIEXPORT jboolean JNICALL Java_nsk_jvmti_scenarios_events_EM01_em01t002_startThread(JNIEnv *jni_env, jobject o, jobject thread) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass klass; jmethodID methodID; - klass = jni_env->GetObjectClass(thread); - if (!NSK_JNI_VERIFY(jni_env, klass != NULL)) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } - - methodID = jni_env->GetMethodID(klass, "start", "()V"); - if (!NSK_JNI_VERIFY(jni_env, methodID != NULL)) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } - - if (!NSK_JNI_VERIFY_VOID(jni_env,jni_env->CallVoidMethod(thread, methodID))) { - nsk_jvmti_setFailStatus(); - return NSK_FALSE; - } - + klass = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL); + methodID = ec_jni->GetMethodID(klass, "start", "()V", TRACE_JNI_CALL); + ec_jni->CallVoidMethod(thread, methodID, TRACE_JNI_CALL); return NSK_TRUE; } @@ -224,17 +196,14 @@ void threadEventHandler(jvmtiEvent event, jvmtiEnv* jvmti_env, JNIEnv* jni_env, jthread thread) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jclass classObject; char *className; char *generic; jvmtiPhase phase; - classObject = jni_env->GetObjectClass(thread); - if (!NSK_JNI_VERIFY(jni_env, classObject != NULL)) { - nsk_jvmti_setFailStatus(); - return; - } + classObject = ec_jni->GetObjectClass(thread, TRACE_JNI_CALL); if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classObject, &className, &generic))) { nsk_jvmti_setFailStatus(); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t002/libem01t002.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t002/libem01t002.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM01/em01t002/libem01t002.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t001/em02t001.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t001/em02t001.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t001/em02t001.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" #include "JVMTITools.h" @@ -102,24 +103,20 @@ getStaticObjField(const char* className, const char* objFieldName, const char* signature) { + ExceptionCheckingJniEnvPtr ec_jni(jni); jfieldID fieldID; jclass klass = NULL; - klass = jni->FindClass(className); - if (!NSK_JNI_VERIFY(jni, klass != NULL)) - return NULL; - - fieldID = jni->GetStaticFieldID(klass, objFieldName, signature); - if (!NSK_JNI_VERIFY(jni, fieldID != NULL)) - return NULL; - - return jni->GetStaticObjectField(klass, fieldID); + klass = ec_jni->FindClass(className, TRACE_JNI_CALL); + fieldID = ec_jni->GetStaticFieldID(klass, objFieldName, signature, TRACE_JNI_CALL); + return ec_jni->GetStaticObjectField(klass, fieldID, TRACE_JNI_CALL); } /* ============================================================================= */ static int prepare() { + ExceptionCheckingJniEnvPtr ec_jni(jni); mainThread = findThread(MAIN_THREAD_NAME); if (!NSK_VERIFY(mainThread != NULL)) { NSK_COMPLAIN1("<%s> thread not found\n", MAIN_THREAD_NAME); @@ -127,29 +124,20 @@ } /* make thread accessable for a long time */ - mainThread = jni->NewGlobalRef(mainThread); - if (!NSK_JNI_VERIFY(jni, mainThread != NULL)) - return NSK_FALSE; - + mainThread = ec_jni->NewGlobalRef(mainThread, TRACE_JNI_CALL); startObject = getStaticObjField(DEBUGEE_CLASS_NAME, START_FIELD_NAME, OBJECT_FIELD_SIG); if (!NSK_VERIFY(startObject != NULL)) return NSK_FALSE; /*make object accessable for a long time*/ - startObject = jni->NewGlobalRef(startObject); - if (!NSK_JNI_VERIFY(jni, startObject != NULL)) - return NSK_FALSE; - + startObject = ec_jni->NewGlobalRef(startObject, TRACE_JNI_CALL); endObject = getStaticObjField(DEBUGEE_CLASS_NAME, END_FIELD_NAME, OBJECT_FIELD_SIG); if (!NSK_VERIFY(endObject != NULL)) return NSK_FALSE; /*make object accessable for a long time*/ - endObject = jni->NewGlobalRef(endObject); - if (!NSK_JNI_VERIFY(jni, endObject != NULL)) - return NSK_FALSE; - + endObject = ec_jni->NewGlobalRef(endObject, TRACE_JNI_CALL); debuggeeThread = (jthread) getStaticObjField(DEBUGEE_CLASS_NAME, THREAD_FIELD_NAME, @@ -158,10 +146,7 @@ return NSK_FALSE; /* make thread accessable for a long time */ - debuggeeThread = jni->NewGlobalRef(debuggeeThread); - if (!NSK_JNI_VERIFY(jni, debuggeeThread != NULL)) - return NSK_FALSE; - + debuggeeThread = ec_jni->NewGlobalRef(debuggeeThread, TRACE_JNI_CALL); return NSK_TRUE; } @@ -170,6 +155,7 @@ static int clean() { + ExceptionCheckingJniEnvPtr ec_jni(jni); /* disable MonitorContendedEnter event */ if (!NSK_JVMTI_VERIFY( jvmti->SetEventNotificationMode( @@ -177,10 +163,10 @@ nsk_jvmti_setFailStatus(); /* dispose global references */ - jni->DeleteGlobalRef(startObject); - jni->DeleteGlobalRef(endObject); - jni->DeleteGlobalRef(debuggeeThread); - jni->DeleteGlobalRef(mainThread); + ec_jni->DeleteGlobalRef(startObject, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(endObject, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(debuggeeThread, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(mainThread, TRACE_JNI_CALL); startObject = NULL; endObject = NULL; @@ -409,18 +395,19 @@ handlerMC1(jvmtiEvent event, jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread, jobject object, jthread expectedThread, jobject expectedObject) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); if (expectedThread == NULL || expectedObject == NULL) return; /* check if event is for tested thread and for tested object */ - if (jni_env->IsSameObject(expectedThread, thread) && - jni_env->IsSameObject(expectedObject, object)) { + if (ec_jni->IsSameObject(expectedThread, thread, TRACE_JNI_CALL) && + ec_jni->IsSameObject(expectedObject, object, TRACE_JNI_CALL)) { NSK_DISPLAY1("--->%-40s is received\n", TranslateEvent(event)); showThreadInfo(thread); - if (jni_env->IsSameObject(expectedObject, endObject)) + if (ec_jni->IsSameObject(expectedObject, endObject, TRACE_JNI_CALL)) NSK_DISPLAY0("\tobject: 'endingMonitor'\n"); else NSK_DISPLAY0("\tobject: 'startingMonitor'\n"); @@ -495,18 +482,19 @@ handlerMC2(jvmtiEvent event, jvmtiEnv* jvmti, JNIEnv* jni_env, jthread thread, jobject object, jthread expectedThread, jobject expectedObject) { + ExceptionCheckingJniEnvPtr ec_jni(jni_env); if (expectedThread == NULL || expectedObject == NULL) return; /* check if event is for tested thread and for tested object */ - if (jni_env->IsSameObject(expectedThread, thread) && - jni_env->IsSameObject(expectedObject, object)) { + if (ec_jni->IsSameObject(expectedThread, thread, TRACE_JNI_CALL) && + ec_jni->IsSameObject(expectedObject, object, TRACE_JNI_CALL)) { NSK_DISPLAY1("--->%-40s is received (new callbacks)\n", TranslateEvent(event)); showThreadInfo(thread); - if (jni_env->IsSameObject(expectedObject, endObject)) + if (ec_jni->IsSameObject(expectedObject, endObject, TRACE_JNI_CALL)) NSK_DISPLAY0("\tobject: 'endingMonitor'\n"); else NSK_DISPLAY0("\tobject: 'startingMonitor'\n"); diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t001/libem02t001.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t001/libem02t001.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t001/libem02t001.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t010/em02t010.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t010/em02t010.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t010/em02t010.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" #include "JVMTITools.h" @@ -451,6 +452,7 @@ static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { + ExceptionCheckingJniEnvPtr ec_jni(agentJNI); int i; jfieldID field_accID, field_modID; jclass cls; @@ -459,17 +461,9 @@ if (!nsk_jvmti_waitForSync(timeout)) return; - cls = agentJNI->FindClass(CLASS_NAME); - if (!NSK_JNI_VERIFY(agentJNI, cls != NULL)) - return; - - field_accID = agentJNI->GetStaticFieldID(cls, FIELD_ACC_NAME, "I"); - if (!NSK_JNI_VERIFY(agentJNI, field_accID != NULL)) - return; - - field_modID = agentJNI->GetStaticFieldID(cls, FIELD_MOD_NAME, "I"); - if (!NSK_JNI_VERIFY(agentJNI, field_modID != NULL)) - return; + cls = ec_jni->FindClass(CLASS_NAME, TRACE_JNI_CALL); + field_accID = ec_jni->GetStaticFieldID(cls, FIELD_ACC_NAME, "I", TRACE_JNI_CALL); + field_modID = ec_jni->GetStaticFieldID(cls, FIELD_MOD_NAME, "I", TRACE_JNI_CALL); if (!NSK_JVMTI_VERIFY(jvmti->SetFieldModificationWatch(cls, field_modID))) return; diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t010/libem02t010.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t010/libem02t010.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t010/libem02t010.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t011/em02t011.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t011/em02t011.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t011/em02t011.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" #include "JVMTITools.h" @@ -436,6 +437,7 @@ static void JNICALL agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) { + ExceptionCheckingJniEnvPtr ec_jni(agentJNI); int i; jmethodID methodID; jclass cls; @@ -444,13 +446,8 @@ if (!nsk_jvmti_waitForSync(timeout)) return; - cls = agentJNI->FindClass(CLASS_NAME); - if (!NSK_JNI_VERIFY(agentJNI, cls != NULL)) - return; - - methodID = agentJNI->GetStaticMethodID(cls, METHOD_NAME, "()I"); - if (!NSK_JNI_VERIFY(agentJNI, methodID != NULL)) - return; + cls = ec_jni->FindClass(CLASS_NAME, TRACE_JNI_CALL); + methodID = ec_jni->GetStaticMethodID(cls, METHOD_NAME, "()I", TRACE_JNI_CALL); if (!NSK_JVMTI_VERIFY(jvmti->SetBreakpoint(methodID, 0))) return; diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t011/libem02t011.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t011/libem02t011.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t011/libem02t011.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t012/em02t012.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t012/em02t012.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t012/em02t012.cpp Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -24,6 +24,7 @@ #include <string.h> #include "jvmti.h" #include "agent_common.h" +#include "ExceptionCheckingJniEnv.hpp" #include "jni_tools.h" #include "jvmti_tools.h" #include "JVMTITools.h" @@ -48,12 +49,11 @@ /* ============================================================================= */ JNIEXPORT void JNICALL -Java_nsk_jvmti_scenarios_events_EM02_em02t012_setThread(JNIEnv *jni_env, +Java_nsk_jvmti_scenarios_events_EM02_em02t012_setThread(JNIEnv *jni, jobject o, jthread thrd) { - + ExceptionCheckingJniEnvPtr ec_jni(jni); /* make thread accessable for a long time */ - testedThread = jni_env->NewGlobalRef(thrd); - NSK_JNI_VERIFY(jni_env, testedThread != NULL); + testedThread = ec_jni->NewGlobalRef(thrd, TRACE_JNI_CALL); } static void diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t012/libem02t012.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t012/libem02t012.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/events/EM02/em02t012/libem02t012.cpp Tue May 07 17:30:14 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 @@ -21,6 +21,7 @@ * questions. */ +#include "ExceptionCheckingJniEnv.cpp" #include "native_thread.cpp" #include "nsk_tools.cpp" #include "jni_tools.cpp" diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001/exceptionjni001.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001/exceptionjni001.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ExceptionCheckingJniEnv/exceptionjni001/exceptionjni001.cpp Tue May 07 17:30:14 2019 -0400 @@ -79,69 +79,69 @@ } static bool checkSuccess(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); is_error_called = false; - jni->GetFieldID(cls, "anInteger", "I", TRACE_JNI_CALL); + ec_jni->GetFieldID(cls, "anInteger", "I", TRACE_JNI_CALL); return !is_error_called; } static bool checkFailureMessageReturnNull(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); expected_message_start = null_return_expected_message_start; expected_line_number = __LINE__ + 1; - jni->GetFieldID(cls, "whatever", "does not matter", TRACE_JNI_CALL); + ec_jni->GetFieldID(cls, "whatever", "does not matter", TRACE_JNI_CALL); return is_error_called && error_message_ok; } static bool checkFailureMessageEmptyFile(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); expected_message_start = null_file_expected_message_start; expected_line_number = __LINE__ + 1; - jni->GetFieldID(cls, "whatever", "does not matter", __LINE__, NULL); + ec_jni->GetFieldID(cls, "whatever", "does not matter", __LINE__, NULL); return is_error_called && error_message_ok; } static bool checkFailureMessageNilLine(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); expected_message_start = null_return_expected_message_start; expected_line_number = 0; - jni->GetFieldID(cls, "whatever", "does not matter", 0, __FILE__); + ec_jni->GetFieldID(cls, "whatever", "does not matter", 0, __FILE__); return is_error_called && error_message_ok; } static bool checkFailureMessageNegativeLine(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); expected_message_start = null_return_expected_message_start; expected_line_number = -1; - jni->GetFieldID(cls, "whatever", "does not matter", -1, __FILE__); + ec_jni->GetFieldID(cls, "whatever", "does not matter", -1, __FILE__); return is_error_called && error_message_ok; } static bool checkFailureMessageMinLine(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); expected_message_start = null_return_expected_message_start; expected_line_number = INT32_MIN; - jni->GetFieldID(cls, "whatever", "does not matter", INT32_MIN, __FILE__); + ec_jni->GetFieldID(cls, "whatever", "does not matter", INT32_MIN, __FILE__); return is_error_called && error_message_ok; } static bool checkFailureMessageMaxLine(JNIEnv* env, jclass cls) { - ExceptionCheckingJniEnvPtr jni(env, ErrorCheckerMessage); + ExceptionCheckingJniEnvPtr ec_jni(env, ErrorCheckerMessage); expected_message_start = null_return_expected_message_start; expected_line_number = INT32_MAX; - jni->GetFieldID(cls, "whatever", "does not matter", INT32_MAX, __FILE__); + ec_jni->GetFieldID(cls, "whatever", "does not matter", INT32_MAX, __FILE__); return is_error_called && error_message_ok; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jboolean JNICALL Java_nsk_share_gc_lock_jni_BooleanArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jbooleanArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jbooleanArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jbooleanArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jboolean*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jboolean*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = JNI_FALSE; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -36,7 +36,7 @@ */ JNIEXPORT jbyte JNICALL Java_nsk_share_gc_lock_jni_ByteArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jbyteArray arr; @@ -45,18 +45,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jbyteArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jbyteArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jbyte*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jbyte*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -64,11 +64,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_CharArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jcharArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jcharArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jcharArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); current_time = 0; enterTime /= 1000; while (current_time - start_time < enterTime) { - pa = (jchar*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jchar*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jdouble JNICALL Java_nsk_share_gc_lock_jni_DoubleArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jdoubleArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jdoubleArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jdoubleArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jdouble*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jdouble*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash += pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jfloat JNICALL Java_nsk_share_gc_lock_jni_FloatArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jfloatArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jfloatArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jfloatArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jfloat*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jfloat*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash += pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jint JNICALL Java_nsk_share_gc_lock_jni_IntArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jintArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jintArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jintArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jint*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jint*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jlong JNICALL Java_nsk_share_gc_lock_jni_LongArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jlongArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jlongArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jlongArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jlong*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jlong*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jshort JNICALL Java_nsk_share_gc_lock_jni_ShortArrayCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jshortArray arr; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - arr = (jshortArray) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + arr = (jshortArray) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetArrayLength(arr, TRACE_JNI_CALL); + size = ec_jni->GetArrayLength(arr, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = (jshort*) jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); + pa = (jshort*) ec_jni->GetPrimitiveArrayCritical(arr, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = 0; } mssleep((long) sleepTime); - jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); + ec_jni->ReleasePrimitiveArrayCritical(arr, pa, 0, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, arr, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,7 +37,7 @@ */ JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_StringCriticalLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jsize size, i; jstring str; @@ -46,18 +46,18 @@ time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - str = (jstring) jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + str = (jstring) ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); - size = jni->GetStringLength(str, TRACE_JNI_CALL); + size = ec_jni->GetStringLength(str, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - pa = jni->GetStringCritical(str, NULL, TRACE_JNI_CALL); + pa = ec_jni->GetStringCritical(str, NULL, TRACE_JNI_CALL); if (pa != NULL) { for (i = 0; i < size; ++i) hash ^= pa[i]; @@ -65,11 +65,11 @@ hash = JNI_FALSE; } mssleep((long) sleepTime); - jni->ReleaseStringCritical(str, pa, TRACE_JNI_CALL); + ec_jni->ReleaseStringCritical(str, pa, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, str, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, str, TRACE_JNI_CALL); return hash; } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -38,29 +38,29 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIGlobalRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jobject obj; jobject gref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + obj = ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = jni->NewGlobalRef(obj, TRACE_JNI_CALL); + gref = ec_jni->NewGlobalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - jni->DeleteGlobalRef(gref, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(gref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,29 +37,29 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNILocalRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jobject obj; jobject gref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + obj = ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = jni->NewLocalRef(obj, TRACE_JNI_CALL); + gref = ec_jni->NewLocalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - jni->DeleteLocalRef(gref, TRACE_JNI_CALL); + ec_jni->DeleteLocalRef(gref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,35 +37,35 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jobject obj; jobject gref, lref, gwref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + obj = ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = jni->NewGlobalRef(obj, TRACE_JNI_CALL); - lref = jni->NewLocalRef(obj, TRACE_JNI_CALL); - gwref = jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL); + gref = ec_jni->NewGlobalRef(obj, TRACE_JNI_CALL); + lref = ec_jni->NewLocalRef(obj, TRACE_JNI_CALL); + gwref = ec_jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - jni->DeleteGlobalRef(gref, TRACE_JNI_CALL); - jni->DeleteLocalRef(lref, TRACE_JNI_CALL); - jni->DeleteWeakGlobalRef(gwref, TRACE_JNI_CALL); + ec_jni->DeleteGlobalRef(gref, TRACE_JNI_CALL); + ec_jni->DeleteLocalRef(lref, TRACE_JNI_CALL); + ec_jni->DeleteWeakGlobalRef(gwref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.cpp Tue May 07 17:30:14 2019 -0400 @@ -37,30 +37,30 @@ */ JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIWeakGlobalRefLocker_criticalNative (JNIEnv *jni_env, jobject o, jlong enterTime, jlong sleepTime) { - ExceptionCheckingJniEnvPtr jni(jni_env); + ExceptionCheckingJniEnvPtr ec_jni(jni_env); jobject obj; jobject gref; time_t start_time, current_time; if (objFieldId == NULL) { - jclass klass = jni->GetObjectClass(o, TRACE_JNI_CALL); - objFieldId = jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); + jclass klass = ec_jni->GetObjectClass(o, TRACE_JNI_CALL); + objFieldId = ec_jni->GetFieldID(klass, "obj", "Ljava/lang/Object;", TRACE_JNI_CALL); } - obj = jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); - jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); + obj = ec_jni->GetObjectField(o, objFieldId, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, NULL, TRACE_JNI_CALL); start_time = time(NULL); enterTime /= 1000; current_time = 0; while (current_time - start_time < enterTime) { - gref = jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL); + gref = ec_jni->NewWeakGlobalRef(obj, TRACE_JNI_CALL); mssleep((long) sleepTime); - jni->DeleteWeakGlobalRef(gref, TRACE_JNI_CALL); + ec_jni->DeleteWeakGlobalRef(gref, TRACE_JNI_CALL); mssleep((long) sleepTime); current_time = time(NULL); } - jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); + ec_jni->SetObjectField(o, objFieldId, obj, TRACE_JNI_CALL); } } diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp Tue May 07 17:30:14 2019 -0400 @@ -426,6 +426,17 @@ return marker.ResultNotNull(_jni_env->GetMethodID(klass, name, sig)); } +jmethodID ExceptionCheckingJniEnv::GetStaticMethodID(jclass klass, const char* name, const char* sig, + int line, const char* file_name) { + JNIVerifier<jmethodID> marker(this, "GetStaticMethodID", klass, name, sig, line, file_name); + return marker.ResultNotNull(_jni_env->GetStaticMethodID(klass, name, sig)); +} + +jboolean ExceptionCheckingJniEnv::IsSameObject(jobject ref1, jobject ref2, int line, const char* file_name) { + JNIVerifier<> marker(this, "IsSameObject", ref1, ref2, line, file_name); + return _jni_env->IsSameObject(ref1, ref2); +} + jobject ExceptionCheckingJniEnv::NewObject(jclass klass, jmethodID methodID, int line, const char* file_name, ...) { // In the case of NewObject, we miss the extra arguments passed to NewObject sadly. @@ -437,3 +448,24 @@ va_end(args); return result; } + +jobject ExceptionCheckingJniEnv::CallObjectMethod(jobject obj, jmethodID methodID, int line, + const char* file_name, ...) { + JNIVerifier<> marker(this, "CallObjectMethod", obj, methodID, line, file_name); + + va_list args; + va_start(args, file_name); + jobject result = _jni_env->CallObjectMethodV(obj, methodID, args); + va_end(args); + return result; +} + +void ExceptionCheckingJniEnv::CallVoidMethod(jobject obj, jmethodID methodID, int line, + const char* file_name, ...) { + JNIVerifier<> marker(this, "CallVoidMethod", obj, methodID, line, file_name); + + va_list args; + va_start(args, file_name); + _jni_env->CallVoidMethodV(obj, methodID, args); + va_end(args); +} diff -r bf3d37105ef9 -r 51709d9aab69 test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp Fri May 03 14:59:32 2019 -0400 +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.hpp Tue May 07 17:30:14 2019 -0400 @@ -59,6 +59,7 @@ */ #define TRACE_JNI_CALL __LINE__, __FILE__ +#define TRACE_JNI_CALL_VARARGS(...) __LINE__, __FILE__, __VA_ARGS__ class ExceptionCheckingJniEnv { public: @@ -69,6 +70,8 @@ int line, const char* file_name); jfieldID GetFieldID(jclass klass, const char* name, const char* type, int line, const char* file_name); + jmethodID GetStaticMethodID(jclass klass, const char* name, const char* sig, + int line, const char* file_name); jmethodID GetMethodID(jclass klass, const char* name, const char* sig, int line, const char* file_name); @@ -106,6 +109,14 @@ jweak NewWeakGlobalRef(jobject obj, int line, const char* file_name); void DeleteWeakGlobalRef(jweak obj, int line, const char* file_name); + jboolean IsSameObject(jobject ref1, jobject ref2, int line, + const char* file_name); + + jobject CallObjectMethod(jobject obj, jmethodID methodID, int line, + const char* file_name, ...); + void CallVoidMethod(jobject obj, jmethodID methodID, int line, + const char* file_name, ...); + // ExceptionCheckingJniEnv methods. JNIEnv* GetJNIEnv() { return _jni_env; diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/lang/String/LiteralReplace.java --- a/test/jdk/java/lang/String/LiteralReplace.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/java/lang/String/LiteralReplace.java Tue May 07 17:30:14 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 @@ -22,7 +22,7 @@ */ /* @test - * @bug 8058779 8054307 + * @bug 8058779 8054307 8222955 * @library /test/lib * @build jdk.test.lib.RandomFactory * @run testng LiteralReplace @@ -79,6 +79,10 @@ source.replace(target, replacement); } + @Test(expectedExceptions = {OutOfMemoryError.class}) + public void testOOM() { + "1".repeat(65537).replace("1", "2".repeat(65537)); + } @DataProvider public static Object[][] sourceTargetReplacementExpected() { @@ -104,6 +108,14 @@ {"abcdefgh", "[a-h]", "X", "abcdefgh"}, {"aa+", "a+", "", "a"}, {"^abc$", "abc", "x", "^x$"}, + {"abc", "b", "_", "a_c"}, + {"abc", "bc", "_", "a_"}, + {"abc".repeat(65537) + "end", "b", "_XYZ_", "a_XYZ_c".repeat(65537) + "end"}, + {"abc".repeat(65537) + "end", "a", "_", "_bc".repeat(65537) + "end"}, + {"a".repeat(65537), "a", "", ""}, + {"ab".repeat(65537), "a", "", "b".repeat(65537)}, + {"ab".repeat(65537), "ab", "", ""}, + {"b" + "ab".repeat(65537), "ab", "", "b"}, // more with non-latin1 characters {"\u4e00\u4e00\u4e00", @@ -207,6 +219,42 @@ "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05", "", ""}, + + {"\u4e01\u4e02\u4e03", "\u4e02", "\u4e02", "\u4e01\u4e02\u4e03"}, + {"\u4e01\u4e02\u4e03", "\u4e02", "\u4e04", "\u4e01\u4e04\u4e03"}, + {"\u4e01\u4e02\u4e03", "\u4e02", "_", "\u4e01_\u4e03"}, + {"a\u4e02c", "\u4e02", "_", "a_c"}, + {"\u4e01@\u4e03", "@", "_", "\u4e01_\u4e03"}, + {"\u4e01@\u4e03", "@", "\u4e02", "\u4e01\u4e02\u4e03"}, + {"\u4e01\u4e02\u4e03", "\u4e02\u4e03", "\u4e02\u4e03", "\u4e01\u4e02\u4e03"}, + {"\u4e01\u4e02\u4e03", "\u4e02\u4e03", "\u4e04\u4e05", "\u4e01\u4e04\u4e05"}, + {"\u4e01\u4e02\u4e03", "\u4e02\u4e03", "\u4e06", "\u4e01\u4e06"}, + {"\u4e01\u4e02\u4e03", "\u4e02\u4e03", "<>", "\u4e01<>"}, + {"@\u4e02\u4e03", "\u4e02\u4e03", "<>", "@<>"}, + {"\u4e01@@", "\u4e01@", "", "@"}, + {"\u4e01@@", "\u4e01@", "#", "#@"}, + {"\u4e01@@", "\u4e01@", "\u4e09", "\u4e09@"}, + {"\u4e01@@", "\u4e01@", "#\u4e09", "#\u4e09@"}, + {"\u4e01\u4e02\u4e03".repeat(32771) + "end", "\u4e02", "\u4e02", "\u4e01\u4e02\u4e03".repeat(32771) + "end"}, + {"\u4e01\u4e02\u4e03".repeat(32771) + "end", "\u4e02", "\u4e04", "\u4e01\u4e04\u4e03".repeat(32771) + "end"}, + {"\u4e01\u4e02\u4e03".repeat(32771) + "end", "\u4e02", "\u4e04\u4e05", "\u4e01\u4e04\u4e05\u4e03".repeat(32771) + "end"}, + {"\u4e01\u4e02\u4e03".repeat(32771) + "end", "\u4e02", "_", "\u4e01_\u4e03".repeat(32771) + "end"}, + {"\u4e01_\u4e03".repeat(32771) + "end", "_", "_", "\u4e01_\u4e03".repeat(32771) + "end"}, + {"\u4e01_\u4e03".repeat(32771) + "end", "_", "\u4e06", "\u4e01\u4e06\u4e03".repeat(32771) + "end"}, + {"\u4e01_\u4e03".repeat(32771) + "end", "_", "\u4e06\u4e06", "\u4e01\u4e06\u4e06\u4e03".repeat(32771) + "end"}, + {"X_Y".repeat(32771) + "end", "_", "\u4e07", "X\u4e07Y".repeat(32771) + "end"}, + {"X_Y".repeat(32771) + "end", "_", "\u4e07\u4e08", "X\u4e07\u4e08Y".repeat(32771) + "end"}, + {"X_Y".repeat(32771) + "end", "_", ".\u4e08.", "X.\u4e08.Y".repeat(32771) + "end"}, + {"\u4e0a".repeat(32771), "\u4e0a", "", ""}, + {"\u4e0a\u4e0b".repeat(32771), "\u4e0a", "", "\u4e0b".repeat(32771)}, + {"\u4e0a\u4e0b".repeat(32771), "\u4e0b", "", "\u4e0a".repeat(32771)}, + {"\u4e0a\u4e0b".repeat(32771), "\u4e0a\u4e0b", "", ""}, + {"\u4e0b" + "\u4e0a\u4e0b".repeat(32771), "\u4e0a\u4e0b", "", "\u4e0b"}, + {"\u4e0a\u4e0b".repeat(32771) + "\u4e0a", "\u4e0a\u4e0b", "", "\u4e0a"}, + {"\u4e0b" + "\u4e0a\u4e0b".repeat(32771) + "\u4e0a", "\u4e0a\u4e0b", "", "\u4e0b\u4e0a"}, + {"b" + "\u4e0a\u4e0b".repeat(32771), "\u4e0a\u4e0b", "", "b"}, + {"\u4e0a\u4e0b".repeat(32771) + "a", "\u4e0a\u4e0b", "", "a"}, + {"b" + "\u4e0a\u4e0b".repeat(32771) + "a", "\u4e0a\u4e0b", "", "ba"}, }; } diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/lang/constant/ClassDescTest.java --- a/test/jdk/java/lang/constant/ClassDescTest.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/java/lang/constant/ClassDescTest.java Tue May 07 17:30:14 2019 -0400 @@ -306,4 +306,28 @@ assertEquals(s.resolveConstantDesc(LOOKUP), s); assertEquals(s.describeConstable().get(), s); } + + public void testNullNestedClasses() { + ClassDesc cd = ClassDesc.of("Bar"); + try { + cd.nested(null); + fail(""); + } catch (NullPointerException e) { + // good + } + + try { + cd.nested("good", null); + fail(""); + } catch (NullPointerException e) { + // good + } + + try { + cd.nested("good", "goodToo", null); + fail(""); + } catch (NullPointerException e) { + // good + } + } } diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/net/ServerSocket/AcceptInheritHandle.java --- a/test/jdk/java/net/ServerSocket/AcceptInheritHandle.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/java/net/ServerSocket/AcceptInheritHandle.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 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 @@ -32,6 +32,7 @@ import java.net.*; import java.nio.channels.ServerSocketChannel; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -41,8 +42,8 @@ enum ServerSocketProducer { JAVA_NET(() -> { try { - return new ServerSocket(); } - catch(IOException x) { + return new ServerSocket(); + } catch(IOException x) { throw new UncheckedIOException(x); } }), @@ -86,13 +87,13 @@ test(ServerSocketProducer.NIO_CHANNELS); } - static void test(ServerSocketProducer ssp, String... sysProps) throws Exception { + static void test(ServerSocketProducer ssp, String... jvmArgs) throws Exception { System.out.println("\nStarting test for " + ssp.name()); List<String> commands = new ArrayList<>(); commands.add(JAVA); - for (String prop : sysProps) - commands.add(prop); + for (String arg : jvmArgs) + commands.add(arg); commands.add("-cp"); commands.add(CLASSPATH); commands.add("AcceptInheritHandle"); @@ -107,7 +108,14 @@ int port = dis.readInt(); System.out.println("Server process listening on " + port + ", connecting..."); - Socket socket = new Socket("localhost", port); + String address; + if (Arrays.stream(jvmArgs).anyMatch("-Djava.net.preferIPv4Stack=true"::equals)) { + address = "127.0.0.1"; + } else { + InetAddress loopback = InetAddress.getLoopbackAddress(); + address = loopback.getHostAddress(); + } + Socket socket = new Socket(address, port); String s = dis.readUTF(); System.out.println("Server process said " + s); @@ -128,7 +136,8 @@ static void server(ServerSocketProducer producer) throws Exception { try (ServerSocket ss = producer.supplier().get()) { - ss.bind(new InetSocketAddress(0)); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ss.bind(new InetSocketAddress(loopback, 0)); int port = ss.getLocalPort(); DataOutputStream dos = new DataOutputStream(System.out); dos.writeInt(port); diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/net/ServerSocket/NullConstructor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/net/ServerSocket/NullConstructor.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,42 @@ +/* + * 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 8223457 + * @run main NullConstructor + * @summary java.net.ServerSocket protected constructor should throw NPE if impl null + */ + +import java.net.ServerSocket; +import java.net.SocketImpl; + +public class NullConstructor { + + public static void main(String args[]) throws Exception { + try { + ServerSocket server = new ServerSocket((SocketImpl)null) {}; + throw new RuntimeException("Test failed"); + } catch (NullPointerException ee) {} + } +} diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/net/URLConnection/Responses.java --- a/test/jdk/java/net/URLConnection/Responses.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/java/net/URLConnection/Responses.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -60,7 +60,9 @@ public HttpServer() { try { - ss = new ServerSocket(0); + InetAddress loopback = InetAddress.getLoopbackAddress(); + ss = new ServerSocket(); + ss.bind(new InetSocketAddress(loopback, 0)); } catch (IOException ioe) { throw new Error("Unable to create ServerSocket: " + ioe); } @@ -70,6 +72,16 @@ return ss.getLocalPort(); } + public String authority() { + InetAddress address = ss.getInetAddress(); + String hostaddr = address.isAnyLocalAddress() + ? "localhost" : address.getHostAddress(); + if (hostaddr.indexOf(':') > -1) { + hostaddr = "[" + hostaddr + "]"; + } + return hostaddr + ":" + port(); + } + public void shutdown() throws IOException { ss.close(); } @@ -116,7 +128,8 @@ HttpServer svr = new HttpServer(); (new Thread(svr)).start(); - int port = svr.port(); + String authority = svr.authority(); + System.out.println("Server listening on: " + authority); /* * Iterate through each test case and check that getResponseCode @@ -129,7 +142,7 @@ System.out.println("******************"); System.out.println("Test with response: >" + tests[i][0] + "<"); - URL url = new URL("http://localhost:" + port + "/" + i); + URL url = new URL("http://" + authority + "/" + i); HttpURLConnection http = (HttpURLConnection)url.openConnection(); try { diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/net/ipv6tests/TcpTest.java --- a/test/jdk/java/net/ipv6tests/TcpTest.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/java/net/ipv6tests/TcpTest.java Tue May 07 17:30:14 2019 -0400 @@ -25,7 +25,9 @@ * @test * @bug 4868820 * @key intermittent - * @summary IPv6 support for Windows XP and 2003 server + * @summary IPv6 support for Windows XP and 2003 server. This test requires + * binding to the wildcard address, and as such is susceptible + * of intermittent failures caused by port reuse policy. * @library /test/lib * @build jdk.test.lib.NetworkConfiguration * jdk.test.lib.Platform @@ -216,4 +218,3 @@ System.out.println ("Test4: OK"); } } - diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java --- a/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/java/util/TimeZone/CLDRDisplayNamesTest.java Tue May 07 17:30:14 2019 -0400 @@ -23,7 +23,7 @@ /* * @test - * @bug 8005471 8008577 8129881 8130845 8136518 8181157 8210490 + * @bug 8005471 8008577 8129881 8130845 8136518 8181157 8210490 8220037 * @modules jdk.localedata * @run main/othervm -Djava.locale.providers=CLDR CLDRDisplayNamesTest * @summary Make sure that localized time zone names of CLDR are used @@ -130,13 +130,10 @@ System.err.printf("Wrong display name for timezone Etc/GMT-5 : expected GMT+05:00, Actual " + displayName); errors++; } - if (errors > 0) { - throw new RuntimeException("test failed"); - } // 8217366: No "no inheritance marker" should be left in the returned array // from DateFormatSymbols.getZoneStrings() - List.of(Locale.ROOT, + errors += List.of(Locale.ROOT, Locale.CHINA, Locale.GERMANY, Locale.JAPAN, @@ -149,11 +146,26 @@ .flatMap(zoneStrings -> Arrays.stream(zoneStrings)) .filter(namesArray -> Arrays.stream(namesArray) .anyMatch(aName -> aName.equals(NO_INHERITANCE_MARKER))) - .findAny() - .ifPresentOrElse(marker -> { - throw new RuntimeException("No inheritance marker detected with tzid: " + .peek(marker -> { + System.err.println("No-inheritance-marker is detected with tzid: " + marker[0]); - }, - () -> System.out.println("Success: No \"no inheritance marker\" detected.")); + }) + .count(); + + // 8220037: Make sure CLDRConverter uniquely produces bundles, regardless of the + // source file enumeration order. + tz = TimeZone.getTimeZone("America/Argentina/La_Rioja"); + if (!"ARST".equals(tz.getDisplayName(true, TimeZone.SHORT, + new Locale.Builder() + .setLanguage("en") + .setRegion("CA") + .build()))) { + System.err.println("Short display name of \"" + tz.getID() + "\" was not \"ARST\""); + errors++; + } + + if (errors > 0) { + throw new RuntimeException("test failed"); + } } } diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/java/util/regex/NegativeArraySize.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/util/regex/NegativeArraySize.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,42 @@ +/* + * 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 8223174 + * @summary Pattern.compile() can throw confusing NegativeArraySizeException + * @requires os.maxMemory >= 5g + * @run main/othervm NegativeArraySize -Xms5G -Xmx5G + */ + +import java.util.regex.Pattern; + +public class NegativeArraySize { + public static void main(String[] args) { + try { + Pattern.compile("\\Q" + "a".repeat(42 + Integer.MAX_VALUE / 3)); + throw new AssertionError("expected to throw"); + } catch (OutOfMemoryError expected) { + } + } +} diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java --- a/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/jdk/jfr/event/gc/collection/TestG1ParallelPhases.java Tue May 07 17:30:14 2019 -0400 @@ -100,7 +100,6 @@ "CMRefRoots", "WaitForStrongCLD", "WeakCLDRoots", - "SATBFiltering", "UpdateRS", "ScanHCC", "ScanRS", diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java --- a/test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/jdk/modules/etc/JdkQualifiedExportTest.java Tue May 07 17:30:14 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 @@ -71,6 +71,9 @@ static Set<String> KNOWN_EXCEPTIONS = Set.of("jdk.internal.vm.ci/jdk.vm.ci.services", "jdk.internal.vm.ci/jdk.vm.ci.runtime", + "jdk.internal.vm.ci/jdk.vm.ci.hotspot", + "jdk.internal.vm.ci/jdk.vm.ci.meta", + "jdk.internal.vm.ci/jdk.vm.ci.code", "jdk.jsobject/jdk.internal.netscape.javascript.spi"); static void checkExports(ModuleDescriptor md) { diff -r bf3d37105ef9 -r 51709d9aab69 test/jdk/sun/net/ftp/FtpURL.java --- a/test/jdk/sun/net/ftp/FtpURL.java Fri May 03 14:59:32 2019 -0400 +++ b/test/jdk/sun/net/ftp/FtpURL.java Tue May 07 17:30:14 2019 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, 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 @@ -36,8 +36,8 @@ */ private class FtpServer extends Thread { - private ServerSocket server; - private int port; + private final ServerSocket server; + private final int port; private boolean done = false; private boolean portEnabled = true; private boolean pasvEnabled = true; @@ -253,8 +253,12 @@ continue; } try { - if (pasv == null) - pasv = new ServerSocket(0); + if (pasv == null) { + // Not sure how to support PASV mode over + // IPv6 + pasv = new ServerSocket(); + pasv.bind(new InetSocketAddress("127.0.0.1", 0)); + } int port = pasv.getLocalPort(); out.println("227 Entering Passive Mode (127,0,0,1," + (port >> 8) + "," + (port & 0xff) +")"); @@ -369,21 +373,39 @@ } public FtpServer(int port) { + this(InetAddress.getLoopbackAddress(), port); + } + + public FtpServer(InetAddress address, int port) { this.port = port; try { - server = new ServerSocket(port); + if (address == null) { + server = new ServerSocket(port); + } else { + server = new ServerSocket(); + server.bind(new InetSocketAddress(address, port)); + } } catch (IOException e) { + throw new UncheckedIOException(e); } } public FtpServer() { - this(21); + this(null, 21); } public int getPort() { - if (server != null) - return server.getLocalPort(); - return 0; + return server.getLocalPort(); + } + + public String getAuthority() { + InetAddress address = server.getInetAddress(); + String hostaddr = address.isAnyLocalAddress() + ? "localhost" : address.getHostAddress(); + if (hostaddr.indexOf(':') > -1) { + hostaddr = "[" + hostaddr +"]"; + } + return hostaddr + ":" + getPort(); } /** @@ -449,15 +471,17 @@ } public FtpURL() throws Exception { - FtpServer server = new FtpServer(0); + FtpServer server = new FtpServer(InetAddress.getLoopbackAddress(), 0); BufferedReader in = null; try { server.start(); - int port = server.getPort(); + String authority = server.getAuthority(); + System.out.println("FTP server waiting for connections at: " + authority); + assert authority != null; // Now let's check the URL handler - URL url = new URL("ftp://user:password@localhost:" + port + "/%2Fetc/motd;type=a"); + URL url = new URL("ftp://user:password@" + authority + "/%2Fetc/motd;type=a"); URLConnection con = url.openConnection(); in = new BufferedReader(new InputStreamReader(con.getInputStream())); String s; @@ -479,11 +503,10 @@ // We're done! // Second URL test - port = server.getPort(); // Now let's check the URL handler - url = new URL("ftp://user2@localhost:" + port + "/%2Fusr/bin;type=d"); + url = new URL("ftp://user2@" + authority + "/%2Fusr/bin;type=d"); con = url.openConnection(); in = new BufferedReader(new InputStreamReader(con.getInputStream())); do { diff -r bf3d37105ef9 -r 51709d9aab69 test/lib/sun/hotspot/WhiteBox.java --- a/test/lib/sun/hotspot/WhiteBox.java Fri May 03 14:59:32 2019 -0400 +++ b/test/lib/sun/hotspot/WhiteBox.java Tue May 07 17:30:14 2019 -0400 @@ -330,6 +330,7 @@ return enqueueInitializerForCompilation0(aClass, compLevel); } private native void clearMethodState0(Executable method); + public native void markMethodProfiled(Executable method); public void clearMethodState(Executable method) { Objects.requireNonNull(method); clearMethodState0(method); diff -r bf3d37105ef9 -r 51709d9aab69 test/micro/org/openjdk/bench/java/lang/StringReplace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/micro/org/openjdk/bench/java/lang/StringReplace.java Tue May 07 17:30:14 2019 -0400 @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package org.openjdk.bench.java.lang; + +import org.openjdk.jmh.annotations.*; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Benchmark) +public class StringReplace { + + public String slat1 = new String("java.lang.String"); + public String sutf16 = new String("\u1D36\u1D43\u1D5B\u1D43 \uFF11\uFF13"); + + @Benchmark + public String replace0x1_1_Latin1() { + return slat1.replace("Z", "z"); + } + + @Benchmark + public String replace1x1_0_Latin1() { + return slat1.replace("g", ""); + } + + @Benchmark + public String replace1x1_1_Latin1() { + return slat1.replace("g", "k"); + } + + @Benchmark + public String replace1x1_2_Latin1() { + return slat1.replace("g", "th"); + } + + @Benchmark + public String replace2x1_0_Latin1() { + return slat1.replace(".", ""); + } + + @Benchmark + public String replace2x1_1_Latin1() { + return slat1.replace(".", "/"); + } + + @Benchmark + public String replace2x1_2_Latin1() { + return slat1.replace(".", "::"); + } + + @Benchmark + public String replace0x1_1_UTF16() { + return sutf16.replace("\u1D36", "\u1D38\u1D3A"); + } + + @Benchmark + public String replace1x1_0_UTF16() { + return sutf16.replace("\uFF11", ""); + } + + @Benchmark + public String replace1x1_1_UTF16() { + return sutf16.replace("\u1D36", "\u24BF"); + } + + @Benchmark + public String replace1x1_2_UTF16() { + return sutf16.replace("\uFF11", "\uFF11\uFF12"); + } + + @Benchmark + public String replace2x1_0_UTF16() { + return sutf16.replace("\u1D43", ""); + } + + @Benchmark + public String replace2x1_1_UTF16() { + return sutf16.replace("\u1D43", "\u1D2C"); + } + + @Benchmark + public String replace2x1_2_UTF16() { + return sutf16.replace("\u1D43", "\u21DB\u21DB"); + } +}