# HG changeset patch # User amurillo # Date 1436507176 25200 # Node ID 75c6dcc9351dd438f4e9428af7361de8dd9b94b1 # Parent 9b3a9d72f07b40c648de79961679f42283af1bb5# Parent 6bf7a358ca179ec5ce1e937bdfb206414b6a92fb Merge diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/code/CodeCache.java Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,13 @@ Type type = db.lookupType("CodeCache"); // Get array of CodeHeaps + // Note: CodeHeap may be subclassed with optional private heap mechanisms. + Type codeHeapType = db.lookupType("CodeHeap"); + VirtualBaseConstructor heapConstructor = + new VirtualBaseConstructor(db, codeHeapType, "sun.jvm.hotspot.memory", CodeHeap.class); + AddressField heapsField = type.getAddressField("_heaps"); - heapArray = GrowableArray.create(heapsField.getValue(), new StaticBaseConstructor(CodeHeap.class)); + heapArray = GrowableArray.create(heapsField.getValue(), heapConstructor); scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods"); @@ -180,31 +185,9 @@ public void iterate(CodeCacheVisitor visitor) { visitor.prologue(lowBound(), highBound()); - CodeBlob lastBlob = null; - for (int i = 0; i < heapArray.length(); ++i) { CodeHeap current_heap = heapArray.at(i); - Address ptr = current_heap.begin(); - while (ptr != null && ptr.lessThan(current_heap.end())) { - try { - // Use findStart to get a pointer inside blob other findBlob asserts - CodeBlob blob = findBlobUnsafe(current_heap.findStart(ptr)); - if (blob != null) { - visitor.visit(blob); - if (blob == lastBlob) { - throw new InternalError("saw same blob twice"); - } - lastBlob = blob; - } - } catch (RuntimeException e) { - e.printStackTrace(); - } - Address next = current_heap.nextBlock(ptr); - if (next != null && next.lessThan(ptr)) { - throw new InternalError("pointer moved backwards"); - } - ptr = next; - } + current_heap.iterate(visitor, this); } visitor.epilogue(); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CodeHeap.java --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CodeHeap.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CodeHeap.java Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package sun.jvm.hotspot.memory; import java.util.*; +import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; @@ -90,7 +91,7 @@ return h.getAllocatedSpace(); } - public Address nextBlock(Address ptr) { + private Address nextBlock(Address ptr) { Address base = blockBase(ptr); if (base == null) { return null; @@ -99,6 +100,31 @@ return base.addOffsetTo(block.getLength() * (1 << getLog2SegmentSize())); } + public void iterate(CodeCacheVisitor visitor, CodeCache cache) { + CodeBlob lastBlob = null; + Address ptr = begin(); + while (ptr != null && ptr.lessThan(end())) { + try { + // Use findStart to get a pointer inside blob other findBlob asserts + CodeBlob blob = cache.createCodeBlobWrapper(findStart(ptr)); + if (blob != null) { + visitor.visit(blob); + if (blob == lastBlob) { + throw new InternalError("saw same blob twice"); + } + lastBlob = blob; + } + } catch (RuntimeException e) { + e.printStackTrace(); + } + Address next = nextBlock(ptr); + if (next != null && next.lessThan(ptr)) { + throw new InternalError("pointer moved backwards"); + } + ptr = next; + } + } + //-------------------------------------------------------------------------------- // Internals only below this point // diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Symbol.java diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/aix/makefiles/mapfile-vers-debug --- a/hotspot/make/aix/makefiles/mapfile-vers-debug Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/aix/makefiles/mapfile-vers-debug Thu Jul 09 22:46:16 2015 -0700 @@ -141,6 +141,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/aix/makefiles/mapfile-vers-product --- a/hotspot/make/aix/makefiles/mapfile-vers-product Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/aix/makefiles/mapfile-vers-product Thu Jul 09 22:46:16 2015 -0700 @@ -139,6 +139,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug Thu Jul 09 22:46:16 2015 -0700 @@ -139,6 +139,18 @@ _JVM_Halt _JVM_HoldsLock _JVM_IHashCode + _JVM_ImageAttributeOffsets + _JVM_ImageAttributeOffsetsLength + _JVM_ImageClose + _JVM_ImageFindAttributes + _JVM_ImageGetAttributes + _JVM_ImageGetAttributesCount + _JVM_ImageGetDataAddress + _JVM_ImageGetIndexAddress + _JVM_ImageGetStringBytes + _JVM_ImageOpen + _JVM_ImageRead + _JVM_ImageReadCompressed _JVM_InitAgentProperties _JVM_InitProperties _JVM_InternString @@ -188,7 +200,7 @@ _JVM_Yield _JVM_handle_bsd_signal - # miscellaneous functions + # miscellaneous functions _jio_fprintf _jio_printf _jio_snprintf diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/bsd/makefiles/mapfile-vers-darwin-product --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product Thu Jul 09 22:46:16 2015 -0700 @@ -139,6 +139,18 @@ _JVM_Halt _JVM_HoldsLock _JVM_IHashCode + _JVM_ImageAttributeOffsets + _JVM_ImageAttributeOffsetsLength + _JVM_ImageClose + _JVM_ImageFindAttributes + _JVM_ImageGetAttributes + _JVM_ImageGetAttributesCount + _JVM_ImageGetDataAddress + _JVM_ImageGetIndexAddress + _JVM_ImageGetStringBytes + _JVM_ImageOpen + _JVM_ImageRead + _JVM_ImageReadCompressed _JVM_InitAgentProperties _JVM_InitProperties _JVM_InternString diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/bsd/makefiles/mapfile-vers-debug --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug Thu Jul 09 22:46:16 2015 -0700 @@ -141,6 +141,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/bsd/makefiles/mapfile-vers-product --- a/hotspot/make/bsd/makefiles/mapfile-vers-product Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product Thu Jul 09 22:46:16 2015 -0700 @@ -141,6 +141,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/linux/makefiles/buildtree.make --- a/hotspot/make/linux/makefiles/buildtree.make Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/linux/makefiles/buildtree.make Thu Jul 09 22:46:16 2015 -0700 @@ -118,7 +118,8 @@ $(PLATFORM_DIR)/generated/dependencies \ $(PLATFORM_DIR)/generated/adfiles \ $(PLATFORM_DIR)/generated/jvmtifiles \ - $(PLATFORM_DIR)/generated/tracefiles + $(PLATFORM_DIR)/generated/tracefiles \ + $(PLATFORM_DIR)/generated/extensions TARGETS = debug fastdebug optimized product SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/linux/makefiles/mapfile-vers-debug --- a/hotspot/make/linux/makefiles/mapfile-vers-debug Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug Thu Jul 09 22:46:16 2015 -0700 @@ -141,6 +141,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/linux/makefiles/mapfile-vers-product --- a/hotspot/make/linux/makefiles/mapfile-vers-product Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/linux/makefiles/mapfile-vers-product Thu Jul 09 22:46:16 2015 -0700 @@ -141,6 +141,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/linux/makefiles/rules.make --- a/hotspot/make/linux/makefiles/rules.make Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/linux/makefiles/rules.make Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ CC_COMPILE = $(CC) $(CXXFLAGS) $(CFLAGS) CXX_COMPILE = $(CXX) $(CXXFLAGS) $(CFLAGS) -AS.S = $(AS) $(ASFLAGS) +AS.S = $(AS) $(ASFLAGS) COMPILE.CC = $(CC_COMPILE) -c GENASM.CC = $(CC_COMPILE) -S @@ -170,6 +170,12 @@ $(QUIETLY) $(REMOVE_TARGET) $(QUIETLY) $(AS.S) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) +# gcc applies preprocessing if the file extension is .S instead of .s +%.o: %.S + @echo $(LOG_INFO) Preprocessing and assembling $< + $(QUIETLY) $(REMOVE_TARGET) + $(QUIETLY) $(AS.S) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) + %.s: %.cpp @echo $(LOG_INFO) Generating assembly for $< $(QUIETLY) $(GENASM.CXX) -o $@ $< diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/linux/makefiles/vm.make --- a/hotspot/make/linux/makefiles/vm.make Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/linux/makefiles/vm.make Thu Jul 09 22:46:16 2015 -0700 @@ -54,7 +54,7 @@ # Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm # The adfiles directory contains ad_.[ch]pp. # The jvmtifiles directory contains jvmti*.[ch]pp -Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles $(GENERATED)/tracefiles +Src_Dirs_V += $(GENERATED)/adfiles $(GENERATED)/jvmtifiles $(GENERATED)/tracefiles $(GENERATED)/extensions VPATH += $(Src_Dirs_V:%=%:) # set INCLUDES for C preprocessor. @@ -161,6 +161,8 @@ fi) endif +CORE_PATHS+=$(GENERATED)/extensions + COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) COMPILER1_PATHS += $(HS_COMMON_SRC)/share/vm/c1 @@ -207,6 +209,8 @@ Src_Files_EXCLUDE += \*x86_32\* endif +Src_Files_BASE += \*.c \*.cpp \*.s + # Alternate vm.make # This has to be included here to allow changes to the source # directories and excluded files before they are expanded @@ -216,13 +220,13 @@ # Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE. define findsrc $(notdir $(shell find $(1)/. ! -name . -prune \ - -a \( -name \*.c -o -name \*.cpp -o -name \*.s \) \ + -a \( -name DUMMY $(addprefix -o -name ,$(Src_Files_BASE)) \) \ -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \))) endef Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) -Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files)))) +Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files))) $(EXTENDED_JVM_OBJ_FILES)) JVM_OBJ_FILES = $(Obj_Files) @@ -244,10 +248,16 @@ VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT) VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT) VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(VMDEF_PAT) +ifneq ($(VMDEF_PAT_EXT),) + VMDEF_PAT := $(VMDEF_PAT_EXT)|$(VMDEF_PAT) +endif -vm.def: $(Res_Files) $(Obj_Files) +vm.def: $(Res_Files) $(Obj_Files) $(VM_DEF_EXT) $(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \ awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@ +ifneq ($(VM_DEF_EXT),) + cat $(VM_DEF_EXT) >> $@ +endif mapfile_ext: rm -f $@ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/solaris/makefiles/mapfile-vers --- a/hotspot/make/solaris/makefiles/mapfile-vers Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/solaris/makefiles/mapfile-vers Thu Jul 09 22:46:16 2015 -0700 @@ -141,6 +141,18 @@ JVM_Halt; JVM_HoldsLock; JVM_IHashCode; + JVM_ImageAttributeOffsets; + JVM_ImageAttributeOffsetsLength; + JVM_ImageClose; + JVM_ImageFindAttributes; + JVM_ImageGetAttributes; + JVM_ImageGetAttributesCount; + JVM_ImageGetDataAddress; + JVM_ImageGetIndexAddress; + JVM_ImageGetStringBytes; + JVM_ImageOpen; + JVM_ImageRead; + JVM_ImageReadCompressed; JVM_InitAgentProperties; JVM_InitProperties; JVM_InternString; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/make/solaris/makefiles/vm.make --- a/hotspot/make/solaris/makefiles/vm.make Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/make/solaris/makefiles/vm.make Thu Jul 09 22:46:16 2015 -0700 @@ -143,7 +143,7 @@ LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle endif # sparcWorks -LIBS += -lkstat +LIBS += -lkstat -lrt # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -2270,17 +2270,21 @@ } // CRC32 instructions -#define INSN(NAME, sf, sz) \ +#define INSN(NAME, c, sf, sz) \ void NAME(Register Rd, Register Rn, Register Rm) { \ starti; \ - f(sf, 31), f(0b0011010110, 30, 21), f(0b0100, 15, 12), f(sz, 11, 10); \ - rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \ + f(sf, 31), f(0b0011010110, 30, 21), f(0b010, 15, 13), f(c, 12); \ + f(sz, 11, 10), rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \ } - INSN(crc32b, 0, 0b00); - INSN(crc32h, 0, 0b01); - INSN(crc32w, 0, 0b10); - INSN(crc32x, 1, 0b11); + INSN(crc32b, 0, 0, 0b00); + INSN(crc32h, 0, 0, 0b01); + INSN(crc32w, 0, 0, 0b10); + INSN(crc32x, 0, 1, 0b11); + INSN(crc32cb, 1, 0, 0b00); + INSN(crc32ch, 1, 0, 0b01); + INSN(crc32cw, 1, 0, 0b10); + INSN(crc32cx, 1, 1, 0b11); #undef INSN diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/globalDefinitions_aarch64.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,12 +28,6 @@ const int StackAlignmentInBytes = 16; -// Indicates whether the C calling conventions require that -// 32-bit integer argument values are properly extended to 64 bits. -// If set, SharedRuntime::c_calling_convention() must adapt -// signatures accordingly. -const bool CCallingConventionRequiresIntsAsLongs = true; - #define SUPPORTS_NATIVE_CX8 // The maximum B/BL offset range on AArch64 is 128MB. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -2914,6 +2914,65 @@ ornw(crc, zr, crc); } +/** + * @param crc register containing existing CRC (32-bit) + * @param buf register pointing to input byte buffer (byte*) + * @param len register containing number of bytes + * @param table register that will contain address of CRC table + * @param tmp scratch register + */ +void MacroAssembler::kernel_crc32c(Register crc, Register buf, Register len, + Register table0, Register table1, Register table2, Register table3, + Register tmp, Register tmp2, Register tmp3) { + Label L_exit; + Label CRC_by64_loop, CRC_by4_loop, CRC_by1_loop; + + subs(len, len, 64); + br(Assembler::GE, CRC_by64_loop); + adds(len, len, 64-4); + br(Assembler::GE, CRC_by4_loop); + adds(len, len, 4); + br(Assembler::GT, CRC_by1_loop); + b(L_exit); + + BIND(CRC_by4_loop); + ldrw(tmp, Address(post(buf, 4))); + subs(len, len, 4); + crc32cw(crc, crc, tmp); + br(Assembler::GE, CRC_by4_loop); + adds(len, len, 4); + br(Assembler::LE, L_exit); + BIND(CRC_by1_loop); + ldrb(tmp, Address(post(buf, 1))); + subs(len, len, 1); + crc32cb(crc, crc, tmp); + br(Assembler::GT, CRC_by1_loop); + b(L_exit); + + align(CodeEntryAlignment); + BIND(CRC_by64_loop); + subs(len, len, 64); + ldp(tmp, tmp3, Address(post(buf, 16))); + crc32cx(crc, crc, tmp); + crc32cx(crc, crc, tmp3); + ldp(tmp, tmp3, Address(post(buf, 16))); + crc32cx(crc, crc, tmp); + crc32cx(crc, crc, tmp3); + ldp(tmp, tmp3, Address(post(buf, 16))); + crc32cx(crc, crc, tmp); + crc32cx(crc, crc, tmp3); + ldp(tmp, tmp3, Address(post(buf, 16))); + crc32cx(crc, crc, tmp); + crc32cx(crc, crc, tmp3); + br(Assembler::GE, CRC_by64_loop); + adds(len, len, 64-4); + br(Assembler::GE, CRC_by4_loop); + adds(len, len, 4); + br(Assembler::GT, CRC_by1_loop); + BIND(L_exit); + return; +} + SkipIfEqual::SkipIfEqual( MacroAssembler* masm, const bool* flag_addr, bool value) { _masm = masm; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -967,6 +967,10 @@ void kernel_crc32(Register crc, Register buf, Register len, Register table0, Register table1, Register table2, Register table3, Register tmp, Register tmp2, Register tmp3); + // CRC32 code for java.util.zip.CRC32C::updateBytes() instrinsic. + void kernel_crc32c(Register crc, Register buf, Register len, + Register table0, Register table1, Register table2, Register table3, + Register tmp, Register tmp2, Register tmp3); #undef VIRTUAL diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -2359,6 +2359,47 @@ /** * Arguments: * + * Inputs: + * c_rarg0 - int crc + * c_rarg1 - byte* buf + * c_rarg2 - int length + * c_rarg3 - int* table + * + * Ouput: + * rax - int crc result + */ + address generate_updateBytesCRC32C() { + assert(UseCRC32CIntrinsics, "what are we doing here?"); + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C"); + + address start = __ pc(); + + const Register crc = c_rarg0; // crc + const Register buf = c_rarg1; // source java byte array address + const Register len = c_rarg2; // length + const Register table0 = c_rarg3; // crc_table address + const Register table1 = c_rarg4; + const Register table2 = c_rarg5; + const Register table3 = c_rarg6; + const Register tmp3 = c_rarg7; + + BLOCK_COMMENT("Entry:"); + __ enter(); // required for proper stackwalking of RuntimeStub frame + + __ kernel_crc32c(crc, buf, len, + table0, table1, table2, table3, rscratch1, rscratch2, tmp3); + + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(lr); + + return start; + } + + /** + * Arguments: + * * Input: * c_rarg0 - x address * c_rarg1 - x length @@ -2579,6 +2620,10 @@ StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB"); } + if (UseCRC32CIntrinsics) { + StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(); + } + // Safefetch stubs. generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, &StubRoutines::_safefetch32_fault_pc, diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -199,9 +199,12 @@ UseCRC32Intrinsics = true; } - if (UseCRC32CIntrinsics) { - if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) - warning("CRC32C intrinsics are not available on this CPU"); + if (auxv & HWCAP_CRC32) { + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + } else if (UseCRC32CIntrinsics) { + warning("CRC32C is not available on the CPU"); FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); } @@ -214,34 +217,31 @@ FLAG_SET_DEFAULT(UseSHA, false); } - if (!UseSHA) { + if (UseSHA && (auxv & HWCAP_SHA1)) { + if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); + } + } else if (UseSHA1Intrinsics) { + warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); - FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); - FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); - } else { - if (auxv & HWCAP_SHA1) { - if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); - } - } else if (UseSHA1Intrinsics) { - warning("SHA1 instruction is not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); + } + + if (UseSHA && (auxv & HWCAP_SHA2)) { + if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); } - if (auxv & HWCAP_SHA2) { - if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); - } - } else if (UseSHA256Intrinsics) { - warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); - } - if (UseSHA512Intrinsics) { - warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); - } - if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA, false); - } + } else if (UseSHA256Intrinsics) { + warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); + } + + if (UseSHA512Intrinsics) { + warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + } + + if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA, false); } // This machine allows unaligned memory accesses diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp --- a/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/aarch64/vm/vtableStubs_aarch64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -105,7 +105,7 @@ __ flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d", vtable_index, p2i(s->entry_point()), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); @@ -184,7 +184,7 @@ __ flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d", itable_index, p2i(s->entry_point()), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2013 SAP AG. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,6 @@ const int StackAlignmentInBytes = 16; -// Indicates whether the C calling conventions require that -// 32-bit integer argument values are properly extended to 64 bits. -// If set, SharedRuntime::c_calling_convention() must adapt -// signatures accordingly. -const bool CCallingConventionRequiresIntsAsLongs = true; - #define SUPPORTS_NATIVE_CX8 // The PPC CPUs are NOT multiple-copy-atomic. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -465,7 +465,7 @@ bool has_mh = (strstr(adaptername, "/static") == NULL && strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23"; - tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT, + tty->print_cr("MH %s %s=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, adaptername, mh_reg_name, p2i(mh), p2i(entry_sp)); if (Verbose) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -731,23 +731,8 @@ case T_SHORT: case T_INT: // We must cast ints to longs and use full 64 bit stack slots - // here. We do the cast in GraphKit::gen_stub() and just guard - // here against loosing that change. - assert(CCallingConventionRequiresIntsAsLongs, - "argument of type int should be promoted to type long"); - guarantee(i > 0 && sig_bt[i-1] == T_LONG, - "argument of type (bt) should have been promoted to type (T_LONG,bt) for bt in " - "{T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); - // Do not count halves. - regs[i].set_bad(); - --arg; - break; + // here. Thus fall through, handle as long. case T_LONG: - guarantee(sig_bt[i+1] == T_VOID || - sig_bt[i+1] == T_BOOLEAN || sig_bt[i+1] == T_CHAR || - sig_bt[i+1] == T_BYTE || sig_bt[i+1] == T_SHORT || - sig_bt[i+1] == T_INT, - "expecting type (T_LONG,half) or type (T_LONG,bt) with bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); case T_OBJECT: case T_ARRAY: case T_ADDRESS: @@ -1273,7 +1258,7 @@ static void int_move(MacroAssembler*masm, VMRegPair src, VMRegPair dst, Register r_caller_sp, Register r_temp) { - assert(src.first()->is_valid() && src.second() == src.first()->next(), "incoming must be long-int"); + assert(src.first()->is_valid(), "incoming must be int"); assert(dst.first()->is_valid() && dst.second() == dst.first()->next(), "outgoing must be long"); if (src.first()->is_stack()) { @@ -1762,13 +1747,6 @@ // the jni function will expect them. To figure out where they go // we convert the java signature to a C signature by inserting // the hidden arguments as arg[0] and possibly arg[1] (static method) - // - // Additionally, on ppc64 we must convert integers to longs in the C - // signature. We do this in advance in order to have no trouble with - // indexes into the bt-arrays. - // So convert the signature and registers now, and adjust the total number - // of in-arguments accordingly. - int i2l_argcnt = convert_ints_to_longints_argcnt(total_in_args, in_sig_bt); // PPC64: pass ints as longs. // Calculate the total number of C arguments and create arrays for the // signature and the outgoing registers. @@ -1776,7 +1754,7 @@ // some floating-point arguments must be passed in registers _and_ // in stack locations. bool method_is_static = method->is_static(); - int total_c_args = i2l_argcnt; + int total_c_args = total_in_args; if (!is_critical_native) { int n_hidden_args = method_is_static ? 2 : 1; @@ -1785,7 +1763,7 @@ // No JNIEnv*, no this*, but unpacked arrays (base+length). for (int i = 0; i < total_in_args; i++) { if (in_sig_bt[i] == T_ARRAY) { - total_c_args += 2; // PPC64: T_LONG, T_INT, T_ADDRESS (see convert_ints_to_longints and c_calling_convention) + total_c_args++; } } } @@ -1803,8 +1781,6 @@ int argc = 0; if (!is_critical_native) { - convert_ints_to_longints(i2l_argcnt, total_in_args, in_sig_bt, in_regs); // PPC64: pass ints as longs. - out_sig_bt[argc++] = T_ADDRESS; if (method->is_static()) { out_sig_bt[argc++] = T_OBJECT; @@ -1815,7 +1791,7 @@ } } else { Thread* THREAD = Thread::current(); - in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, i2l_argcnt); + in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); SignatureStream ss(method->signature()); int o = 0; for (int i = 0; i < total_in_args ; i++, o++) { @@ -1839,28 +1815,16 @@ } } else { in_elem_bt[o] = T_VOID; - switch(in_sig_bt[i]) { // PPC64: pass ints as longs. - case T_BOOLEAN: - case T_CHAR: - case T_BYTE: - case T_SHORT: - case T_INT: in_elem_bt[++o] = T_VOID; break; - default: break; - } } if (in_sig_bt[i] != T_VOID) { assert(in_sig_bt[i] == ss.type(), "must match"); ss.next(); } } - assert(i2l_argcnt==o, "must match"); - - convert_ints_to_longints(i2l_argcnt, total_in_args, in_sig_bt, in_regs); // PPC64: pass ints as longs. for (int i = 0; i < total_in_args ; i++ ) { if (in_sig_bt[i] == T_ARRAY) { // Arrays are passed as int, elem* pair. - out_sig_bt[argc++] = T_LONG; // PPC64: pass ints as longs. out_sig_bt[argc++] = T_INT; out_sig_bt[argc++] = T_ADDRESS; } else { @@ -1921,7 +1885,8 @@ case T_BYTE: case T_SHORT: case T_CHAR: - case T_INT: /*single_slots++;*/ break; // PPC64: pass ints as longs. + case T_INT: + // Fall through. case T_ARRAY: case T_LONG: double_slots++; break; default: ShouldNotReachHere(); @@ -2019,7 +1984,7 @@ __ save_LR_CR(r_temp_1); __ generate_stack_overflow_check(frame_size_in_bytes); // Check before creating frame. - __ mr(r_callers_sp, R1_SP); // Remember frame pointer. + __ mr(r_callers_sp, R1_SP); // Remember frame pointer. __ push_frame(frame_size_in_bytes, r_temp_1); // Push the c2n adapter's frame. frame_done_pc = (intptr_t)__ pc(); @@ -2098,24 +2063,16 @@ case T_BYTE: case T_SHORT: case T_INT: - guarantee(in > 0 && in_sig_bt[in-1] == T_LONG, - "expecting type (T_LONG,bt) for bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); + // Move int and do sign extension. + int_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); break; case T_LONG: - if (in_sig_bt[in+1] == T_VOID) { - long_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); - } else { - guarantee(in_sig_bt[in+1] == T_BOOLEAN || in_sig_bt[in+1] == T_CHAR || - in_sig_bt[in+1] == T_BYTE || in_sig_bt[in+1] == T_SHORT || - in_sig_bt[in+1] == T_INT, - "expecting type (T_LONG,bt) for bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); - int_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); - } + long_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); break; case T_ARRAY: if (is_critical_native) { int body_arg = out; - out -= 2; // Point to length arg. PPC64: pass ints as longs. + out -= 1; // Point to length arg. unpack_array_argument(masm, in_regs[in], in_elem_bt[in], out_regs[body_arg], out_regs[out], r_callers_sp, r_temp_1, r_temp_2); break; @@ -2187,7 +2144,6 @@ // Make sure that thread is non-volatile; it crosses a bunch of VM calls below. assert(R16_thread->is_nonvolatile(), "thread must be in non-volatile register"); - # if 0 // DTrace method entry # endif diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp --- a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * 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,12 +30,6 @@ const int StackAlignmentInBytes = (2*wordSize); -// Indicates whether the C calling conventions require that -// 32-bit integer argument values are properly extended to 64 bits. -// If set, SharedRuntime::c_calling_convention() must adapt -// signatures accordingly. -const bool CCallingConventionRequiresIntsAsLongs = false; - #define SUPPORTS_NATIVE_CX8 // The expected size in bytes of a cache line, used to pad data structures. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -483,7 +483,7 @@ bool has_mh = (strstr(adaptername, "/static") == NULL && strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH const char* mh_reg_name = has_mh ? "G3_mh" : "G3"; - tty->print_cr("MH %s %s="INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, + tty->print_cr("MH %s %s=" INTPTR_FORMAT " saved_sp=" INTPTR_FORMAT " args=" INTPTR_FORMAT, adaptername, mh_reg_name, p2i(mh), p2i(saved_sp), p2i(args)); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -329,39 +329,35 @@ FLAG_SET_DEFAULT(UseSHA, false); } - if (!UseSHA) { + if (UseSHA && has_sha1()) { + if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); + } + } else if (UseSHA1Intrinsics) { + warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); - FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); - FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); - } else { - if (has_sha1()) { - if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); - } - } else if (UseSHA1Intrinsics) { - warning("SHA1 instruction is not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); + } + + if (UseSHA && has_sha256()) { + if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); } - if (has_sha256()) { - if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); - } - } else if (UseSHA256Intrinsics) { - warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); - } + } else if (UseSHA256Intrinsics) { + warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); + } - if (has_sha512()) { - if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA512Intrinsics, true); - } - } else if (UseSHA512Intrinsics) { - warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + if (UseSHA && has_sha512()) { + if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA512Intrinsics, true); } - if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { - FLAG_SET_DEFAULT(UseSHA, false); - } + } else if (UseSHA512Intrinsics) { + warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); + FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + } + + if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA, false); } // SPARC T4 and above should have support for CRC32C instruction diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -110,7 +110,7 @@ masm->flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d", vtable_index, p2i(s->entry_point()), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); @@ -205,7 +205,7 @@ masm->flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d", itable_index, p2i(s->entry_point()), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp --- a/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/globalDefinitions_x86.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -27,12 +27,6 @@ const int StackAlignmentInBytes = 16; -// Indicates whether the C calling conventions require that -// 32-bit integer argument values are properly extended to 64 bits. -// If set, SharedRuntime::c_calling_convention() must adapt -// signatures accordingly. -const bool CCallingConventionRequiresIntsAsLongs = false; - #define SUPPORTS_NATIVE_CX8 // The expected size in bytes of a cache line, used to pad data structures. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -5152,7 +5152,7 @@ { ResourceMark rm; stringStream ss; - ss.print("DelayedValue="INTPTR_FORMAT, delayed_value_addr[1]); + ss.print("DelayedValue=" INTPTR_FORMAT, delayed_value_addr[1]); buf = code_string(ss.as_string()); } jcc(Assembler::notZero, L); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/methodHandles_x86.cpp --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -484,7 +484,7 @@ bool has_mh = (strstr(adaptername, "/static") == NULL && strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx"; - tty->print_cr("MH %s %s="PTR_FORMAT" sp="PTR_FORMAT, + tty->print_cr("MH %s %s=" PTR_FORMAT " sp=" PTR_FORMAT, adaptername, mh_reg_name, (void *)mh, entry_sp); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -23,6 +23,9 @@ */ #include "precompiled.hpp" +#ifndef _WINDOWS +#include "alloca.h" +#endif #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/debugInfoRec.hpp" @@ -3511,6 +3514,250 @@ } +//------------------------------Montgomery multiplication------------------------ +// + +#ifndef _WINDOWS + +#define ASM_SUBTRACT + +#ifdef ASM_SUBTRACT +// Subtract 0:b from carry:a. Return carry. +static unsigned long +sub(unsigned long a[], unsigned long b[], unsigned long carry, long len) { + long i = 0, cnt = len; + unsigned long tmp; + asm volatile("clc; " + "0: ; " + "mov (%[b], %[i], 8), %[tmp]; " + "sbb %[tmp], (%[a], %[i], 8); " + "inc %[i]; dec %[cnt]; " + "jne 0b; " + "mov %[carry], %[tmp]; sbb $0, %[tmp]; " + : [i]"+r"(i), [cnt]"+r"(cnt), [tmp]"=&r"(tmp) + : [a]"r"(a), [b]"r"(b), [carry]"r"(carry) + : "memory"); + return tmp; +} +#else // ASM_SUBTRACT +typedef int __attribute__((mode(TI))) int128; + +// Subtract 0:b from carry:a. Return carry. +static unsigned long +sub(unsigned long a[], unsigned long b[], unsigned long carry, int len) { + int128 tmp = 0; + int i; + for (i = 0; i < len; i++) { + tmp += a[i]; + tmp -= b[i]; + a[i] = tmp; + tmp >>= 64; + assert(-1 <= tmp && tmp <= 0, "invariant"); + } + return tmp + carry; +} +#endif // ! ASM_SUBTRACT + +// Multiply (unsigned) Long A by Long B, accumulating the double- +// length result into the accumulator formed of T0, T1, and T2. +#define MACC(A, B, T0, T1, T2) \ +do { \ + unsigned long hi, lo; \ + __asm__ ("mul %5; add %%rax, %2; adc %%rdx, %3; adc $0, %4" \ + : "=&d"(hi), "=a"(lo), "+r"(T0), "+r"(T1), "+g"(T2) \ + : "r"(A), "a"(B) : "cc"); \ + } while(0) + +// As above, but add twice the double-length result into the +// accumulator. +#define MACC2(A, B, T0, T1, T2) \ +do { \ + unsigned long hi, lo; \ + __asm__ ("mul %5; add %%rax, %2; adc %%rdx, %3; adc $0, %4; " \ + "add %%rax, %2; adc %%rdx, %3; adc $0, %4" \ + : "=&d"(hi), "=a"(lo), "+r"(T0), "+r"(T1), "+g"(T2) \ + : "r"(A), "a"(B) : "cc"); \ + } while(0) + +// Fast Montgomery multiplication. The derivation of the algorithm is +// in A Cryptographic Library for the Motorola DSP56000, +// Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237. + +static void __attribute__((noinline)) +montgomery_multiply(unsigned long a[], unsigned long b[], unsigned long n[], + unsigned long m[], unsigned long inv, int len) { + unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator + int i; + + assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply"); + + for (i = 0; i < len; i++) { + int j; + for (j = 0; j < i; j++) { + MACC(a[j], b[i-j], t0, t1, t2); + MACC(m[j], n[i-j], t0, t1, t2); + } + MACC(a[i], b[0], t0, t1, t2); + m[i] = t0 * inv; + MACC(m[i], n[0], t0, t1, t2); + + assert(t0 == 0, "broken Montgomery multiply"); + + t0 = t1; t1 = t2; t2 = 0; + } + + for (i = len; i < 2*len; i++) { + int j; + for (j = i-len+1; j < len; j++) { + MACC(a[j], b[i-j], t0, t1, t2); + MACC(m[j], n[i-j], t0, t1, t2); + } + m[i-len] = t0; + t0 = t1; t1 = t2; t2 = 0; + } + + while (t0) + t0 = sub(m, n, t0, len); +} + +// Fast Montgomery squaring. This uses asymptotically 25% fewer +// multiplies so it should be up to 25% faster than Montgomery +// multiplication. However, its loop control is more complex and it +// may actually run slower on some machines. + +static void __attribute__((noinline)) +montgomery_square(unsigned long a[], unsigned long n[], + unsigned long m[], unsigned long inv, int len) { + unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator + int i; + + assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply"); + + for (i = 0; i < len; i++) { + int j; + int end = (i+1)/2; + for (j = 0; j < end; j++) { + MACC2(a[j], a[i-j], t0, t1, t2); + MACC(m[j], n[i-j], t0, t1, t2); + } + if ((i & 1) == 0) { + MACC(a[j], a[j], t0, t1, t2); + } + for (; j < i; j++) { + MACC(m[j], n[i-j], t0, t1, t2); + } + m[i] = t0 * inv; + MACC(m[i], n[0], t0, t1, t2); + + assert(t0 == 0, "broken Montgomery square"); + + t0 = t1; t1 = t2; t2 = 0; + } + + for (i = len; i < 2*len; i++) { + int start = i-len+1; + int end = start + (len - start)/2; + int j; + for (j = start; j < end; j++) { + MACC2(a[j], a[i-j], t0, t1, t2); + MACC(m[j], n[i-j], t0, t1, t2); + } + if ((i & 1) == 0) { + MACC(a[j], a[j], t0, t1, t2); + } + for (; j < len; j++) { + MACC(m[j], n[i-j], t0, t1, t2); + } + m[i-len] = t0; + t0 = t1; t1 = t2; t2 = 0; + } + + while (t0) + t0 = sub(m, n, t0, len); +} + +// Swap words in a longword. +static unsigned long swap(unsigned long x) { + return (x << 32) | (x >> 32); +} + +// Copy len longwords from s to d, word-swapping as we go. The +// destination array is reversed. +static void reverse_words(unsigned long *s, unsigned long *d, int len) { + d += len; + while(len-- > 0) { + d--; + *d = swap(*s); + s++; + } +} + +// The threshold at which squaring is advantageous was determined +// experimentally on an i7-3930K (Ivy Bridge) CPU @ 3.5GHz. +#define MONTGOMERY_SQUARING_THRESHOLD 64 + +void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints, + jint len, jlong inv, + jint *m_ints) { + assert(len % 2 == 0, "array length in montgomery_multiply must be even"); + int longwords = len/2; + + // Make very sure we don't use so much space that the stack might + // overflow. 512 jints corresponds to an 16384-bit integer and + // will use here a total of 8k bytes of stack space. + int total_allocation = longwords * sizeof (unsigned long) * 4; + guarantee(total_allocation <= 8192, "must be"); + unsigned long *scratch = (unsigned long *)alloca(total_allocation); + + // Local scratch arrays + unsigned long + *a = scratch + 0 * longwords, + *b = scratch + 1 * longwords, + *n = scratch + 2 * longwords, + *m = scratch + 3 * longwords; + + reverse_words((unsigned long *)a_ints, a, longwords); + reverse_words((unsigned long *)b_ints, b, longwords); + reverse_words((unsigned long *)n_ints, n, longwords); + + ::montgomery_multiply(a, b, n, m, (unsigned long)inv, longwords); + + reverse_words(m, (unsigned long *)m_ints, longwords); +} + +void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints, + jint len, jlong inv, + jint *m_ints) { + assert(len % 2 == 0, "array length in montgomery_square must be even"); + int longwords = len/2; + + // Make very sure we don't use so much space that the stack might + // overflow. 512 jints corresponds to an 16384-bit integer and + // will use here a total of 6k bytes of stack space. + int total_allocation = longwords * sizeof (unsigned long) * 3; + guarantee(total_allocation <= 8192, "must be"); + unsigned long *scratch = (unsigned long *)alloca(total_allocation); + + // Local scratch arrays + unsigned long + *a = scratch + 0 * longwords, + *n = scratch + 1 * longwords, + *m = scratch + 2 * longwords; + + reverse_words((unsigned long *)a_ints, a, longwords); + reverse_words((unsigned long *)n_ints, n, longwords); + + if (len >= MONTGOMERY_SQUARING_THRESHOLD) { + ::montgomery_square(a, n, m, (unsigned long)inv, longwords); + } else { + ::montgomery_multiply(a, a, n, m, (unsigned long)inv, longwords); + } + + reverse_words(m, (unsigned long *)m_ints, longwords); +} + +#endif // WINDOWS + #ifdef COMPILER2 // This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame // diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -4318,7 +4318,18 @@ if (UseMulAddIntrinsic) { StubRoutines::_mulAdd = generate_mulAdd(); } -#endif + +#ifndef _WINDOWS + if (UseMontgomeryMultiplyIntrinsic) { + StubRoutines::_montgomeryMultiply + = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_multiply); + } + if (UseMontgomerySquareIntrinsic) { + StubRoutines::_montgomerySquare + = CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square); + } +#endif // WINDOWS +#endif // COMPILER2 } public: diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/vm_version_x86.cpp --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -692,10 +692,19 @@ warning("SHA instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseSHA, false); } - if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) { - warning("SHA intrinsics are not available on this CPU"); + + if (UseSHA1Intrinsics) { + warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); + } + + if (UseSHA256Intrinsics) { + warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); + } + + if (UseSHA512Intrinsics) { + warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } @@ -813,6 +822,12 @@ if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { UseMulAddIntrinsic = true; } + if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { + UseMontgomeryMultiplyIntrinsic = true; + } + if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + UseMontgomerySquareIntrinsic = true; + } #else if (UseMultiplyToLenIntrinsic) { if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { @@ -820,6 +835,18 @@ } FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false); } + if (UseMontgomeryMultiplyIntrinsic) { + if (!FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { + warning("montgomeryMultiply intrinsic is not available in 32-bit VM"); + } + FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false); + } + if (UseMontgomerySquareIntrinsic) { + if (!FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + warning("montgomerySquare intrinsic is not available in 32-bit VM"); + } + FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false); + } if (UseSquareToLenIntrinsic) { if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { warning("squareToLen intrinsic is not available in 32-bit VM"); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -117,7 +117,7 @@ masm->flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d", vtable_index, p2i(s->entry_point()), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); @@ -198,7 +198,7 @@ masm->flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d", itable_index, p2i(s->entry_point()), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -112,7 +112,7 @@ __ flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d", vtable_index, s->entry_point(), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); @@ -205,7 +205,7 @@ __ flush(); if (PrintMiscellaneous && (WizardMode || Verbose)) { - tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d", + tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d", itable_index, s->entry_point(), (int)(s->code_end() - s->entry_point()), (int)(s->code_end() - __ pc())); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp --- a/hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/cpu/zero/vm/globalDefinitions_zero.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2009 Red Hat, Inc. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2009, 2015, Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,10 +28,4 @@ #include -// Indicates whether the C calling conventions require that -// 32-bit integer argument values are properly extended to 64 bits. -// If set, SharedRuntime::c_calling_convention() must adapt -// signatures accordingly. -const bool CCallingConventionRequiresIntsAsLongs = false; - #endif // CPU_ZERO_VM_GLOBALDEFINITIONS_ZERO_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/bsd/vm/jsig.c --- a/hotspot/src/os/bsd/vm/jsig.c Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os/bsd/vm/jsig.c Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ static struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */ static unsigned int jvmsigs = 0; /* signals used by jvm */ +static __thread bool reentry = false; /* prevent reentry deadlock (per-thread) */ /* used to synchronize the installation of signal handlers */ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; @@ -76,6 +77,8 @@ static sa_handler_t call_os_signal(int sig, sa_handler_t disp, bool is_sigset) { + sa_handler_t res; + if (os_signal == NULL) { if (!is_sigset) { os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); @@ -87,7 +90,10 @@ exit(0); } } - return (*os_signal)(sig, disp); + reentry = true; + res = (*os_signal)(sig, disp); + reentry = false; + return res; } static void save_signal_handler(int sig, sa_handler_t disp) { @@ -161,6 +167,10 @@ bool sigused; struct sigaction oldAct; + if (reentry) { + return call_os_sigaction(sig, act, oact); + } + signal_lock(); sigused = (MASK(sig) & jvmsigs) != 0; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/bsd/vm/os_bsd.cpp --- a/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -59,6 +59,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" +#include "semaphore_bsd.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -1940,47 +1941,54 @@ #define SEM_DESTROY(sem) sem_destroy(&sem) #endif -class Semaphore : public StackObj { - public: - Semaphore(); - ~Semaphore(); - void signal(); - void wait(); - bool trywait(); - bool timedwait(unsigned int sec, int nsec); - private: - jlong currenttime() const; - os_semaphore_t _semaphore; -}; - -Semaphore::Semaphore() : _semaphore(0) { - SEM_INIT(_semaphore, 0); +#ifdef __APPLE__ +// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used. + +static const char* sem_init_strerror(kern_return_t value) { + switch (value) { + case KERN_INVALID_ARGUMENT: return "Invalid argument"; + case KERN_RESOURCE_SHORTAGE: return "Resource shortage"; + default: return "Unknown"; + } } -Semaphore::~Semaphore() { +OSXSemaphore::OSXSemaphore(uint value) { + kern_return_t ret = SEM_INIT(_semaphore, value); + + guarantee(ret == KERN_SUCCESS, err_msg("Failed to create semaphore: %s", sem_init_strerror(ret))); +} + +OSXSemaphore::~OSXSemaphore() { SEM_DESTROY(_semaphore); } -void Semaphore::signal() { - SEM_POST(_semaphore); +void OSXSemaphore::signal(uint count) { + for (uint i = 0; i < count; i++) { + kern_return_t ret = SEM_POST(_semaphore); + + assert(ret == KERN_SUCCESS, "Failed to signal semaphore"); + } } -void Semaphore::wait() { - SEM_WAIT(_semaphore); +void OSXSemaphore::wait() { + kern_return_t ret; + while ((ret = SEM_WAIT(_semaphore)) == KERN_ABORTED) { + // Semaphore was interrupted. Retry. + } + assert(ret == KERN_SUCCESS, "Failed to wait on semaphore"); } -jlong Semaphore::currenttime() const { +jlong OSXSemaphore::currenttime() { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); } -#ifdef __APPLE__ -bool Semaphore::trywait() { +bool OSXSemaphore::trywait() { return timedwait(0, 0); } -bool Semaphore::timedwait(unsigned int sec, int nsec) { +bool OSXSemaphore::timedwait(unsigned int sec, int nsec) { kern_return_t kr = KERN_ABORTED; mach_timespec_t waitspec; waitspec.tv_sec = sec; @@ -2011,33 +2019,24 @@ } #else - -bool Semaphore::trywait() { - return sem_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { +// Use POSIX implementation of semaphores. + +struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) { struct timespec ts; unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); - while (1) { - int result = sem_timedwait(&_semaphore, &ts); - if (result == 0) { - return true; - } else if (errno == EINTR) { - continue; - } else if (errno == ETIMEDOUT) { - return false; - } else { - return false; - } - } + return ts; } #endif // __APPLE__ static os_semaphore_t sig_sem; -static Semaphore sr_semaphore; + +#ifdef __APPLE__ +static OSXSemaphore sr_semaphore; +#else +static PosixSemaphore sr_semaphore; +#endif void os::signal_init_pd() { // Initialize signal structures diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/bsd/vm/semaphore_bsd.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/os/bsd/vm/semaphore_bsd.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_BSD_VM_SEMAPHORE_BSD_HPP +#define OS_BSD_VM_SEMAPHORE_BSD_HPP + +#ifndef __APPLE__ +// Use POSIX semaphores. +# include "semaphore_posix.hpp" + +#else +// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used. +# include "memory/allocation.hpp" +# include + +class OSXSemaphore : public CHeapObj{ + semaphore_t _semaphore; + + // Prevent copying and assignment. + OSXSemaphore(const OSXSemaphore&); + OSXSemaphore& operator=(const OSXSemaphore&); + + public: + OSXSemaphore(uint value = 0); + ~OSXSemaphore(); + + void signal(uint count = 1); + + void wait(); + + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + + private: + static jlong currenttime(); +}; + +typedef OSXSemaphore SemaphoreImpl; + +#endif // __APPLE__ + +#endif // OS_BSD_VM_SEMAPHORE_BSD_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/linux/vm/os_linux.cpp --- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os/linux/vm/os_linux.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -60,6 +60,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" +#include "semaphore_posix.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -2315,40 +2316,7 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } -class Semaphore : public StackObj { - public: - Semaphore(); - ~Semaphore(); - void signal(); - void wait(); - bool trywait(); - bool timedwait(unsigned int sec, int nsec); - private: - sem_t _semaphore; -}; - -Semaphore::Semaphore() { - sem_init(&_semaphore, 0, 0); -} - -Semaphore::~Semaphore() { - sem_destroy(&_semaphore); -} - -void Semaphore::signal() { - sem_post(&_semaphore); -} - -void Semaphore::wait() { - sem_wait(&_semaphore); -} - -bool Semaphore::trywait() { - return sem_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { - +struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) { struct timespec ts; // Semaphore's are always associated with CLOCK_REALTIME os::Linux::clock_gettime(CLOCK_REALTIME, &ts); @@ -2365,18 +2333,7 @@ } } - while (1) { - int result = sem_timedwait(&_semaphore, &ts); - if (result == 0) { - return true; - } else if (errno == EINTR) { - continue; - } else if (errno == ETIMEDOUT) { - return false; - } else { - return false; - } - } + return ts; } extern "C" { @@ -2416,7 +2373,7 @@ // Linux(POSIX) specific hand shaking semaphore. static sem_t sig_sem; -static Semaphore sr_semaphore; +static PosixSemaphore sr_semaphore; void os::signal_init_pd() { // Initialize signal structures diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/posix/vm/os_posix.cpp --- a/hotspot/src/os/posix/vm/os_posix.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os/posix/vm/os_posix.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -24,6 +24,7 @@ #include "utilities/globalDefinitions.hpp" #include "prims/jvm.h" +#include "semaphore_posix.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" @@ -34,6 +35,7 @@ #include #include #include +#include #include PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC @@ -1015,3 +1017,73 @@ } } } + +#define check_with_errno(check_type, cond, msg) \ + do { \ + int err = errno; \ + check_type(cond, err_msg("%s; error='%s' (errno=%d)", msg, strerror(err), err)); \ +} while (false) + +#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) +#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) + +// POSIX unamed semaphores are not supported on OS X. +#ifndef __APPLE__ + +PosixSemaphore::PosixSemaphore(uint value) { + int ret = sem_init(&_semaphore, 0, value); + + guarantee_with_errno(ret == 0, "Failed to initialize semaphore"); +} + +PosixSemaphore::~PosixSemaphore() { + sem_destroy(&_semaphore); +} + +void PosixSemaphore::signal(uint count) { + for (uint i = 0; i < count; i++) { + int ret = sem_post(&_semaphore); + + assert_with_errno(ret == 0, "sem_post failed"); + } +} + +void PosixSemaphore::wait() { + int ret; + + do { + ret = sem_wait(&_semaphore); + } while (ret != 0 && errno == EINTR); + + assert_with_errno(ret == 0, "sem_wait failed"); +} + +bool PosixSemaphore::trywait() { + int ret; + + do { + ret = sem_trywait(&_semaphore); + } while (ret != 0 && errno == EINTR); + + assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed"); + + return ret == 0; +} + +bool PosixSemaphore::timedwait(const struct timespec ts) { + while (true) { + int result = sem_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIMEDOUT) { + return false; + } else { + assert_with_errno(false, "timedwait failed"); + return false; + } + } +} + +#endif // __APPLE__ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/posix/vm/semaphore_posix.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/os/posix/vm/semaphore_posix.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_POSIX_VM_SEMAPHORE_POSIX_HPP +#define OS_POSIX_VM_SEMAPHORE_POSIX_HPP + +#include "memory/allocation.hpp" + +#include + +class PosixSemaphore : public CHeapObj { + sem_t _semaphore; + + // Prevent copying and assignment. + PosixSemaphore(const PosixSemaphore&); + PosixSemaphore& operator=(const PosixSemaphore&); + + public: + PosixSemaphore(uint value = 0); + ~PosixSemaphore(); + + void signal(uint count = 1); + + void wait(); + + bool trywait(); + bool timedwait(unsigned int sec, int nsec) { + return timedwait(create_timespec(sec, nsec)); + } + + private: + bool timedwait(struct timespec ts); + + // OS specific implementation to create a timespec suitable for semaphores. + struct timespec create_timespec(unsigned int set, int nsec); +}; + +typedef PosixSemaphore SemaphoreImpl; + +#endif // OS_POSIX_VM_SEMAPHORE_POSIX_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/solaris/vm/os_solaris.cpp --- a/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -60,6 +60,7 @@ #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" #include "runtime/vm_version.hpp" +#include "semaphore_posix.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -2263,55 +2264,11 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } -class Semaphore : public StackObj { - public: - Semaphore(); - ~Semaphore(); - void signal(); - void wait(); - bool trywait(); - bool timedwait(unsigned int sec, int nsec); - private: - sema_t _semaphore; -}; - - -Semaphore::Semaphore() { - sema_init(&_semaphore, 0, NULL, NULL); -} - -Semaphore::~Semaphore() { - sema_destroy(&_semaphore); -} - -void Semaphore::signal() { - sema_post(&_semaphore); -} - -void Semaphore::wait() { - sema_wait(&_semaphore); -} - -bool Semaphore::trywait() { - return sema_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { +struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) { struct timespec ts; unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); - while (1) { - int result = sema_timedwait(&_semaphore, &ts); - if (result == 0) { - return true; - } else if (errno == EINTR) { - continue; - } else if (errno == ETIME) { - return false; - } else { - return false; - } - } + return ts; } extern "C" { @@ -3711,7 +3668,7 @@ osthread->set_ucontext(context); } -static Semaphore sr_semaphore; +static PosixSemaphore sr_semaphore; void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { // Save and restore errno to avoid confusing native code with EINTR diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/windows/vm/os_windows.cpp --- a/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -63,6 +63,7 @@ #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" #include "runtime/vm_version.hpp" +#include "semaphore_windows.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -1901,6 +1902,30 @@ return (int)error; } +WindowsSemaphore::WindowsSemaphore(uint value) { + _semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL); + + guarantee(_semaphore != NULL, err_msg("CreateSemaphore failed with error code: %lu", GetLastError())); +} + +WindowsSemaphore::~WindowsSemaphore() { + ::CloseHandle(_semaphore); +} + +void WindowsSemaphore::signal(uint count) { + if (count > 0) { + BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL); + + assert(ret != 0, err_msg("ReleaseSemaphore failed with error code: %lu", GetLastError())); + } +} + +void WindowsSemaphore::wait() { + DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE); + assert(ret != WAIT_FAILED, err_msg("WaitForSingleObject failed with error code: %lu", GetLastError())); + assert(ret == WAIT_OBJECT_0, err_msg("WaitForSingleObject failed with return value: %lu", ret)); +} + // sun.misc.Signal // NOTE that this is a workaround for an apparent kernel bug where if // a signal handler for SIGBREAK is installed then that signal handler @@ -5890,7 +5915,7 @@ char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), NULL, false); if (result == NULL) { if (VerboseInternalVMTests) { - gclog_or_tty->print("Failed to allocate control block with size "SIZE_FORMAT". Skipping remainder of test.", + gclog_or_tty->print("Failed to allocate control block with size " SIZE_FORMAT ". Skipping remainder of test.", large_allocation_size); } } else { @@ -5903,7 +5928,7 @@ char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), expected_location, false); if (actual_location == NULL) { if (VerboseInternalVMTests) { - gclog_or_tty->print("Failed to allocate any memory at "PTR_FORMAT" size "SIZE_FORMAT". Skipping remainder of test.", + gclog_or_tty->print("Failed to allocate any memory at " PTR_FORMAT " size " SIZE_FORMAT ". Skipping remainder of test.", expected_location, large_allocation_size); } } else { @@ -5911,7 +5936,7 @@ os::release_memory_special(actual_location, expected_allocation_size); // only now check, after releasing any memory to avoid any leaks. assert(actual_location == expected_location, - err_msg("Failed to allocate memory at requested location "PTR_FORMAT" of size "SIZE_FORMAT", is "PTR_FORMAT" instead", + err_msg("Failed to allocate memory at requested location " PTR_FORMAT " of size " SIZE_FORMAT ", is " PTR_FORMAT " instead", expected_location, expected_allocation_size, actual_location)); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os/windows/vm/semaphore_windows.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/os/windows/vm/semaphore_windows.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP +#define OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP + +#include "memory/allocation.hpp" + +#include + +class WindowsSemaphore : public CHeapObj { + HANDLE _semaphore; + + // Prevent copying and assignment. + WindowsSemaphore(const WindowsSemaphore&); + WindowsSemaphore& operator=(const WindowsSemaphore&); + + public: + WindowsSemaphore(uint value = 0); + ~WindowsSemaphore(); + + void signal(uint count = 1); + + void wait(); +}; + +typedef WindowsSemaphore SemaphoreImpl; + +#endif // OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -191,7 +191,7 @@ return CPUVisitor::visit(nodeh, state); } - PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) { + PICL(bool is_fujitsu, bool is_sun4v) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) { if (!open_library()) { return; } @@ -203,7 +203,7 @@ if (is_fujitsu) { cpu_class = "core"; } - CPUVisitor cpu_visitor(this, os::processor_count()); + CPUVisitor cpu_visitor(this, (is_sun4v && !is_fujitsu) ? 1 : os::processor_count()); _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper); if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value? _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value(); @@ -447,7 +447,7 @@ } // Figure out cache line sizes using PICL - PICL picl((features & sparc64_family_m) != 0); + PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); _L1_data_cache_line_size = picl.L1_data_cache_line_size(); _L2_data_cache_line_size = picl.L2_data_cache_line_size(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/tools/hsdis/Makefile --- a/hotspot/src/share/tools/hsdis/Makefile Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/tools/hsdis/Makefile Thu Jul 09 22:46:16 2015 -0700 @@ -70,7 +70,8 @@ else #linux CPU = $(shell uname -m) ARCH1=$(CPU:x86_64=amd64) -ARCH=$(ARCH1:i686=i386) +ARCH2=$(ARCH1:i686=i386) +ARCH=$(ARCH2:ppc64le=ppc64) ifdef LP64 CFLAGS/sparcv9 += -m64 CFLAGS/amd64 += -m64 diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/asm/codeBuffer.cpp --- a/hotspot/src/share/vm/asm/codeBuffer.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1093,9 +1093,11 @@ void CodeStrings::assign(CodeStrings& other) { other.check_valid(); - // Cannot do following because CodeStrings constructor is not alway run! assert(is_null(), "Cannot assign onto non-empty CodeStrings"); _strings = other._strings; +#ifdef ASSERT + _defunct = false; +#endif other.set_null_and_invalidate(); } @@ -1115,13 +1117,15 @@ } } +const char* CodeStrings::_prefix = " ;; "; // default: can be changed via set_prefix + void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const { check_valid(); if (_strings != NULL) { CodeString* c = find(offset); while (c && c->offset() == offset) { stream->bol(); - stream->print(" ;; "); + stream->print("%s", _prefix); stream->print_cr("%s", c->string()); c = c->next_comment(); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/asm/codeBuffer.hpp --- a/hotspot/src/share/vm/asm/codeBuffer.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/asm/codeBuffer.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,6 +249,7 @@ // Becomes true after copy-out, forbids further use. bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env #endif + static const char* _prefix; // defaults to " ;; " #endif CodeString* find(intptr_t offset) const; @@ -289,13 +290,20 @@ void assign(CodeStrings& other) PRODUCT_RETURN; // COPY strings from other to this; leave other valid. void copy(CodeStrings& other) PRODUCT_RETURN; + // FREE strings; invalidate this. void free() PRODUCT_RETURN; - // Guarantee that _strings are used at most once; assign invalidates a buffer. + // Guarantee that _strings are used at most once; assign and free invalidate a buffer. inline void check_valid() const { #ifdef ASSERT assert(!_defunct, "Use of invalid CodeStrings"); #endif } + + static void set_prefix(const char *prefix) { +#ifndef PRODUCT + _prefix = prefix; +#endif + } }; // A CodeBuffer describes a memory space into which assembly @@ -379,6 +387,7 @@ _oop_recorder = NULL; _decode_begin = NULL; _overflow_arena = NULL; + _code_strings = CodeStrings(); } void initialize(address code_start, csize_t code_size) { @@ -495,6 +504,7 @@ // Properties const char* name() const { return _name; } + void set_name(const char* name) { _name = name; } CodeBuffer* before_expand() const { return _before_expand; } BufferBlob* blob() const { return _blob; } void set_blob(BufferBlob* blob); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/c1/c1_CFGPrinter.cpp --- a/hotspot/src/share/vm/c1/c1_CFGPrinter.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/c1/c1_CFGPrinter.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -161,7 +161,7 @@ print("name \"%s\"", method_name(_compilation->method(), true)); print("method \"%s\"", method_name(_compilation->method())); - print("date "INT64_FORMAT, (int64_t) os::javaTimeMillis()); + print("date " INT64_FORMAT, (int64_t) os::javaTimeMillis()); print_end("compilation"); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -3157,6 +3157,9 @@ // code for the inlined version will be different than the root // compiled version which could lead to monotonicity problems on // intel. + if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) { + BAILOUT("failed to inline intrinsic, method not annotated"); + } // Set up a stream so that appending instructions works properly. ciBytecodeStream s(scope->method()); @@ -3197,6 +3200,9 @@ // result in the referent being marked live and the reference // object removed from the list of discovered references during // reference processing. + if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) { + BAILOUT("failed to inline intrinsic, method not annotated"); + } // Also we need intrinsic to prevent commoning reads from this field // across safepoint since GC can change its value. @@ -3317,7 +3323,8 @@ } // handle intrinsics - if (callee->intrinsic_id() != vmIntrinsics::_none) { + if (callee->intrinsic_id() != vmIntrinsics::_none && + (CheckIntrinsics ? callee->intrinsic_candidate() : true)) { if (try_inline_intrinsics(callee)) { print_inlining(callee, "intrinsic"); return true; @@ -4278,7 +4285,7 @@ assert(result_type->is_int(), "int result"); Values* args = state()->pop_arguments(callee->arg_size()); - // Pop off some args to speically handle, then push back + // Pop off some args to specially handle, then push back Value newval = args->pop(); Value cmpval = args->pop(); Value offset = args->pop(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/c1/c1_Runtime1.cpp --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -33,6 +33,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeBlob.hpp" +#include "code/codeCacheExtensions.hpp" #include "code/compiledIC.hpp" #include "code/pcDesc.hpp" #include "code/scopeDesc.hpp" @@ -183,20 +184,25 @@ // create code buffer for code storage CodeBuffer code(buffer_blob); - Compilation::setup_code_buffer(&code, 0); + OopMapSet* oop_maps; + int frame_size; + bool must_gc_arguments; - // create assembler for code generation - StubAssembler* sasm = new StubAssembler(&code, name_for(id), id); - // generate code for runtime stub - OopMapSet* oop_maps; - oop_maps = generate_code_for(id, sasm); - assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, - "if stub has an oop map it must have a valid frame size"); + if (!CodeCacheExtensions::skip_compiler_support()) { + // bypass useless code generation + Compilation::setup_code_buffer(&code, 0); + + // create assembler for code generation + StubAssembler* sasm = new StubAssembler(&code, name_for(id), id); + // generate code for runtime stub + oop_maps = generate_code_for(id, sasm); + assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, + "if stub has an oop map it must have a valid frame size"); #ifdef ASSERT - // Make sure that stubs that need oopmaps have them - switch (id) { - // These stubs don't need to have an oopmap + // Make sure that stubs that need oopmaps have them + switch (id) { + // These stubs don't need to have an oopmap case dtrace_object_alloc_id: case g1_pre_barrier_slow_id: case g1_post_barrier_slow_id: @@ -209,23 +215,32 @@ #endif break; - // All other stubs should have oopmaps + // All other stubs should have oopmaps default: assert(oop_maps != NULL, "must have an oopmap"); - } + } #endif - // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) - sasm->align(BytesPerWord); - // make sure all code is in code buffer - sasm->flush(); + // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned) + sasm->align(BytesPerWord); + // make sure all code is in code buffer + sasm->flush(); + + frame_size = sasm->frame_size(); + must_gc_arguments = sasm->must_gc_arguments(); + } else { + /* ignored values */ + oop_maps = NULL; + frame_size = 0; + must_gc_arguments = false; + } // create blob - distinguish a few special cases CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id), &code, CodeOffsets::frame_never_safe, - sasm->frame_size(), + frame_size, oop_maps, - sasm->must_gc_arguments()); + must_gc_arguments); // install blob assert(blob != NULL, "blob must exist"); _blobs[id] = blob; @@ -399,7 +414,7 @@ CompLevel level = (CompLevel)nm->comp_level(); int bci = InvocationEntryBci; if (branch_bci != InvocationEntryBci) { - // Compute desination bci + // Compute destination bci address pc = method()->code_base() + branch_bci; Bytecodes::Code branch = Bytecodes::code_at(method(), pc); int offset = 0; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp --- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1185,7 +1185,6 @@ vmIntrinsics::ID iid = method()->intrinsic_id(); if (iid == vmIntrinsics::_getClass || - iid == vmIntrinsics::_fillInStackTrace || iid == vmIntrinsics::_hashCode) return iid; else @@ -1199,10 +1198,6 @@ case vmIntrinsics::_getClass: _return_local = false; break; - case vmIntrinsics::_fillInStackTrace: - arg.set(0); // 'this' - set_returned(arg); - break; case vmIntrinsics::_hashCode: // initialized state is correct break; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/ci/ciMethod.hpp --- a/hotspot/src/share/vm/ci/ciMethod.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/ci/ciMethod.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -178,9 +178,10 @@ // Code size for inlining decisions. int code_size_for_inlining(); - bool caller_sensitive() const { return get_Method()->caller_sensitive(); } - bool force_inline() const { return get_Method()->force_inline(); } - bool dont_inline() const { return get_Method()->dont_inline(); } + bool caller_sensitive() const { return get_Method()->caller_sensitive(); } + bool force_inline() const { return get_Method()->force_inline(); } + bool dont_inline() const { return get_Method()->dont_inline(); } + bool intrinsic_candidate() const { return get_Method()->intrinsic_candidate(); } int comp_level(); int highest_osr_comp_level(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1751,6 +1751,10 @@ if (_location != _in_method) break; // only allow for methods if (!privileged) break; // only allow in privileged code return _method_LambdaForm_Hidden; + case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_HotSpotIntrinsicCandidate_signature): + if (_location != _in_method) break; // only allow for methods + if (!privileged) break; // only allow in privileged code + return _method_HotSpotIntrinsicCandidate; case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature): if (_location != _in_field) break; // only allow for fields if (!privileged) break; // only allow in privileged code @@ -1790,6 +1794,8 @@ m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm); if (has_annotation(_method_LambdaForm_Hidden)) m->set_hidden(true); + if (has_annotation(_method_HotSpotIntrinsicCandidate) && !m->is_synthetic()) + m->set_intrinsic_candidate(true); } void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) { @@ -4132,9 +4138,78 @@ // (We used to do this lazily, but now we query it in Rewriter, // which is eagerly done for every method, so we might as well do it now, // when everything is fresh in memory.) - if (Method::klass_id_for_intrinsics(this_klass()) != vmSymbols::NO_SID) { + vmSymbols::SID klass_id = Method::klass_id_for_intrinsics(this_klass()); + if (klass_id != vmSymbols::NO_SID) { for (int j = 0; j < methods->length(); j++) { - methods->at(j)->init_intrinsic_id(); + Method* method = methods->at(j); + method->init_intrinsic_id(); + + if (CheckIntrinsics) { + // Check if an intrinsic is defined for method 'method', + // but the method is not annotated with @HotSpotIntrinsicCandidate. + if (method->intrinsic_id() != vmIntrinsics::_none && + !method->intrinsic_candidate()) { + tty->print("Compiler intrinsic is defined for method [%s], " + "but the method is not annotated with @HotSpotIntrinsicCandidate.%s", + method->name_and_sig_as_C_string(), + NOT_DEBUG(" Method will not be inlined.") DEBUG_ONLY(" Exiting.") + ); + tty->cr(); + DEBUG_ONLY(vm_exit(1)); + } + // Check is the method 'method' is annotated with @HotSpotIntrinsicCandidate, + // but there is no intrinsic available for it. + if (method->intrinsic_candidate() && + method->intrinsic_id() == vmIntrinsics::_none) { + tty->print("Method [%s] is annotated with @HotSpotIntrinsicCandidate, " + "but no compiler intrinsic is defined for the method.%s", + method->name_and_sig_as_C_string(), + NOT_DEBUG("") DEBUG_ONLY(" Exiting.") + ); + tty->cr(); + DEBUG_ONLY(vm_exit(1)); + } + } + } + + if (CheckIntrinsics) { + // Check for orphan methods in the current class. A method m + // of a class C is orphan if an intrinsic is defined for method m, + // but class C does not declare m. + + for (int id = vmIntrinsics::FIRST_ID; id < (int)vmIntrinsics::ID_LIMIT; id++) { + if (id == vmIntrinsics::_compiledLambdaForm) { + // The _compiledLamdbdaForm intrinsic is a special marker for bytecode + // generated for the JVM from a LambdaForm and therefore no method + // is defined for it. + continue; + } + + if (vmIntrinsics::class_for(vmIntrinsics::ID_from(id)) == klass_id) { + // Check if the current class contains a method with the same + // name, flags, signature. + bool match = false; + for (int j = 0; j < methods->length(); j++) { + Method* method = methods->at(j); + if (id == method->intrinsic_id()) { + match = true; + break; + } + } + + if (!match) { + char buf[1000]; + tty->print("Compiler intrinsic is defined for method [%s], " + "but the method is not available in class [%s].%s", + vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID_from(id), buf, sizeof(buf)), + this_klass->name()->as_C_string(), + NOT_DEBUG("") DEBUG_ONLY(" Exiting.") + ); + tty->cr(); + DEBUG_ONLY(vm_exit(1)); + } + } + } } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/classFileParser.hpp --- a/hotspot/src/share/vm/classfile/classFileParser.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -130,6 +130,7 @@ _method_InjectedProfile, _method_LambdaForm_Compiled, _method_LambdaForm_Hidden, + _method_HotSpotIntrinsicCandidate, _sun_misc_Contended, _field_Stable, _annotation_LIMIT diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/classLoader.cpp --- a/hotspot/src/share/vm/classfile/classLoader.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -68,7 +68,6 @@ #include "classfile/sharedPathsMiscInfo.hpp" #endif - // Entry points in zip.dll for loading zip/jar file entries and image file entries typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg); @@ -157,17 +156,12 @@ } -bool ClassPathEntry::is_lazy() { - return false; -} - ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() { char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass); strcpy(copy, dir); _dir = copy; } - ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) { // construct full path name char path[JVM_MAXPATHLEN]; @@ -278,90 +272,25 @@ } } -LazyClassPathEntry::LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() { - _path = os::strdup_check_oom(path); - _st = *st; - _resolved_entry = NULL; - _has_error = false; - _throw_exception = throw_exception; -} - -LazyClassPathEntry::~LazyClassPathEntry() { - os::free((void*)_path); -} - -bool LazyClassPathEntry::is_jar_file() { - size_t len = strlen(_path); - if (len < 4 || strcmp(_path + len - 4, ".jar") != 0) return false; - return ((_st.st_mode & S_IFREG) == S_IFREG); -} - -ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { - if (_resolved_entry != NULL) { - return (ClassPathEntry*) _resolved_entry; - } - ClassPathEntry* new_entry = NULL; - new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, _throw_exception, CHECK_NULL); - if (!_throw_exception && new_entry == NULL) { - assert(!HAS_PENDING_EXCEPTION, "must be"); - return NULL; - } - { - ThreadCritical tc; - if (_resolved_entry == NULL) { - _resolved_entry = new_entry; - return new_entry; - } - } - assert(_resolved_entry != NULL, "bug in MT-safe resolution logic"); - delete new_entry; - return (ClassPathEntry*) _resolved_entry; -} +ClassPathImageEntry::ClassPathImageEntry(ImageFileReader* image) : + ClassPathEntry(), + _image(image), + _module_data(NULL) { + guarantee(image != NULL, "image file is null"); -ClassFileStream* LazyClassPathEntry::open_stream(const char* name, TRAPS) { - if (_has_error) { - return NULL; - } - ClassPathEntry* cpe = resolve_entry(THREAD); - if (cpe == NULL) { - _has_error = true; - return NULL; - } else { - return cpe->open_stream(name, THREAD); - } -} - -bool LazyClassPathEntry::is_lazy() { - return true; -} - -u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { - if (_has_error) { - return NULL; - } - ClassPathEntry* cpe = resolve_entry(THREAD); - if (cpe == NULL) { - _has_error = true; - return NULL; - } else if (cpe->is_jar_file()) { - return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD); - } else { - ShouldNotReachHere(); - *filesize = 0; - return NULL; - } -} - -ClassPathImageEntry::ClassPathImageEntry(char* name) : ClassPathEntry(), _image(new ImageFile(name)) { - bool opened = _image->open(); - if (!opened) { - _image = NULL; - } + char module_data_name[JVM_MAXPATHLEN]; + ImageModuleData::module_data_name(module_data_name, _image->name()); + _module_data = new ImageModuleData(_image, module_data_name); } ClassPathImageEntry::~ClassPathImageEntry() { - if (_image) { - _image->close(); + if (_module_data != NULL) { + delete _module_data; + _module_data = NULL; + } + + if (_image != NULL) { + ImageFileReader::close(_image); _image = NULL; } } @@ -371,15 +300,39 @@ } ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) { - u1* buffer; - u8 size; - _image->get_resource(name, buffer, size); + ImageLocation location; + bool found = _image->find_location(name, location); + + if (!found) { + const char *pslash = strrchr(name, '/'); + int len = pslash - name; + + // NOTE: IMAGE_MAX_PATH is used here since this path is internal to the jimage + // (effectively unlimited.) There are several JCK tests that use paths over + // 1024 characters long, the limit on Windows systems. + if (pslash && 0 < len && len < IMAGE_MAX_PATH) { - if (buffer) { + char path[IMAGE_MAX_PATH]; + strncpy(path, name, len); + path[len] = '\0'; + const char* moduleName = _module_data->package_to_module(path); + + if (moduleName != NULL && (len + strlen(moduleName) + 2) < IMAGE_MAX_PATH) { + jio_snprintf(path, IMAGE_MAX_PATH - 1, "/%s/%s", moduleName, name); + location.clear_data(); + found = _image->find_location(path, location); + } + } + } + + if (found) { + u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); if (UsePerfData) { ClassLoader::perf_sys_classfile_bytes_read()->inc(size); } - return new ClassFileStream(buffer, (int)size, (char*)name); // Resource allocated + u1* data = NEW_RESOURCE_ARRAY(u1, size); + _image->get_resource(location, data); + return new ClassFileStream(data, (int)size, _image->name()); // Resource allocated } return NULL; @@ -391,20 +344,14 @@ tty->cr(); const ImageStrings strings = _image->get_strings(); // Retrieve each path component string. - u4 count = _image->get_location_count(); - for (u4 i = 0; i < count; i++) { + u4 length = _image->table_length(); + for (u4 i = 0; i < length; i++) { u1* location_data = _image->get_location_data(i); - if (location_data) { + if (location_data != NULL) { ImageLocation location(location_data); - const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); - const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); - const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); - assert((strlen(parent) + strlen(base) + strlen(extension)) < JVM_MAXPATHLEN, "path exceeds buffer"); - char path[JVM_MAXPATHLEN]; - strcpy(path, parent); - strcat(path, base); - strcat(path, extension); + char path[IMAGE_MAX_PATH]; + _image->location_path(location, path, IMAGE_MAX_PATH); ClassLoader::compile_the_world_in(path, loader, CHECK); } } @@ -420,7 +367,7 @@ } bool ClassPathImageEntry::is_jrt() { - return string_ends_with(name(), "bootmodules.jimage"); + return string_ends_with(name(), BOOT_IMAGE_NAME); } #endif @@ -539,11 +486,8 @@ } ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st, - bool lazy, bool throw_exception, TRAPS) { + bool throw_exception, TRAPS) { JavaThread* thread = JavaThread::current(); - if (lazy) { - return new LazyClassPathEntry(path, st, throw_exception); - } ClassPathEntry* new_entry = NULL; if ((st->st_mode & S_IFREG) == S_IFREG) { // Regular file, should be a zip or image file @@ -557,38 +501,38 @@ return NULL; } } - // TODO - add proper criteria for selecting image file - ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path); - if (entry->is_open()) { - new_entry = entry; - } else { - char* error_msg = NULL; - jzfile* zip; - { - // enable call to C land - ThreadToNativeFromVM ttn(thread); - HandleMark hm(thread); - zip = (*ZipOpen)(canonical_path, &error_msg); - } - if (zip != NULL && error_msg == NULL) { - new_entry = new ClassPathZipEntry(zip, path); + ImageFileReader* image = ImageFileReader::open(canonical_path); + if (image != NULL) { + new_entry = new ClassPathImageEntry(image); } else { - ResourceMark rm(thread); - char *msg; - if (error_msg == NULL) { - msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ; - jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path); + char* error_msg = NULL; + jzfile* zip; + { + // enable call to C land + ThreadToNativeFromVM ttn(thread); + HandleMark hm(thread); + zip = (*ZipOpen)(canonical_path, &error_msg); + } + if (zip != NULL && error_msg == NULL) { + new_entry = new ClassPathZipEntry(zip, path); } else { - int len = (int)(strlen(path) + strlen(error_msg) + 128); - msg = NEW_RESOURCE_ARRAY(char, len); ; - jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); + ResourceMark rm(thread); + char *msg; + if (error_msg == NULL) { + msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ; + jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path); + } else { + int len = (int)(strlen(path) + strlen(error_msg) + 128); + msg = NEW_RESOURCE_ARRAY(char, len); ; + jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); + } + // Don't complain about bad jar files added via -Xbootclasspath/a:. + if (throw_exception && is_init_completed()) { + THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); + } else { + return NULL; + } } - if (throw_exception) { - THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); - } else { - return NULL; - } - } } if (TraceClassLoading || TraceClassPaths) { tty->print_cr("[Opened %s]", path); @@ -666,7 +610,7 @@ // File or directory found ClassPathEntry* new_entry = NULL; Thread* THREAD = Thread::current(); - new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, throw_exception, CHECK_(false)); + new_entry = create_class_path_entry(path, &st, throw_exception, CHECK_(false)); if (new_entry == NULL) { return false; } @@ -1319,19 +1263,6 @@ return false; } -void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { - ClassPathEntry* cpe = resolve_entry(THREAD); - if (cpe != NULL) { - cpe->compile_the_world(loader, CHECK); - } -} - -bool LazyClassPathEntry::is_jrt() { - Thread* THREAD = Thread::current(); - ClassPathEntry* cpe = resolve_entry(THREAD); - return (cpe != NULL) ? cpe->is_jar_file() : false; -} - void ClassLoader::compile_the_world() { EXCEPTION_MARK; HandleMark hm(THREAD); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/classLoader.hpp --- a/hotspot/src/share/vm/classfile/classLoader.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classLoader.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -32,9 +32,14 @@ // The VM class loader. #include +// Name of boot module image +#define BOOT_IMAGE_NAME "bootmodules.jimage" // Class path entry (directory or zip file) +class ImageFileReader; +class ImageModuleData; + class ClassPathEntry: public CHeapObj { private: ClassPathEntry* _next; @@ -47,7 +52,7 @@ } virtual bool is_jar_file() = 0; virtual const char* name() = 0; - virtual bool is_lazy(); + virtual ImageFileReader* image() = 0; // Constructor ClassPathEntry(); // Attempt to locate file_name through this class path entry. @@ -63,8 +68,9 @@ private: const char* _dir; // Name of directory public: - bool is_jar_file() { return false; } - const char* name() { return _dir; } + bool is_jar_file() { return false; } + const char* name() { return _dir; } + ImageFileReader* image() { return NULL; } ClassPathDirEntry(const char* dir); ClassFileStream* open_stream(const char* name, TRAPS); // Debugging @@ -92,8 +98,9 @@ jzfile* _zip; // The zip archive const char* _zip_name; // Name of zip archive public: - bool is_jar_file() { return true; } - const char* name() { return _zip_name; } + bool is_jar_file() { return true; } + const char* name() { return _zip_name; } + ImageFileReader* image() { return NULL; } ClassPathZipEntry(jzfile* zip, const char* zip_name); ~ClassPathZipEntry(); u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); @@ -105,39 +112,18 @@ }; -// For lazier loading of boot class path entries -class LazyClassPathEntry: public ClassPathEntry { - private: - const char* _path; // dir or file - struct stat _st; - bool _has_error; - bool _throw_exception; - volatile ClassPathEntry* _resolved_entry; - ClassPathEntry* resolve_entry(TRAPS); - public: - bool is_jar_file(); - const char* name() { return _path; } - LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception); - virtual ~LazyClassPathEntry(); - u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); - - ClassFileStream* open_stream(const char* name, TRAPS); - virtual bool is_lazy(); - // Debugging - NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) - NOT_PRODUCT(bool is_jrt();) -}; - // For java image files -class ImageFile; class ClassPathImageEntry: public ClassPathEntry { private: - ImageFile *_image; + ImageFileReader* _image; + ImageModuleData* _module_data; public: bool is_jar_file() { return false; } bool is_open() { return _image != NULL; } const char* name(); - ClassPathImageEntry(char* name); + ImageFileReader* image() { return _image; } + ImageModuleData* module_data() { return _module_data; } + ClassPathImageEntry(ImageFileReader* image); ~ClassPathImageEntry(); ClassFileStream* open_stream(const char* name, TRAPS); @@ -157,7 +143,6 @@ package_hash_table_size = 31 // Number of buckets }; protected: - friend class LazyClassPathEntry; // Performance counters static PerfCounter* _perf_accumulated_time; @@ -222,7 +207,7 @@ static void load_zip_library(); static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st, - bool lazy, bool throw_exception, TRAPS); + bool throw_exception, TRAPS); // Canonicalizes path names, so strcmp will work properly. This is mainly // to avoid confusing the zip library diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/classLoaderData.cpp --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -494,7 +494,7 @@ void ClassLoaderData::dump(outputStream * const out) { ResourceMark rm; - out->print("ClassLoaderData CLD: "PTR_FORMAT", loader: "PTR_FORMAT", loader_klass: "PTR_FORMAT" %s {", + out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: " PTR_FORMAT " %s {", p2i(this), p2i((void *)class_loader()), p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name()); if (claimed()) out->print(" claimed "); @@ -513,7 +513,7 @@ ResourceMark rm; Klass* k = _klasses; while (k != NULL) { - out->print_cr("klass "PTR_FORMAT", %s, CT: %d, MUT: %d", k, k->name()->as_C_string(), + out->print_cr("klass " PTR_FORMAT ", %s, CT: %d, MUT: %d", k, k->name()->as_C_string(), k->has_modified_oops(), k->has_accumulated_modified_oops()); assert(k != k->next_link(), "no loops!"); k = k->next_link(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/dictionary.cpp --- a/hotspot/src/share/vm/classfile/dictionary.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/dictionary.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -557,7 +557,7 @@ } void ProtectionDomainCacheEntry::print() { - tty->print_cr("entry "PTR_FORMAT" value "PTR_FORMAT" strongly_reachable %d next "PTR_FORMAT, + tty->print_cr("entry " PTR_FORMAT " value " PTR_FORMAT " strongly_reachable %d next " PTR_FORMAT, this, (void*)literal(), _strongly_reachable, next()); } #endif diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/dictionary.hpp --- a/hotspot/src/share/vm/classfile/dictionary.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/dictionary.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -370,7 +370,7 @@ void print_on(outputStream* st) const { symbol()->print_value_on(st); - st->print("/mode="INTX_FORMAT, symbol_mode()); + st->print("/mode=" INTX_FORMAT, symbol_mode()); st->print(" -> "); bool printed = false; if (method() != NULL) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/imageDecompressor.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/classfile/imageDecompressor.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 "runtime/thread.inline.hpp" +#include "precompiled.hpp" +#include "classfile/imageDecompressor.hpp" +#include "runtime/thread.hpp" +#include "utilities/bytes.hpp" + +/* + * Allocate in C Heap not in resource area, otherwise JVM crashes. + * This array life time is the VM life time. Array is never freed and + * is not expected to contain more than few references. + */ +GrowableArray* ImageDecompressor::_decompressors = + new(ResourceObj::C_HEAP, mtInternal) GrowableArray(2, true); + +static Symbol* createSymbol(const char* str) { + Thread* THREAD = Thread::current(); + Symbol* sym = SymbolTable::lookup(str, (int) strlen(str), THREAD); + if (HAS_PENDING_EXCEPTION) { + warning("can't create symbol\n"); + CLEAR_PENDING_EXCEPTION; + return NULL; + } + return sym; +} + +/* + * Initialize the array of decompressors. + */ +bool image_decompressor_init() { + Symbol* zipSymbol = createSymbol("zip"); + if (zipSymbol == NULL) { + return false; + } + ImageDecompressor::add_decompressor(new ZipDecompressor(zipSymbol)); + + return true; +} + +/* + * Decompression entry point. Called from ImageFileReader::get_resource. + */ +void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed, + u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap) { + bool has_header = false; + u1* decompressed_resource = compressed; + u1* compressed_resource = compressed; + + // Resource could have been transformed by a stack of decompressors. + // Iterate and decompress resources until there is no more header. + do { + ResourceHeader _header; + memcpy(&_header, compressed_resource, sizeof (ResourceHeader)); + has_header = _header._magic == ResourceHeader::resource_header_magic; + if (has_header) { + // decompressed_resource array contains the result of decompression + // when a resource content is terminal, it means that it is an actual resource, + // not an intermediate not fully uncompressed content. In this case + // the resource is allocated as an mtClass, otherwise as an mtOther + decompressed_resource = is_C_heap && _header._is_terminal ? + NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtClass) : + NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtOther); + // Retrieve the decompressor name + const char* decompressor_name = strings->get(_header._decompressor_name_offset); + if (decompressor_name == NULL) warning("image decompressor not found\n"); + guarantee(decompressor_name, "image decompressor not found"); + // Retrieve the decompressor instance + ImageDecompressor* decompressor = get_decompressor(decompressor_name); + if (decompressor == NULL) { + warning("image decompressor %s not found\n", decompressor_name); + } + guarantee(decompressor, "image decompressor not found"); + u1* compressed_resource_base = compressed_resource; + compressed_resource += ResourceHeader::resource_header_length; + // Ask the decompressor to decompress the compressed content + decompressor->decompress_resource(compressed_resource, decompressed_resource, + &_header, strings); + if (compressed_resource_base != compressed) { + FREE_C_HEAP_ARRAY(char, compressed_resource_base); + } + compressed_resource = decompressed_resource; + } + } while (has_header); + memcpy(uncompressed, decompressed_resource, uncompressed_size); +} + +// Zip decompressor + +void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed, + ResourceHeader* header, const ImageStrings* strings) { + char* msg = NULL; + jboolean res = ClassLoader::decompress(data, header->_size, uncompressed, + header->_uncompressed_size, &msg); + if (!res) warning("decompression failed due to %s\n", msg); + guarantee(res, "decompression failed"); +} + +// END Zip Decompressor diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/imageDecompressor.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/classfile/imageDecompressor.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP +#define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP + +#include "runtime/thread.inline.hpp" +#include "precompiled.hpp" +#include "classfile/classLoader.hpp" +#include "classfile/imageFile.hpp" +#include "classfile/symbolTable.hpp" +#include "oops/symbol.hpp" +#include "utilities/growableArray.hpp" + +/* + * Compressed resources located in image have an header. + * This header contains: + * - _magic: A magic u4, required to retrieved the header in the compressed content + * - _size: The size of the compressed resource. + * - _uncompressed_size: The uncompressed size of the compressed resource. + * - _decompressor_name_offset: The ImageDecompressor instance name StringsTable offset. + * - _decompressor_config_offset: StringsTable offset of configuration that could be needed by + * the decompressor in order to decompress. + * - _is_terminal: 1: the compressed content is terminal. Uncompressing it would + * create the actual resource. 0: the compressed content is not terminal. Uncompressing it + * will result in a compressed content to be decompressed (This occurs when a stack of compressors + * have been used to compress the resource. + */ +struct ResourceHeader { + /* Length of header, needed to retrieve content offset */ + static const u1 resource_header_length = 21; + /* magic bytes that identifies a compressed resource header*/ + static const u4 resource_header_magic = 0xCAFEFAFA; + u4 _magic; // Resource header + u4 _size; // Resource size + u4 _uncompressed_size; // Expected uncompressed size + u4 _decompressor_name_offset; // Strings table decompressor offset + u4 _decompressor_config_offset; // Strings table config offset + u1 _is_terminal; // Last decompressor 1, otherwise 0. +}; + +/* + * Resources located in jimage file can be compressed. Compression occurs at + * jimage file creation time. When compressed a resource is added an header that + * contains the name of the compressor that compressed it. + * Various compression strategies can be applied to compress a resource. + * The same resource can even be compressed multiple time by a stack of compressors. + * At runtime, a resource is decompressed in a loop until there is no more header + * meaning that the resource is equivalent to the not compressed resource. + * In each iteration, the name of the compressor located in the current header + * is used to retrieve the associated instance of ImageDecompressor. + * For example “zip” is the name of the compressor that compresses resources + * using the zip algorithm. The ZipDecompressor class name is also “zip”. + * ImageDecompressor instances are retrieved from a static array in which + * they are registered. + */ +class ImageDecompressor: public CHeapObj { + +private: + const Symbol* _name; + + /* + * Array of concrete decompressors. This array is used to retrieve the decompressor + * that can handle resource decompression. + */ + static GrowableArray* _decompressors; + + /* + * Identifier of a decompressor. This name is the identification key to retrieve + * decompressor from a resource header. + */ + inline const Symbol* get_name() const { return _name; } + +protected: + ImageDecompressor(const Symbol* name) : _name(name) { + } + virtual void decompress_resource(u1* data, u1* uncompressed, + ResourceHeader* header, const ImageStrings* strings) = 0; + +public: + inline static void add_decompressor(ImageDecompressor* decompressor) { + _decompressors->append(decompressor); + } + inline static ImageDecompressor* get_decompressor(const char * decompressor_name) { + Thread* THREAD = Thread::current(); + TempNewSymbol sym = SymbolTable::new_symbol(decompressor_name, + (int) strlen(decompressor_name), CHECK_NULL); + if (HAS_PENDING_EXCEPTION) { + warning("can't create symbol\n"); + CLEAR_PENDING_EXCEPTION; + return NULL; + } + for (int i = 0; i < _decompressors->length(); i++) { + ImageDecompressor* decompressor = _decompressors->at(i); + if (decompressor->get_name()->fast_compare(sym) == 0) { + return decompressor; + } + } + guarantee(false, "No decompressor found."); + return NULL; + } + static void decompress_resource(u1* compressed, u1* uncompressed, + u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap); +}; + +/** + * Zip decompressor. + */ +class ZipDecompressor : public ImageDecompressor { +public: + ZipDecompressor(const Symbol* sym) : ImageDecompressor(sym) { } + void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header, + const ImageStrings* strings); +}; + +#endif // SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/imageFile.cpp --- a/hotspot/src/share/vm/classfile/imageFile.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/imageFile.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,77 +23,311 @@ */ #include "precompiled.hpp" +#include "classfile/imageDecompressor.hpp" #include "classfile/imageFile.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/mutex.hpp" +#include "runtime/mutexLocker.hpp" #include "runtime/os.inline.hpp" -#include "utilities/bytes.hpp" - +#include "utilities/endian.hpp" +#include "utilities/growableArray.hpp" -// Compute the Perfect Hashing hash code for the supplied string. -u4 ImageStrings::hash_code(const char* string, u4 seed) { +// Image files are an alternate file format for storing classes and resources. The +// goal is to supply file access which is faster and smaller than the jar format. +// +// (More detailed nodes in the header.) +// + +// Compute the Perfect Hashing hash code for the supplied UTF-8 string. +s4 ImageStrings::hash_code(const char* string, s4 seed) { + // Access bytes as unsigned. u1* bytes = (u1*)string; - // Compute hash code. for (u1 byte = *bytes++; byte; byte = *bytes++) { seed = (seed * HASH_MULTIPLIER) ^ byte; } - - // Ensure the result is unsigned. + // Ensure the result is not signed. return seed & 0x7FFFFFFF; } -// Test to see if string begins with start. If so returns remaining portion -// of string. Otherwise, NULL. +// Match up a string in a perfect hash table. Result still needs validation +// for precise match (false positive.) +s4 ImageStrings::find(Endian* endian, const char* name, s4* redirect, u4 length) { + // If the table is empty, then short cut. + if (redirect == NULL || length == 0) { + return NOT_FOUND; + } + // Compute the basic perfect hash for name. + s4 hash_code = ImageStrings::hash_code(name); + // Modulo table size. + s4 index = hash_code % length; + // Get redirect entry. + // value == 0 then not found + // value < 0 then -1 - value is true index + // value > 0 then value is seed for recomputing hash. + s4 value = endian->get(redirect[index]); + // if recompute is required. + if (value > 0) { + // Entry collision value, need to recompute hash. + hash_code = ImageStrings::hash_code(name, value); + // Modulo table size. + return hash_code % length; + } else if (value < 0) { + // Compute direct index. + return -1 - value; + } + // No entry found. + return NOT_FOUND; +} + +// Test to see if UTF-8 string begins with the start UTF-8 string. If so, +// return non-NULL address of remaining portion of string. Otherwise, return +// NULL. Used to test sections of a path without copying from image string +// table. const char* ImageStrings::starts_with(const char* string, const char* start) { char ch1, ch2; - // Match up the strings the best we can. while ((ch1 = *string) && (ch2 = *start)) { if (ch1 != ch2) { // Mismatch, return NULL. return NULL; } - + // Next characters. string++, start++; } - // Return remainder of string. return string; } -ImageLocation::ImageLocation(u1* data) { +// Inflates the attribute stream into individual values stored in the long +// array _attributes. This allows an attribute value to be quickly accessed by +// direct indexing. Unspecified values default to zero (from constructor.) +void ImageLocation::set_data(u1* data) { // Deflate the attribute stream into an array of attributes. - memset(_attributes, 0, sizeof(_attributes)); u1 byte; - - while ((byte = *data) != ATTRIBUTE_END) { + // Repeat until end header is found. + while ((byte = *data)) { + // Extract kind from header byte. u1 kind = attribute_kind(byte); + guarantee(kind < ATTRIBUTE_COUNT, "invalid image location attribute"); + // Extract length of data (in bytes). u1 n = attribute_length(byte); - assert(kind < ATTRIBUTE_COUNT, "invalid image location attribute"); + // Read value (most significant first.) _attributes[kind] = attribute_value(data + 1, n); + // Position to next attribute by skipping attribute header and data bytes. data += n + 1; } } -ImageFile::ImageFile(const char* name) { +// Zero all attribute values. +void ImageLocation::clear_data() { + // Set defaults to zero. + memset(_attributes, 0, sizeof(_attributes)); +} + +// ImageModuleData constructor maps out sub-tables for faster access. +ImageModuleData::ImageModuleData(const ImageFileReader* image_file, + const char* module_data_name) : + _image_file(image_file), + _endian(image_file->endian()), + _strings(image_file->get_strings()) { + // Retrieve the resource containing the module data for the image file. + ImageLocation location; + bool found = image_file->find_location(module_data_name, location); + guarantee(found, "missing module data"); + u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); + _data = (u1*)NEW_C_HEAP_ARRAY(char, data_size, mtClass); + _image_file->get_resource(location, _data); + // Map out the header. + _header = (Header*)_data; + // Get the package to module entry count. + u4 ptm_count = _header->ptm_count(_endian); + // Get the module to package entry count. + u4 mtp_count = _header->mtp_count(_endian); + // Compute the offset of the package to module perfect hash redirect. + u4 ptm_redirect_offset = sizeof(Header); + // Compute the offset of the package to module data. + u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4); + // Compute the offset of the module to package perfect hash redirect. + u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData); + // Compute the offset of the module to package data. + u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4); + // Compute the offset of the module to package tables. + u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData); + // Compute the address of the package to module perfect hash redirect. + _ptm_redirect = (s4*)(_data + ptm_redirect_offset); + // Compute the address of the package to module data. + _ptm_data = (PTMData*)(_data + ptm_data_offset); + // Compute the address of the module to package perfect hash redirect. + _mtp_redirect = (s4*)(_data + mtp_redirect_offset); + // Compute the address of the module to package data. + _mtp_data = (MTPData*)(_data + mtp_data_offset); + // Compute the address of the module to package tables. + _mtp_packages = (s4*)(_data + mtp_packages_offset); +} + +// Release module data resource. +ImageModuleData::~ImageModuleData() { + if (_data != NULL) { + FREE_C_HEAP_ARRAY(u1, _data); + } +} + +// Return the name of the module data resource. Ex. "./lib/modules/file.jimage" +// yields "file.jdata" +void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) { + // Locate the last slash in the file name path. + const char* slash = strrchr(image_file_name, os::file_separator()[0]); + // Trim the path to name and extension. + const char* name = slash != NULL ? slash + 1 : (char *)image_file_name; + // Locate the extension period. + const char* dot = strrchr(name, '.'); + guarantee(dot, "missing extension on jimage name"); + // Trim to only base name. + int length = dot - name; + strncpy(buffer, name, length); + buffer[length] = '\0'; + // Append extension. + strcat(buffer, ".jdata"); +} + +// Return the module in which a package resides. Returns NULL if not found. +const char* ImageModuleData::package_to_module(const char* package_name) { + // Search the package to module table. + s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect, + _header->ptm_count(_endian)); + // If entry is found. + if (index != ImageStrings::NOT_FOUND) { + // Retrieve the package to module entry. + PTMData* data = _ptm_data + index; + // Verify that it is the correct data. + if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) { + return NULL; + } + // Return the module name. + return get_string(data->module_name_offset(_endian)); + } + return NULL; +} + +// Returns all the package names in a module. Returns NULL if module not found. +GrowableArray* ImageModuleData::module_to_packages(const char* module_name) { + // Search the module to package table. + s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect, + _header->mtp_count(_endian)); + // If entry is found. + if (index != ImageStrings::NOT_FOUND) { + // Retrieve the module to package entry. + MTPData* data = _mtp_data + index; + // Verify that it is the correct data. + if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) { + return NULL; + } + // Construct an array of all the package entries. + GrowableArray* packages = new GrowableArray(); + s4 package_offset = data->package_offset(_endian); + for (u4 i = 0; i < data->package_count(_endian); i++) { + u4 package_name_offset = mtp_package(package_offset + i); + const char* package_name = get_string(package_name_offset); + packages->append(package_name); + } + return packages; + } + return NULL; +} + +// Table to manage multiple opens of an image file. +GrowableArray* ImageFileReader::_reader_table = + new(ResourceObj::C_HEAP, mtInternal) GrowableArray(2, true); + +// Open an image file, reuse structure if file already open. +ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) { + // Lock out _reader_table. + MutexLocker ml(ImageFileReaderTable_lock); + ImageFileReader* reader; + // Search for an exist image file. + for (int i = 0; i < _reader_table->length(); i++) { + // Retrieve table entry. + reader = _reader_table->at(i); + // If name matches, then reuse (bump up use count.) + if (strcmp(reader->name(), name) == 0) { + reader->inc_use(); + return reader; + } + } + // Need a new image reader. + reader = new ImageFileReader(name, big_endian); + bool opened = reader->open(); + // If failed to open. + if (!opened) { + delete reader; + return NULL; + } + // Bump use count and add to table. + reader->inc_use(); + _reader_table->append(reader); + return reader; +} + +// Close an image file if the file is not in use elsewhere. +void ImageFileReader::close(ImageFileReader *reader) { + // Lock out _reader_table. + MutexLocker ml(ImageFileReaderTable_lock); + // If last use then remove from table and then close. + if (reader->dec_use()) { + _reader_table->remove(reader); + delete reader; + } +} + +// Return an id for the specifed ImageFileReader. +u8 ImageFileReader::readerToID(ImageFileReader *reader) { + // ID is just the cloaked reader address. + return (u8)reader; +} + +// Validate the image id. +bool ImageFileReader::idCheck(u8 id) { + // Make sure the ID is a managed (_reader_table) reader. + MutexLocker ml(ImageFileReaderTable_lock); + return _reader_table->contains((ImageFileReader*)id); +} + +// Return an id for the specifed ImageFileReader. +ImageFileReader* ImageFileReader::idToReader(u8 id) { +#ifdef PRODUCT + // Fast convert. + return (ImageFileReader*)id; +#else + // Do a slow check before fast convert. + return idCheck(id) ? (ImageFileReader*)id : NULL; +#endif +} + +// Constructor intializes to a closed state. +ImageFileReader::ImageFileReader(const char* name, bool big_endian) { // Copy the image file name. - _name = NEW_C_HEAP_ARRAY(char, strlen(name)+1, mtClass); + _name = NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtClass); strcpy(_name, name); - // Initialize for a closed file. _fd = -1; - _memory_mapped = true; + _endian = Endian::get_handler(big_endian); _index_data = NULL; } -ImageFile::~ImageFile() { +// Close image and free up data structures. +ImageFileReader::~ImageFileReader() { // Ensure file is closed. close(); - // Free up name. - FREE_C_HEAP_ARRAY(char, _name); + if (_name != NULL) { + FREE_C_HEAP_ARRAY(char, _name); + _name = NULL; + } } -bool ImageFile::open() { +// Open image file for read access. +bool ImageFileReader::open() { // If file exists open for reading. struct stat st; if (os::stat(_name, &st) != 0 || @@ -101,186 +335,212 @@ (_fd = os::open(_name, 0, O_RDONLY)) == -1) { return false; } - - // Read image file header and verify. - u8 header_size = sizeof(ImageHeader); - if (os::read(_fd, &_header, header_size) != header_size || - _header._magic != IMAGE_MAGIC || - _header._major_version != MAJOR_VERSION || - _header._minor_version != MINOR_VERSION) { + // Retrieve the file size. + _file_size = (u8)st.st_size; + // Read image file header and verify it has a valid header. + size_t header_size = sizeof(ImageHeader); + if (_file_size < header_size || + !read_at((u1*)&_header, header_size, 0) || + _header.magic(_endian) != IMAGE_MAGIC || + _header.major_version(_endian) != MAJOR_VERSION || + _header.minor_version(_endian) != MINOR_VERSION) { close(); return false; } - - // Memory map index. + // Size of image index. _index_size = index_size(); - _index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, _index_size, true, false); - - // Failing that, read index into C memory. - if (_index_data == NULL) { - _memory_mapped = false; - _index_data = NEW_RESOURCE_ARRAY(u1, _index_size); - - if (os::seek_to_file_offset(_fd, 0) == -1) { - close(); - return false; - } - - if (os::read(_fd, _index_data, _index_size) != _index_size) { - close(); - return false; - } - - return true; + // Make sure file is large enough to contain the index. + if (_file_size < _index_size) { + return false; } - -// Used to advance a pointer, unstructured. -#undef nextPtr -#define nextPtr(base, fromType, count, toType) (toType*)((fromType*)(base) + (count)) - // Pull tables out from the index. - _redirect_table = nextPtr(_index_data, u1, header_size, s4); - _offsets_table = nextPtr(_redirect_table, s4, _header._location_count, u4); - _location_bytes = nextPtr(_offsets_table, u4, _header._location_count, u1); - _string_bytes = nextPtr(_location_bytes, u1, _header._locations_size, u1); -#undef nextPtr - + // Determine how much of the image is memory mapped. + off_t map_size = (off_t)(MemoryMapImage ? _file_size : _index_size); + // Memory map image (minimally the index.) + _index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, map_size, true, false); + guarantee(_index_data, "image file not memory mapped"); + // Retrieve length of index perfect hash table. + u4 length = table_length(); + // Compute offset of the perfect hash table redirect table. + u4 redirect_table_offset = (u4)header_size; + // Compute offset of index attribute offsets. + u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4); + // Compute offset of index location attribute data. + u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4); + // Compute offset of index string table. + u4 string_bytes_offset = location_bytes_offset + locations_size(); + // Compute address of the perfect hash table redirect table. + _redirect_table = (s4*)(_index_data + redirect_table_offset); + // Compute address of index attribute offsets. + _offsets_table = (u4*)(_index_data + offsets_table_offset); + // Compute address of index location attribute data. + _location_bytes = _index_data + location_bytes_offset; + // Compute address of index string table. + _string_bytes = _index_data + string_bytes_offset; // Successful open. return true; } -void ImageFile::close() { +// Close image file. +void ImageFileReader::close() { // Dealllocate the index. - if (_index_data) { - if (_memory_mapped) { - os::unmap_memory((char*)_index_data, _index_size); - } else { - FREE_RESOURCE_ARRAY(u1, _index_data, _index_size); - } - + if (_index_data != NULL) { + os::unmap_memory((char*)_index_data, _index_size); _index_data = NULL; } - - // close file. + // Close file. if (_fd != -1) { os::close(_fd); _fd = -1; } +} +// Read directly from the file. +bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const { + return os::read_at(_fd, data, size, offset) == size; } -// Return the attribute stream for a named resourced. -u1* ImageFile::find_location_data(const char* path) const { - // Compute hash. - u4 hash = ImageStrings::hash_code(path) % _header._location_count; - s4 redirect = _redirect_table[hash]; - - if (!redirect) { - return NULL; - } - - u4 index; - - if (redirect < 0) { - // If no collision. - index = -redirect - 1; - } else { - // If collision, recompute hash code. - index = ImageStrings::hash_code(path, redirect) % _header._location_count; +// Find the location attributes associated with the path. Returns true if +// the location is found, false otherwise. +bool ImageFileReader::find_location(const char* path, ImageLocation& location) const { + // Locate the entry in the index perfect hash table. + s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length()); + // If is found. + if (index != ImageStrings::NOT_FOUND) { + // Get address of first byte of location attribute stream. + u1* data = get_location_data(index); + // Expand location attributes. + location.set_data(data); + // Make sure result is not a false positive. + return verify_location(location, path); } - - assert(index < _header._location_count, "index exceeds location count"); - u4 offset = _offsets_table[index]; - assert(offset < _header._locations_size, "offset exceeds location attributes size"); - - if (offset == 0) { - return NULL; - } - - return _location_bytes + offset; -} - -// Verify that a found location matches the supplied path. -bool ImageFile::verify_location(ImageLocation& location, const char* path) const { - // Retrieve each path component string. - ImageStrings strings(_string_bytes, _header._strings_size); - // Match a path with each subcomponent without concatenation (copy). - // Match up path parent. - const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); - const char* next = ImageStrings::starts_with(path, parent); - // Continue only if a complete match. - if (!next) return false; - // Match up path base. - const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); - next = ImageStrings::starts_with(next, base); - // Continue only if a complete match. - if (!next) return false; - // Match up path extension. - const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); - next = ImageStrings::starts_with(next, extension); - - // True only if complete match and no more characters. - return next && *next == '\0'; + return false; } -// Return the resource for the supplied location. -u1* ImageFile::get_resource(ImageLocation& location) const { - // Retrieve the byte offset and size of the resource. - u8 offset = _index_size + location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET); - u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); - u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED); - u8 read_size = compressed_size ? compressed_size : size; - - // Allocate space for the resource. - u1* data = NEW_RESOURCE_ARRAY(u1, read_size); - - bool is_read = os::read_at(_fd, data, read_size, offset) == read_size; - guarantee(is_read, "error reading from image or short read"); - - // If not compressed, just return the data. - if (!compressed_size) { - return data; +// Assemble the location path from the string fragments indicated in the location attributes. +void ImageFileReader::location_path(ImageLocation& location, char* path, size_t max) const { + // Manage the image string table. + ImageStrings strings(_string_bytes, _header.strings_size(_endian)); + // Position to first character of the path buffer. + char* next = path; + // Temp for string length. + size_t length; + // Get module string. + const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings); + // If module string is not empty string. + if (*module != '\0') { + // Get length of module name. + length = strlen(module); + // Make sure there is no buffer overflow. + guarantee(next - path + length + 2 < max, "buffer overflow"); + // Append '/module/'. + *next++ = '/'; + strcpy(next, module); next += length; + *next++ = '/'; } - - u1* uncompressed = NEW_RESOURCE_ARRAY(u1, size); - char* msg = NULL; - jboolean res = ClassLoader::decompress(data, compressed_size, uncompressed, size, &msg); - if (!res) warning("decompression failed due to %s\n", msg); - guarantee(res, "decompression failed"); - - return uncompressed; + // Get parent (package) string. + const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); + // If parent string is not empty string. + if (*parent != '\0') { + // Get length of module string. + length = strlen(parent); + // Make sure there is no buffer overflow. + guarantee(next - path + length + 1 < max, "buffer overflow"); + // Append 'patent/' . + strcpy(next, parent); next += length; + *next++ = '/'; + } + // Get base name string. + const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); + // Get length of base name. + length = strlen(base); + // Make sure there is no buffer overflow. + guarantee(next - path + length < max, "buffer overflow"); + // Append base name. + strcpy(next, base); next += length; + // Get extension string. + const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); + // If extension string is not empty string. + if (*extension != '\0') { + // Get length of extension string. + length = strlen(extension); + // Make sure there is no buffer overflow. + guarantee(next - path + length + 1 < max, "buffer overflow"); + // Append '.extension' . + *next++ = '.'; + strcpy(next, extension); next += length; + } + // Make sure there is no buffer overflow. + guarantee((size_t)(next - path) < max, "buffer overflow"); + // Terminate string. + *next = '\0'; } -void ImageFile::get_resource(const char* path, u1*& buffer, u8& size) const { - buffer = NULL; - size = 0; - u1* data = find_location_data(path); - if (data) { - ImageLocation location(data); - if (verify_location(location, path)) { - size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); - buffer = get_resource(location); - } +// Verify that a found location matches the supplied path (without copying.) +bool ImageFileReader::verify_location(ImageLocation& location, const char* path) const { + // Manage the image string table. + ImageStrings strings(_string_bytes, _header.strings_size(_endian)); + // Position to first character of the path string. + const char* next = path; + // Get module name string. + const char* module = location.get_attribute(ImageLocation::ATTRIBUTE_MODULE, strings); + // If module string is not empty. + if (*module != '\0') { + // Compare '/module/' . + if (*next++ != '/') return false; + if (!(next = ImageStrings::starts_with(next, module))) return false; + if (*next++ != '/') return false; } + // Get parent (package) string + const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); + // If parent string is not empty string. + if (*parent != '\0') { + // Compare 'parent/' . + if (!(next = ImageStrings::starts_with(next, parent))) return false; + if (*next++ != '/') return false; + } + // Get base name string. + const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); + // Compare with basne name. + if (!(next = ImageStrings::starts_with(next, base))) return false; + // Get extension string. + const char* extension = location.get_attribute(ImageLocation::ATTRIBUTE_EXTENSION, strings); + // If extension is not empty. + if (*extension != '\0') { + // Compare '.extension' . + if (*next++ != '.') return false; + if (!(next = ImageStrings::starts_with(next, extension))) return false; + } + // True only if complete match and no more characters. + return *next == '\0'; } -GrowableArray* ImageFile::packages(const char* name) { - char entry[JVM_MAXPATHLEN]; - bool overflow = jio_snprintf(entry, sizeof(entry), "%s/packages.offsets", name) == -1; - guarantee(!overflow, "package name overflow"); - - u1* buffer; - u8 size; - - get_resource(entry, buffer, size); - guarantee(buffer, "missing module packages reource"); - ImageStrings strings(_string_bytes, _header._strings_size); - GrowableArray* pkgs = new GrowableArray(); - int count = size / 4; - for (int i = 0; i < count; i++) { - u4 offset = Bytes::get_Java_u4(buffer + (i*4)); - const char* p = strings.get(offset); - pkgs->append(p); +// Return the resource data for the supplied location. +void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const { + // Retrieve the byte offset and size of the resource. + u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET); + u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); + u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED); + if (compressed_size != 0) { + ResourceMark rm; + u1* compressed_data; + // If not memory mapped read in bytes. + if (!MemoryMapImage) { + // Allocate buffer for compression. + compressed_data = NEW_RESOURCE_ARRAY(u1, compressed_size); + // Read bytes from offset beyond the image index. + bool is_read = read_at(compressed_data, compressed_size, _index_size + offset); + guarantee(is_read, "error reading from image or short read"); + } else { + compressed_data = get_data_address() + offset; + } + // Get image string table. + const ImageStrings strings = get_strings(); + // Decompress resource. + ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size, + &strings, false); + } else { + // Read bytes from offset beyond the image index. + bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset); + guarantee(is_read, "error reading from image or short read"); } - - return pkgs; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/imageFile.hpp --- a/hotspot/src/share/vm/classfile/imageFile.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/imageFile.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -28,13 +28,15 @@ #include "classfile/classLoader.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" +#include "utilities/endian.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/growableArray.hpp" // Image files are an alternate file format for storing classes and resources. The -// goal is to supply file access which is faster and smaller that the jar format. -// It should be noted that unlike jars information stored in an image is in native -// endian format. This allows the image to be memory mapped into memory without -// endian translation. This also means that images are platform dependent. +// goal is to supply file access which is faster and smaller than the jar format. +// It should be noted that unlike jars, information stored in an image is in native +// endian format. This allows the image to be mapped into memory without endian +// translation. This also means that images are platform dependent. // // Image files are structured as three sections; // @@ -42,7 +44,7 @@ // | Header | // +-----------+ // | | -// | Directory | +// | Index | // | | // +-----------+ // | | @@ -60,7 +62,11 @@ // +------------+------------+ // | Major Vers | Minor Vers | // +------------+------------+ -// | Location Count | +// | Flags | +// +-------------------------+ +// | Resource Count | +// +-------------------------+ +// | Table Length | // +-------------------------+ // | Attributes Size | // +-------------------------+ @@ -71,23 +77,24 @@ // special file extension. // Major vers, minor vers - differences in version numbers indicate structural // changes in the image. -// Location count - number of locations/resources in the file. This count is also -// the length of lookup tables used in the directory. +// Flags - various image wide flags (future). +// Resource count - number of resources in the file. +// Table length - the length of lookup tables used in the index. // Attributes size - number of bytes in the region used to store location attribute // streams. // Strings size - the size of the region used to store strings used by the -// directory and meta data. +// index and meta data. // -// The directory contains information related to resource lookup. The algorithm +// The index contains information related to resource lookup. The algorithm // used for lookup is "A Practical Minimal Perfect Hashing Method" // (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string -// in the form /. return the resource location +// in the form ///. return the resource location // information; // -// redirectIndex = hash(path, DEFAULT_SEED) % count; +// redirectIndex = hash(path, DEFAULT_SEED) % table_length; // redirect = redirectTable[redirectIndex]; // if (redirect == 0) return not found; -// locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % count; +// locationIndex = redirect < 0 ? -1 - redirect : hash(path, redirect) % table_length; // location = locationTable[locationIndex]; // if (!verify(location, path)) return not found; // return location; @@ -97,7 +104,7 @@ // other seeds. The verify function guarantees the found resource location is // indeed the resource we are looking for. // -// The following is the format of the directory; +// The following is the format of the index; // // +-------------------+ // | Redirect Table | @@ -117,54 +124,74 @@ // offsets. Zero indicates not found. // Attribute Offsets - Array of 32-bit unsigned values representing offsets into // attribute data. Attribute offsets can be iterated to do a -// full survey of resources in the image. +// full survey of resources in the image. Offset of zero +// indicates no attributes. // Attribute Data - Bytes representing compact attribute data for locations. (See // comments in ImageLocation.) -// Strings - Collection of zero terminated UTF-8 strings used by the directory and +// Strings - Collection of zero terminated UTF-8 strings used by the index and // image meta data. Each string is accessed by offset. Each string is // unique. Offset zero is reserved for the empty string. // -// Note that the memory mapped directory assumes 32 bit alignment of the image -// header, the redirect table and the attribute offsets. +// Note that the memory mapped index assumes 32 bit alignment of each component +// in the index. +// +// Endianness of an image. +// An image booted by hotspot is always in native endian. However, it is possible +// to read (by the JDK) in alternate endian format. Primarily, this is during +// cross platform scenarios. Ex, where javac needs to read an embedded image +// to access classes for crossing compilation. // +class ImageFileReader; // forward declaration // Manage image file string table. -class ImageStrings { +class ImageStrings VALUE_OBJ_CLASS_SPEC { private: - // Data bytes for strings. - u1* _data; - // Number of bytes in the string table. - u4 _size; - + u1* _data; // Data bytes for strings. + u4 _size; // Number of bytes in the string table. public: - // Prime used to generate hash for Perfect Hashing. - static const u4 HASH_MULTIPLIER = 0x01000193; + enum { + // Not found result from find routine. + NOT_FOUND = -1, + // Prime used to generate hash for Perfect Hashing. + HASH_MULTIPLIER = 0x01000193 + }; ImageStrings(u1* data, u4 size) : _data(data), _size(size) {} // Return the UTF-8 string beginning at offset. inline const char* get(u4 offset) const { - assert(offset < _size, "offset exceeds string table size"); + guarantee(offset < _size, "offset exceeds string table size"); return (const char*)(_data + offset); } - // Compute the Perfect Hashing hash code for the supplied string. + // Compute the Perfect Hashing hash code for the supplied UTF-8 string. inline static u4 hash_code(const char* string) { return hash_code(string, HASH_MULTIPLIER); } // Compute the Perfect Hashing hash code for the supplied string, starting at seed. - static u4 hash_code(const char* string, u4 seed); + static s4 hash_code(const char* string, s4 seed); - // Test to see if string begins with start. If so returns remaining portion - // of string. Otherwise, NULL. Used to test sections of a path without - // copying. + // Match up a string in a perfect hash table. Result still needs validation + // for precise match. + static s4 find(Endian* endian, const char* name, s4* redirect, u4 length); + + // Test to see if UTF-8 string begins with the start UTF-8 string. If so, + // return non-NULL address of remaining portion of string. Otherwise, return + // NULL. Used to test sections of a path without copying from image string + // table. static const char* starts_with(const char* string, const char* start); + // Test to see if UTF-8 string begins with start char. If so, return non-NULL + // address of remaining portion of string. Otherwise, return NULL. Used + // to test a character of a path without copying. + inline static const char* starts_with(const char* string, const char ch) { + return *string == ch ? string + 1 : NULL; + } }; -// Manage image file location attribute streams. Within an image, a location's +// Manage image file location attribute data. Within an image, a location's // attributes are compressed into a stream of bytes. An attribute stream is // composed of individual attribute sequences. Each attribute sequence begins with // a header byte containing the attribute 'kind' (upper 5 bits of header) and the @@ -188,7 +215,7 @@ // stream. // - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region // storing the resources. Thus, in an image this represents the number of bytes -// after the directory. +// after the index. // - Currently, compressed resources are represented by having a non-zero // ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the // image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the @@ -198,17 +225,19 @@ // represented differently. // - Package strings include trailing slash and extensions include prefix period. // -class ImageLocation { +class ImageLocation VALUE_OBJ_CLASS_SPEC { public: - // Attribute kind enumeration. - static const u1 ATTRIBUTE_END = 0; // End of attribute stream marker - static const u1 ATTRIBUTE_BASE = 1; // String table offset of resource path base - static const u1 ATTRIBUTE_PARENT = 2; // String table offset of resource path parent - static const u1 ATTRIBUTE_EXTENSION = 3; // String table offset of resource path extension - static const u1 ATTRIBUTE_OFFSET = 4; // Container byte offset of resource - static const u1 ATTRIBUTE_COMPRESSED = 5; // In image byte size of the compressed resource - static const u1 ATTRIBUTE_UNCOMPRESSED = 6; // In memory byte size of the uncompressed resource - static const u1 ATTRIBUTE_COUNT = 7; // Number of attribute kinds + enum { + ATTRIBUTE_END, // End of attribute stream marker + ATTRIBUTE_MODULE, // String table offset of module name + ATTRIBUTE_PARENT, // String table offset of resource path parent + ATTRIBUTE_BASE, // String table offset of resource path base + ATTRIBUTE_EXTENSION, // String table offset of resource path extension + ATTRIBUTE_OFFSET, // Container byte offset of resource + ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource + ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource + ATTRIBUTE_COUNT // Number of attribute kinds + }; private: // Values of inflated attributes. @@ -222,30 +251,43 @@ // Return the attribute kind. inline static u1 attribute_kind(u1 data) { u1 kind = data >> 3; - assert(kind < ATTRIBUTE_COUNT, "invalid attribute kind"); + guarantee(kind < ATTRIBUTE_COUNT, "invalid attribute kind"); return kind; } // Return the attribute length. inline static u8 attribute_value(u1* data, u1 n) { - assert(0 < n && n <= 8, "invalid attribute value length"); + guarantee(0 < n && n <= 8, "invalid attribute value length"); u8 value = 0; - // Most significant bytes first. for (u1 i = 0; i < n; i++) { value <<= 8; value |= data[i]; } - return value; } public: - ImageLocation(u1* data); + ImageLocation() { + clear_data(); + } + + ImageLocation(u1* data) { + clear_data(); + set_data(data); + } + + // Inflates the attribute stream into individual values stored in the long + // array _attributes. This allows an attribute value to be quickly accessed by + // direct indexing. Unspecified values default to zero. + void set_data(u1* data); + + // Zero all attribute values. + void clear_data(); // Retrieve an attribute value from the inflated array. inline u8 get_attribute(u1 kind) const { - assert(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT, "invalid attribute kind"); + guarantee(ATTRIBUTE_END < kind && kind < ATTRIBUTE_COUNT, "invalid attribute kind"); return _attributes[kind]; } @@ -255,89 +297,306 @@ } }; -// Manage the image file. -class ImageFile: public CHeapObj { -private: - // Image file marker. - static const u4 IMAGE_MAGIC = 0xCAFEDADA; - // Image file major version number. - static const u2 MAJOR_VERSION = 0; - // Image file minor version number. - static const u2 MINOR_VERSION = 1; +// +// NOTE: needs revision. +// Each loader requires set of module meta data to identify which modules and +// packages are managed by that loader. Currently, there is one image file per +// builtin loader, so only one module meta data resource per file. +// +// Each element in the module meta data is a native endian 4 byte integer. Note +// that entries with zero offsets for string table entries should be ignored ( +// padding for hash table lookup.) +// +// Format: +// Count of package to module entries +// Count of module to package entries +// Perfect Hash redirect table[Count of package to module entries] +// Package to module entries[Count of package to module entries] +// Offset to package name in string table +// Offset to module name in string table +// Perfect Hash redirect table[Count of module to package entries] +// Module to package entries[Count of module to package entries] +// Offset to module name in string table +// Count of packages in module +// Offset to first package in packages table +// Packages[] +// Offset to package name in string table +// +// Manage the image module meta data. +class ImageModuleData : public CHeapObj { + class Header VALUE_OBJ_CLASS_SPEC { + private: + u4 _ptm_count; // Count of package to module entries + u4 _mtp_count; // Count of module to package entries + public: + inline u4 ptm_count(Endian* endian) const { return endian->get(_ptm_count); } + inline u4 mtp_count(Endian* endian) const { return endian->get(_mtp_count); } + }; - struct ImageHeader { - u4 _magic; // Image file marker - u2 _major_version; // Image file major version number - u2 _minor_version; // Image file minor version number - u4 _location_count; // Number of locations managed in index. - u4 _locations_size; // Number of bytes in attribute table. - u4 _strings_size; // Number of bytes in string table. + // Hashtable entry + class HashData VALUE_OBJ_CLASS_SPEC { + private: + u4 _name_offset; // Name offset in string table + public: + inline s4 name_offset(Endian* endian) const { return endian->get(_name_offset); } + }; + + // Package to module hashtable entry + class PTMData : public HashData { + private: + u4 _module_name_offset; // Module name offset in string table + public: + inline s4 module_name_offset(Endian* endian) const { return endian->get(_module_name_offset); } + }; + + // Module to package hashtable entry + class MTPData : public HashData { + private: + u4 _package_count; // Number of packages in module + u4 _package_offset; // Offset in package list + public: + inline u4 package_count(Endian* endian) const { return endian->get(_package_count); } + inline u4 package_offset(Endian* endian) const { return endian->get(_package_offset); } }; - char* _name; // Name of image - int _fd; // File descriptor - bool _memory_mapped; // Is file memory mapped - ImageHeader _header; // Image header - u8 _index_size; // Total size of index - u1* _index_data; // Raw index data - s4* _redirect_table; // Perfect hash redirect table - u4* _offsets_table; // Location offset table - u1* _location_bytes; // Location attributes - u1* _string_bytes; // String table + const ImageFileReader* _image_file; // Source image file + Endian* _endian; // Endian handler + ImageStrings _strings; // Image file strings + u1* _data; // Module data resource data + u8 _data_size; // Size of resource data + Header* _header; // Module data header + s4* _ptm_redirect; // Package to module hashtable redirect + PTMData* _ptm_data; // Package to module data + s4* _mtp_redirect; // Module to packages hashtable redirect + MTPData* _mtp_data; // Module to packages data + s4* _mtp_packages; // Package data (name offsets) + + // Return a string from the string table. + inline const char* get_string(u4 offset) { + return _strings.get(offset); + } + + inline u4 mtp_package(u4 index) { + return _endian->get(_mtp_packages[index]); + } + +public: + ImageModuleData(const ImageFileReader* image_file, const char* module_data_name); + ~ImageModuleData(); + + // Return the name of the module data resource. + static void module_data_name(char* buffer, const char* image_file_name); + + // Return the module in which a package resides. Returns NULL if not found. + const char* package_to_module(const char* package_name); + + // Returns all the package names in a module. Returns NULL if module not found. + GrowableArray* module_to_packages(const char* module_name); +}; + +// Image file header, starting at offset 0. +class ImageHeader VALUE_OBJ_CLASS_SPEC { +private: + u4 _magic; // Image file marker + u4 _version; // Image file major version number + u4 _flags; // Image file flags + u4 _resource_count; // Number of resources in file + u4 _table_length; // Number of slots in index tables + u4 _locations_size; // Number of bytes in attribute table + u4 _strings_size; // Number of bytes in string table + +public: + u4 magic() const { return _magic; } + u4 magic(Endian* endian) const { return endian->get(_magic); } + void set_magic(Endian* endian, u4 magic) { return endian->set(_magic, magic); } + + u4 major_version(Endian* endian) const { return endian->get(_version) >> 16; } + u4 minor_version(Endian* endian) const { return endian->get(_version) & 0xFFFF; } + void set_version(Endian* endian, u4 major_version, u4 minor_version) { + return endian->set(_version, major_version << 16 | minor_version); + } + + u4 flags(Endian* endian) const { return endian->get(_flags); } + void set_flags(Endian* endian, u4 value) { return endian->set(_flags, value); } + + u4 resource_count(Endian* endian) const { return endian->get(_resource_count); } + void set_resource_count(Endian* endian, u4 count) { return endian->set(_resource_count, count); } + + u4 table_length(Endian* endian) const { return endian->get(_table_length); } + void set_table_length(Endian* endian, u4 count) { return endian->set(_table_length, count); } + + u4 locations_size(Endian* endian) const { return endian->get(_locations_size); } + void set_locations_size(Endian* endian, u4 size) { return endian->set(_locations_size, size); } + + u4 strings_size(Endian* endian) const { return endian->get(_strings_size); } + void set_strings_size(Endian* endian, u4 size) { return endian->set(_strings_size, size); } +}; + +// Max path length limit independent of platform. Windows max path is 1024, +// other platforms use 4096. The JCK fails several tests when 1024 is used. +#define IMAGE_MAX_PATH 4096 + +// Manage the image file. +// ImageFileReader manages the content of an image file. +// Initially, the header of the image file is read for validation. If valid, +// values in the header are used calculate the size of the image index. The +// index is then memory mapped to allow load on demand and sharing. The +// -XX:+MemoryMapImage flag determines if the entire file is loaded (server use.) +// An image can be used by Hotspot and multiple reference points in the JDK, thus +// it is desirable to share a reader. To accomodate sharing, a share table is +// defined (see ImageFileReaderTable in imageFile.cpp) To track the number of +// uses, ImageFileReader keeps a use count (_use). Use is incremented when +// 'opened' by reference point and decremented when 'closed'. Use of zero +// leads the ImageFileReader to be actually closed and discarded. +class ImageFileReader : public CHeapObj { +private: + // Manage a number of image files such that an image can be shared across + // multiple uses (ex. loader.) + static GrowableArray* _reader_table; + + char* _name; // Name of image + s4 _use; // Use count + int _fd; // File descriptor + Endian* _endian; // Endian handler + u8 _file_size; // File size in bytes + ImageHeader _header; // Image header + size_t _index_size; // Total size of index + u1* _index_data; // Raw index data + s4* _redirect_table; // Perfect hash redirect table + u4* _offsets_table; // Location offset table + u1* _location_bytes; // Location attributes + u1* _string_bytes; // String table + + ImageFileReader(const char* name, bool big_endian); + ~ImageFileReader(); // Compute number of bytes in image file index. inline u8 index_size() { return sizeof(ImageHeader) + - _header._location_count * sizeof(u4) * 2 + - _header._locations_size + - _header._strings_size; + table_length() * sizeof(u4) * 2 + locations_size() + strings_size(); } public: - ImageFile(const char* name); - ~ImageFile(); + enum { + // Image file marker. + IMAGE_MAGIC = 0xCAFEDADA, + // Endian inverted Image file marker. + IMAGE_MAGIC_INVERT = 0xDADAFECA, + // Image file major version number. + MAJOR_VERSION = 1, + // Image file minor version number. + MINOR_VERSION = 0 + }; + + // Open an image file, reuse structure if file already open. + static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian()); - // Open image file for access. + // Close an image file if the file is not in use elsewhere. + static void close(ImageFileReader *reader); + + // Return an id for the specifed ImageFileReader. + static u8 readerToID(ImageFileReader *reader); + + // Validate the image id. + static bool idCheck(u8 id); + + // Return an id for the specifed ImageFileReader. + static ImageFileReader* idToReader(u8 id); + + // Open image file for read access. bool open(); + // Close image file. void close(); + // Read directly from the file. + bool read_at(u1* data, u8 size, u8 offset) const; + + inline Endian* endian() const { return _endian; } + // Retrieve name of image file. inline const char* name() const { return _name; } + // Retrieve size of image file. + inline u8 file_size() const { + return _file_size; + } + + // Return first address of index data. + inline u1* get_index_address() const { + return _index_data; + } + + // Return first address of resource data. + inline u1* get_data_address() const { + return _index_data + _index_size; + } + + // Get the size of the index data. + size_t get_index_size() const { + return _index_size; + } + + inline u4 table_length() const { + return _header.table_length(_endian); + } + + inline u4 locations_size() const { + return _header.locations_size(_endian); + } + + inline u4 strings_size()const { + return _header.strings_size(_endian); + } + + inline u4* offsets_table() const { + return _offsets_table; + } + + // Increment use count. + inline void inc_use() { + _use++; + } + + // Decrement use count. + inline bool dec_use() { + return --_use == 0; + } + // Return a string table accessor. inline const ImageStrings get_strings() const { - return ImageStrings(_string_bytes, _header._strings_size); + return ImageStrings(_string_bytes, _header.strings_size(_endian)); } - // Return number of locations in image file index. - inline u4 get_location_count() const { - return _header._location_count; + // Return location attribute stream at offset. + inline u1* get_location_offset_data(u4 offset) const { + guarantee((u4)offset < _header.locations_size(_endian), + "offset exceeds location attributes size"); + return offset != 0 ? _location_bytes + offset : NULL; } // Return location attribute stream for location i. - inline u1* get_location_data(u4 i) const { - u4 offset = _offsets_table[i]; + inline u1* get_location_data(u4 index) const { + guarantee((u4)index < _header.table_length(_endian), + "index exceeds location count"); + u4 offset = _endian->get(_offsets_table[index]); - return offset != 0 ? _location_bytes + offset : NULL; + return get_location_offset_data(offset); } - // Return the attribute stream for a named resourced. - u1* find_location_data(const char* path) const; + // Find the location attributes associated with the path. Returns true if + // the location is found, false otherwise. + bool find_location(const char* path, ImageLocation& location) const; + + // Assemble the location path. + void location_path(ImageLocation& location, char* path, size_t max) const; // Verify that a found location matches the supplied path. bool verify_location(ImageLocation& location, const char* path) const; - // Return the resource for the supplied location info. - u1* get_resource(ImageLocation& location) const; - - // Return the resource associated with the path else NULL if not found. - void get_resource(const char* path, u1*& buffer, u8& size) const; - - // Return an array of packages for a given module - GrowableArray* packages(const char* name); + // Return the resource for the supplied path. + void get_resource(ImageLocation& location, u1* uncompressed_data) const; }; - #endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/javaClasses.cpp --- a/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1707,8 +1707,7 @@ // - rest of the stack if (!skip_fillInStackTrace_check) { - if ((method->name() == vmSymbols::fillInStackTrace_name() || - method->name() == vmSymbols::fillInStackTrace0_name()) && + if (method->name() == vmSymbols::fillInStackTrace_name() && throwable->is_a(method->method_holder())) { continue; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/classfile/vmSymbols.hpp --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -258,6 +258,8 @@ /* Type Annotations (JDK 8 and above) */ \ template(type_annotations_name, "typeAnnotations") \ \ + /* Intrinsic Annotation (JDK 9 and above) */ \ + template(jdk_internal_HotSpotIntrinsicCandidate_signature, "Ljdk/internal/HotSpotIntrinsicCandidate;") \ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ @@ -345,7 +347,6 @@ template(dispatch_name, "dispatch") \ template(getSystemClassLoader_name, "getSystemClassLoader") \ template(fillInStackTrace_name, "fillInStackTrace") \ - template(fillInStackTrace0_name, "fillInStackTrace0") \ template(getCause_name, "getCause") \ template(initCause_name, "initCause") \ template(setProperty_name, "setProperty") \ @@ -635,7 +636,43 @@ // The F_xx is one of the Flags enum; see below. // // for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t)) +// +// +// There are two types of intrinsic methods: (1) Library intrinsics and (2) bytecode intrinsics. +// +// (1) A library intrinsic method may be replaced with hand-crafted assembly code, +// with hand-crafted compiler IR, or with a combination of the two. The semantics +// of the replacement code may differ from the semantics of the replaced code. +// +// (2) Bytecode intrinsic methods are not replaced by special code, but they are +// treated in some other special way by the compiler. For example, the compiler +// may delay inlining for some String-related intrinsic methods (e.g., some methods +// defined in the StringBuilder and StringBuffer classes, see +// Compile::should_delay_string_inlining() for more details). +// +// Due to the difference between the semantics of an intrinsic method as defined +// in the (Java) source code and the semantics of the method as defined +// by the code in the VM, intrinsic methods must be explicitly marked. +// +// Intrinsic methods are marked by the jdk.internal.HotSpotIntrinsicCandidate +// annotation. If CheckIntrinsics is enabled, the VM performs the following +// checks when a class C is loaded: (1) all intrinsics defined by the VM for +// class C are present in the loaded class file and are marked; +// (2) an intrinsic is defined by the VM for all marked methods of class C. +// +// If a mismatch is detected for a method, the VM behaves differently depending +// on the type of build. A fastdebug build exits and reports an error on a mismatch. +// A product build will not replace an unmarked library intrinsic method with +// hand-crafted code, that is, unmarked library intrinsics are treated as ordinary +// methods in a product build. The special treatment of a bytecode intrinsic method +// persists even if the method not marked. +// +// When adding an intrinsic for a method, please make sure to appropriately +// annotate the method in the source code. The list below contains all +// library intrinsics followed by bytecode intrinsics. Please also make sure to +// add the declaration of the intrinsic to the approriate section of the list. #define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \ + /* (1) Library intrinsics */ \ do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \ do_name( hashCode_name, "hashCode") \ do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \ @@ -792,12 +829,12 @@ \ do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ - do_name( encodeISOArray_name, "encodeISOArray") \ + do_name( encodeISOArray_name, "implEncodeISOArray") \ do_signature(encodeISOArray_signature, "([CI[BII)I") \ \ do_class(java_math_BigInteger, "java/math/BigInteger") \ - do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_R) \ - do_name( multiplyToLen_name, "multiplyToLen") \ + do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \ + do_name( multiplyToLen_name, "implMultiplyToLen") \ do_signature(multiplyToLen_signature, "([II[II[I)[I") \ \ do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \ @@ -808,6 +845,14 @@ do_name( mulAdd_name, "implMulAdd") \ do_signature(mulAdd_signature, "([I[IIII)I") \ \ + do_intrinsic(_montgomeryMultiply, java_math_BigInteger, montgomeryMultiply_name, montgomeryMultiply_signature, F_S) \ + do_name( montgomeryMultiply_name, "implMontgomeryMultiply") \ + do_signature(montgomeryMultiply_signature, "([I[I[IIJ[I)[I") \ + \ + do_intrinsic(_montgomerySquare, java_math_BigInteger, montgomerySquare_name, montgomerySquare_signature, F_S) \ + do_name( montgomerySquare_name, "implMontgomerySquare") \ + do_signature(montgomerySquare_signature, "([I[IIJ[I)[I") \ + \ /* java/lang/ref/Reference */ \ do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ \ @@ -815,21 +860,21 @@ do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \ do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ - do_name( encryptBlock_name, "encryptBlock") \ - do_name( decryptBlock_name, "decryptBlock") \ + do_name( encryptBlock_name, "implEncryptBlock") \ + do_name( decryptBlock_name, "implDecryptBlock") \ do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \ \ do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \ do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ - do_name( encrypt_name, "encrypt") \ - do_name( decrypt_name, "decrypt") \ + do_name( encrypt_name, "implEncrypt") \ + do_name( decrypt_name, "implDecrypt") \ do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \ \ /* support for sun.security.provider.SHA */ \ do_class(sun_security_provider_sha, "sun/security/provider/SHA") \ do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \ - do_name( implCompress_name, "implCompress") \ + do_name( implCompress_name, "implCompress0") \ do_signature(implCompress_signature, "([BI)V") \ \ /* support for sun.security.provider.SHA2 */ \ @@ -843,7 +888,7 @@ /* support for sun.security.provider.DigestBase */ \ do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \ - do_name( implCompressMB_name, "implCompressMultiBlock") \ + do_name( implCompressMB_name, "implCompressMultiBlock0") \ do_signature(implCompressMB_signature, "([BII)I") \ \ /* support for com.sun.crypto.provider.GHASH */ \ @@ -857,17 +902,18 @@ do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ do_name( update_name, "update") \ do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \ - do_name( updateBytes_name, "updateBytes") \ + do_name( updateBytes_name, "updateBytes0") \ do_signature(updateBytes_signature, "(I[BII)I") \ do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \ - do_name( updateByteBuffer_name, "updateByteBuffer") \ + do_name( updateByteBuffer_name, "updateByteBuffer0") \ do_signature(updateByteBuffer_signature, "(IJII)I") \ \ /* support for java.util.zip.CRC32C */ \ do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \ - do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_name, updateBytes_signature, F_S) \ - do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \ - do_name( updateDirectByteBuffer_name, "updateDirectByteBuffer") \ + do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_C_name, updateBytes_signature, F_S) \ + do_name( updateBytes_C_name, "updateBytes") \ + do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \ + do_name( updateDirectByteBuffer_C_name, "updateDirectByteBuffer") \ \ /* support for sun.misc.Unsafe */ \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ @@ -878,12 +924,6 @@ do_intrinsic(_copyMemory, sun_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ do_name( copyMemory_name, "copyMemory") \ do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ - do_intrinsic(_park, sun_misc_Unsafe, park_name, park_signature, F_RN) \ - do_name( park_name, "park") \ - do_signature(park_signature, "(ZJ)V") \ - do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \ - do_name( unpark_name, "unpark") \ - do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \ do_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ do_name( loadFence_name, "loadFence") \ do_alias( loadFence_signature, void_method_signature) \ @@ -1066,11 +1106,15 @@ do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\ do_name( getAndSetObject_name, "getAndSetObject") \ do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \ - /*== LAST_COMPILER_INLINE*/ \ - /*the compiler does have special inlining code for these; bytecode inline is just fine */ \ + \ + /* (2) Bytecode intrinsics */ \ \ - do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ - \ + do_intrinsic(_park, sun_misc_Unsafe, park_name, park_signature, F_RN) \ + do_name( park_name, "park") \ + do_signature(park_signature, "(ZJ)V") \ + do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \ + do_name( unpark_name, "unpark") \ + do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \ do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \ do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \ do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/codeBlob.cpp --- a/hotspot/src/share/vm/code/codeBlob.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/codeBlob.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" +#include "code/codeCacheExtensions.hpp" #include "code/relocInfo.hpp" #include "compiler/disassembler.hpp" #include "interpreter/bytecode.hpp" @@ -88,6 +89,7 @@ _data_offset = size; _frame_size = 0; set_oop_maps(NULL); + _strings = CodeStrings(); } @@ -114,6 +116,7 @@ _code_offset = _content_offset + cb->total_offset_of(cb->insts()); _data_offset = _content_offset + round_to(cb->total_content_size(), oopSize); assert(_data_offset <= size, "codeBlob is too small"); + _strings = CodeStrings(); cb->copy_code_and_locs_to(this); set_oop_maps(oop_maps); @@ -192,6 +195,7 @@ BufferBlob* blob = NULL; unsigned int size = sizeof(BufferBlob); + CodeCacheExtensions::size_blob(name, &buffer_size); // align the size to CodeEntryAlignment size = align_code_offset(size); size += round_to(buffer_size, oopSize); @@ -275,6 +279,7 @@ MethodHandlesAdapterBlob* blob = NULL; unsigned int size = sizeof(MethodHandlesAdapterBlob); + CodeCacheExtensions::size_blob("MethodHandles adapters", &buffer_size); // align the size to CodeEntryAlignment size = align_code_offset(size); size += round_to(buffer_size, oopSize); @@ -315,11 +320,13 @@ { RuntimeStub* stub = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock - { + if (!CodeCacheExtensions::skip_code_generation()) { + // bypass useless code generation MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(RuntimeStub)); stub = new (size) RuntimeStub(stub_name, cb, size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments); } + stub = (RuntimeStub*) CodeCacheExtensions::handle_generated_blob(stub, stub_name); trace_new_stub(stub, "RuntimeStub - ", stub_name); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/codeBlob.hpp --- a/hotspot/src/share/vm/code/codeBlob.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/codeBlob.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * 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,7 +38,8 @@ MethodProfiled = 1, // Execution level 2 and 3 (profiled) nmethods NonNMethod = 2, // Non-nmethods like Buffers, Adapters and Runtime Stubs All = 3, // All types (No code cache segmentation) - NumTypes = 4 // Number of CodeBlobTypes + Pregenerated = 4, // Special blobs, managed by CodeCacheExtensions + NumTypes = 5 // Number of CodeBlobTypes }; }; @@ -63,6 +64,7 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC { friend class VMStructs; + friend class CodeCacheDumper; private: const char* _name; @@ -206,6 +208,14 @@ void set_strings(CodeStrings& strings) { _strings.assign(strings); } + + static ByteSize name_field_offset() { + return byte_offset_of(CodeBlob, _name); + } + + static ByteSize oop_maps_field_offset() { + return byte_offset_of(CodeBlob, _oop_maps); + } }; class WhiteBox; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/codeCache.cpp --- a/hotspot/src/share/vm/code/codeCache.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/codeCache.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -409,7 +409,7 @@ } if (PrintCodeCacheExtension) { ResourceMark rm; - if (SegmentedCodeCache) { + if (_heaps->length() >= 1) { tty->print("%s", heap->name()); } else { tty->print("CodeCache"); @@ -1211,7 +1211,7 @@ int i = 0; FOR_ALL_HEAPS(heap) { - if (SegmentedCodeCache && Verbose) { + if ((_heaps->length() >= 1) && Verbose) { tty->print_cr("-- %s --", (*heap)->name()); } FOR_ALL_BLOBS(cb, *heap) { @@ -1360,7 +1360,7 @@ FOR_ALL_HEAPS(heap_iterator) { CodeHeap* heap = (*heap_iterator); size_t total = (heap->high_boundary() - heap->low_boundary()); - if (SegmentedCodeCache) { + if (_heaps->length() >= 1) { st->print("%s:", heap->name()); } else { st->print("CodeCache:"); @@ -1397,7 +1397,7 @@ nmethod* nm = iter.method(); ResourceMark rm; char *method_name = nm->method()->name_and_sig_as_C_string(); - st->print_cr("%d %d %s ["INTPTR_FORMAT", "INTPTR_FORMAT" - "INTPTR_FORMAT"]", + st->print_cr("%d %d %s [" INTPTR_FORMAT ", " INTPTR_FORMAT " - " INTPTR_FORMAT "]", nm->compile_id(), nm->comp_level(), method_name, (intptr_t)nm->header_begin(), (intptr_t)nm->code_begin(), (intptr_t)nm->code_end()); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/codeCache.hpp --- a/hotspot/src/share/vm/code/codeCache.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/codeCache.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -78,6 +78,7 @@ friend class VMStructs; friend class NMethodIterator; friend class WhiteBox; + friend class CodeCacheLoader; private: // CodeHeaps of the cache static GrowableArray* _heaps; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/codeCacheExtensions.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/code/codeCacheExtensions.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_HPP +#define SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_HPP + +#include "memory/allocation.hpp" + +class CodeCacheExtensionsSteps: AllStatic { +public: + enum Step { + // Support for optional fine grain initialization hooks + // Note: these hooks must support refining the granularity + // (e.g. adding intermediate steps in the ordered enum + // if needed for future features) + Start, + VMVersion, + StubRoutines1, + Universe, + TemplateInterpreter, + Interpreter, + StubRoutines2, + InitGlobals, + CreateVM, + LastStep + }; +}; + +#include "code/codeCacheExtensions_ext.hpp" + +#endif // SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/codeCacheExtensions_ext.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/code/codeCacheExtensions_ext.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_EXT_HPP +#define SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_EXT_HPP + +#include "utilities/macros.hpp" +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" +#include "interpreter/bytecodes.hpp" + +class AdapterHandlerEntry; +class CodeBlob; +class CodeBuffer; +class InterpreterMacroAssembler; +class Template; + +// All the methods defined here are placeholders for possible extensions. + +class CodeCacheExtensions: AllStatic { + friend class CodeCacheDumper; + +public: + // init both code saving and loading + // Must be called very early, before any code is generated. + static void initialize() {} + + // Check whether the generated interpreter will be saved. + static bool saving_generated_interpreter() { return false; } + + // Check whether a pregenerated interpreter is used. + static bool use_pregenerated_interpreter() { return false; } + + // Placeholder for additional VM initialization code + static void complete_step(CodeCacheExtensionsSteps::Step phase) {} + + // Return false for newly generated code, on systems where it is not + // executable. + static bool is_executable(void *pc) { return true; } + + // Return whether dynamically generated code can be executable + static bool support_dynamic_code() { return true; } + + // Skip new code generation when known to be useless. + static bool skip_code_generation() { return false; } + + // Skip stubs used only for compiled code support. + static bool skip_compiler_support() { return false; } + + // Ignore UseFastSignatureHandlers when returning false + static bool support_fast_signature_handlers() { return true; } + + ///////////////////////// + // Handle generated code: + // - allow newly generated code to be shared + // - allow pregenerated code to be used in place of the newly generated one + // (modifying pc). + // - support remapping when doing both save and load + // 'remap' can be set to false if the addresses handled are not referenced + // from code generated later. + + // Associate a name to a generated codelet and possibly modify the pc + // Note: use instead the specialized versions when they exist: + // - handle_generated_blob for CodeBlob + // - handle_generated_handler for SignatureHandlers + // See also the optimized calls below that handle several PCs at once. + static void handle_generated_pc(address &pc, const char *name) {} + + // Adds a safe definition of the codelet, for codelets used right after + // generation (else we would need to immediately stop the JVM and convert + // the generated code to executable format before being able to go further). + static void handle_generated_pc(address &pc, const char *name, address default_entry) {} + + // Special cases + + // Special case for CodeBlobs, which may require blob specific actions. + static CodeBlob* handle_generated_blob(CodeBlob* blob, const char *name = NULL) { return blob; } + + // Special case for Signature Handlers. + static void handle_generated_handler(address &handler_start, const char *name, address handler_end) {} + + // Support for generating different variants of the interpreter + // that can be dynamically selected after reload. + // + // - init_interpreter_assembler allows to configure the assembler for + // the current variant + // + // - needs_other_interpreter_variant returns true as long as other + // variants are needed. + // + // - skip_template_interpreter_entries returns true if new entries + // need not be generated for this masm setup and this bytecode + // + // - completed_template_interpreter_entries is called after new + // entries have been generated and installed, for any non skipped + // bytecode. + static void init_interpreter_assembler(InterpreterMacroAssembler* masm, CodeBuffer* code) {} + static bool needs_other_interpreter_variant() { return false; } + static bool skip_template_interpreter_entries(Bytecodes::Code code) { return false; } + static void completed_template_interpreter_entries(InterpreterMacroAssembler* masm, Bytecodes::Code code) {} + + // Code size optimization. May optimize the requested size. + static void size_blob(const char* name, int *updatable_size) {} + + // ergonomics + static void set_ergonomics_flags() {} +}; + +#endif // SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_EXT_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/exceptionHandlerTable.cpp --- a/hotspot/src/share/vm/code/exceptionHandlerTable.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/exceptionHandlerTable.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -186,7 +186,7 @@ void ImplicitExceptionTable::print(address base) const { tty->print("{"); for( uint i=0; iprint("< "INTPTR_FORMAT", "INTPTR_FORMAT" > ",base + *adr(i), base + *(adr(i)+1)); + tty->print("< " INTPTR_FORMAT ", " INTPTR_FORMAT " > ",base + *adr(i), base + *(adr(i)+1)); tty->print_cr("}"); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/nmethod.cpp --- a/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/nmethod.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -2118,7 +2118,7 @@ void maybe_print(oop* p) { if (_print_nm == NULL) return; if (!_detected_scavenge_root) _print_nm->print_on(tty, "new scavenge root"); - tty->print_cr(""PTR_FORMAT"[offset=%d] detected scavengable oop "PTR_FORMAT" (found at "PTR_FORMAT")", + tty->print_cr("" PTR_FORMAT "[offset=%d] detected scavengable oop " PTR_FORMAT " (found at " PTR_FORMAT ")", _print_nm, (int)((intptr_t)p - (intptr_t)_print_nm), (void *)(*p), (intptr_t)p); (*p)->print(); @@ -2518,7 +2518,7 @@ _nm->print_nmethod(true); _ok = false; } - tty->print_cr("*** non-oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)", + tty->print_cr("*** non-oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)", (void *)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm)); } virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } @@ -2642,7 +2642,7 @@ _nm->print_nmethod(true); _ok = false; } - tty->print_cr("*** scavengable oop "PTR_FORMAT" found at "PTR_FORMAT" (offset %d)", + tty->print_cr("*** scavengable oop " PTR_FORMAT " found at " PTR_FORMAT " (offset %d)", (void *)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm)); (*p)->print(); } @@ -2687,7 +2687,7 @@ print_on(tty, NULL); if (WizardMode) { - tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); + tty->print("((nmethod*) " INTPTR_FORMAT ") ", this); tty->print(" for method " INTPTR_FORMAT , (address)method()); tty->print(" { "); if (is_in_use()) tty->print("in_use "); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/stubs.cpp --- a/hotspot/src/share/vm/code/stubs.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/stubs.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,3 +261,17 @@ stub_print(s); } } + +// Fixup for pregenerated code +void StubQueue::fix_buffer(address buffer, address queue_end, address buffer_end, int number_of_stubs) { + const int extra_bytes = CodeEntryAlignment; + _stub_buffer = buffer; + _queue_begin = 0; + _queue_end = queue_end - buffer; + _number_of_stubs = number_of_stubs; + int size = buffer_end - buffer; + // Note: _buffer_limit must differ from _queue_end in the iteration loops + // => add extra space at the end (preserving alignment for asserts) if needed + if (buffer_end == queue_end) size += extra_bytes; + _buffer_limit = _buffer_size = size; +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/code/stubs.hpp --- a/hotspot/src/share/vm/code/stubs.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/code/stubs.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -216,6 +216,9 @@ // Debugging/printing void verify(); // verifies the stub queue void print(); // prints information about the stub queue + + // Fixup for pregenerated code + void fix_buffer(address buffer, address queue_end, address buffer_end, int number_of_stubs); }; #endif // SHARE_VM_CODE_STUBS_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/compiler/compileBroker.cpp --- a/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -172,7 +172,7 @@ } void log_nmethod(JavaThread* thread, nmethod* nm) { - log(thread, "nmethod %d%s " INTPTR_FORMAT " code ["INTPTR_FORMAT ", " INTPTR_FORMAT "]", + log(thread, "nmethod %d%s " INTPTR_FORMAT " code [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", nm->compile_id(), nm->is_osr_method() ? "%" : "", p2i(nm), p2i(nm->code_begin()), p2i(nm->code_end())); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/compiler/compilerOracle.cpp --- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -578,7 +578,7 @@ int* bytes_read, const char*& error_msg) { *bytes_read = 0; error_msg = NULL; - if (2 == sscanf(line, "%*[ \t]%255" RANGESLASH "%*[ ]" "%255" RANGE0 "%n", class_name, method_name, bytes_read)) { + if (2 == sscanf(line, "%*[ \t]%255" RANGESLASH "%*[ ]" "%255" RANGE0 "%n", class_name, method_name, bytes_read)) { *c_mode = check_mode(class_name, error_msg); *m_mode = check_mode(method_name, error_msg); return *c_mode != MethodMatcher::Unknown && *m_mode != MethodMatcher::Unknown; @@ -586,8 +586,6 @@ return false; } - - // Scan next flag and value in line, return MethodMatcher object on success, NULL on failure. // On failure, error_msg contains description for the first error. // For future extensions: set error_msg on first error. @@ -665,7 +663,7 @@ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); } } else { - jio_snprintf(errorbuf, sizeof(errorbuf), " Value cannot be read for flag %s of type %s", flag, type); + jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); } } else if (strcmp(type, "double") == 0) { char buffer[2][256]; @@ -680,10 +678,10 @@ jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type); } } else { - jio_snprintf(errorbuf, sizeof(errorbuf), " Type %s not supported ", type); + jio_snprintf(errorbuf, buf_size, " Type %s not supported ", type); } } else { - jio_snprintf(errorbuf, sizeof(errorbuf), " Flag name for type %s should be alphanumeric ", type); + jio_snprintf(errorbuf, buf_size, " Flag name for type %s should be alphanumeric ", type); } return NULL; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/compiler/disassembler.cpp --- a/hotspot/src/share/vm/compiler/disassembler.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/compiler/disassembler.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -65,7 +65,7 @@ Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL; Disassembler::decode_func Disassembler::_decode_instructions = NULL; -static const char hsdis_library_name[] = "hsdis-"HOTSPOT_LIB_ARCH; +static const char hsdis_library_name[] = "hsdis-" HOTSPOT_LIB_ARCH; static const char decode_instructions_virtual_name[] = "decode_instructions_virtual"; static const char decode_instructions_name[] = "decode_instructions"; static bool use_new_version = true; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -688,18 +688,18 @@ "The CMS generation should be the old generation"); uint level = 1; if (Verbose) { - gclog_or_tty->print("[%u %s-%s: "SIZE_FORMAT"("SIZE_FORMAT")]", + gclog_or_tty->print("[%u %s-%s: " SIZE_FORMAT "(" SIZE_FORMAT ")]", level, short_name(), s, used(), capacity()); } else { - gclog_or_tty->print("[%u %s-%s: "SIZE_FORMAT"K("SIZE_FORMAT"K)]", + gclog_or_tty->print("[%u %s-%s: " SIZE_FORMAT "K(" SIZE_FORMAT "K)]", level, short_name(), s, used() / K, capacity() / K); } } if (Verbose) { - gclog_or_tty->print(" "SIZE_FORMAT"("SIZE_FORMAT")", + gclog_or_tty->print(" " SIZE_FORMAT "(" SIZE_FORMAT ")", gch->used(), gch->capacity()); } else { - gclog_or_tty->print(" "SIZE_FORMAT"K("SIZE_FORMAT"K)", + gclog_or_tty->print(" " SIZE_FORMAT "K(" SIZE_FORMAT "K)", gch->used() / K, gch->capacity() / K); } } @@ -729,8 +729,8 @@ bool res = (available >= av_promo) || (available >= max_promotion_in_bytes); if (Verbose && PrintGCDetails) { gclog_or_tty->print_cr( - "CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT")," - "max_promo("SIZE_FORMAT")", + "CMS: promo attempt is%s safe: available(" SIZE_FORMAT ") %s av_promo(" SIZE_FORMAT ")," + "max_promo(" SIZE_FORMAT ")", res? "":" not", available, res? ">=":"<", av_promo, max_promotion_in_bytes); } @@ -805,18 +805,18 @@ desired_free_percentage); gclog_or_tty->print_cr(" Maximum free fraction %f", maximum_free_percentage); - gclog_or_tty->print_cr(" Capacity "SIZE_FORMAT, capacity()/1000); - gclog_or_tty->print_cr(" Desired capacity "SIZE_FORMAT, + gclog_or_tty->print_cr(" Capacity " SIZE_FORMAT, capacity()/1000); + gclog_or_tty->print_cr(" Desired capacity " SIZE_FORMAT, desired_capacity/1000); GenCollectedHeap* gch = GenCollectedHeap::heap(); assert(gch->is_old_gen(this), "The CMS generation should always be the old generation"); size_t young_size = gch->young_gen()->capacity(); gclog_or_tty->print_cr(" Young gen size " SIZE_FORMAT, young_size / 1000); - gclog_or_tty->print_cr(" unsafe_max_alloc_nogc "SIZE_FORMAT, + gclog_or_tty->print_cr(" unsafe_max_alloc_nogc " SIZE_FORMAT, unsafe_max_alloc_nogc()/1000); - gclog_or_tty->print_cr(" contiguous available "SIZE_FORMAT, + gclog_or_tty->print_cr(" contiguous available " SIZE_FORMAT, contiguous_available()/1000); - gclog_or_tty->print_cr(" Expand by "SIZE_FORMAT" (bytes)", + gclog_or_tty->print_cr(" Expand by " SIZE_FORMAT " (bytes)", expand_bytes); } // safe if expansion fails @@ -1182,8 +1182,8 @@ stats().print_on(gclog_or_tty); gclog_or_tty->print_cr("time_until_cms_gen_full %3.7f", stats().time_until_cms_gen_full()); - gclog_or_tty->print_cr("free="SIZE_FORMAT, _cmsGen->free()); - gclog_or_tty->print_cr("contiguous_available="SIZE_FORMAT, + gclog_or_tty->print_cr("free=" SIZE_FORMAT, _cmsGen->free()); + gclog_or_tty->print_cr("contiguous_available=" SIZE_FORMAT, _cmsGen->contiguous_available()); gclog_or_tty->print_cr("promotion_rate=%g", stats().promotion_rate()); gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate()); @@ -2160,8 +2160,8 @@ assert(_numObjectsPromoted == 0, "check"); assert(_numWordsPromoted == 0, "check"); if (Verbose && PrintGC) { - gclog_or_tty->print("Allocated "SIZE_FORMAT" objects, " - SIZE_FORMAT" bytes concurrently", + gclog_or_tty->print("Allocated " SIZE_FORMAT " objects, " + SIZE_FORMAT " bytes concurrently", _numObjectsAllocated, _numWordsAllocated*sizeof(HeapWord)); } _numObjectsAllocated = 0; @@ -2241,8 +2241,8 @@ assert(_numObjectsAllocated == 0, "check"); assert(_numWordsAllocated == 0, "check"); if (Verbose && PrintGC) { - gclog_or_tty->print("Promoted "SIZE_FORMAT" objects, " - SIZE_FORMAT" bytes", + gclog_or_tty->print("Promoted " SIZE_FORMAT " objects, " + SIZE_FORMAT " bytes", _numObjectsPromoted, _numWordsPromoted*sizeof(HeapWord)); } _numObjectsPromoted = 0; @@ -2252,7 +2252,7 @@ if (PrintGC && Verbose) { // Call down the chain in contiguous_available needs the freelistLock // so print this out before releasing the freeListLock. - gclog_or_tty->print(" Contiguous available "SIZE_FORMAT" bytes ", + gclog_or_tty->print(" Contiguous available " SIZE_FORMAT " bytes ", contiguous_available()); } } @@ -2340,7 +2340,7 @@ HeapWord* addr = _marks->offsetToHeapWord(offset); if (!_marks->isMarked(addr)) { oop(addr)->print_on(gclog_or_tty); - gclog_or_tty->print_cr(" ("INTPTR_FORMAT" should have been marked)", p2i(addr)); + gclog_or_tty->print_cr(" (" INTPTR_FORMAT " should have been marked)", p2i(addr)); _failed = true; } return true; @@ -2702,9 +2702,11 @@ // Not unloading classes this cycle assert(!should_unload_classes(), "Inconsistency!"); + // If we are not unloading classes then add SO_AllCodeCache to root + // scanning options. + add_root_scanning_option(rso); + if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) { - // Include symbols, strings and code cache elements to prevent their resurrection. - add_root_scanning_option(rso); set_verifying(true); } else if (verifying() && !should_verify) { // We were verifying, but some verification flags got disabled. @@ -4269,7 +4271,7 @@ verify_overflow_empty(); if (PrintGCDetails) { - gclog_or_tty->print("[YG occupancy: "SIZE_FORMAT" K ("SIZE_FORMAT" K)]", + gclog_or_tty->print("[YG occupancy: " SIZE_FORMAT " K (" SIZE_FORMAT " K)]", _young_gen->used() / K, _young_gen->capacity() / K); } @@ -4381,8 +4383,8 @@ if (ser_ovflw > 0) { if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr("Marking stack overflow (benign) " - "(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT - ", kac_preclean="SIZE_FORMAT")", + "(pmc_pc=" SIZE_FORMAT ", pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT + ", kac_preclean=" SIZE_FORMAT ")", _ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw, _ser_kac_ovflw, _ser_kac_preclean_ovflw); } @@ -4395,7 +4397,7 @@ if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) { if (PrintCMSStatistics != 0) { gclog_or_tty->print_cr("Work queue overflow (benign) " - "(pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT")", + "(pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT ")", _par_pmc_remark_ovflw, _par_kac_ovflw); } _par_pmc_remark_ovflw = 0; @@ -4403,12 +4405,12 @@ } if (PrintCMSStatistics != 0) { if (_markStack._hit_limit > 0) { - gclog_or_tty->print_cr(" (benign) Hit max stack size limit ("SIZE_FORMAT")", + gclog_or_tty->print_cr(" (benign) Hit max stack size limit (" SIZE_FORMAT ")", _markStack._hit_limit); } if (_markStack._failed_double > 0) { - gclog_or_tty->print_cr(" (benign) Failed stack doubling ("SIZE_FORMAT")," - " current capacity "SIZE_FORMAT, + gclog_or_tty->print_cr(" (benign) Failed stack doubling (" SIZE_FORMAT ")," + " current capacity " SIZE_FORMAT, _markStack._failed_double, _markStack.capacity()); } @@ -5161,7 +5163,7 @@ &markFromDirtyCardsClosure); verify_work_stacks_empty(); if (PrintCMSStatistics != 0) { - gclog_or_tty->print(" (re-scanned "SIZE_FORMAT" dirty cards in cms gen) ", + gclog_or_tty->print(" (re-scanned " SIZE_FORMAT " dirty cards in cms gen) ", markFromDirtyCardsClosure.num_dirty_cards()); } } @@ -6035,8 +6037,8 @@ } else if (_failed_double++ == 0 && !CMSConcurrentMTEnabled && PrintGCDetails) { // Failed to double capacity, continue; // we print a detail message only once per CMS cycle. - gclog_or_tty->print(" (benign) Failed to expand marking stack from "SIZE_FORMAT"K to " - SIZE_FORMAT"K", + gclog_or_tty->print(" (benign) Failed to expand marking stack from " SIZE_FORMAT "K to " + SIZE_FORMAT "K", _capacity / K, new_capacity / K); } } @@ -7335,25 +7337,25 @@ ShouldNotReachHere(); } if (Verbose && PrintGC) { - gclog_or_tty->print("Collected "SIZE_FORMAT" objects, " SIZE_FORMAT " bytes", + gclog_or_tty->print("Collected " SIZE_FORMAT " objects, " SIZE_FORMAT " bytes", _numObjectsFreed, _numWordsFreed*sizeof(HeapWord)); - gclog_or_tty->print_cr("\nLive "SIZE_FORMAT" objects, " - SIZE_FORMAT" bytes " - "Already free "SIZE_FORMAT" objects, "SIZE_FORMAT" bytes", + gclog_or_tty->print_cr("\nLive " SIZE_FORMAT " objects, " + SIZE_FORMAT " bytes " + "Already free " SIZE_FORMAT " objects, " SIZE_FORMAT " bytes", _numObjectsLive, _numWordsLive*sizeof(HeapWord), _numObjectsAlreadyFree, _numWordsAlreadyFree*sizeof(HeapWord)); size_t totalBytes = (_numWordsFreed + _numWordsLive + _numWordsAlreadyFree) * sizeof(HeapWord); - gclog_or_tty->print_cr("Total sweep: "SIZE_FORMAT" bytes", totalBytes); + gclog_or_tty->print_cr("Total sweep: " SIZE_FORMAT " bytes", totalBytes); if (PrintCMSStatistics && CMSVerifyReturnedBytes) { size_t indexListReturnedBytes = _sp->sumIndexedFreeListArrayReturnedBytes(); size_t dict_returned_bytes = _sp->dictionary()->sum_dict_returned_bytes(); size_t returned_bytes = indexListReturnedBytes + dict_returned_bytes; - gclog_or_tty->print("Returned "SIZE_FORMAT" bytes", returned_bytes); - gclog_or_tty->print(" Indexed List Returned "SIZE_FORMAT" bytes", + gclog_or_tty->print("Returned " SIZE_FORMAT " bytes", returned_bytes); + gclog_or_tty->print(" Indexed List Returned " SIZE_FORMAT " bytes", indexListReturnedBytes); - gclog_or_tty->print_cr(" Dictionary Returned "SIZE_FORMAT" bytes", + gclog_or_tty->print_cr(" Dictionary Returned " SIZE_FORMAT " bytes", dict_returned_bytes); } } @@ -7432,12 +7434,12 @@ // coalesced chunk to the appropriate free list. if (inFreeRange()) { assert(freeFinger() >= _sp->bottom() && freeFinger() < _limit, - err_msg("freeFinger() " PTR_FORMAT" is out-of-bounds", p2i(freeFinger()))); + err_msg("freeFinger() " PTR_FORMAT " is out-of-bounds", p2i(freeFinger()))); flush_cur_free_chunk(freeFinger(), pointer_delta(addr, freeFinger())); if (CMSTraceSweeper) { gclog_or_tty->print("Sweep: last chunk: "); - gclog_or_tty->print("put_free_blk " PTR_FORMAT " ("SIZE_FORMAT") " + gclog_or_tty->print("put_free_blk " PTR_FORMAT " (" SIZE_FORMAT ") " "[coalesced:%d]\n", p2i(freeFinger()), pointer_delta(addr, freeFinger()), lastFreeRangeCoalesced() ? 1 : 0); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/cms/parNewGeneration.cpp --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1021,7 +1021,7 @@ to()->set_concurrent_iteration_safe_limit(to()->top()); if (ResizePLAB) { - plab_stats()->adjust_desired_plab_sz(active_workers); + plab_stats()->adjust_desired_plab_sz(); } if (PrintGC && !PrintGCDetails) { @@ -1059,6 +1059,10 @@ _gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); } +size_t ParNewGeneration::desired_plab_sz() { + return _plab_stats.desired_plab_sz(GenCollectedHeap::heap()->workers()->active_workers()); +} + static int sum; void ParNewGeneration::waste_some_time() { for (int i = 0; i < 100; i++) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/cms/parNewGeneration.hpp --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -411,9 +411,7 @@ return &_plab_stats; } - size_t desired_plab_sz() { - return _plab_stats.desired_plab_sz(); - } + size_t desired_plab_sz(); const ParNewTracer* gc_tracer() const { return &_gc_tracer; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp --- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -119,7 +119,7 @@ } guarantee(sum_of_reclaimable_bytes == _remaining_reclaimable_bytes, err_msg("reclaimable bytes inconsistent, " - "remaining: "SIZE_FORMAT" sum: "SIZE_FORMAT, + "remaining: " SIZE_FORMAT " sum: " SIZE_FORMAT, _remaining_reclaimable_bytes, sum_of_reclaimable_bytes)); } #endif // !PRODUCT diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp --- a/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/collectionSetChooser.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -92,7 +92,7 @@ regions_at_put(_curr_index, NULL); assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes, err_msg("remaining reclaimable bytes inconsistent " - "from region: "SIZE_FORMAT" remaining: "SIZE_FORMAT, + "from region: " SIZE_FORMAT " remaining: " SIZE_FORMAT, hr->reclaimable_bytes(), _remaining_reclaimable_bytes)); _remaining_reclaimable_bytes -= hr->reclaimable_bytes(); _curr_index += 1; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/concurrentMark.cpp --- a/hotspot/src/share/vm/gc/g1/concurrentMark.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -307,7 +307,7 @@ if (PrintGCDetails && Verbose) { // Failed to double capacity, continue; gclog_or_tty->print(" (benign) Failed to expand marking stack capacity from " - SIZE_FORMAT"K to " SIZE_FORMAT"K", + SIZE_FORMAT "K to " SIZE_FORMAT "K", _capacity / K, new_capacity / K); } } @@ -555,7 +555,7 @@ _verbose_level = verbose_level; if (verbose_low()) { - gclog_or_tty->print_cr("[global] init, heap start = "PTR_FORMAT", " + gclog_or_tty->print_cr("[global] init, heap start = " PTR_FORMAT ", " "heap end = " PTR_FORMAT, p2i(_heap_start), p2i(_heap_end)); } @@ -802,7 +802,7 @@ // in a STW phase. assert(!concurrent_marking_in_progress(), "invariant"); assert(out_of_regions(), - err_msg("only way to get here: _finger: "PTR_FORMAT", _heap_end: "PTR_FORMAT, + err_msg("only way to get here: _finger: " PTR_FORMAT ", _heap_end: " PTR_FORMAT, p2i(_finger), p2i(_heap_end))); } } @@ -1424,7 +1424,7 @@ assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), err_msg("Preconditions not met - " - "start: "PTR_FORMAT", ntams: "PTR_FORMAT", end: "PTR_FORMAT, + "start: " PTR_FORMAT ", ntams: " PTR_FORMAT ", end: " PTR_FORMAT, p2i(start), p2i(ntams), p2i(hr->end()))); // Find the first marked object at or after "start". @@ -1725,10 +1725,10 @@ } assert(end_idx <= _card_bm->size(), - err_msg("oob: end_idx= "SIZE_FORMAT", bitmap size= "SIZE_FORMAT, + err_msg("oob: end_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, end_idx, _card_bm->size())); assert(start_idx < _card_bm->size(), - err_msg("oob: start_idx= "SIZE_FORMAT", bitmap size= "SIZE_FORMAT, + err_msg("oob: start_idx= " SIZE_FORMAT ", bitmap size= " SIZE_FORMAT, start_idx, _card_bm->size())); _cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); @@ -2133,7 +2133,7 @@ oop obj = oopDesc::load_decode_heap_oop(p); if (_cm->verbose_high()) { gclog_or_tty->print_cr("\t[%u] we're looking at location " - "*"PTR_FORMAT" = "PTR_FORMAT, + "*" PTR_FORMAT " = " PTR_FORMAT, _task->worker_id(), p2i(p), p2i((void*) obj)); } @@ -2660,9 +2660,9 @@ HeapWord* limit = curr_region->next_top_at_mark_start(); if (verbose_low()) { - gclog_or_tty->print_cr("[%u] curr_region = "PTR_FORMAT" " - "["PTR_FORMAT", "PTR_FORMAT"), " - "limit = "PTR_FORMAT, + gclog_or_tty->print_cr("[%u] curr_region = " PTR_FORMAT " " + "[" PTR_FORMAT ", " PTR_FORMAT "), " + "limit = " PTR_FORMAT, worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit)); } @@ -2677,7 +2677,7 @@ if (limit > bottom) { if (verbose_low()) { - gclog_or_tty->print_cr("[%u] region "PTR_FORMAT" is not empty, " + gclog_or_tty->print_cr("[%u] region " PTR_FORMAT " is not empty, " "returning it ", worker_id, p2i(curr_region)); } return curr_region; @@ -2685,7 +2685,7 @@ assert(limit == bottom, "the region limit should be at bottom"); if (verbose_low()) { - gclog_or_tty->print_cr("[%u] region "PTR_FORMAT" is empty, " + gclog_or_tty->print_cr("[%u] region " PTR_FORMAT " is empty, " "returning NULL", worker_id, p2i(curr_region)); } // we return NULL and the caller should try calling @@ -2697,13 +2697,13 @@ if (verbose_low()) { if (curr_region == NULL) { gclog_or_tty->print_cr("[%u] found uncommitted region, moving finger, " - "global finger = "PTR_FORMAT", " - "our finger = "PTR_FORMAT, + "global finger = " PTR_FORMAT ", " + "our finger = " PTR_FORMAT, worker_id, p2i(_finger), p2i(finger)); } else { gclog_or_tty->print_cr("[%u] somebody else moved the finger, " - "global finger = "PTR_FORMAT", " - "our finger = "PTR_FORMAT, + "global finger = " PTR_FORMAT ", " + "our finger = " PTR_FORMAT, worker_id, p2i(_finger), p2i(finger)); } } @@ -2739,7 +2739,7 @@ void do_object_work(oop obj) { guarantee(!_g1h->obj_in_cs(obj), - err_msg("obj: "PTR_FORMAT" in CSet, phase: %s, info: %d", + err_msg("obj: " PTR_FORMAT " in CSet, phase: %s, info: %d", p2i((void*) obj), phase_str(), _info)); } @@ -2800,7 +2800,7 @@ // here. HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger); guarantee(global_hr == NULL || global_finger == global_hr->bottom(), - err_msg("global finger: "PTR_FORMAT" region: "HR_FORMAT, + err_msg("global finger: " PTR_FORMAT " region: " HR_FORMAT, p2i(global_finger), HR_FORMAT_PARAMS(global_hr))); } @@ -2814,7 +2814,7 @@ HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger); guarantee(task_hr == NULL || task_finger == task_hr->bottom() || !task_hr->in_collection_set(), - err_msg("task finger: "PTR_FORMAT" region: "HR_FORMAT, + err_msg("task finger: " PTR_FORMAT " region: " HR_FORMAT, p2i(task_finger), HR_FORMAT_PARAMS(task_hr))); } } @@ -2856,8 +2856,8 @@ assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(), err_msg("Preconditions not met - " - "start: "PTR_FORMAT", limit: "PTR_FORMAT", " - "top: "PTR_FORMAT", end: "PTR_FORMAT, + "start: " PTR_FORMAT ", limit: " PTR_FORMAT ", " + "top: " PTR_FORMAT ", end: " PTR_FORMAT, p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end()))); assert(hr->next_marked_bytes() == 0, "Precondition"); @@ -3118,7 +3118,7 @@ #ifndef PRODUCT // for debugging purposes void ConcurrentMark::print_finger() { - gclog_or_tty->print_cr("heap ["PTR_FORMAT", "PTR_FORMAT"), global finger = "PTR_FORMAT, + gclog_or_tty->print_cr("heap [" PTR_FORMAT ", " PTR_FORMAT "), global finger = " PTR_FORMAT, p2i(_heap_start), p2i(_heap_end), p2i(_finger)); for (uint i = 0; i < _max_worker_id; ++i) { gclog_or_tty->print(" %u: " PTR_FORMAT, i, p2i(_tasks[i]->finger())); @@ -3203,7 +3203,7 @@ "claim_region() should have filtered out continues humongous regions"); if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] setting up for region "PTR_FORMAT, + gclog_or_tty->print_cr("[%u] setting up for region " PTR_FORMAT, _worker_id, p2i(hr)); } @@ -3220,7 +3220,7 @@ if (limit == bottom) { if (_cm->verbose_low()) { gclog_or_tty->print_cr("[%u] found an empty region " - "["PTR_FORMAT", "PTR_FORMAT")", + "[" PTR_FORMAT ", " PTR_FORMAT ")", _worker_id, p2i(bottom), p2i(limit)); } // The region was collected underneath our feet. @@ -3252,7 +3252,7 @@ void CMTask::giveup_current_region() { assert(_curr_region != NULL, "invariant"); if (_cm->verbose_low()) { - gclog_or_tty->print_cr("[%u] giving up region "PTR_FORMAT, + gclog_or_tty->print_cr("[%u] giving up region " PTR_FORMAT, _worker_id, p2i(_curr_region)); } clear_region_fields(); @@ -3374,7 +3374,7 @@ if (_cm->verbose_medium()) { gclog_or_tty->print_cr("[%u] regular clock, interval = %1.2lfms, " - "scanned = "SIZE_FORMAT"%s, refs reached = "SIZE_FORMAT"%s", + "scanned = " SIZE_FORMAT "%s, refs reached = " SIZE_FORMAT "%s", _worker_id, last_interval_ms, _words_scanned, (_words_scanned >= _words_scanned_limit) ? " (*)" : "", @@ -3543,7 +3543,7 @@ statsOnly( ++_local_pops ); if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] popped "PTR_FORMAT, _worker_id, + gclog_or_tty->print_cr("[%u] popped " PTR_FORMAT, _worker_id, p2i((void*) obj)); } @@ -3900,8 +3900,8 @@ if (_cm->verbose_low()) { gclog_or_tty->print_cr("[%u] we're scanning part " - "["PTR_FORMAT", "PTR_FORMAT") " - "of region "HR_FORMAT, + "[" PTR_FORMAT ", " PTR_FORMAT ") " + "of region " HR_FORMAT, _worker_id, p2i(_finger), p2i(_region_limit), HR_FORMAT_PARAMS(_curr_region)); } @@ -3988,7 +3988,7 @@ if (_cm->verbose_low()) { gclog_or_tty->print_cr("[%u] we successfully claimed " - "region "PTR_FORMAT, + "region " PTR_FORMAT, _worker_id, p2i(claimed_region)); } @@ -4049,7 +4049,7 @@ if (_cm->try_stealing(_worker_id, &_hash_seed, obj)) { if (_cm->verbose_medium()) { - gclog_or_tty->print_cr("[%u] stolen "PTR_FORMAT" successfully", + gclog_or_tty->print_cr("[%u] stolen " PTR_FORMAT " successfully", _worker_id, p2i((void*) obj)); } @@ -4257,7 +4257,7 @@ // identify them easily in a large log file. #define G1PPRL_LINE_PREFIX "###" -#define G1PPRL_ADDR_BASE_FORMAT " "PTR_FORMAT"-"PTR_FORMAT +#define G1PPRL_ADDR_BASE_FORMAT " " PTR_FORMAT "-" PTR_FORMAT #ifdef _LP64 #define G1PPRL_ADDR_BASE_H_FORMAT " %37s" #else // _LP64 @@ -4267,16 +4267,16 @@ // For per-region info #define G1PPRL_TYPE_FORMAT " %-4s" #define G1PPRL_TYPE_H_FORMAT " %4s" -#define G1PPRL_BYTE_FORMAT " "SIZE_FORMAT_W(9) +#define G1PPRL_BYTE_FORMAT " " SIZE_FORMAT_W(9) #define G1PPRL_BYTE_H_FORMAT " %9s" #define G1PPRL_DOUBLE_FORMAT " %14.1f" #define G1PPRL_DOUBLE_H_FORMAT " %14s" // For summary info -#define G1PPRL_SUM_ADDR_FORMAT(tag) " "tag":"G1PPRL_ADDR_BASE_FORMAT -#define G1PPRL_SUM_BYTE_FORMAT(tag) " "tag": "SIZE_FORMAT -#define G1PPRL_SUM_MB_FORMAT(tag) " "tag": %1.2f MB" -#define G1PPRL_SUM_MB_PERC_FORMAT(tag) G1PPRL_SUM_MB_FORMAT(tag)" / %1.2f %%" +#define G1PPRL_SUM_ADDR_FORMAT(tag) " " tag ":" G1PPRL_ADDR_BASE_FORMAT +#define G1PPRL_SUM_BYTE_FORMAT(tag) " " tag ": " SIZE_FORMAT +#define G1PPRL_SUM_MB_FORMAT(tag) " " tag ": %1.2f MB" +#define G1PPRL_SUM_MB_PERC_FORMAT(tag) G1PPRL_SUM_MB_FORMAT(tag) " / %1.2f %%" G1PrintRegionLivenessInfoClosure:: G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp --- a/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/concurrentMark.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -197,8 +197,8 @@ assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \ "outside underlying space?"); \ assert(G1CollectedHeap::heap()->is_in_exact(addr), \ - err_msg("Trying to access not available bitmap "PTR_FORMAT \ - " corresponding to "PTR_FORMAT" (%u)", \ + err_msg("Trying to access not available bitmap " PTR_FORMAT \ + " corresponding to " PTR_FORMAT " (%u)", \ p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr))); inline void CMBitMap::mark(HeapWord* addr) { @@ -344,7 +344,7 @@ inline void CMTask::deal_with_reference(oop obj) { if (_cm->verbose_high()) { - gclog_or_tty->print_cr("[%u] we're dealing with reference = "PTR_FORMAT, + gclog_or_tty->print_cr("[%u] we're dealing with reference = " PTR_FORMAT, _worker_id, p2i((void*) obj)); } @@ -393,7 +393,7 @@ // assert that word_size is under an upper bound which is its // containing region's capacity. assert(word_size * HeapWordSize <= hr->capacity(), - err_msg("size: "SIZE_FORMAT" capacity: "SIZE_FORMAT" "HR_FORMAT, + err_msg("size: " SIZE_FORMAT " capacity: " SIZE_FORMAT " " HR_FORMAT, word_size * HeapWordSize, hr->capacity(), HR_FORMAT_PARAMS(hr))); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -44,8 +44,7 @@ ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : ConcurrentGCThread(), _cm(cm), - _started(false), - _in_progress(false), + _state(Idle), _vtime_accum(0.0), _vtime_mark_accum(0.0) { @@ -307,7 +306,6 @@ if (started()) { set_in_progress(); - clear_started(); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp --- a/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/concurrentMarkThread.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -47,8 +47,14 @@ private: ConcurrentMark* _cm; - volatile bool _started; - volatile bool _in_progress; + + enum State { + Idle, + Started, + InProgress + }; + + volatile State _state; void sleepBeforeNextCycle(); @@ -68,23 +74,22 @@ ConcurrentMark* cm() { return _cm; } - void set_started() { assert(!_in_progress, "cycle in progress"); _started = true; } - void clear_started() { assert(_in_progress, "must be starting a cycle"); _started = false; } - bool started() { return _started; } + void set_idle() { assert(_state != Started, "must not be starting a new cycle"); _state = Idle; } + bool idle() { return _state == Idle; } + void set_started() { assert(_state == Idle, "cycle in progress"); _state = Started; } + bool started() { return _state == Started; } + void set_in_progress() { assert(_state == Started, "must be starting a cycle"); _state = InProgress; } + bool in_progress() { return _state == InProgress; } - void set_in_progress() { assert(_started, "must be starting a cycle"); _in_progress = true; } - void clear_in_progress() { assert(!_started, "must not be starting a new cycle"); _in_progress = false; } - bool in_progress() { return _in_progress; } - - // This flag returns true from the moment a marking cycle is + // Returns true from the moment a marking cycle is // initiated (during the initial-mark pause when started() is set) // to the moment when the cycle completes (just after the next // marking bitmap has been cleared and in_progress() is - // cleared). While this flag is true we will not start another cycle + // cleared). While during_cycle() is true we will not start another cycle // so that cycles do not overlap. We cannot use just in_progress() // as the CM thread might take some time to wake up before noticing // that started() is set and set in_progress(). - bool during_cycle() { return started() || in_progress(); } + bool during_cycle() { return !idle(); } // shutdown void stop(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp --- a/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1AllocRegion.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -140,7 +140,7 @@ } void G1AllocRegion::fill_in_ext_msg(ar_ext_msg* msg, const char* message) { - msg->append("[%s] %s c: %u b: %s r: "PTR_FORMAT" u: "SIZE_FORMAT, + msg->append("[%s] %s c: %u b: %s r: " PTR_FORMAT " u: " SIZE_FORMAT, _name, message, _count, BOOL_TO_STR(_bot_updates), p2i(_alloc_region), _used_bytes_before); } @@ -217,7 +217,7 @@ if (G1_ALLOC_REGION_TRACING > 1) { if (result != NULL) { - jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT" "PTR_FORMAT, + jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT " " PTR_FORMAT, word_size, result); } else if (word_size != 0) { jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT, word_size); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1Allocator.cpp --- a/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -86,7 +86,7 @@ &_retained_old_gc_alloc_region); } -void G1DefaultAllocator::release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info) { +void G1DefaultAllocator::release_gc_alloc_regions(EvacuationInfo& evacuation_info) { AllocationContext_t context = AllocationContext::current(); evacuation_info.set_allocation_regions(survivor_gc_alloc_region(context)->count() + old_gc_alloc_region(context)->count()); @@ -102,8 +102,8 @@ } if (ResizePLAB) { - _g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz(no_of_gc_workers); - _g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz(no_of_gc_workers); + _g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz(); + _g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz(); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1Allocator.hpp --- a/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1Allocator.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -53,7 +53,7 @@ virtual void release_mutator_alloc_region() = 0; virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0; - virtual void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info) = 0; + virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0; virtual void abandon_gc_alloc_regions() = 0; virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0; @@ -76,7 +76,7 @@ void decrease_used(size_t bytes) { assert(_summary_bytes_used >= bytes, - err_msg("invariant: _summary_bytes_used: "SIZE_FORMAT" should be >= bytes: "SIZE_FORMAT, + err_msg("invariant: _summary_bytes_used: " SIZE_FORMAT " should be >= bytes: " SIZE_FORMAT, _summary_bytes_used, bytes)); _summary_bytes_used -= bytes; } @@ -114,7 +114,7 @@ virtual void release_mutator_alloc_region(); virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info); - virtual void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info); + virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info); virtual void abandon_gc_alloc_regions(); virtual bool is_retained_old_region(HeapRegion* hr) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1BiasedArray.cpp --- a/hotspot/src/share/vm/gc/g1/g1BiasedArray.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1BiasedArray.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -36,19 +36,19 @@ #ifndef PRODUCT void G1BiasedMappedArrayBase::verify_index(idx_t index) const { guarantee(_base != NULL, "Array not initialized"); - guarantee(index < length(), err_msg("Index out of bounds index: "SIZE_FORMAT" length: "SIZE_FORMAT, index, length())); + guarantee(index < length(), err_msg("Index out of bounds index: " SIZE_FORMAT " length: " SIZE_FORMAT, index, length())); } void G1BiasedMappedArrayBase::verify_biased_index(idx_t biased_index) const { guarantee(_biased_base != NULL, "Array not initialized"); guarantee(biased_index >= bias() && biased_index < (bias() + length()), - err_msg("Biased index out of bounds, index: "SIZE_FORMAT" bias: "SIZE_FORMAT" length: "SIZE_FORMAT, biased_index, bias(), length())); + err_msg("Biased index out of bounds, index: " SIZE_FORMAT " bias: " SIZE_FORMAT " length: " SIZE_FORMAT, biased_index, bias(), length())); } void G1BiasedMappedArrayBase::verify_biased_index_inclusive_end(idx_t biased_index) const { guarantee(_biased_base != NULL, "Array not initialized"); guarantee(biased_index >= bias() && biased_index <= (bias() + length()), - err_msg("Biased index out of inclusive bounds, index: "SIZE_FORMAT" bias: "SIZE_FORMAT" length: "SIZE_FORMAT, biased_index, bias(), length())); + err_msg("Biased index out of inclusive bounds, index: " SIZE_FORMAT " bias: " SIZE_FORMAT " length: " SIZE_FORMAT, biased_index, bias(), length())); } class TestMappedArray : public G1BiasedMappedArray { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp --- a/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1BiasedArray.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -71,10 +71,10 @@ assert(is_power_of_2(mapping_granularity_in_bytes), err_msg("mapping granularity must be power of 2, is %zd", mapping_granularity_in_bytes)); assert((uintptr_t)bottom % mapping_granularity_in_bytes == 0, - err_msg("bottom mapping area address must be a multiple of mapping granularity %zd, is "PTR_FORMAT, + err_msg("bottom mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT, mapping_granularity_in_bytes, p2i(bottom))); assert((uintptr_t)end % mapping_granularity_in_bytes == 0, - err_msg("end mapping area address must be a multiple of mapping granularity %zd, is "PTR_FORMAT, + err_msg("end mapping area address must be a multiple of mapping granularity %zd, is " PTR_FORMAT, mapping_granularity_in_bytes, p2i(end))); size_t num_target_elems = pointer_delta(end, bottom, mapping_granularity_in_bytes); idx_t bias = (uintptr_t)bottom / mapping_granularity_in_bytes; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -69,10 +69,10 @@ #ifdef ASSERT void G1BlockOffsetSharedArray::check_index(size_t index, const char* msg) const { assert((index) < (_reserved.word_size() >> LogN_words), - err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, + err_msg("%s - index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT, msg, (index), (_reserved.word_size() >> LogN_words))); assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)), - err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT + err_msg("Index " SIZE_FORMAT " corresponding to " PTR_FORMAT " (%u) is not in committed area.", (index), p2i(address_for_index_raw(index)), @@ -430,11 +430,11 @@ G1BlockOffsetArray::print_on(outputStream* out) { size_t from_index = _array->index_for(_bottom); size_t to_index = _array->index_for(_end); - out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") " - "cards ["SIZE_FORMAT","SIZE_FORMAT")", + out->print_cr(">> BOT for area [" PTR_FORMAT "," PTR_FORMAT ") " + "cards [" SIZE_FORMAT "," SIZE_FORMAT ")", p2i(_bottom), p2i(_end), from_index, to_index); for (size_t i = from_index; i < to_index; ++i) { - out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u", + out->print_cr(" entry " SIZE_FORMAT_W(8) " | " PTR_FORMAT " : %3u", i, p2i(_array->address_for_index(i)), (uint) _array->offset_array(i)); } @@ -514,7 +514,7 @@ void G1BlockOffsetArrayContigSpace::print_on(outputStream* out) { G1BlockOffsetArray::print_on(out); - out->print_cr(" next offset threshold: "PTR_FORMAT, p2i(_next_offset_threshold)); - out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index); + out->print_cr(" next offset threshold: " PTR_FORMAT, p2i(_next_offset_threshold)); + out->print_cr(" next offset index: " SIZE_FORMAT, _next_offset_index); } #endif // !PRODUCT diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp --- a/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1BlockOffsetTable.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -150,7 +150,7 @@ void check_offset(size_t offset, const char* msg) const { assert(offset <= N_words, err_msg("%s - " - "offset: " SIZE_FORMAT", N_words: %u", + "offset: " SIZE_FORMAT ", N_words: %u", msg, offset, (uint)N_words)); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CardCounts.cpp --- a/hotspot/src/share/vm/gc/g1/g1CardCounts.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CardCounts.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -53,7 +53,7 @@ void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) { if (has_count_table()) { assert(from_card_num < to_card_num, - err_msg("Wrong order? from: " SIZE_FORMAT ", to: "SIZE_FORMAT, + err_msg("Wrong order? from: " SIZE_FORMAT ", to: " SIZE_FORMAT, from_card_num, to_card_num)); Copy::fill_to_bytes(&_card_counts[from_card_num], (to_card_num - from_card_num)); } @@ -96,7 +96,7 @@ if (has_count_table()) { size_t card_num = ptr_2_card_num(card_ptr); assert(card_num < _reserved_max_card_num, - err_msg("Card "SIZE_FORMAT" outside of card counts table (max size "SIZE_FORMAT")", + err_msg("Card " SIZE_FORMAT " outside of card counts table (max size " SIZE_FORMAT ")", card_num, _reserved_max_card_num)); count = (uint) _card_counts[card_num]; if (count < G1ConcRSHotCardLimit) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CardCounts.hpp --- a/hotspot/src/share/vm/gc/g1/g1CardCounts.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CardCounts.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -91,7 +91,7 @@ jbyte* card_num_2_ptr(size_t card_num) { assert(card_num < _reserved_max_card_num, - err_msg("card num out of range: "SIZE_FORMAT, card_num)); + err_msg("card num out of range: " SIZE_FORMAT, card_num)); return (jbyte*) (_ct_bot + card_num); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp --- a/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CodeCacheRemSet.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -350,11 +350,11 @@ assert(set1.is_empty(), "Code root set must be initially empty but is not."); assert(G1CodeRootSet::static_mem_size() == sizeof(void*), - err_msg("The code root set's static memory usage is incorrect, "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size())); + err_msg("The code root set's static memory usage is incorrect, " SIZE_FORMAT " bytes", G1CodeRootSet::static_mem_size())); set1.add((nmethod*)1); assert(set1.length() == 1, err_msg("Added exactly one element, but set contains " - SIZE_FORMAT" elements", set1.length())); + SIZE_FORMAT " elements", set1.length())); const size_t num_to_add = (size_t)G1CodeRootSet::Threshold + 1; @@ -363,14 +363,14 @@ } assert(set1.length() == 1, err_msg("Duplicate detection should not have increased the set size but " - "is "SIZE_FORMAT, set1.length())); + "is " SIZE_FORMAT, set1.length())); for (size_t i = 2; i <= num_to_add; i++) { set1.add((nmethod*)(uintptr_t)(i)); } assert(set1.length() == num_to_add, - err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they " - "need to be in the set, but there are only "SIZE_FORMAT, + err_msg("After adding in total " SIZE_FORMAT " distinct code roots, they " + "need to be in the set, but there are only " SIZE_FORMAT, num_to_add, set1.length())); assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable"); @@ -385,7 +385,7 @@ } } assert(num_popped == num_to_add, - err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" " + err_msg("Managed to pop " SIZE_FORMAT " code roots, but only " SIZE_FORMAT " " "were added", num_popped, num_to_add)); assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable"); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -197,7 +197,7 @@ HeapRegion* last = NULL; while (curr != NULL) { if (!curr->is_young()) { - gclog_or_tty->print_cr("### YOUNG REGION "PTR_FORMAT"-"PTR_FORMAT" " + gclog_or_tty->print_cr("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " " "incorrectly tagged (y: %d, surv: %d)", p2i(curr->bottom()), p2i(curr->end()), curr->is_young(), curr->is_survivor()); @@ -326,7 +326,7 @@ if (curr == NULL) gclog_or_tty->print_cr(" empty"); while (curr != NULL) { - gclog_or_tty->print_cr(" "HR_FORMAT", P: "PTR_FORMAT ", N: "PTR_FORMAT", age: %4d", + gclog_or_tty->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT ", N: " PTR_FORMAT ", age: %4d", HR_FORMAT_PARAMS(curr), p2i(curr->prev_top_at_mark_start()), p2i(curr->next_top_at_mark_start()), @@ -430,7 +430,7 @@ HeapRegion* res = _hrm.allocate_free_region(is_old); if (G1ConcRegionFreeingVerbose) { gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : " - "allocated "HR_FORMAT" from secondary_free_list", + "allocated " HR_FORMAT " from secondary_free_list", HR_FORMAT_PARAMS(res)); } return res; @@ -1670,8 +1670,8 @@ // This assert only makes sense here, before we adjust them // with respect to the min and max heap size. assert(minimum_desired_capacity <= maximum_desired_capacity, - err_msg("minimum_desired_capacity = "SIZE_FORMAT", " - "maximum_desired_capacity = "SIZE_FORMAT, + err_msg("minimum_desired_capacity = " SIZE_FORMAT ", " + "maximum_desired_capacity = " SIZE_FORMAT, minimum_desired_capacity, maximum_desired_capacity)); // Should not be greater than the heap max size. No need to adjust @@ -2332,7 +2332,7 @@ virtual bool doHeapRegion(HeapRegion* hr) { unsigned region_gc_time_stamp = hr->get_gc_time_stamp(); if (_gc_time_stamp != region_gc_time_stamp) { - gclog_or_tty->print_cr("Region "HR_FORMAT" has GC time stamp = %d, " + gclog_or_tty->print_cr("Region " HR_FORMAT " has GC time stamp = %d, " "expected %d", HR_FORMAT_PARAMS(hr), region_gc_time_stamp, _gc_time_stamp); _failures = true; @@ -2487,7 +2487,7 @@ // is set) so that if a waiter requests another System.gc() it doesn't // incorrectly see that a marking cycle is still in progress. if (concurrent) { - _cmThread->clear_in_progress(); + _cmThread->set_idle(); } // This notify_all() will ensure that a thread that called @@ -2926,10 +2926,10 @@ if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); if (_g1h->is_obj_dead_cond(obj, _vo)) { - gclog_or_tty->print_cr("Root location "PTR_FORMAT" " - "points to dead obj "PTR_FORMAT, p2i(p), p2i(obj)); + gclog_or_tty->print_cr("Root location " PTR_FORMAT " " + "points to dead obj " PTR_FORMAT, p2i(p), p2i(obj)); if (_vo == VerifyOption_G1UseMarkWord) { - gclog_or_tty->print_cr(" Mark word: "INTPTR_FORMAT, (intptr_t)obj->mark()); + gclog_or_tty->print_cr(" Mark word: " INTPTR_FORMAT, (intptr_t)obj->mark()); } obj->print_on(gclog_or_tty); _failures = true; @@ -2976,9 +2976,9 @@ // Verify that the strong code root list for this region // contains the nmethod if (!hrrs->strong_code_roots_list_contains(_nm)) { - gclog_or_tty->print_cr("Code root location "PTR_FORMAT" " - "from nmethod "PTR_FORMAT" not in strong " - "code roots for region ["PTR_FORMAT","PTR_FORMAT")", + gclog_or_tty->print_cr("Code root location " PTR_FORMAT " " + "from nmethod " PTR_FORMAT " not in strong " + "code roots for region [" PTR_FORMAT "," PTR_FORMAT ")", p2i(p), p2i(_nm), p2i(hr->bottom()), p2i(hr->end())); _failures = true; } @@ -3157,9 +3157,9 @@ r->object_iterate(¬_dead_yet_cl); if (_vo != VerifyOption_G1UseNextMarking) { if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) { - gclog_or_tty->print_cr("["PTR_FORMAT","PTR_FORMAT"] " - "max_live_bytes "SIZE_FORMAT" " - "< calculated "SIZE_FORMAT, + gclog_or_tty->print_cr("[" PTR_FORMAT "," PTR_FORMAT "] " + "max_live_bytes " SIZE_FORMAT " " + "< calculated " SIZE_FORMAT, p2i(r->bottom()), p2i(r->end()), r->max_live_bytes(), not_dead_yet_cl.live_bytes()); @@ -3444,7 +3444,7 @@ size_t occupied = hrrs->occupied(); _occupied_sum += occupied; - gclog_or_tty->print_cr("Printing RSet for region "HR_FORMAT, + gclog_or_tty->print_cr("Printing RSet for region " HR_FORMAT, HR_FORMAT_PARAMS(r)); if (occupied == 0) { gclog_or_tty->print_cr(" RSet is empty"); @@ -3463,7 +3463,7 @@ } ~PrintRSetsClosure() { - gclog_or_tty->print_cr("Occupied Sum: "SIZE_FORMAT, _occupied_sum); + gclog_or_tty->print_cr("Occupied Sum: " SIZE_FORMAT, _occupied_sum); gclog_or_tty->print_cr("========================================"); gclog_or_tty->cr(); } @@ -4273,7 +4273,7 @@ void G1CollectedHeap::remove_self_forwarding_pointers() { double remove_self_forwards_start = os::elapsedTime(); - G1ParRemoveSelfForwardPtrsTask rsfp_task(this); + G1ParRemoveSelfForwardPtrsTask rsfp_task; workers()->run_task(&rsfp_task); // Now restore saved marks, if any. @@ -4308,7 +4308,7 @@ G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state, oop old) { assert(obj_in_cs(old), - err_msg("obj: "PTR_FORMAT" should still be in the CSet", + err_msg("obj: " PTR_FORMAT " should still be in the CSet", p2i(old))); markOop m = old->mark(); oop forward_ptr = old->forward_to_atomic(old); @@ -4342,7 +4342,7 @@ // space for this object (old != forward_ptr) or they beat us in // self-forwarding it (old == forward_ptr). assert(old == forward_ptr || !obj_in_cs(forward_ptr), - err_msg("obj: "PTR_FORMAT" forwarded to: "PTR_FORMAT" " + err_msg("obj: " PTR_FORMAT " forwarded to: " PTR_FORMAT " " "should not be in the CSet", p2i(old), p2i(forward_ptr))); return forward_ptr; @@ -4730,8 +4730,8 @@ if (G1TraceStringSymbolTableScrubbing) { gclog_or_tty->print_cr("Cleaned string and symbol table, " - "strings: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed, " - "symbols: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed", + "strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, " + "symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed", strings_processed(), strings_removed(), symbols_processed(), symbols_removed()); } @@ -5644,7 +5644,7 @@ phase_times->record_string_dedup_fixup_time(fixup_time_ms); } - _allocator->release_gc_alloc_regions(n_workers, evacuation_info); + _allocator->release_gc_alloc_regions(evacuation_info); g1_rem_set()->cleanup_after_oops_into_collection_set_do(); // Reset and re-enable the hot card cache. @@ -5828,13 +5828,13 @@ bool G1CollectedHeap::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap, HeapWord* tams, HeapWord* end) { guarantee(tams <= end, - err_msg("tams: "PTR_FORMAT" end: "PTR_FORMAT, p2i(tams), p2i(end))); + err_msg("tams: " PTR_FORMAT " end: " PTR_FORMAT, p2i(tams), p2i(end))); HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end); if (result < end) { gclog_or_tty->cr(); - gclog_or_tty->print_cr("## wrong marked address on %s bitmap: "PTR_FORMAT, + gclog_or_tty->print_cr("## wrong marked address on %s bitmap: " PTR_FORMAT, bitmap_name, p2i(result)); - gclog_or_tty->print_cr("## %s tams: "PTR_FORMAT" end: "PTR_FORMAT, + gclog_or_tty->print_cr("## %s tams: " PTR_FORMAT " end: " PTR_FORMAT, bitmap_name, p2i(tams), p2i(end)); return false; } @@ -5860,7 +5860,7 @@ res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end); } if (!res_p || !res_n) { - gclog_or_tty->print_cr("#### Bitmap verification failed for "HR_FORMAT, + gclog_or_tty->print_cr("#### Bitmap verification failed for " HR_FORMAT, HR_FORMAT_PARAMS(hr)); gclog_or_tty->print_cr("#### Caller: %s", caller); return false; @@ -6157,7 +6157,7 @@ !r->rem_set()->is_empty()) { if (G1TraceEagerReclaimHumongousObjects) { - gclog_or_tty->print_cr("Live humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length %u with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d reclaim candidate %d type array %d", + gclog_or_tty->print_cr("Live humongous region %u size " SIZE_FORMAT " start " PTR_FORMAT " length %u with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d", region_idx, (size_t)obj->size() * HeapWordSize, p2i(r->bottom()), @@ -6179,7 +6179,7 @@ p2i(r->bottom()))); if (G1TraceEagerReclaimHumongousObjects) { - gclog_or_tty->print_cr("Dead humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length %u with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d reclaim candidate %d type array %d", + gclog_or_tty->print_cr("Dead humongous region %u size " SIZE_FORMAT " start " PTR_FORMAT " length %u with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d", region_idx, (size_t)obj->size() * HeapWordSize, p2i(r->bottom()), @@ -6333,7 +6333,7 @@ NoYoungRegionsClosure() : _success(true) { } bool doHeapRegion(HeapRegion* r) { if (r->is_young()) { - gclog_or_tty->print_cr("Region ["PTR_FORMAT", "PTR_FORMAT") tagged as young", + gclog_or_tty->print_cr("Region [" PTR_FORMAT ", " PTR_FORMAT ") tagged as young", p2i(r->bottom()), p2i(r->end())); _success = false; } @@ -6470,7 +6470,7 @@ } assert(_allocator->used_unlocked() == recalculate_used(), err_msg("inconsistent _allocator->used_unlocked(), " - "value: "SIZE_FORMAT" recalculated: "SIZE_FORMAT, + "value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT, _allocator->used_unlocked(), recalculate_used())); } @@ -6697,8 +6697,8 @@ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing(obj); assert(!hr->is_continues_humongous(), - err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT - " starting at "HR_FORMAT, + err_msg("trying to add code root " PTR_FORMAT " in continuation of humongous region " HR_FORMAT + " starting at " HR_FORMAT, p2i(_nm), HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); // HeapRegion::add_strong_code_root_locked() avoids adding duplicate entries. @@ -6724,8 +6724,8 @@ oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); HeapRegion* hr = _g1h->heap_region_containing(obj); assert(!hr->is_continues_humongous(), - err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT - " starting at "HR_FORMAT, + err_msg("trying to remove code root " PTR_FORMAT " in continuation of humongous region " HR_FORMAT + " starting at " HR_FORMAT, p2i(_nm), HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()))); hr->remove_strong_code_root(_nm); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -281,7 +281,7 @@ void init_gc_alloc_regions(EvacuationInfo& evacuation_info); // It releases the GC alloc regions at the end of a GC. - void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info); + void release_gc_alloc_regions(EvacuationInfo& evacuation_info); // It does any cleanup that needs to be done on the GC alloc regions // before a Full GC. @@ -1109,6 +1109,8 @@ // The STW reference processor.... ReferenceProcessor* ref_processor_stw() const { return _ref_processor_stw; } + G1NewTracer* gc_tracer_stw() const { return _gc_tracer_stw; } + // The Concurrent Marking reference processor... ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -49,7 +49,7 @@ } size_t G1CollectedHeap::desired_plab_sz(InCSetState dest) { - size_t gclab_word_size = alloc_buffer_stats(dest)->desired_plab_sz(); + size_t gclab_word_size = alloc_buffer_stats(dest)->desired_plab_sz(G1CollectedHeap::heap()->workers()->active_workers()); // Prevent humongous PLAB sizes for two reasons: // * PLABs are allocated using a similar paths as oops, but should // never be in a humongous region @@ -82,7 +82,7 @@ inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const { assert(is_in_reserved(addr), - err_msg("Cannot calculate region index for address "PTR_FORMAT" that is outside of the heap ["PTR_FORMAT", "PTR_FORMAT")", + err_msg("Cannot calculate region index for address " PTR_FORMAT " that is outside of the heap [" PTR_FORMAT ", " PTR_FORMAT ")", p2i(addr), p2i(reserved_region().start()), p2i(reserved_region().end()))); return (uint)(pointer_delta(addr, reserved_region().start(), sizeof(uint8_t)) >> HeapRegion::LogOfHRGrainBytes); } @@ -95,7 +95,7 @@ inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const { assert(addr != NULL, "invariant"); assert(is_in_g1_reserved((const void*) addr), - err_msg("Address "PTR_FORMAT" is outside of the heap ranging from ["PTR_FORMAT" to "PTR_FORMAT")", + err_msg("Address " PTR_FORMAT " is outside of the heap ranging from [" PTR_FORMAT " to " PTR_FORMAT ")", p2i((void*)addr), p2i(g1_reserved().start()), p2i(g1_reserved().end()))); return _hrm.addr_to_region((HeapWord*) addr); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -184,7 +184,7 @@ const size_t region_size = HeapRegion::GrainWords; if (YoungPLABSize > region_size || OldPLABSize > region_size) { char buffer[128]; - jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most "SIZE_FORMAT, + jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most " SIZE_FORMAT, OldPLABSize > region_size ? "Old" : "Young", region_size); vm_exit_during_initialization(buffer); } @@ -821,7 +821,7 @@ update_survivors_policy(); assert(_g1->used() == _g1->recalculate_used(), - err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT, + err_msg("sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT, _g1->used(), _g1->recalculate_used())); double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; @@ -865,7 +865,7 @@ _cur_mark_stop_world_time_ms += elapsed_time_ms; _prev_collection_pause_end_ms += elapsed_time_ms; - _mmu_tracker->add_pause(_mark_remark_start_sec, end_time_sec, true); + _mmu_tracker->add_pause(_mark_remark_start_sec, end_time_sec, _g1->gc_tracer_cm()->gc_id()); } void G1CollectorPolicy::record_concurrent_mark_cleanup_start() { @@ -961,7 +961,7 @@ } _mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0, - end_time_sec, false); + end_time_sec, _g1->gc_tracer_stw()->gc_id()); evacuation_info.set_collectionset_used_before(_collection_set_bytes_used_before); evacuation_info.set_bytes_copied(_bytes_copied_during_gc); @@ -1216,10 +1216,10 @@ (_young_list_target_length * HeapRegion::GrainBytes) - survivor_used_bytes_after_gc; gclog_or_tty->print( - " [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") " - "Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" " - "Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->" - EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]", + " [Eden: " EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ")->" EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ") " + "Survivors: " EXT_SIZE_FORMAT "->" EXT_SIZE_FORMAT " " + "Heap: " EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ")->" + EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ")]", EXT_SIZE_PARAMS(_eden_used_bytes_before_gc), EXT_SIZE_PARAMS(_eden_capacity_bytes_before_gc), EXT_SIZE_PARAMS(eden_used_bytes_after_gc), @@ -1597,7 +1597,7 @@ _concurrent_mark_cleanup_times_ms->add(elapsed_time_ms); _cur_mark_stop_world_time_ms += elapsed_time_ms; _prev_collection_pause_end_ms += elapsed_time_ms; - _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_sec, true); + _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_sec, _g1->gc_tracer_cm()->gc_id()); } // Add the heap region at the head of the non-incremental collection set @@ -1787,7 +1787,7 @@ while (csr != NULL) { HeapRegion* next = csr->next_in_collection_set(); assert(csr->in_collection_set(), "bad CS"); - st->print_cr(" "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d", + st->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d", HR_FORMAT_PARAMS(csr), p2i(csr->prev_top_at_mark_start()), p2i(csr->next_top_at_mark_start()), csr->age_in_surv_rate_group_cond()); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1ErgoVerbose.hpp --- a/hotspot/src/share/vm/gc/g1/g1ErgoVerbose.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1ErgoVerbose.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -121,15 +121,15 @@ // Single parameter format strings #define ergo_format_str(_name_) ", " _name_ ": %s" #define ergo_format_region(_name_) ", " _name_ ": %u regions" -#define ergo_format_byte(_name_) ", " _name_ ": "SIZE_FORMAT" bytes" +#define ergo_format_byte(_name_) ", " _name_ ": " SIZE_FORMAT " bytes" #define ergo_format_double(_name_) ", " _name_ ": %1.2f" #define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%" #define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms" -#define ergo_format_size(_name_) ", " _name_ ": "SIZE_FORMAT +#define ergo_format_size(_name_) ", " _name_ ": " SIZE_FORMAT // Double parameter format strings #define ergo_format_byte_perc(_name_) \ - ", " _name_ ": "SIZE_FORMAT" bytes (%1.2f %%)" + ", " _name_ ": " SIZE_FORMAT " bytes (%1.2f %%)" // Generates the format string #define ergo_format(_extra_format_) \ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -40,8 +40,8 @@ G1SATBCardTableModRefBS* _ct_bs; public: - UpdateRSetDeferred(G1CollectedHeap* g1, DirtyCardQueue* dcq) : - _g1(g1), _ct_bs(_g1->g1_barrier_set()), _dcq(dcq) {} + UpdateRSetDeferred(DirtyCardQueue* dcq) : + _g1(G1CollectedHeap::heap()), _ct_bs(_g1->g1_barrier_set()), _dcq(dcq) {} virtual void do_oop(narrowOop* p) { do_oop_work(p); } virtual void do_oop( oop* p) { do_oop_work(p); } @@ -65,60 +65,41 @@ size_t _marked_bytes; OopsInHeapRegionClosure *_update_rset_cl; bool _during_initial_mark; - bool _during_conc_mark; uint _worker_id; - HeapWord* _end_of_last_gap; - HeapWord* _last_gap_threshold; - HeapWord* _last_obj_threshold; + HeapWord* _last_forwarded_object_end; public: - RemoveSelfForwardPtrObjClosure(G1CollectedHeap* g1, ConcurrentMark* cm, - HeapRegion* hr, + RemoveSelfForwardPtrObjClosure(HeapRegion* hr, OopsInHeapRegionClosure* update_rset_cl, bool during_initial_mark, - bool during_conc_mark, uint worker_id) : - _g1(g1), _cm(cm), _hr(hr), _marked_bytes(0), + _g1(G1CollectedHeap::heap()), + _cm(_g1->concurrent_mark()), + _hr(hr), + _marked_bytes(0), _update_rset_cl(update_rset_cl), _during_initial_mark(during_initial_mark), - _during_conc_mark(during_conc_mark), _worker_id(worker_id), - _end_of_last_gap(hr->bottom()), - _last_gap_threshold(hr->bottom()), - _last_obj_threshold(hr->bottom()) { } + _last_forwarded_object_end(hr->bottom()) { } size_t marked_bytes() { return _marked_bytes; } - // - // The original idea here was to coalesce evacuated and dead objects. - // However that caused complications with the block offset table (BOT). - // In particular if there were two TLABs, one of them partially refined. - // |----- TLAB_1--------|----TLAB_2-~~~(partially refined part)~~~| - // The BOT entries of the unrefined part of TLAB_2 point to the start - // of TLAB_2. If the last object of the TLAB_1 and the first object - // of TLAB_2 are coalesced, then the cards of the unrefined part - // would point into middle of the filler object. - // The current approach is to not coalesce and leave the BOT contents intact. - // - // - // We now reset the BOT when we start the object iteration over the - // region and refine its entries for every object we come across. So - // the above comment is not really relevant and we should be able - // to coalesce dead objects if we want to. + // Iterate over the live objects in the region to find self-forwarded objects + // that need to be kept live. We need to update the remembered sets of these + // objects. Further update the BOT and marks. + // We can coalesce and overwrite the remaining heap contents with dummy objects + // as they have either been dead or evacuated (which are unreferenced now, i.e. + // dead too) already. void do_object(oop obj) { HeapWord* obj_addr = (HeapWord*) obj; assert(_hr->is_in(obj_addr), "sanity"); size_t obj_size = obj->size(); HeapWord* obj_end = obj_addr + obj_size; - if (_end_of_last_gap != obj_addr) { - // there was a gap before obj_addr - _last_gap_threshold = _hr->cross_threshold(_end_of_last_gap, obj_addr); - } - if (obj->is_forwarded() && obj->forwardee() == obj) { // The object failed to move. + zap_dead_objects(_last_forwarded_object_end, obj_addr); // We consider all objects that we find self-forwarded to be // live. What we'll do is that we'll update the prev marking // info so that they are all under PTAMS and explicitly marked. @@ -154,24 +135,52 @@ // remembered set entries missing given that we skipped cards on // the collection set. So, we'll recreate such entries now. obj->oop_iterate(_update_rset_cl); - } else { + + _last_forwarded_object_end = obj_end; + _hr->cross_threshold(obj_addr, obj_end); + } + } + + // Fill the memory area from start to end with filler objects, and update the BOT + // and the mark bitmap accordingly. + void zap_dead_objects(HeapWord* start, HeapWord* end) { + if (start == end) { + return; + } + + size_t gap_size = pointer_delta(end, start); + MemRegion mr(start, gap_size); + if (gap_size >= CollectedHeap::min_fill_size()) { + CollectedHeap::fill_with_objects(start, gap_size); - // The object has been either evacuated or is dead. Fill it with a - // dummy object. - MemRegion mr(obj_addr, obj_size); - CollectedHeap::fill_with_object(mr); + HeapWord* end_first_obj = start + ((oop)start)->size(); + _hr->cross_threshold(start, end_first_obj); + // Fill_with_objects() may have created multiple (i.e. two) + // objects, as the max_fill_size() is half a region. + // After updating the BOT for the first object, also update the + // BOT for the second object to make the BOT complete. + if (end_first_obj != end) { + _hr->cross_threshold(end_first_obj, end); +#ifdef ASSERT + size_t size_second_obj = ((oop)end_first_obj)->size(); + HeapWord* end_of_second_obj = end_first_obj + size_second_obj; + assert(end == end_of_second_obj, + err_msg("More than two objects were used to fill the area from " PTR_FORMAT " to " PTR_FORMAT ", " + "second objects size " SIZE_FORMAT " ends at " PTR_FORMAT, + p2i(start), p2i(end), size_second_obj, p2i(end_of_second_obj))); +#endif + } + } + _cm->clearRangePrevBitmap(mr); + } - // must nuke all dead objects which we skipped when iterating over the region - _cm->clearRangePrevBitmap(MemRegion(_end_of_last_gap, obj_end)); - } - _end_of_last_gap = obj_end; - _last_obj_threshold = _hr->cross_threshold(obj_addr, obj_end); + void zap_remainder() { + zap_dead_objects(_last_forwarded_object_end, _hr->top()); } }; class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; - ConcurrentMark* _cm; uint _worker_id; HeapRegionClaimer* _hrclaimer; @@ -179,11 +188,27 @@ UpdateRSetDeferred _update_rset_cl; public: - RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h, - uint worker_id, + RemoveSelfForwardPtrHRClosure(uint worker_id, HeapRegionClaimer* hrclaimer) : - _g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq), - _worker_id(worker_id), _cm(_g1h->concurrent_mark()), _hrclaimer(hrclaimer) { + _g1h(G1CollectedHeap::heap()), + _dcq(&_g1h->dirty_card_queue_set()), + _update_rset_cl(&_dcq), + _worker_id(worker_id), + _hrclaimer(hrclaimer) { + } + + size_t remove_self_forward_ptr_by_walking_hr(HeapRegion* hr, + bool during_initial_mark) { + RemoveSelfForwardPtrObjClosure rspc(hr, + &_update_rset_cl, + during_initial_mark, + _worker_id); + _update_rset_cl.set_region(hr); + hr->object_iterate(&rspc); + // Need to zap the remainder area of the processed region. + rspc.zap_remainder(); + + return rspc.marked_bytes(); } bool doHeapRegion(HeapRegion *hr) { @@ -195,11 +220,6 @@ if (_hrclaimer->claim_region(hr->hrm_index())) { if (hr->evacuation_failed()) { - RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl, - during_initial_mark, - during_conc_mark, - _worker_id); - hr->note_self_forwarding_removal_start(during_initial_mark, during_conc_mark); _g1h->check_bitmaps("Self-Forwarding Ptr Removal", hr); @@ -214,26 +234,27 @@ // whenever this might be required in the future. hr->rem_set()->reset_for_par_iteration(); hr->reset_bot(); - _update_rset_cl.set_region(hr); - hr->object_iterate(&rspc); + + size_t live_bytes = remove_self_forward_ptr_by_walking_hr(hr, during_initial_mark); hr->rem_set()->clean_strong_code_roots(hr); hr->note_self_forwarding_removal_end(during_initial_mark, during_conc_mark, - rspc.marked_bytes()); + live_bytes); } } return false; } }; -G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) : - AbstractGangTask("G1 Remove Self-forwarding Pointers"), _g1h(g1h), - _hrclaimer(g1h->workers()->active_workers()) {} +G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask() : + AbstractGangTask("G1 Remove Self-forwarding Pointers"), + _g1h(G1CollectedHeap::heap()), + _hrclaimer(_g1h->workers()->active_workers()) { } void G1ParRemoveSelfForwardPtrsTask::work(uint worker_id) { - RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id, &_hrclaimer); + RemoveSelfForwardPtrHRClosure rsfp_cl(worker_id, &_hrclaimer); HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id); _g1h->collection_set_iterate_from(hr, &rsfp_cl); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -40,7 +40,7 @@ HeapRegionClaimer _hrclaimer; public: - G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h); + G1ParRemoveSelfForwardPtrsTask(); void work(uint worker_id); }; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -331,7 +331,7 @@ } void G1GCPhaseTimes::print_stats(int level, const char* str, size_t value) { - LineBuffer(level).append_and_print_cr("[%s: "SIZE_FORMAT"]", str, value); + LineBuffer(level).append_and_print_cr("[%s: " SIZE_FORMAT "]", str, value); } void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) { @@ -451,7 +451,7 @@ if (phase->_thread_work_items != NULL) { LineBuffer buf2(phase->_thread_work_items->_indent_level); - buf2.append_and_print_cr("[%s: "SIZE_FORMAT"]", phase->_thread_work_items->_title, _phase_times->sum_thread_work_items(phase_id)); + buf2.append_and_print_cr("[%s: " SIZE_FORMAT "]", phase->_thread_work_items->_title, _phase_times->sum_thread_work_items(phase_id)); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp --- a/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1HRPrinter.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -83,18 +83,18 @@ if (type_str != NULL) { if (top != NULL) { - gclog_or_tty->print_cr(G1HR_PREFIX" %s(%s) "PTR_FORMAT" "PTR_FORMAT, + gclog_or_tty->print_cr(G1HR_PREFIX " %s(%s) " PTR_FORMAT " " PTR_FORMAT, action_str, type_str, p2i(bottom), p2i(top)); } else { - gclog_or_tty->print_cr(G1HR_PREFIX" %s(%s) "PTR_FORMAT, + gclog_or_tty->print_cr(G1HR_PREFIX " %s(%s) " PTR_FORMAT, action_str, type_str, p2i(bottom)); } } else { if (top != NULL) { - gclog_or_tty->print_cr(G1HR_PREFIX" %s "PTR_FORMAT" "PTR_FORMAT, + gclog_or_tty->print_cr(G1HR_PREFIX " %s " PTR_FORMAT " " PTR_FORMAT, action_str, p2i(bottom), p2i(top)); } else { - gclog_or_tty->print_cr(G1HR_PREFIX" %s "PTR_FORMAT, + gclog_or_tty->print_cr(G1HR_PREFIX " %s " PTR_FORMAT, action_str, p2i(bottom)); } } @@ -103,11 +103,11 @@ void G1HRPrinter::print(ActionType action, HeapWord* bottom, HeapWord* end) { const char* action_str = action_name(action); - gclog_or_tty->print_cr(G1HR_PREFIX" %s ["PTR_FORMAT","PTR_FORMAT"]", + gclog_or_tty->print_cr(G1HR_PREFIX " %s [" PTR_FORMAT "," PTR_FORMAT "]", action_str, p2i(bottom), p2i(end)); } void G1HRPrinter::print(PhaseType phase, size_t phase_num) { const char* phase_str = phase_name(phase); - gclog_or_tty->print_cr(G1HR_PREFIX" #%s "SIZE_FORMAT, phase_str, phase_num); + gclog_or_tty->print_cr(G1HR_PREFIX " #%s " SIZE_FORMAT, phase_str, phase_num); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1InCSetState.hpp --- a/hotspot/src/share/vm/gc/g1/g1InCSetState.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1InCSetState.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -104,7 +104,7 @@ public: void set_humongous(uintptr_t index) { assert(get_by_index(index).is_default(), - err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); + err_msg("State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); set_by_index(index, InCSetState::Humongous); } @@ -114,13 +114,13 @@ void set_in_young(uintptr_t index) { assert(get_by_index(index).is_default(), - err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); + err_msg("State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); set_by_index(index, InCSetState::Young); } void set_in_old(uintptr_t index) { assert(get_by_index(index).is_default(), - err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); + err_msg("State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); set_by_index(index, InCSetState::Old); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1MMUTracker.cpp --- a/hotspot/src/share/vm/gc/g1/g1MMUTracker.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1MMUTracker.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "gc/g1/g1MMUTracker.hpp" +#include "gc/shared/gcTrace.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/ostream.hpp" @@ -75,7 +76,7 @@ return gc_time; } -void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) { +void G1MMUTrackerQueue::add_pause(double start, double end, const GCId& gcId) { double duration = end - start; remove_expired_entries(end); @@ -102,6 +103,10 @@ ++_no_entries; } _array[_head_index] = G1MMUTrackerQueueElem(start, end); + + // Current entry needs to be added before calculating the value + double slice_time = calculate_gc_time(end); + G1MMUTracer::report_mmu(gcId, _time_slice, slice_time, _max_gc_time); } // basically the _internal call does not remove expired entries diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp --- a/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1MMUTracker.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_G1_G1MMUTRACKER_HPP #define SHARE_VM_GC_G1_G1MMUTRACKER_HPP +#include "gc/shared/gcId.hpp" #include "memory/allocation.hpp" #include "utilities/debug.hpp" @@ -42,7 +43,7 @@ public: G1MMUTracker(double time_slice, double max_gc_time); - virtual void add_pause(double start, double end, bool gc_thread) = 0; + virtual void add_pause(double start, double end, const GCId& gcId) = 0; virtual double when_sec(double current_time, double pause_time) = 0; double max_gc_time() { @@ -126,7 +127,7 @@ public: G1MMUTrackerQueue(double time_slice, double max_gc_time); - virtual void add_pause(double start, double end, bool gc_thread); + virtual void add_pause(double start, double end, const GCId& gcId); virtual double when_sec(double current_time, double pause_time); }; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp --- a/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1OopClosures.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -118,7 +118,7 @@ oop obj = oopDesc::load_decode_heap_oop(p); if (_cm->verbose_high()) { gclog_or_tty->print_cr("[%u] we're looking at location " - "*"PTR_FORMAT" = "PTR_FORMAT, + "*" PTR_FORMAT " = " PTR_FORMAT, _task->worker_id(), p2i(p), p2i((void*) obj)); } _task->deal_with_reference(obj); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1RemSet.cpp --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -424,7 +424,7 @@ bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i, bool check_for_refs_into_cset) { assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)), - err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap", + err_msg("Card at " PTR_FORMAT " index " SIZE_FORMAT " representing heap at " PTR_FORMAT " (%u) must be in committed heap", p2i(card_ptr), _ct_bs->index_for(_ct_bs->addr_for(card_ptr)), p2i(_ct_bs->addr_for(card_ptr)), diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp --- a/hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1RemSetSummary.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -187,22 +187,22 @@ size_t code_root_elems() const { return _code_root_elems; } void print_rs_mem_info_on(outputStream * out, size_t total) { - out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions", + out->print_cr(" " SIZE_FORMAT_W(8) "K (%5.1f%%) by " SIZE_FORMAT " %s regions", round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name); } void print_cards_occupied_info_on(outputStream * out, size_t total) { - out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) entries by "SIZE_FORMAT" %s regions", + out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) entries by " SIZE_FORMAT " %s regions", cards_occupied(), cards_occupied_percent_of(total), amount(), _name); } void print_code_root_mem_info_on(outputStream * out, size_t total) { - out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions", + out->print_cr(" " SIZE_FORMAT_W(8) "K (%5.1f%%) by " SIZE_FORMAT " %s regions", round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name); } void print_code_root_elems_info_on(outputStream * out, size_t total) { - out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) elements by "SIZE_FORMAT" %s regions", + out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) elements by " SIZE_FORMAT " %s regions", code_root_elems(), code_root_elems_percent_of(total), amount(), _name); } }; @@ -280,19 +280,19 @@ RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL }; out->print_cr("\n Current rem set statistics"); - out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K." - " Max = "SIZE_FORMAT"K.", + out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "K." + " Max = " SIZE_FORMAT "K.", round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz())); for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_rs_mem_info_on(out, total_rs_mem_sz()); } - out->print_cr(" Static structures = "SIZE_FORMAT"K," - " free_lists = "SIZE_FORMAT"K.", + out->print_cr(" Static structures = " SIZE_FORMAT "K," + " free_lists = " SIZE_FORMAT "K.", round_to_K(HeapRegionRemSet::static_mem_size()), round_to_K(HeapRegionRemSet::fl_mem_size())); - out->print_cr(" "SIZE_FORMAT" occupied cards represented.", + out->print_cr(" " SIZE_FORMAT " occupied cards represented.", total_cards_occupied()); for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_cards_occupied_info_on(out, total_cards_occupied()); @@ -300,30 +300,30 @@ // Largest sized rem set region statistics HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set(); - out->print_cr(" Region with largest rem set = "HR_FORMAT", " - "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.", + out->print_cr(" Region with largest rem set = " HR_FORMAT ", " + "size = " SIZE_FORMAT "K, occupied = " SIZE_FORMAT "K.", HR_FORMAT_PARAMS(max_rs_mem_sz_region()), round_to_K(rem_set->mem_size()), round_to_K(rem_set->occupied())); // Strong code root statistics HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); - out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K." - " Max = "SIZE_FORMAT"K.", + out->print_cr(" Total heap region code root sets sizes = " SIZE_FORMAT "K." + " Max = " SIZE_FORMAT "K.", round_to_K(total_code_root_mem_sz()), round_to_K(max_code_root_rem_set->strong_code_roots_mem_size())); for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz()); } - out->print_cr(" "SIZE_FORMAT" code roots represented.", + out->print_cr(" " SIZE_FORMAT " code roots represented.", total_code_root_elems()); for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { (*current)->print_code_root_elems_info_on(out, total_code_root_elems()); } - out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", " - "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".", + out->print_cr(" Region with largest amount of code roots = " HR_FORMAT ", " + "size = " SIZE_FORMAT "K, num_elems = " SIZE_FORMAT ".", HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()), round_to_K(max_code_root_rem_set->strong_code_roots_list_length())); @@ -332,16 +332,16 @@ void G1RemSetSummary::print_on(outputStream* out) { out->print_cr("\n Recent concurrent refinement statistics"); - out->print_cr(" Processed "SIZE_FORMAT" cards", + out->print_cr(" Processed " SIZE_FORMAT " cards", num_concurrent_refined_cards()); - out->print_cr(" Of "SIZE_FORMAT" completed buffers:", num_processed_buf_total()); - out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by concurrent RS threads.", + out->print_cr(" Of " SIZE_FORMAT " completed buffers:", num_processed_buf_total()); + out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by concurrent RS threads.", num_processed_buf_total(), percent_of(num_processed_buf_rs_threads(), num_processed_buf_total())); - out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by mutator threads.", + out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by mutator threads.", num_processed_buf_mutator(), percent_of(num_processed_buf_mutator(), num_processed_buf_total())); - out->print_cr(" Did "SIZE_FORMAT" coarsenings.", num_coarsenings()); + out->print_cr(" Did " SIZE_FORMAT " coarsenings.", num_coarsenings()); out->print_cr(" Concurrent RS threads times (s)"); out->print(" "); for (uint i = 0; i < _num_vtimes; i++) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1StringDedupQueue.cpp --- a/hotspot/src/share/vm/gc/g1/g1StringDedupQueue.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1StringDedupQueue.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -155,7 +155,7 @@ void G1StringDedupQueue::print_statistics(outputStream* st) { st->print_cr( " [Queue]\n" - " [Dropped: "UINTX_FORMAT"]", _queue->_dropped); + " [Dropped: " UINTX_FORMAT "]", _queue->_dropped); } void G1StringDedupQueue::verify() { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1StringDedupStat.cpp --- a/hotspot/src/share/vm/gc/g1/g1StringDedupStat.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1StringDedupStat.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -80,8 +80,8 @@ st->stamp(PrintGCTimeStamps); st->print_cr( "[GC concurrent-string-deduplication, " - G1_STRDEDUP_BYTES_FORMAT_NS"->"G1_STRDEDUP_BYTES_FORMAT_NS"("G1_STRDEDUP_BYTES_FORMAT_NS"), avg " - G1_STRDEDUP_PERCENT_FORMAT_NS", "G1_STRDEDUP_TIME_FORMAT"]", + G1_STRDEDUP_BYTES_FORMAT_NS "->" G1_STRDEDUP_BYTES_FORMAT_NS "(" G1_STRDEDUP_BYTES_FORMAT_NS "), avg " + G1_STRDEDUP_PERCENT_FORMAT_NS ", " G1_STRDEDUP_TIME_FORMAT "]", G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes), G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes - last_stat._deduped_bytes), G1_STRDEDUP_BYTES_PARAM(last_stat._deduped_bytes), @@ -135,22 +135,22 @@ if (total) { st->print_cr( - " [Total Exec: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT", Idle: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT", Blocked: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT"]", + " [Total Exec: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Idle: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]", stat._exec, stat._exec_elapsed, stat._idle, stat._idle_elapsed, stat._block, stat._block_elapsed); } else { st->print_cr( - " [Last Exec: "G1_STRDEDUP_TIME_FORMAT", Idle: "G1_STRDEDUP_TIME_FORMAT", Blocked: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT"]", + " [Last Exec: " G1_STRDEDUP_TIME_FORMAT ", Idle: " G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]", stat._exec_elapsed, stat._idle_elapsed, stat._block, stat._block_elapsed); } st->print_cr( - " [Inspected: "G1_STRDEDUP_OBJECTS_FORMAT"]\n" - " [Skipped: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n" - " [Hashed: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n" - " [Known: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n" - " [New: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"]\n" - " [Deduplicated: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n" - " [Young: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n" - " [Old: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]", + " [Inspected: " G1_STRDEDUP_OBJECTS_FORMAT "]\n" + " [Skipped: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n" + " [Hashed: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n" + " [Known: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n" + " [New: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "]\n" + " [Deduplicated: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n" + " [Young: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n" + " [Old: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]", stat._inspected, stat._skipped, skipped_percent, stat._hashed, hashed_percent, diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp --- a/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/g1StringDedupTable.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -556,12 +556,12 @@ void G1StringDedupTable::print_statistics(outputStream* st) { st->print_cr( " [Table]\n" - " [Memory Usage: "G1_STRDEDUP_BYTES_FORMAT_NS"]\n" - " [Size: "SIZE_FORMAT", Min: "SIZE_FORMAT", Max: "SIZE_FORMAT"]\n" - " [Entries: "UINTX_FORMAT", Load: "G1_STRDEDUP_PERCENT_FORMAT_NS", Cached: " UINTX_FORMAT ", Added: "UINTX_FORMAT", Removed: "UINTX_FORMAT"]\n" - " [Resize Count: "UINTX_FORMAT", Shrink Threshold: "UINTX_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT_NS"), Grow Threshold: "UINTX_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT_NS")]\n" - " [Rehash Count: "UINTX_FORMAT", Rehash Threshold: "UINTX_FORMAT", Hash Seed: 0x%x]\n" - " [Age Threshold: "UINTX_FORMAT"]", + " [Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS "]\n" + " [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]\n" + " [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]\n" + " [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]\n" + " [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x]\n" + " [Age Threshold: " UINTX_FORMAT "]", G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)), _table->_size, _min_size, _max_size, _table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed, diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegion.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -327,7 +327,7 @@ bool during_conc_mark, size_t marked_bytes) { assert(marked_bytes <= used(), - err_msg("marked: "SIZE_FORMAT" used: "SIZE_FORMAT, marked_bytes, used())); + err_msg("marked: " SIZE_FORMAT " used: " SIZE_FORMAT, marked_bytes, used())); _prev_top_at_mark_start = top(); _prev_marked_bytes = marked_bytes; } @@ -504,9 +504,9 @@ // Object is in the region. Check that its less than top if (_hr->top() <= (HeapWord*)obj) { // Object is above top - gclog_or_tty->print_cr("Object "PTR_FORMAT" in region " - "["PTR_FORMAT", "PTR_FORMAT") is above " - "top "PTR_FORMAT, + gclog_or_tty->print_cr("Object " PTR_FORMAT " in region " + "[" PTR_FORMAT ", " PTR_FORMAT ") is above " + "top " PTR_FORMAT, p2i(obj), p2i(_hr->bottom()), p2i(_hr->end()), p2i(_hr->top())); _failures = true; return; @@ -540,22 +540,22 @@ if (nm != NULL) { // Verify that the nemthod is live if (!nm->is_alive()) { - gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has dead nmethod " - PTR_FORMAT" in its strong code roots", + gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] has dead nmethod " + PTR_FORMAT " in its strong code roots", p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); _failures = true; } else { VerifyStrongCodeRootOopClosure oop_cl(_hr, nm); nm->oops_do(&oop_cl); if (!oop_cl.has_oops_in_region()) { - gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has nmethod " - PTR_FORMAT" in its strong code roots " + gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod " + PTR_FORMAT " in its strong code roots " "with no pointers into region", p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); _failures = true; } else if (oop_cl.failures()) { - gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has other " - "failures for nmethod "PTR_FORMAT, + gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] has other " + "failures for nmethod " PTR_FORMAT, p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm)); _failures = true; } @@ -589,8 +589,8 @@ // on its strong code root list if (is_empty()) { if (strong_code_roots_length > 0) { - gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is empty " - "but has "SIZE_FORMAT" code root entries", + gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] is empty " + "but has " SIZE_FORMAT " code root entries", p2i(bottom()), p2i(end()), strong_code_roots_length); *failures = true; } @@ -599,8 +599,8 @@ if (is_continues_humongous()) { if (strong_code_roots_length > 0) { - gclog_or_tty->print_cr("region "HR_FORMAT" is a continuation of a humongous " - "region but has "SIZE_FORMAT" code root entries", + gclog_or_tty->print_cr("region " HR_FORMAT " is a continuation of a humongous " + "region but has " SIZE_FORMAT " code root entries", HR_FORMAT_PARAMS(this), strong_code_roots_length); *failures = true; } @@ -625,7 +625,7 @@ else st->print(" "); st->print(" TS %5d", _gc_time_stamp); - st->print(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT, + st->print(" PTAMS " PTR_FORMAT " NTAMS " PTR_FORMAT, p2i(prev_top_at_mark_start()), p2i(next_top_at_mark_start())); G1OffsetTableContigSpace::print_on(st); } @@ -686,25 +686,25 @@ } if (!_g1h->is_in_closed_subset(obj)) { HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); - gclog_or_tty->print_cr("Field "PTR_FORMAT - " of live obj "PTR_FORMAT" in region " - "["PTR_FORMAT", "PTR_FORMAT")", + gclog_or_tty->print_cr("Field " PTR_FORMAT + " of live obj " PTR_FORMAT " in region " + "[" PTR_FORMAT ", " PTR_FORMAT ")", p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end())); print_object(gclog_or_tty, _containing_obj); - gclog_or_tty->print_cr("points to obj "PTR_FORMAT" not in the heap", + gclog_or_tty->print_cr("points to obj " PTR_FORMAT " not in the heap", p2i(obj)); } else { HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p); HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj); - gclog_or_tty->print_cr("Field "PTR_FORMAT - " of live obj "PTR_FORMAT" in region " - "["PTR_FORMAT", "PTR_FORMAT")", + gclog_or_tty->print_cr("Field " PTR_FORMAT + " of live obj " PTR_FORMAT " in region " + "[" PTR_FORMAT ", " PTR_FORMAT ")", p2i(p), p2i(_containing_obj), p2i(from->bottom()), p2i(from->end())); print_object(gclog_or_tty, _containing_obj); - gclog_or_tty->print_cr("points to dead obj "PTR_FORMAT" in region " - "["PTR_FORMAT", "PTR_FORMAT")", + gclog_or_tty->print_cr("points to dead obj " PTR_FORMAT " in region " + "[" PTR_FORMAT ", " PTR_FORMAT ")", p2i(obj), p2i(to->bottom()), p2i(to->end())); print_object(gclog_or_tty, obj); } @@ -740,14 +740,14 @@ gclog_or_tty->print_cr("----------"); } gclog_or_tty->print_cr("Missing rem set entry:"); - gclog_or_tty->print_cr("Field "PTR_FORMAT" " - "of obj "PTR_FORMAT", " - "in region "HR_FORMAT, + gclog_or_tty->print_cr("Field " PTR_FORMAT " " + "of obj " PTR_FORMAT ", " + "in region " HR_FORMAT, p2i(p), p2i(_containing_obj), HR_FORMAT_PARAMS(from)); _containing_obj->print_on(gclog_or_tty); - gclog_or_tty->print_cr("points to obj "PTR_FORMAT" " - "in region "HR_FORMAT, + gclog_or_tty->print_cr("points to obj " PTR_FORMAT " " + "in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to)); obj->print_on(gclog_or_tty); @@ -783,8 +783,8 @@ if (is_region_humongous != g1->is_humongous(obj_size) && !g1->is_obj_dead(obj, this)) { // Dead objects may have bigger block_size since they span several objects. - gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size (" - SIZE_FORMAT" words) in a %shumongous region", + gclog_or_tty->print_cr("obj " PTR_FORMAT " is of %shumongous size (" + SIZE_FORMAT " words) in a %shumongous region", p2i(p), g1->is_humongous(obj_size) ? "" : "non-", obj_size, is_region_humongous ? "" : "non-"); *failures = true; @@ -798,12 +798,12 @@ (vo == VerifyOption_G1UsePrevMarking && ClassLoaderDataGraph::unload_list_contains(klass)); if (!is_metaspace_object) { - gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " + gclog_or_tty->print_cr("klass " PTR_FORMAT " of object " PTR_FORMAT " " "not metadata", p2i(klass), p2i(obj)); *failures = true; return; } else if (!klass->is_klass()) { - gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " + gclog_or_tty->print_cr("klass " PTR_FORMAT " of object " PTR_FORMAT " " "not a klass", p2i(klass), p2i(obj)); *failures = true; return; @@ -819,7 +819,7 @@ } } } else { - gclog_or_tty->print_cr(PTR_FORMAT" no an oop", p2i(obj)); + gclog_or_tty->print_cr(PTR_FORMAT " no an oop", p2i(obj)); *failures = true; return; } @@ -833,8 +833,8 @@ } if (p != top()) { - gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " - "does not match top "PTR_FORMAT, p2i(p), p2i(top())); + gclog_or_tty->print_cr("end of last object " PTR_FORMAT " " + "does not match top " PTR_FORMAT, p2i(p), p2i(top())); *failures = true; return; } @@ -849,8 +849,8 @@ HeapWord* addr_1 = p; HeapWord* b_start_1 = _offsets.block_start_const(addr_1); if (b_start_1 != p) { - gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" " - " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + gclog_or_tty->print_cr("BOT look up for top: " PTR_FORMAT " " + " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, p2i(addr_1), p2i(b_start_1), p2i(p)); *failures = true; return; @@ -861,8 +861,8 @@ if (addr_2 < the_end) { HeapWord* b_start_2 = _offsets.block_start_const(addr_2); if (b_start_2 != p) { - gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" " - " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + gclog_or_tty->print_cr("BOT look up for top + 1: " PTR_FORMAT " " + " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, p2i(addr_2), p2i(b_start_2), p2i(p)); *failures = true; return; @@ -875,8 +875,8 @@ if (addr_3 < the_end) { HeapWord* b_start_3 = _offsets.block_start_const(addr_3); if (b_start_3 != p) { - gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" " - " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + gclog_or_tty->print_cr("BOT look up for top + diff: " PTR_FORMAT " " + " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, p2i(addr_3), p2i(b_start_3), p2i(p)); *failures = true; return; @@ -887,8 +887,8 @@ HeapWord* addr_4 = the_end - 1; HeapWord* b_start_4 = _offsets.block_start_const(addr_4); if (b_start_4 != p) { - gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" " - " yielded "PTR_FORMAT", expecting "PTR_FORMAT, + gclog_or_tty->print_cr("BOT look up for end - 1: " PTR_FORMAT " " + " yielded " PTR_FORMAT ", expecting " PTR_FORMAT, p2i(addr_4), p2i(b_start_4), p2i(p)); *failures = true; return; @@ -896,8 +896,8 @@ } if (is_region_humongous && object_num > 1) { - gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous " - "but has "SIZE_FORMAT", objects", + gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] is humongous " + "but has " SIZE_FORMAT ", objects", p2i(bottom()), p2i(end()), object_num); *failures = true; return; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegion.hpp --- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -51,7 +51,7 @@ class HeapRegionSetBase; class nmethod; -#define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]" +#define HR_FORMAT "%u:(%s)[" PTR_FORMAT "," PTR_FORMAT "," PTR_FORMAT "]" #define HR_FORMAT_PARAMS(_hr_) \ (_hr_)->hrm_index(), \ (_hr_)->get_short_type_str(), \ @@ -538,8 +538,8 @@ void set_containing_set(HeapRegionSetBase* containing_set) { assert((containing_set == NULL && _containing_set != NULL) || (containing_set != NULL && _containing_set == NULL), - err_msg("containing_set: "PTR_FORMAT" " - "_containing_set: "PTR_FORMAT, + err_msg("containing_set: " PTR_FORMAT " " + "_containing_set: " PTR_FORMAT, p2i(containing_set), p2i(_containing_set))); _containing_set = containing_set; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp --- a/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegion.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -113,7 +113,7 @@ assert(ClassUnloadingWithConcurrentMark, err_msg("All blocks should be objects if G1 Class Unloading isn't used. " - "HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") " + "HR: [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ") " "addr: " PTR_FORMAT, p2i(bottom()), p2i(top()), p2i(end()), p2i(addr))); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegionManager.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -486,7 +486,7 @@ HeapRegion* hr = _regions.get_by_index(i); guarantee(hr != NULL, err_msg("invariant: i: %u", i)); guarantee(!prev_committed || hr->bottom() == prev_end, - err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT, + err_msg("invariant i: %u " HR_FORMAT " prev_end: " PTR_FORMAT, i, HR_FORMAT_PARAMS(hr), p2i(prev_end))); guarantee(hr->hrm_index() == i, err_msg("invariant: i: %u hrm_index(): %u", i, hr->hrm_index())); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -31,9 +31,9 @@ inline HeapRegion* HeapRegionManager::addr_to_region(HeapWord* addr) const { assert(addr < heap_end(), - err_msg("addr: "PTR_FORMAT" end: "PTR_FORMAT, p2i(addr), p2i(heap_end()))); + err_msg("addr: " PTR_FORMAT " end: " PTR_FORMAT, p2i(addr), p2i(heap_end()))); assert(addr >= heap_bottom(), - err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, p2i(addr), p2i(heap_bottom()))); + err_msg("addr: " PTR_FORMAT " bottom: " PTR_FORMAT, p2i(addr), p2i(heap_bottom()))); HeapRegion* hr = _regions.get_by_address(addr); return hr; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -90,7 +90,7 @@ // concurrency. if (G1TraceHeapRegionRememberedSet) { - gclog_or_tty->print_cr(" PRT::Add_reference_work(" PTR_FORMAT "->" PTR_FORMAT").", + gclog_or_tty->print_cr(" PRT::Add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").", p2i(from), UseCompressedOops ? p2i(oopDesc::load_decode_heap_oop((narrowOop*)from)) @@ -376,7 +376,7 @@ void FromCardCache::invalidate(uint start_idx, size_t new_num_regions) { guarantee((size_t)start_idx + new_num_regions <= max_uintx, - err_msg("Trying to invalidate beyond maximum region, from %u size "SIZE_FORMAT, + err_msg("Trying to invalidate beyond maximum region, from %u size " SIZE_FORMAT, start_idx, new_num_regions)); for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) { uint end_idx = (start_idx + (uint)new_num_regions); @@ -630,13 +630,13 @@ assert(_coarse_map.size() == region_bm->size(), "Precondition"); if (G1RSScrubVerbose) { - gclog_or_tty->print(" Coarse map: before = "SIZE_FORMAT"...", + gclog_or_tty->print(" Coarse map: before = " SIZE_FORMAT "...", _n_coarse_entries); } _coarse_map.set_intersection(*region_bm); _n_coarse_entries = _coarse_map.count_one_bits(); if (G1RSScrubVerbose) { - gclog_or_tty->print_cr(" after = "SIZE_FORMAT".", _n_coarse_entries); + gclog_or_tty->print_cr(" after = " SIZE_FORMAT ".", _n_coarse_entries); } // Now do the fine-grained maps. @@ -1013,7 +1013,7 @@ card_index = _cur_region_card_offset + _cur_card_in_prt; guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion, - err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt)); + err_msg("Card index " SIZE_FORMAT " must be within the region", _cur_card_in_prt)); return true; } @@ -1182,8 +1182,8 @@ size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize; assert(dummy->mem_size() > min_prt_size, - err_msg("PerRegionTable memory usage is suspiciously small, only has "SIZE_FORMAT" bytes. " - "Should be at least "SIZE_FORMAT" bytes.", dummy->mem_size(), min_prt_size)); + err_msg("PerRegionTable memory usage is suspiciously small, only has " SIZE_FORMAT " bytes. " + "Should be at least " SIZE_FORMAT " bytes.", dummy->mem_size(), min_prt_size)); free(dummy); guarantee(dummy->mem_size() == fl_mem_size(), "fl_mem_size() does not return the correct element size"); // try to reset the state diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/heapRegionSet.cpp --- a/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/heapRegionSet.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -30,7 +30,7 @@ uint FreeRegionList::_unrealistically_long_length = 0; void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) { - msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT, + msg->append("[%s] %s ln: %u cy: " SIZE_FORMAT, name(), message, length(), total_capacity_bytes()); fill_in_ext_msg_extra(msg); } @@ -83,13 +83,13 @@ void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) { out->cr(); - out->print_cr("Set: %s ("PTR_FORMAT")", name(), p2i(this)); + out->print_cr("Set: %s (" PTR_FORMAT ")", name(), p2i(this)); out->print_cr(" Region Assumptions"); out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous())); out->print_cr(" free : %s", BOOL_TO_STR(regions_free())); out->print_cr(" Attributes"); out->print_cr(" length : %14u", length()); - out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes", + out->print_cr(" total capacity : " SIZE_FORMAT_W(14) " bytes", total_capacity_bytes()); } @@ -105,7 +105,7 @@ } void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) { - msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, p2i(_head), p2i(_tail)); + msg->append(" hd: " PTR_FORMAT " tl: " PTR_FORMAT, p2i(_head), p2i(_tail)); } void FreeRegionList::remove_all() { @@ -276,8 +276,8 @@ void FreeRegionList::print_on(outputStream* out, bool print_contents) { HeapRegionSetBase::print_on(out, print_contents); out->print_cr(" Linking"); - out->print_cr(" head : "PTR_FORMAT, p2i(_head)); - out->print_cr(" tail : "PTR_FORMAT, p2i(_tail)); + out->print_cr(" head : " PTR_FORMAT, p2i(_head)); + out->print_cr(" tail : " PTR_FORMAT, p2i(_tail)); if (print_contents) { out->print_cr(" Contents"); @@ -305,7 +305,7 @@ count++; guarantee(count < _unrealistically_long_length, - hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: %u", + hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: " PTR_FORMAT " prev0: " PTR_FORMAT " " "prev1: " PTR_FORMAT " length: %u", name(), count, p2i(curr), p2i(prev0), p2i(prev1), length())); if (curr->next() != NULL) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/g1/satbQueue.cpp --- a/hotspot/src/share/vm/gc/g1/satbQueue.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/g1/satbQueue.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -200,8 +200,8 @@ void ObjPtrQueue::print(const char* name, void** buf, size_t index, size_t sz) { - gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: "PTR_FORMAT" " - "index: "SIZE_FORMAT" sz: "SIZE_FORMAT, + gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " " + "index: " SIZE_FORMAT " sz: " SIZE_FORMAT, name, p2i(buf), index, sz); } #endif // PRODUCT diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp --- a/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/parallel/mutableNUMASpace.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -85,7 +85,7 @@ while (words_left_to_fill > 0) { size_t words_to_fill = MIN2(words_left_to_fill, CollectedHeap::filler_array_max_size()); assert(words_to_fill >= CollectedHeap::min_fill_size(), - err_msg("Remaining size ("SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")", + err_msg("Remaining size (" SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")", words_to_fill, words_left_to_fill, CollectedHeap::filler_array_max_size())); CollectedHeap::fill_with_object((HeapWord*)cur_top, words_to_fill); if (!os::numa_has_static_binding()) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp --- a/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/parallel/psAdaptiveSizePolicy.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -130,8 +130,7 @@ // Update the pause time. _major_timer.stop(); - if (!GCCause::is_user_requested_gc(gc_cause) || - UseAdaptiveSizePolicyWithSystemGC) { + if (should_update_promo_stats(gc_cause)) { double major_pause_in_seconds = _major_timer.seconds(); double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp --- a/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/parallel/psMarkSweep.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -272,8 +272,7 @@ // Don't check if the size_policy is ready here. Let // the size_policy check that internally. if (UseAdaptiveGenerationSizePolicyAtMajorCollection && - (!GCCause::is_user_requested_gc(gc_cause) || - UseAdaptiveSizePolicyWithSystemGC)) { + AdaptiveSizePolicy::should_update_promo_stats(gc_cause)) { // Swap the survivor spaces if from_space is empty. The // resize_young_gen() called below is normally used after // a successful young GC and swapping of survivor spaces; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/parallel/psOldGen.hpp --- a/hotspot/src/share/vm/gc/parallel/psOldGen.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/parallel/psOldGen.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -65,9 +65,9 @@ // Explictly capture current covered_region in a local MemRegion covered_region = this->start_array()->covered_region(); assert(covered_region.contains(new_memregion), - err_msg("new region is not in covered_region [ "PTR_FORMAT", "PTR_FORMAT" ], " - "new region [ "PTR_FORMAT", "PTR_FORMAT" ], " - "object space [ "PTR_FORMAT", "PTR_FORMAT" ]", + err_msg("new region is not in covered_region [ " PTR_FORMAT ", " PTR_FORMAT " ], " + "new region [ " PTR_FORMAT ", " PTR_FORMAT " ], " + "object space [ " PTR_FORMAT ", " PTR_FORMAT " ]", p2i(covered_region.start()), p2i(covered_region.end()), p2i(new_memregion.start()), diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/parallel/psParallelCompact.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -2089,8 +2089,7 @@ // Don't check if the size_policy is ready here. Let // the size_policy check that internally. if (UseAdaptiveGenerationSizePolicyAtMajorCollection && - (!GCCause::is_user_requested_gc(gc_cause) || - UseAdaptiveSizePolicyWithSystemGC)) { + AdaptiveSizePolicy::should_update_promo_stats(gc_cause)) { // Swap the survivor spaces if from_space is empty. The // resize_young_gen() called below is normally used after // a successful young GC and swapping of survivor spaces; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/parallel/psScavenge.cpp --- a/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/parallel/psScavenge.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -290,8 +290,7 @@ AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); - if (!GCCause::is_user_requested_gc(gc_cause) || - UseAdaptiveSizePolicyWithSystemGC) { + if (AdaptiveSizePolicy::should_update_eden_stats(gc_cause)) { // Gather the feedback data for eden occupancy. young_gen->eden_space()->accumulate_statistics(); } @@ -559,9 +558,7 @@ // Don't check if the size_policy is ready at this // level. Let the size_policy check that internally. if (UseAdaptiveGenerationSizePolicyAtMinorCollection && - ((gc_cause != GCCause::_java_lang_system_gc) || - UseAdaptiveSizePolicyWithSystemGC)) { - + (AdaptiveSizePolicy::should_update_eden_stats(gc_cause))) { // Calculate optimal free space amounts assert(young_gen->max_size() > young_gen->from_space()->capacity_in_bytes() + diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp --- a/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/serial/tenuredGeneration.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -168,8 +168,8 @@ bool res = (available >= av_promo) || (available >= max_promotion_in_bytes); if (PrintGC && Verbose) { gclog_or_tty->print_cr( - "Tenured: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT")," - "max_promo("SIZE_FORMAT")", + "Tenured: promo attempt is%s safe: available(" SIZE_FORMAT ") %s av_promo(" SIZE_FORMAT ")," + "max_promo(" SIZE_FORMAT ")", res? "":" not", available, res? ">=":"<", av_promo, max_promotion_in_bytes); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.hpp --- a/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/adaptiveSizePolicy.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -487,6 +487,18 @@ GCCause::Cause gc_cause, CollectorPolicy* collector_policy); + static bool should_update_promo_stats(GCCause::Cause cause) { + return ((GCCause::is_user_requested_gc(cause) && + UseAdaptiveSizePolicyWithSystemGC) || + GCCause::is_tenured_allocation_failure_gc(cause)); + } + + static bool should_update_eden_stats(GCCause::Cause cause) { + return ((GCCause::is_user_requested_gc(cause) && + UseAdaptiveSizePolicyWithSystemGC) || + GCCause::is_allocation_failure_gc(cause)); + } + // Printing support virtual bool print_adaptive_size_policy_on(outputStream* st) const; bool print_adaptive_size_policy_on(outputStream* st, diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp --- a/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/barrierSet.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -69,7 +69,7 @@ assert(UseCompressedOops || (aligned_start == start && aligned_end == end), "Expected heap word alignment of start and end"); #if 0 - warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT","INTPTR_FORMAT")\t", + warning("Post:\t" INTPTR_FORMAT "[" SIZE_FORMAT "] : [" INTPTR_FORMAT "," INTPTR_FORMAT ")\t", start, count, aligned_start, aligned_end); #endif write_ref_array_work(MemRegion(aligned_start, aligned_end)); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/blockOffsetTable.cpp --- a/hotspot/src/share/vm/gc/shared/blockOffsetTable.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/blockOffsetTable.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -560,7 +560,7 @@ q = n; n += _sp->block_size(n); assert(n > q, - err_msg("Looping at n = " PTR_FORMAT " with last = " PTR_FORMAT"," + err_msg("Looping at n = " PTR_FORMAT " with last = " PTR_FORMAT "," " while querying blk_start(" PTR_FORMAT ")" " on _sp = [" PTR_FORMAT "," PTR_FORMAT ")", p2i(n), p2i(last), p2i(addr), p2i(_sp->bottom()), p2i(_sp->end()))); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp --- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -600,7 +600,7 @@ (val_equals) ? "" : "not ", val); failures = true; } - tty->print_cr("== card "PTR_FORMAT" ["PTR_FORMAT","PTR_FORMAT"], " + tty->print_cr("== card " PTR_FORMAT " [" PTR_FORMAT "," PTR_FORMAT "], " "val: %d", p2i(curr), p2i(addr_for(curr)), p2i((HeapWord*) (((size_t) addr_for(curr)) + card_size)), (int) curr_val); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp --- a/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/cardTableModRefBS.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -158,8 +158,8 @@ // Mapping from address to card marking array entry jbyte* byte_for(const void* p) const { assert(_whole_heap.contains(p), - err_msg("Attempt to access p = "PTR_FORMAT" out of bounds of " - " card marking array's _whole_heap = ["PTR_FORMAT","PTR_FORMAT")", + err_msg("Attempt to access p = " PTR_FORMAT " out of bounds of " + " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", p2i(p), p2i(_whole_heap.start()), p2i(_whole_heap.end()))); jbyte* result = &byte_map_base[uintptr_t(p) >> card_shift]; assert(result >= _byte_map && result < _byte_map + _byte_map_size, @@ -399,8 +399,8 @@ size_t delta = pointer_delta(p, byte_map_base, sizeof(jbyte)); HeapWord* result = (HeapWord*) (delta << card_shift); assert(_whole_heap.contains(result), - err_msg("Returning result = "PTR_FORMAT" out of bounds of " - " card marking array's _whole_heap = ["PTR_FORMAT","PTR_FORMAT")", + err_msg("Returning result = " PTR_FORMAT " out of bounds of " + " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", p2i(result), p2i(_whole_heap.start()), p2i(_whole_heap.end()))); return result; } @@ -408,8 +408,8 @@ // Mapping from address to card marking array index. size_t index_for(void* p) { assert(_whole_heap.contains(p), - err_msg("Attempt to access p = "PTR_FORMAT" out of bounds of " - " card marking array's _whole_heap = ["PTR_FORMAT","PTR_FORMAT")", + err_msg("Attempt to access p = " PTR_FORMAT " out of bounds of " + " card marking array's _whole_heap = [" PTR_FORMAT "," PTR_FORMAT ")", p2i(p), p2i(_whole_heap.start()), p2i(_whole_heap.end()))); return byte_for(p) - _byte_map; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/collectedHeap.cpp --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -488,19 +488,17 @@ DEBUG_ONLY(fill_args_check(start, words);) HandleMark hm; // Free handles before leaving. -#ifdef _LP64 - // A single array can fill ~8G, so multiple objects are needed only in 64-bit. - // First fill with arrays, ensuring that any remaining space is big enough to - // fill. The remainder is filled with a single object. + // Multiple objects may be required depending on the filler array maximum size. Fill + // the range up to that with objects that are filler_array_max_size sized. The + // remainder is filled with a single object. const size_t min = min_fill_size(); const size_t max = filler_array_max_size(); while (words > max) { - const size_t cur = words - max >= min ? max : max - min; + const size_t cur = (words - max) >= min ? max : max - min; fill_with_array(start, cur, zap); start += cur; words -= cur; } -#endif fill_with_object_impl(start, words, zap); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/gcCause.hpp --- a/hotspot/src/share/vm/gc/shared/gcCause.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/gcCause.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -92,6 +92,35 @@ cause == GCCause::_heap_dump); } + // Causes for collection of the tenured gernation + inline static bool is_tenured_allocation_failure_gc(GCCause::Cause cause) { + assert(cause != GCCause::_old_generation_too_full_to_scavenge && + cause != GCCause::_old_generation_expanded_on_last_scavenge, + err_msg("This GCCause may be correct but is not expected yet: %s", + to_string(cause))); + // _tenured_generation_full or _cms_generation_full for full tenured generations + // _adaptive_size_policy for a full collection after a young GC + // _allocation_failure is the generic cause a collection which could result + // in the collection of the tenured generation if there is not enough space + // in the tenured generation to support a young GC. + // _last_ditch_collection is a collection done to include SoftReferences. + return (cause == GCCause::_tenured_generation_full || + cause == GCCause::_cms_generation_full || + cause == GCCause::_adaptive_size_policy || + cause == GCCause::_allocation_failure || + cause == GCCause::_last_ditch_collection); + } + + // Causes for collection of the young generation + inline static bool is_allocation_failure_gc(GCCause::Cause cause) { + // _allocation_failure is the generic cause a collection for allocation failure + // _adaptive_size_policy is for a collecton done before a full GC + // _last_ditch_collection is a collection done to include SoftReferences. + return (cause == GCCause::_allocation_failure || + cause == GCCause::_adaptive_size_policy || + cause == GCCause::_last_ditch_collection); + } + // Return a string describing the GCCause. static const char* to_string(GCCause::Cause cause); }; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/gcTrace.cpp --- a/hotspot/src/share/vm/gc/shared/gcTrace.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/gcTrace.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -221,6 +221,12 @@ } #if INCLUDE_ALL_GCS +void G1MMUTracer::report_mmu(const GCId& gcId, double timeSlice, double gcTime, double maxTime) { + assert(!gcId.is_undefined(), "Undefined GC id"); + + send_g1_mmu_event(gcId, timeSlice, gcTime, maxTime); +} + void G1NewTracer::report_yc_type(G1YCType type) { assert_set_gc_id(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/gcTrace.hpp --- a/hotspot/src/share/vm/gc/shared/gcTrace.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/gcTrace.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -239,6 +239,13 @@ }; #if INCLUDE_ALL_GCS +class G1MMUTracer : public AllStatic { + static void send_g1_mmu_event(const GCId& gcId, double timeSlice, double gcTime, double maxTime); + + public: + static void report_mmu(const GCId& gcId, double timeSlice, double gcTime, double maxTime); +}; + class G1NewTracer : public YoungGCTracer { G1YoungGCInfo _g1_young_gc_info; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/gcTraceSend.cpp --- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -199,6 +199,17 @@ } } +void G1MMUTracer::send_g1_mmu_event(const GCId& gcId, double timeSlice, double gcTime, double maxTime) { + EventGCG1MMU e; + if (e.should_commit()) { + e.set_gcId(gcId.id()); + e.set_timeSlice(timeSlice); + e.set_gcTime(gcTime); + e.set_maxGcTime(maxTime); + e.commit(); + } +} + void G1NewTracer::send_evacuation_info_event(EvacuationInfo* info) { EventEvacuationInfo e; if (e.should_commit()) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/generation.cpp --- a/hotspot/src/share/vm/gc/shared/generation.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/generation.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -173,7 +173,7 @@ bool res = (available >= max_promotion_in_bytes); if (PrintGC && Verbose) { gclog_or_tty->print_cr( - "Generation: promo attempt is%s safe: available("SIZE_FORMAT") %s max_promo("SIZE_FORMAT")", + "Generation: promo attempt is%s safe: available(" SIZE_FORMAT ") %s max_promo(" SIZE_FORMAT ")", res? "":" not", available, res? ">=":"<", max_promotion_in_bytes); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/plab.cpp --- a/hotspot/src/share/vm/gc/shared/plab.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/plab.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -45,7 +45,7 @@ // ArrayOopDesc::header_size depends on command line initialization. AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0; assert(min_size() > AlignmentReserve, - err_msg("Minimum PLAB size " SIZE_FORMAT" must be larger than alignment reserve " SIZE_FORMAT" " + err_msg("Minimum PLAB size " SIZE_FORMAT " must be larger than alignment reserve " SIZE_FORMAT " " "to be able to contain objects", min_size(), AlignmentReserve)); } @@ -109,10 +109,15 @@ } } -// Compute desired plab size and latch result for later +// Calculates plab size for current number of gc worker threads. +size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) { + return MAX2(min_size(), (size_t)align_object_size(_desired_net_plab_sz / no_of_gc_workers)); +} + +// Compute desired plab size for one gc worker thread and latch result for later // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators. -void PLABStats::adjust_desired_plab_sz(uint no_of_gc_workers) { +void PLABStats::adjust_desired_plab_sz() { assert(ResizePLAB, "Not set"); assert(is_object_aligned(max_size()) && min_size() <= max_size(), @@ -121,10 +126,10 @@ if (_allocated == 0) { assert(_unused == 0, err_msg("Inconsistency in PLAB stats: " - "_allocated: "SIZE_FORMAT", " - "_wasted: "SIZE_FORMAT", " - "_unused: "SIZE_FORMAT", " - "_undo_wasted: "SIZE_FORMAT, + "_allocated: " SIZE_FORMAT ", " + "_wasted: " SIZE_FORMAT ", " + "_unused: " SIZE_FORMAT ", " + "_undo_wasted: " SIZE_FORMAT, _allocated, _wasted, _unused, _undo_wasted)); _allocated = 1; @@ -135,7 +140,8 @@ target_refills = 1; } size_t used = _allocated - _wasted - _unused; - size_t recent_plab_sz = used / (target_refills * no_of_gc_workers); + // Assumed to have 1 gc worker thread + size_t recent_plab_sz = used / target_refills; // Take historical weighted average _filter.sample(recent_plab_sz); // Clip from above and below, and align to object boundary @@ -144,9 +150,9 @@ new_plab_sz = align_object_size(new_plab_sz); // Latch the result if (PrintPLAB) { - gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT" desired_plab_sz = " SIZE_FORMAT") ", recent_plab_sz, new_plab_sz); + gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " desired_net_plab_sz = " SIZE_FORMAT ") ", recent_plab_sz, new_plab_sz); } - _desired_plab_sz = new_plab_sz; + _desired_net_plab_sz = new_plab_sz; reset(); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/plab.hpp --- a/hotspot/src/share/vm/gc/shared/plab.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/plab.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -150,13 +150,13 @@ // PLAB book-keeping. class PLABStats VALUE_OBJ_CLASS_SPEC { - size_t _allocated; // Total allocated - size_t _wasted; // of which wasted (internal fragmentation) - size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size) - size_t _unused; // Unused in last buffer - size_t _desired_plab_sz;// Output of filter (below), suitably trimmed and quantized + size_t _allocated; // Total allocated + size_t _wasted; // of which wasted (internal fragmentation) + size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size) + size_t _unused; // Unused in last buffer + size_t _desired_net_plab_sz;// Output of filter (below), suitably trimmed and quantized AdaptiveWeightedAverage - _filter; // Integrator with decay + _filter; // Integrator with decay void reset() { _allocated = 0; @@ -165,12 +165,12 @@ _unused = 0; } public: - PLABStats(size_t desired_plab_sz_, unsigned wt) : + PLABStats(size_t desired_net_plab_sz_, unsigned wt) : _allocated(0), _wasted(0), _undo_wasted(0), _unused(0), - _desired_plab_sz(desired_plab_sz_), + _desired_net_plab_sz(desired_net_plab_sz_), _filter(wt) { } @@ -182,13 +182,12 @@ return PLAB::max_size(); } - size_t desired_plab_sz() { - return _desired_plab_sz; - } + // Calculates plab size for current number of gc worker threads. + size_t desired_plab_sz(uint no_of_gc_workers); - // Updates the current desired PLAB size. Computes the new desired PLAB size, + // Updates the current desired PLAB size. Computes the new desired PLAB size with one gc worker thread, // updates _desired_plab_sz and clears sensor accumulators. - void adjust_desired_plab_sz(uint no_of_gc_workers); + void adjust_desired_plab_sz(); void add_allocated(size_t v) { Atomic::add_ptr(v, &_allocated); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.inline.hpp --- a/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.inline.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/gc/shared/threadLocalAllocBuffer.inline.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -93,10 +93,10 @@ if (PrintTLAB && Verbose) { Thread* thrd = myThread(); - gclog_or_tty->print("TLAB: %s thread: "INTPTR_FORMAT" [id: %2d]" - " obj: "SIZE_FORMAT - " free: "SIZE_FORMAT - " waste: "SIZE_FORMAT"\n", + gclog_or_tty->print("TLAB: %s thread: " INTPTR_FORMAT " [id: %2d]" + " obj: " SIZE_FORMAT + " free: " SIZE_FORMAT + " waste: " SIZE_FORMAT "\n", "slow", p2i(thrd), thrd->osthread()->thread_id(), obj_size, free(), refill_waste_limit()); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/interpreter.cpp --- a/hotspot/src/share/vm/interpreter/interpreter.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/interpreter.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,8 +134,10 @@ tty->print_cr("wasted space = %6dK bytes", (int)_code->available_space()/1024); tty->cr(); tty->print_cr("# of codelets = %6d" , _code->number_of_stubs()); - tty->print_cr("avg codelet size = %6d bytes", _code->used_space() / _code->number_of_stubs()); - tty->cr(); + if (_code->number_of_stubs() != 0) { + tty->print_cr("avg codelet size = %6d bytes", _code->used_space() / _code->number_of_stubs()); + tty->cr(); + } _code->print(); tty->print_cr("----------------------------------------------------------------------"); tty->cr(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/interpreter.hpp --- a/hotspot/src/share/vm/interpreter/interpreter.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/interpreter.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -45,6 +45,7 @@ class InterpreterCodelet: public Stub { friend class VMStructs; + friend class CodeCacheDumper; // possible extension [do not remove] private: int _size; // the size in bytes const char* _description; // a description of the codelet, for debugging & printing diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/interpreterRuntime.cpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -27,6 +27,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" +#include "code/codeCacheExtensions.hpp" #include "compiler/compileBroker.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/collectedHeap.hpp" @@ -1178,6 +1179,7 @@ ICache::invalidate_range(handler, insts_size); _handler = handler + insts_size; } + CodeCacheExtensions::handle_generated_handler(handler, buffer->name(), _handler); return handler; } @@ -1186,7 +1188,7 @@ // use slow signature handler if we can't do better int handler_index = -1; // check if we can use customized (fast) signature handler - if (UseFastSignatureHandlers && method->size_of_parameters() <= Fingerprinter::max_size_of_parameters) { + if (UseFastSignatureHandlers && CodeCacheExtensions::support_fast_signature_handlers() && method->size_of_parameters() <= Fingerprinter::max_size_of_parameters) { // use customized signature handler MutexLocker mu(SignatureHandlerLibrary_lock); // make sure data structure is initialized @@ -1203,14 +1205,23 @@ round_to((intptr_t)_buffer, CodeEntryAlignment) - (address)_buffer; CodeBuffer buffer((address)(_buffer + align_offset), SignatureHandlerLibrary::buffer_size - align_offset); + if (!CodeCacheExtensions::support_dynamic_code()) { + // we need a name for the signature (for lookups or saving) + const int SYMBOL_SIZE = 50; + char *symbolName = NEW_RESOURCE_ARRAY(char, SYMBOL_SIZE); + // support for named signatures + jio_snprintf(symbolName, SYMBOL_SIZE, + "native_" UINT64_FORMAT, fingerprint); + buffer.set_name(symbolName); + } InterpreterRuntime::SignatureHandlerGenerator(method, &buffer).generate(fingerprint); // copy into code heap address handler = set_handler(&buffer); if (handler == NULL) { - // use slow signature handler + // use slow signature handler (without memorizing it in the fingerprints) } else { // debugging suppport - if (PrintSignatureHandlers) { + if (PrintSignatureHandlers && (handler != Interpreter::slow_signature_handler())) { tty->cr(); tty->print_cr("argument handler #%d for: %s %s (fingerprint = " UINT64_FORMAT ", %d bytes generated)", _handlers->length(), @@ -1218,7 +1229,10 @@ method->name_and_sig_as_C_string(), fingerprint, buffer.insts_size()); - Disassembler::decode(handler, handler + buffer.insts_size()); + if (buffer.insts_size() > 0) { + // buffer may be empty for pregenerated handlers + Disassembler::decode(handler, handler + buffer.insts_size()); + } #ifndef PRODUCT address rh_begin = Interpreter::result_handler(method()->result_type()); if (CodeCache::contains(rh_begin)) { @@ -1277,6 +1291,37 @@ #endif // ASSERT } +void SignatureHandlerLibrary::add(uint64_t fingerprint, address handler) { + int handler_index = -1; + // use customized signature handler + MutexLocker mu(SignatureHandlerLibrary_lock); + // make sure data structure is initialized + initialize(); + fingerprint = InterpreterRuntime::normalize_fast_native_fingerprint(fingerprint); + handler_index = _fingerprints->find(fingerprint); + // create handler if necessary + if (handler_index < 0) { + if (PrintSignatureHandlers && (handler != Interpreter::slow_signature_handler())) { + tty->cr(); + tty->print_cr("argument handler #%d at "PTR_FORMAT" for fingerprint " UINT64_FORMAT, + _handlers->length(), + handler, + fingerprint); + } + _fingerprints->append(fingerprint); + _handlers->append(handler); + } else { + if (PrintSignatureHandlers) { + tty->cr(); + tty->print_cr("duplicate argument handler #%d for fingerprint " UINT64_FORMAT "(old: "PTR_FORMAT", new : "PTR_FORMAT")", + _handlers->length(), + fingerprint, + _handlers->at(handler_index), + handler); + } + } +} + BufferBlob* SignatureHandlerLibrary::_handler_blob = NULL; address SignatureHandlerLibrary::_handler = NULL; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/interpreterRuntime.hpp --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -219,6 +219,7 @@ public: static void add(methodHandle method); + static void add(uint64_t fingerprint, address handler); }; #endif // SHARE_VM_INTERPRETER_INTERPRETERRUNTIME_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/rewriter.cpp --- a/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -107,7 +107,7 @@ // more complicated solution is required. A special return bytecode // is used only by Object. to signal the finalization // registration point. Additionally local 0 must be preserved so it's -// available to pass to the registration function. For simplicty we +// available to pass to the registration function. For simplicity we // require that local 0 is never overwritten so it's available as an // argument for registration. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/templateInterpreter.cpp --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "code/codeCacheExtensions.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterGenerator.hpp" #include "interpreter/interpreterRuntime.hpp" @@ -49,10 +50,33 @@ TraceTime timer("Interpreter generation", TraceStartupTime); int code_size = InterpreterCodeSize; NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space +#if INCLUDE_JVMTI + if (CodeCacheExtensions::saving_generated_interpreter()) { + // May requires several versions of the codelets. + // Final size will automatically be optimized. + code_size *= 2; + } +#endif _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, "Interpreter"); InterpreterGenerator g(_code); - if (PrintInterpreter) print(); + } + if (PrintInterpreter) { + if (CodeCacheExtensions::saving_generated_interpreter() && + CodeCacheExtensions::use_pregenerated_interpreter()) { + ResourceMark rm; + tty->print("Printing the newly generated interpreter first"); + print(); + tty->print("Printing the pregenerated interpreter next"); + } + } + + // Install the pregenerated interpreter code before printing it + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::TemplateInterpreter); + + if (PrintInterpreter) { + ResourceMark rm; + print(); } // initialize dispatch table @@ -214,194 +238,203 @@ }; void TemplateInterpreterGenerator::generate_all() { - AbstractInterpreterGenerator::generate_all(); + // Loop, in case we need several variants of the interpreter entries + do { + if (!CodeCacheExtensions::skip_code_generation()) { + // bypass code generation when useless + AbstractInterpreterGenerator::generate_all(); - { CodeletMark cm(_masm, "error exits"); - _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); - _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); - } + { CodeletMark cm(_masm, "error exits"); + _unimplemented_bytecode = generate_error_exit("unimplemented bytecode"); + _illegal_bytecode_sequence = generate_error_exit("illegal bytecode sequence - method not verified"); + } #ifndef PRODUCT - if (TraceBytecodes) { - CodeletMark cm(_masm, "bytecode tracing support"); - Interpreter::_trace_code = - EntryPoint( - generate_trace_code(btos), - generate_trace_code(ctos), - generate_trace_code(stos), - generate_trace_code(atos), - generate_trace_code(itos), - generate_trace_code(ltos), - generate_trace_code(ftos), - generate_trace_code(dtos), - generate_trace_code(vtos) - ); - } + if (TraceBytecodes) { + CodeletMark cm(_masm, "bytecode tracing support"); + Interpreter::_trace_code = + EntryPoint( + generate_trace_code(btos), + generate_trace_code(ctos), + generate_trace_code(stos), + generate_trace_code(atos), + generate_trace_code(itos), + generate_trace_code(ltos), + generate_trace_code(ftos), + generate_trace_code(dtos), + generate_trace_code(vtos) + ); + } #endif // !PRODUCT - { CodeletMark cm(_masm, "return entry points"); - const int index_size = sizeof(u2); - for (int i = 0; i < Interpreter::number_of_return_entries; i++) { - Interpreter::_return_entry[i] = - EntryPoint( - generate_return_entry_for(itos, i, index_size), - generate_return_entry_for(itos, i, index_size), - generate_return_entry_for(itos, i, index_size), - generate_return_entry_for(atos, i, index_size), - generate_return_entry_for(itos, i, index_size), - generate_return_entry_for(ltos, i, index_size), - generate_return_entry_for(ftos, i, index_size), - generate_return_entry_for(dtos, i, index_size), - generate_return_entry_for(vtos, i, index_size) - ); - } - } + { CodeletMark cm(_masm, "return entry points"); + const int index_size = sizeof(u2); + for (int i = 0; i < Interpreter::number_of_return_entries; i++) { + Interpreter::_return_entry[i] = + EntryPoint( + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(atos, i, index_size), + generate_return_entry_for(itos, i, index_size), + generate_return_entry_for(ltos, i, index_size), + generate_return_entry_for(ftos, i, index_size), + generate_return_entry_for(dtos, i, index_size), + generate_return_entry_for(vtos, i, index_size) + ); + } + } - { CodeletMark cm(_masm, "invoke return entry points"); - const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; - const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); - const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); - const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); + { CodeletMark cm(_masm, "invoke return entry points"); + const TosState states[] = {itos, itos, itos, itos, ltos, ftos, dtos, atos, vtos}; + const int invoke_length = Bytecodes::length_for(Bytecodes::_invokestatic); + const int invokeinterface_length = Bytecodes::length_for(Bytecodes::_invokeinterface); + const int invokedynamic_length = Bytecodes::length_for(Bytecodes::_invokedynamic); - for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { - TosState state = states[i]; - Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); - Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); - Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); - } - } + for (int i = 0; i < Interpreter::number_of_return_addrs; i++) { + TosState state = states[i]; + Interpreter::_invoke_return_entry[i] = generate_return_entry_for(state, invoke_length, sizeof(u2)); + Interpreter::_invokeinterface_return_entry[i] = generate_return_entry_for(state, invokeinterface_length, sizeof(u2)); + Interpreter::_invokedynamic_return_entry[i] = generate_return_entry_for(state, invokedynamic_length, sizeof(u4)); + } + } - { CodeletMark cm(_masm, "earlyret entry points"); - Interpreter::_earlyret_entry = - EntryPoint( - generate_earlyret_entry_for(btos), - generate_earlyret_entry_for(ctos), - generate_earlyret_entry_for(stos), - generate_earlyret_entry_for(atos), - generate_earlyret_entry_for(itos), - generate_earlyret_entry_for(ltos), - generate_earlyret_entry_for(ftos), - generate_earlyret_entry_for(dtos), - generate_earlyret_entry_for(vtos) - ); - } + { CodeletMark cm(_masm, "earlyret entry points"); + Interpreter::_earlyret_entry = + EntryPoint( + generate_earlyret_entry_for(btos), + generate_earlyret_entry_for(ctos), + generate_earlyret_entry_for(stos), + generate_earlyret_entry_for(atos), + generate_earlyret_entry_for(itos), + generate_earlyret_entry_for(ltos), + generate_earlyret_entry_for(ftos), + generate_earlyret_entry_for(dtos), + generate_earlyret_entry_for(vtos) + ); + } - { CodeletMark cm(_masm, "deoptimization entry points"); - for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) { - Interpreter::_deopt_entry[i] = - EntryPoint( - generate_deopt_entry_for(itos, i), - generate_deopt_entry_for(itos, i), - generate_deopt_entry_for(itos, i), - generate_deopt_entry_for(atos, i), - generate_deopt_entry_for(itos, i), - generate_deopt_entry_for(ltos, i), - generate_deopt_entry_for(ftos, i), - generate_deopt_entry_for(dtos, i), - generate_deopt_entry_for(vtos, i) - ); - } - } + { CodeletMark cm(_masm, "deoptimization entry points"); + for (int i = 0; i < Interpreter::number_of_deopt_entries; i++) { + Interpreter::_deopt_entry[i] = + EntryPoint( + generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(atos, i), + generate_deopt_entry_for(itos, i), + generate_deopt_entry_for(ltos, i), + generate_deopt_entry_for(ftos, i), + generate_deopt_entry_for(dtos, i), + generate_deopt_entry_for(vtos, i) + ); + } + } - { CodeletMark cm(_masm, "result handlers for native calls"); - // The various result converter stublets. - int is_generated[Interpreter::number_of_result_handlers]; - memset(is_generated, 0, sizeof(is_generated)); + { CodeletMark cm(_masm, "result handlers for native calls"); + // The various result converter stublets. + int is_generated[Interpreter::number_of_result_handlers]; + memset(is_generated, 0, sizeof(is_generated)); - for (int i = 0; i < Interpreter::number_of_result_handlers; i++) { - BasicType type = types[i]; - if (!is_generated[Interpreter::BasicType_as_index(type)]++) { - Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type); + for (int i = 0; i < Interpreter::number_of_result_handlers; i++) { + BasicType type = types[i]; + if (!is_generated[Interpreter::BasicType_as_index(type)]++) { + Interpreter::_native_abi_to_tosca[Interpreter::BasicType_as_index(type)] = generate_result_handler_for(type); + } + } } - } - } - { CodeletMark cm(_masm, "continuation entry points"); - Interpreter::_continuation_entry = - EntryPoint( - generate_continuation_for(btos), - generate_continuation_for(ctos), - generate_continuation_for(stos), - generate_continuation_for(atos), - generate_continuation_for(itos), - generate_continuation_for(ltos), - generate_continuation_for(ftos), - generate_continuation_for(dtos), - generate_continuation_for(vtos) - ); - } + { CodeletMark cm(_masm, "continuation entry points"); + Interpreter::_continuation_entry = + EntryPoint( + generate_continuation_for(btos), + generate_continuation_for(ctos), + generate_continuation_for(stos), + generate_continuation_for(atos), + generate_continuation_for(itos), + generate_continuation_for(ltos), + generate_continuation_for(ftos), + generate_continuation_for(dtos), + generate_continuation_for(vtos) + ); + } - { CodeletMark cm(_masm, "safepoint entry points"); - Interpreter::_safept_entry = - EntryPoint( - generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), - generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)) - ); - } + { CodeletMark cm(_masm, "safepoint entry points"); + Interpreter::_safept_entry = + EntryPoint( + generate_safept_entry_for(btos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ctos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(stos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(atos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(itos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ltos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(ftos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(dtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)), + generate_safept_entry_for(vtos, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)) + ); + } - { CodeletMark cm(_masm, "exception handling"); - // (Note: this is not safepoint safe because thread may return to compiled code) - generate_throw_exception(); - } + { CodeletMark cm(_masm, "exception handling"); + // (Note: this is not safepoint safe because thread may return to compiled code) + generate_throw_exception(); + } - { CodeletMark cm(_masm, "throw exception entrypoints"); - Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException"); - Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); - Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); - Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); - Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); - Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); - } + { CodeletMark cm(_masm, "throw exception entrypoints"); + Interpreter::_throw_ArrayIndexOutOfBoundsException_entry = generate_ArrayIndexOutOfBounds_handler("java/lang/ArrayIndexOutOfBoundsException"); + Interpreter::_throw_ArrayStoreException_entry = generate_klass_exception_handler("java/lang/ArrayStoreException" ); + Interpreter::_throw_ArithmeticException_entry = generate_exception_handler("java/lang/ArithmeticException" , "/ by zero"); + Interpreter::_throw_ClassCastException_entry = generate_ClassCastException_handler(); + Interpreter::_throw_NullPointerException_entry = generate_exception_handler("java/lang/NullPointerException" , NULL ); + Interpreter::_throw_StackOverflowError_entry = generate_StackOverflowError_handler(); + } -#define method_entry(kind) \ - { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ - Interpreter::_entry_table[Interpreter::kind] = ((InterpreterGenerator*)this)->generate_method_entry(Interpreter::kind); \ - } +#define method_entry(kind) \ + { CodeletMark cm(_masm, "method entry point (kind = " #kind ")"); \ + Interpreter::_entry_table[Interpreter::kind] = ((InterpreterGenerator*)this)->generate_method_entry(Interpreter::kind); \ + } - // all non-native method kinds - method_entry(zerolocals) - method_entry(zerolocals_synchronized) - method_entry(empty) - method_entry(accessor) - method_entry(abstract) - method_entry(java_lang_math_sin ) - method_entry(java_lang_math_cos ) - method_entry(java_lang_math_tan ) - method_entry(java_lang_math_abs ) - method_entry(java_lang_math_sqrt ) - method_entry(java_lang_math_log ) - method_entry(java_lang_math_log10) - method_entry(java_lang_math_exp ) - method_entry(java_lang_math_pow ) - method_entry(java_lang_ref_reference_get) + // all non-native method kinds + method_entry(zerolocals) + method_entry(zerolocals_synchronized) + method_entry(empty) + method_entry(accessor) + method_entry(abstract) + method_entry(java_lang_math_sin ) + method_entry(java_lang_math_cos ) + method_entry(java_lang_math_tan ) + method_entry(java_lang_math_abs ) + method_entry(java_lang_math_sqrt ) + method_entry(java_lang_math_log ) + method_entry(java_lang_math_log10) + method_entry(java_lang_math_exp ) + method_entry(java_lang_math_pow ) + method_entry(java_lang_ref_reference_get) - if (UseCRC32Intrinsics) { - method_entry(java_util_zip_CRC32_update) - method_entry(java_util_zip_CRC32_updateBytes) - method_entry(java_util_zip_CRC32_updateByteBuffer) - } + if (UseCRC32Intrinsics) { + method_entry(java_util_zip_CRC32_update) + method_entry(java_util_zip_CRC32_updateBytes) + method_entry(java_util_zip_CRC32_updateByteBuffer) + } - initialize_method_handle_entries(); + initialize_method_handle_entries(); - // all native method kinds (must be one contiguous block) - Interpreter::_native_entry_begin = Interpreter::code()->code_end(); - method_entry(native) - method_entry(native_synchronized) - Interpreter::_native_entry_end = Interpreter::code()->code_end(); + // all native method kinds (must be one contiguous block) + Interpreter::_native_entry_begin = Interpreter::code()->code_end(); + method_entry(native) + method_entry(native_synchronized) + Interpreter::_native_entry_end = Interpreter::code()->code_end(); #undef method_entry - // Bytecodes - set_entry_points_for_all_bytes(); + // Bytecodes + set_entry_points_for_all_bytes(); + } + } while (CodeCacheExtensions::needs_other_interpreter_variant()); + + // installation of code in other places in the runtime + // (ExcutableCodeManager calls not needed to copy the entries) set_safepoints_for_all_bytes(); } @@ -445,6 +478,9 @@ void TemplateInterpreterGenerator::set_entry_points(Bytecodes::Code code) { + if (CodeCacheExtensions::skip_template_interpreter_entries(code)) { + return; + } CodeletMark cm(_masm, Bytecodes::name(code), code); // initialize entry points assert(_unimplemented_bytecode != NULL, "should have been generated before"); @@ -474,6 +510,7 @@ EntryPoint entry(bep, cep, sep, aep, iep, lep, fep, dep, vep); Interpreter::_normal_table.set_entry(code, entry); Interpreter::_wentry_point[code] = wep; + CodeCacheExtensions::completed_template_interpreter_entries(_masm, code); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/interpreter/templateInterpreter.hpp --- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -87,6 +87,7 @@ friend class TemplateInterpreterGenerator; friend class InterpreterGenerator; friend class TemplateTable; + friend class CodeCacheExtensions; // friend class Interpreter; public: diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/memory/allocation.cpp --- a/hotspot/src/share/vm/memory/allocation.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/memory/allocation.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -752,7 +752,7 @@ julong AllocStats::resource_bytes() { return Arena::_bytes_allocated - start_res_bytes; } void AllocStats::print() { tty->print_cr(UINT64_FORMAT " mallocs (" UINT64_FORMAT "MB), " - UINT64_FORMAT" frees (" UINT64_FORMAT "MB), " UINT64_FORMAT "MB resrc", + UINT64_FORMAT " frees (" UINT64_FORMAT "MB), " UINT64_FORMAT "MB resrc", num_mallocs(), alloc_bytes()/M, num_frees(), free_bytes()/M, resource_bytes()/M); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/memory/heap.hpp --- a/hotspot/src/share/vm/memory/heap.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/memory/heap.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -28,6 +28,7 @@ #include "code/codeBlob.hpp" #include "memory/allocation.hpp" #include "memory/virtualspace.hpp" +#include "utilities/macros.hpp" // Blocks @@ -80,6 +81,7 @@ class CodeHeap : public CHeapObj { friend class VMStructs; + friend class PregeneratedCodeHeap; private: VirtualSpace _memory; // the memory holding the blocks VirtualSpace _segmap; // the memory holding the segment map @@ -148,8 +150,8 @@ char* high() const { return _memory.high(); } char* high_boundary() const { return _memory.high_boundary(); } - bool contains(const void* p) const { return low_boundary() <= p && p < high(); } - void* find_start(void* p) const; // returns the block containing p or NULL + virtual bool contains(const void* p) const { return low_boundary() <= p && p < high(); } + virtual void* find_start(void* p) const; // returns the block containing p or NULL size_t alignment_unit() const; // alignment of any block size_t alignment_offset() const; // offset of first byte of any block, within the enclosing alignment unit static size_t header_size(); // returns the header size for each heap block @@ -158,9 +160,9 @@ int freelist_length() const { return _freelist_length; } // number of elements in the freelist // returns the first block or NULL - void* first() const { return next_used(first_block()); } + virtual void* first() const { return next_used(first_block()); } // returns the next block given a block p or NULL - void* next(void* p) const { return next_used(next_block(block_start(p))); } + virtual void* next(void* p) const { return next_used(next_block(block_start(p))); } // Statistics size_t capacity() const; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/memory/universe.cpp --- a/hotspot/src/share/vm/memory/universe.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/memory/universe.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -805,7 +805,7 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { assert(alignment <= Arguments::conservative_max_heap_alignment(), - err_msg("actual alignment "SIZE_FORMAT" must be within maximum heap alignment "SIZE_FORMAT, + err_msg("actual alignment " SIZE_FORMAT " must be within maximum heap alignment " SIZE_FORMAT, alignment, Arguments::conservative_max_heap_alignment())); size_t total_reserved = align_size_up(heap_size, alignment); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/memory/virtualspace.cpp --- a/hotspot/src/share/vm/memory/virtualspace.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/memory/virtualspace.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "code/codeCacheExtensions.hpp" #include "memory/virtualspace.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -603,7 +604,7 @@ ReservedCodeSpace::ReservedCodeSpace(size_t r_size, size_t rs_align, bool large) : - ReservedSpace(r_size, rs_align, large, /*executable*/ true) { + ReservedSpace(r_size, rs_align, large, /*executable*/ CodeCacheExtensions::support_dynamic_code()) { MemTracker::record_virtual_memory_type((address)base(), mtCode); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/constantPool.cpp --- a/hotspot/src/share/vm/oops/constantPool.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/constantPool.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1467,7 +1467,7 @@ } case JVM_CONSTANT_Long: { u8 val = Bytes::get_Java_u8(bytes); - printf("long "INT64_FORMAT, (int64_t) *(jlong *) &val); + printf("long " INT64_FORMAT, (int64_t) *(jlong *) &val); ent_size = 8; idx++; // Long takes two cpool slots break; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/cpCache.cpp --- a/hotspot/src/share/vm/oops/cpCache.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/cpCache.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -308,7 +308,7 @@ adapter->size_of_parameters()); if (TraceInvokeDynamic) { - tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ", + tty->print_cr("set_method_handle bc=%d appendix=" PTR_FORMAT "%s method_type=" PTR_FORMAT "%s method=" PTR_FORMAT " ", invoke_code, (void *)appendix(), (has_appendix ? "" : " (unused)"), (void *)method_type(), (has_method_type ? "" : " (unused)"), @@ -538,12 +538,12 @@ // print separator if (index == 0) st->print_cr(" -------------"); // print entry - st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this); + st->print("%3d (" PTR_FORMAT ") ", index, (intptr_t)this); st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index()); - st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f1); - st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2); - st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags); + st->print_cr(" [ " PTR_FORMAT "]", (intptr_t)_f1); + st->print_cr(" [ " PTR_FORMAT "]", (intptr_t)_f2); + st->print_cr(" [ " PTR_FORMAT "]", (intptr_t)_flags); st->print_cr(" -------------"); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/markOop.cpp --- a/hotspot/src/share/vm/oops/markOop.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/markOop.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -49,7 +49,7 @@ st->print("monitor=NULL"); else { BasicLock * bl = (BasicLock *) mon->owner(); - st->print("monitor={count="INTPTR_FORMAT",waiters="INTPTR_FORMAT",recursions="INTPTR_FORMAT",owner="INTPTR_FORMAT"}", + st->print("monitor={count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}", mon->count(), mon->waiters(), mon->recursions(), p2i(bl)); } } else { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/method.cpp --- a/hotspot/src/share/vm/oops/method.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/method.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -2019,9 +2019,9 @@ assert(is_method(), "must be method"); st->print_cr("%s", internal_name()); // get the effect of PrintOopAddress, always, for methods: - st->print_cr(" - this oop: "INTPTR_FORMAT, (intptr_t)this); + st->print_cr(" - this oop: " INTPTR_FORMAT, (intptr_t)this); st->print (" - method holder: "); method_holder()->print_value_on(st); st->cr(); - st->print (" - constants: "INTPTR_FORMAT" ", (address)constants()); + st->print (" - constants: " INTPTR_FORMAT " ", (address)constants()); constants()->print_value_on(st); st->cr(); st->print (" - access: 0x%x ", access_flags().as_int()); access_flags().print_on(st); st->cr(); st->print (" - name: "); name()->print_value_on(st); st->cr(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/method.hpp --- a/hotspot/src/share/vm/oops/method.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/method.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -82,7 +82,8 @@ _dont_inline = 1 << 3, _hidden = 1 << 4, _has_injected_profile = 1 << 5, - _running_emcp = 1 << 6 + _running_emcp = 1 << 6, + _intrinsic_candidate = 1 << 7 }; u1 _flags; @@ -815,6 +816,13 @@ _flags = x ? (_flags | _hidden) : (_flags & ~_hidden); } + bool intrinsic_candidate() { + return (_flags & _intrinsic_candidate) != 0; + } + void set_intrinsic_candidate(bool x) { + _flags = x ? (_flags | _intrinsic_candidate) : (_flags & ~_intrinsic_candidate); + } + bool has_injected_profile() { return (_flags & _has_injected_profile) != 0; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/objArrayKlass.cpp --- a/hotspot/src/share/vm/oops/objArrayKlass.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -466,7 +466,7 @@ if (i > max_objArray_print_length) { st->print("..."); break; } - st->print(" "INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i)); + st->print(" " INTPTR_FORMAT, (intptr_t)(void*)objArrayOop(obj)->obj_at(i)); } st->print(" }"); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/oop.cpp --- a/hotspot/src/share/vm/oops/oop.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/oops/oop.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -47,7 +47,7 @@ void oopDesc::print_address_on(outputStream* st) const { if (PrintOopAddress) { - st->print("{"INTPTR_FORMAT"}", this); + st->print("{" INTPTR_FORMAT "}", this); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/symbol.cpp diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/oops/symbol.hpp diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/c2_globals.hpp --- a/hotspot/src/share/vm/opto/c2_globals.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/c2_globals.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -688,6 +688,12 @@ product(bool, UseMulAddIntrinsic, false, \ "Enables intrinsification of BigInteger.mulAdd()") \ \ + product(bool, UseMontgomeryMultiplyIntrinsic, false, \ + "Enables intrinsification of BigInteger.montgomeryMultiply()") \ + \ + product(bool, UseMontgomerySquareIntrinsic, false, \ + "Enables intrinsification of BigInteger.montgomerySquare()") \ + \ product(bool, UseTypeSpeculation, true, \ "Speculatively propagate types from profiles") \ \ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/callnode.cpp --- a/hotspot/src/share/vm/opto/callnode.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/callnode.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -342,7 +342,7 @@ const Type *t = n->bottom_type(); switch (t->base()) { case Type::Int: - st->print(" %s%d]=#"INT32_FORMAT,msg,i,t->is_int()->get_con()); + st->print(" %s%d]=#" INT32_FORMAT,msg,i,t->is_int()->get_con()); break; case Type::AnyPtr: assert( t == TypePtr::NULL_PTR || n->in_dump(), "" ); @@ -371,7 +371,7 @@ st->print(" %s%d]=#%fF",msg,i,t->is_float_constant()->_f); break; case Type::Long: - st->print(" %s%d]=#"INT64_FORMAT,msg,i,(int64_t)(t->is_long()->get_con())); + st->print(" %s%d]=#" INT64_FORMAT,msg,i,(int64_t)(t->is_long()->get_con())); break; case Type::Half: case Type::Top: diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/escape.cpp --- a/hotspot/src/share/vm/opto/escape.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/escape.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -976,8 +976,10 @@ strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0 || strcmp(call->as_CallLeaf()->_name, "multiplyToLen") == 0 || strcmp(call->as_CallLeaf()->_name, "squareToLen") == 0 || - strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0) - ))) { + strcmp(call->as_CallLeaf()->_name, "mulAdd") == 0 || + strcmp(call->as_CallLeaf()->_name, "montgomery_multiply") == 0 || + strcmp(call->as_CallLeaf()->_name, "montgomery_square") == 0) + ))) { call->dump(); fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name)); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/generateOptoStub.cpp --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,19 +118,14 @@ // The C routines gets the base of thread-local storage passed in as an // extra argument. Not all calls need it, but its cheap to add here. for (uint pcnt = cnt; pcnt < parm_cnt; pcnt++, cnt++) { - // Convert ints to longs if required. - if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(pcnt)->isa_int()) { - fields[cnt++] = TypeLong::LONG; - fields[cnt] = Type::HALF; // must add an additional half for a long - } else { - fields[cnt] = jdomain->field_at(pcnt); - } + fields[cnt] = jdomain->field_at(pcnt); } fields[cnt++] = TypeRawPtr::BOTTOM; // Thread-local storage // Also pass in the caller's PC, if asked for. - if( return_pc ) + if (return_pc) { fields[cnt++] = TypeRawPtr::BOTTOM; // Return PC + } const TypeTuple* domain = TypeTuple::make(cnt,fields); // The C routine we are about to call cannot return an oop; it can block on @@ -143,21 +138,22 @@ const Type **rfields = TypeTuple::fields(jrange->cnt() - TypeFunc::Parms); // Fixup oop returns int retval_ptr = retval->isa_oop_ptr(); - if( retval_ptr ) { + if (retval_ptr) { assert( pass_tls, "Oop must be returned thru TLS" ); // Fancy-jumps return address; others return void rfields[TypeFunc::Parms] = is_fancy_jump ? TypeRawPtr::BOTTOM : Type::TOP; - } else if( retval->isa_int() ) { // Returning any integer subtype? + } else if (retval->isa_int()) { // Returning any integer subtype? // "Fatten" byte, char & short return types to 'int' to show that // the native C code can return values with junk high order bits. // We'll sign-extend it below later. rfields[TypeFunc::Parms] = TypeInt::INT; // It's "dirty" and needs sign-ext - } else if( jrange->cnt() >= TypeFunc::Parms+1 ) { // Else copy other types + } else if (jrange->cnt() >= TypeFunc::Parms+1) { // Else copy other types rfields[TypeFunc::Parms] = jrange->field_at(TypeFunc::Parms); - if( jrange->cnt() == TypeFunc::Parms+2 ) + if (jrange->cnt() == TypeFunc::Parms+2) { rfields[TypeFunc::Parms+1] = jrange->field_at(TypeFunc::Parms+1); + } } const TypeTuple* range = TypeTuple::make(jrange->cnt(),rfields); @@ -181,14 +177,7 @@ // A little too aggressive on the parm copy; return address is not an input call->set_req(TypeFunc::ReturnAdr, top()); for (; i < parm_cnt; i++) { // Regular input arguments - // Convert ints to longs if required. - if (CCallingConventionRequiresIntsAsLongs && jdomain->field_at(i)->isa_int()) { - Node* int_as_long = _gvn.transform(new ConvI2LNode(map()->in(i))); - call->init_req(cnt++, int_as_long); // long - call->init_req(cnt++, top()); // half - } else { - call->init_req(cnt++, map()->in(i)); - } + call->init_req(cnt++, map()->in(i)); } call->init_req( cnt++, thread ); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/library_call.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -297,6 +297,8 @@ bool inline_multiplyToLen(); bool inline_squareToLen(); bool inline_mulAdd(); + bool inline_montgomeryMultiply(); + bool inline_montgomerySquare(); bool inline_profileBoolean(); bool inline_isCompileConstant(); @@ -508,6 +510,13 @@ if (!UseMulAddIntrinsic) return NULL; break; + case vmIntrinsics::_montgomeryMultiply: + if (!UseMontgomeryMultiplyIntrinsic) return NULL; + break; + case vmIntrinsics::_montgomerySquare: + if (!UseMontgomerySquareIntrinsic) return NULL; + break; + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: if (!UseAESIntrinsics) return NULL; @@ -642,7 +651,8 @@ const int bci = kit.bci(); // Try to inline the intrinsic. - if (kit.try_to_inline(_last_predicate)) { + if ((CheckIntrinsics ? callee->intrinsic_candidate() : true) && + kit.try_to_inline(_last_predicate)) { if (C->print_intrinsics() || C->print_inlining()) { C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); } @@ -663,7 +673,13 @@ if (C->print_intrinsics() || C->print_inlining()) { if (jvms->has_method()) { // Not a root compile. - const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; + const char* msg; + if (callee->intrinsic_candidate()) { + msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; + } else { + msg = is_virtual() ? "failed to inline (intrinsic, virtual), method not annotated" + : "failed to inline (intrinsic), method not annotated"; + } C->print_inlining(callee, jvms->depth() - 1, bci, msg); } else { // Root compile @@ -942,6 +958,11 @@ case vmIntrinsics::_mulAdd: return inline_mulAdd(); + case vmIntrinsics::_montgomeryMultiply: + return inline_montgomeryMultiply(); + case vmIntrinsics::_montgomerySquare: + return inline_montgomerySquare(); + case vmIntrinsics::_ghash_processBlocks: return inline_ghash_processBlocks(); @@ -5244,7 +5265,7 @@ //-------------inline_multiplyToLen----------------------------------- bool LibraryCallKit::inline_multiplyToLen() { - assert(UseMultiplyToLenIntrinsic, "not implementated on this platform"); + assert(UseMultiplyToLenIntrinsic, "not implemented on this platform"); address stubAddr = StubRoutines::multiplyToLen(); if (stubAddr == NULL) { @@ -5254,11 +5275,12 @@ assert(callee()->signature()->size() == 5, "multiplyToLen has 5 parameters"); - Node* x = argument(1); - Node* xlen = argument(2); - Node* y = argument(3); - Node* ylen = argument(4); - Node* z = argument(5); + // no receiver because it is a static method + Node* x = argument(0); + Node* xlen = argument(1); + Node* y = argument(2); + Node* ylen = argument(3); + Node* z = argument(4); const Type* x_type = x->Value(&_gvn); const Type* y_type = y->Value(&_gvn); @@ -5437,6 +5459,121 @@ return true; } +//-------------inline_montgomeryMultiply----------------------------------- +bool LibraryCallKit::inline_montgomeryMultiply() { + address stubAddr = StubRoutines::montgomeryMultiply(); + if (stubAddr == NULL) { + return false; // Intrinsic's stub is not implemented on this platform + } + + assert(UseMontgomeryMultiplyIntrinsic, "not implemented on this platform"); + const char* stubName = "montgomery_square"; + + assert(callee()->signature()->size() == 7, "montgomeryMultiply has 7 parameters"); + + Node* a = argument(0); + Node* b = argument(1); + Node* n = argument(2); + Node* len = argument(3); + Node* inv = argument(4); + Node* m = argument(6); + + const Type* a_type = a->Value(&_gvn); + const TypeAryPtr* top_a = a_type->isa_aryptr(); + const Type* b_type = b->Value(&_gvn); + const TypeAryPtr* top_b = b_type->isa_aryptr(); + const Type* n_type = a->Value(&_gvn); + const TypeAryPtr* top_n = n_type->isa_aryptr(); + const Type* m_type = a->Value(&_gvn); + const TypeAryPtr* top_m = m_type->isa_aryptr(); + if (top_a == NULL || top_a->klass() == NULL || + top_b == NULL || top_b->klass() == NULL || + top_n == NULL || top_n->klass() == NULL || + top_m == NULL || top_m->klass() == NULL) { + // failed array check + return false; + } + + BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType b_elem = b_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (a_elem != T_INT || b_elem != T_INT || n_elem != T_INT || m_elem != T_INT) { + return false; + } + + // Make the call + { + Node* a_start = array_element_address(a, intcon(0), a_elem); + Node* b_start = array_element_address(b, intcon(0), b_elem); + Node* n_start = array_element_address(n, intcon(0), n_elem); + Node* m_start = array_element_address(m, intcon(0), m_elem); + + Node* call = make_runtime_call(RC_LEAF, + OptoRuntime::montgomeryMultiply_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + a_start, b_start, n_start, len, inv, top(), + m_start); + set_result(m); + } + + return true; +} + +bool LibraryCallKit::inline_montgomerySquare() { + address stubAddr = StubRoutines::montgomerySquare(); + if (stubAddr == NULL) { + return false; // Intrinsic's stub is not implemented on this platform + } + + assert(UseMontgomerySquareIntrinsic, "not implemented on this platform"); + const char* stubName = "montgomery_square"; + + assert(callee()->signature()->size() == 6, "montgomerySquare has 6 parameters"); + + Node* a = argument(0); + Node* n = argument(1); + Node* len = argument(2); + Node* inv = argument(3); + Node* m = argument(5); + + const Type* a_type = a->Value(&_gvn); + const TypeAryPtr* top_a = a_type->isa_aryptr(); + const Type* n_type = a->Value(&_gvn); + const TypeAryPtr* top_n = n_type->isa_aryptr(); + const Type* m_type = a->Value(&_gvn); + const TypeAryPtr* top_m = m_type->isa_aryptr(); + if (top_a == NULL || top_a->klass() == NULL || + top_n == NULL || top_n->klass() == NULL || + top_m == NULL || top_m->klass() == NULL) { + // failed array check + return false; + } + + BasicType a_elem = a_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType n_elem = n_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + BasicType m_elem = m_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); + if (a_elem != T_INT || n_elem != T_INT || m_elem != T_INT) { + return false; + } + + // Make the call + { + Node* a_start = array_element_address(a, intcon(0), a_elem); + Node* n_start = array_element_address(n, intcon(0), n_elem); + Node* m_start = array_element_address(m, intcon(0), m_elem); + + Node* call = make_runtime_call(RC_LEAF, + OptoRuntime::montgomerySquare_Type(), + stubAddr, stubName, TypePtr::BOTTOM, + a_start, n_start, len, inv, top(), + m_start); + set_result(m); + } + + return true; +} + /** * Calculate CRC32 for byte. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/loopTransform.cpp --- a/hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/loopTransform.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -2941,13 +2941,6 @@ _igvn.register_new_node_with_optimizer(store_value); } - if (CCallingConventionRequiresIntsAsLongs && - // See StubRoutines::select_fill_function for types. FLOAT has been converted to INT. - (t == T_FLOAT || t == T_INT || is_subword_type(t))) { - store_value = new ConvI2LNode(store_value); - _igvn.register_new_node_with_optimizer(store_value); - } - Node* mem_phi = store->in(MemNode::Memory); Node* result_ctrl; Node* result_mem; @@ -2957,9 +2950,6 @@ uint cnt = 0; call->init_req(TypeFunc::Parms + cnt++, from); call->init_req(TypeFunc::Parms + cnt++, store_value); - if (CCallingConventionRequiresIntsAsLongs) { - call->init_req(TypeFunc::Parms + cnt++, C->top()); - } #ifdef _LP64 len = new ConvI2LNode(len); _igvn.register_new_node_with_optimizer(len); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/regmask.cpp --- a/hotspot/src/share/vm/opto/regmask.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/regmask.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -25,6 +25,8 @@ #include "precompiled.hpp" #include "opto/ad.hpp" #include "opto/compile.hpp" +#include "opto/matcher.hpp" +#include "opto/node.hpp" #include "opto/regmask.hpp" #define RM_SIZE _RM_SIZE /* a constant private to the class RegMask */ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/runtime.cpp --- a/hotspot/src/share/vm/opto/runtime.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/runtime.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -779,18 +779,10 @@ const TypeFunc* OptoRuntime::array_fill_Type() { const Type** fields; int argp = TypeFunc::Parms; - if (CCallingConventionRequiresIntsAsLongs) { // create input type (domain): pointer, int, size_t - fields = TypeTuple::fields(3 LP64_ONLY( + 2)); - fields[argp++] = TypePtr::NOTNULL; - fields[argp++] = TypeLong::LONG; - fields[argp++] = Type::HALF; - } else { - // create input type (domain): pointer, int, size_t - fields = TypeTuple::fields(3 LP64_ONLY( + 1)); - fields[argp++] = TypePtr::NOTNULL; - fields[argp++] = TypeInt::INT; - } + fields = TypeTuple::fields(3 LP64_ONLY( + 1)); + fields[argp++] = TypePtr::NOTNULL; + fields[argp++] = TypeInt::INT; fields[argp++] = TypeX_X; // size in whatevers (size_t) LP64_ONLY(fields[argp++] = Type::HALF); // other half of long length const TypeTuple *domain = TypeTuple::make(argp, fields); @@ -1010,6 +1002,53 @@ return TypeFunc::make(domain, range); } +const TypeFunc* OptoRuntime::montgomeryMultiply_Type() { + // create input type (domain) + int num_args = 7; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // a + fields[argp++] = TypePtr::NOTNULL; // b + fields[argp++] = TypePtr::NOTNULL; // n + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypeLong::LONG; // inv + fields[argp++] = Type::HALF; + fields[argp++] = TypePtr::NOTNULL; // result + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypePtr::NOTNULL; + + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + +const TypeFunc* OptoRuntime::montgomerySquare_Type() { + // create input type (domain) + int num_args = 6; + int argcnt = num_args; + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // a + fields[argp++] = TypePtr::NOTNULL; // n + fields[argp++] = TypeInt::INT; // len + fields[argp++] = TypeLong::LONG; // inv + fields[argp++] = Type::HALF; + fields[argp++] = TypePtr::NOTNULL; // result + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypePtr::NOTNULL; + + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} + // GHASH block processing const TypeFunc* OptoRuntime::ghash_processBlocks_Type() { int argcnt = 4; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/opto/runtime.hpp --- a/hotspot/src/share/vm/opto/runtime.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/opto/runtime.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -311,6 +311,8 @@ static const TypeFunc* digestBase_implCompressMB_Type(); static const TypeFunc* multiplyToLen_Type(); + static const TypeFunc* montgomeryMultiply_Type(); + static const TypeFunc* montgomerySquare_Type(); static const TypeFunc* squareToLen_Type(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/precompiled/precompiled.hpp --- a/hotspot/src/share/vm/precompiled/precompiled.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/precompiled/precompiled.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -57,12 +57,15 @@ # include "classfile/classFileParser.hpp" # include "classfile/classFileStream.hpp" # include "classfile/classLoader.hpp" +# include "classfile/imageDecompressor.hpp" +# include "classfile/imageFile.hpp" # include "classfile/javaClasses.hpp" # include "classfile/symbolTable.hpp" # include "classfile/systemDictionary.hpp" # include "classfile/vmSymbols.hpp" # include "code/codeBlob.hpp" # include "code/codeCache.hpp" +# include "code/codeCacheExtensions.hpp" # include "code/compressedStream.hpp" # include "code/debugInfo.hpp" # include "code/debugInfoRec.hpp" @@ -229,6 +232,7 @@ # include "utilities/constantTag.hpp" # include "utilities/copy.hpp" # include "utilities/debug.hpp" +# include "utilities/endian.hpp" # include "utilities/exceptions.hpp" # include "utilities/globalDefinitions.hpp" # include "utilities/growableArray.hpp" diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/jni.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -3848,6 +3848,7 @@ unit_test_function_call // Forward declaration +void test_semaphore(); void TestOS_test(); void TestReservedSpace_test(); void TestReserveMemorySpecial_test(); @@ -3873,6 +3874,7 @@ void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); + run_unit_test(test_semaphore()); run_unit_test(TestOS_test()); run_unit_test(TestReservedSpace_test()); run_unit_test(TestReserveMemorySpecial_test()); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/jvm.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -24,6 +24,8 @@ #include "precompiled.hpp" #include "classfile/classLoader.hpp" +#include "classfile/imageDecompressor.hpp" +#include "classfile/imageFile.hpp" #include "classfile/javaAssertions.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" @@ -69,6 +71,7 @@ #include "utilities/copy.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" +#include "utilities/endian.hpp" #include "utilities/events.hpp" #include "utilities/histogram.hpp" #include "utilities/macros.hpp" @@ -3665,3 +3668,244 @@ info->is_attachable = AttachListener::is_attach_supported(); } JVM_END + +// jdk.internal.jimage ///////////////////////////////////////////////////////// +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. + +// Java entry to open an image file for sharing. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jlong, +JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian)) { + JVMWrapper("JVM_ImageOpen"); + // Open image file for reading. + ImageFileReader* reader = ImageFileReader::open(nativePath, big_endian != JNI_FALSE); + // Return image ID as a jlong. + return ImageFileReader::readerToID(reader); +} +JVM_END + +// Java entry for closing a shared image file. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(void, +JVM_ImageClose(JNIEnv *env, jlong id)) { + JVMWrapper("JVM_ImageClose"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If valid reader the close. + if (reader != NULL) { + ImageFileReader::close(reader); + } +} +JVM_END + +// Java entry for accessing the base address of the image index. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jlong, +JVM_ImageGetIndexAddress(JNIEnv *env, jlong id)) { + JVMWrapper("JVM_ImageGetIndexAddress"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If valid reader return index base address (as jlong) else zero. + return reader != NULL ? (jlong)reader->get_index_address() : 0L; +} +JVM_END + +// Java entry for accessing the base address of the image data. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jlong, +JVM_ImageGetDataAddress(JNIEnv *env, jlong id)) { + JVMWrapper("JVM_ImageGetDataAddress"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If valid reader return data base address (as jlong) else zero. + return MemoryMapImage && reader != NULL ? (jlong)reader->get_data_address() : 0L; +} +JVM_END + +// Java entry for reading an uncompressed resource from the image. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jboolean, +JVM_ImageRead(JNIEnv *env, jlong id, jlong offset, + unsigned char* uncompressedAddress, jlong uncompressed_size)) { + JVMWrapper("JVM_ImageRead"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id);\ + // If not a valid reader the fail the read. + if (reader == NULL) return false; + // Get the file offset of resource data. + u8 file_offset = reader->get_index_size() + offset; + // Check validity of arguments. + if (offset < 0 || + uncompressed_size < 0 || + file_offset > reader->file_size() - uncompressed_size) { + return false; + } + // Read file content into buffer. + return (jboolean)reader->read_at((u1*)uncompressedAddress, uncompressed_size, + file_offset); +} +JVM_END + +// Java entry for reading a compressed resource from the image. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jboolean, +JVM_ImageReadCompressed(JNIEnv *env, + jlong id, jlong offset, + unsigned char* compressedAddress, jlong compressed_size, + unsigned char* uncompressedAddress, jlong uncompressed_size)) { + JVMWrapper("JVM_ImageReadCompressed"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // If not a valid reader the fail the read. + if (reader == NULL) return false; + // Get the file offset of resource data. + u8 file_offset = reader->get_index_size() + offset; + // Check validity of arguments. + if (offset < 0 || + compressed_size < 0 || + uncompressed_size < 0 || + file_offset > reader->file_size() - compressed_size) { + return false; + } + + // Read file content into buffer. + bool is_read = reader->read_at(compressedAddress, compressed_size, + file_offset); + // If successfully read then decompress. + if (is_read) { + const ImageStrings strings = reader->get_strings(); + ImageDecompressor::decompress_resource(compressedAddress, uncompressedAddress, + uncompressed_size, &strings, true); + } + return (jboolean)is_read; +} +JVM_END + +// Java entry for retrieving UTF-8 bytes from image string table. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(const char*, JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset)) { + JVMWrapper("JVM_ImageGetStringBytes"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Manage image string table. + ImageStrings strings = reader->get_strings(); + // Retrieve string adrress from table. + const char* data = strings.get(offset); + return data; +} +JVM_END + +// Utility function to copy location information into a jlong array. +// WARNING: This function is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +static void image_expand_location(JNIEnv *env, jlong* rawAttributes, ImageLocation& location) { + // Copy attributes from location. + for (int kind = ImageLocation::ATTRIBUTE_END + 1; + kind < ImageLocation::ATTRIBUTE_COUNT; + kind++) { + rawAttributes[kind] = location.get_attribute(kind); + } +} + +// Java entry for retrieving location attributes for attribute offset. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jlong*, JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset)) { + JVMWrapper("JVM_ImageGetAttributes"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Retrieve first byte address of resource's location attribute stream. + u1* data = reader->get_location_offset_data(offset); + // Fail if not valid offset. + if (data == NULL) return NULL; + // Expand stream into array. + ImageLocation location(data); + image_expand_location(env, rawAttributes, location); + return rawAttributes; +} +JVM_END + +// Java entry for retrieving location attributes count for attribute offset. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jsize, JVM_ImageGetAttributesCount(JNIEnv *env)) { + JVMWrapper("JVM_ImageGetAttributesCount"); + return ImageLocation::ATTRIBUTE_COUNT; +} +JVM_END + +// Java entry for retrieving location attributes for named resource. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jlong*, +JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id)) { + JVMWrapper("JVM_ImageFindAttributes"); + // Mark for temporary buffers. + ResourceMark rm; + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Convert byte array to a cstring. + char* path = NEW_RESOURCE_ARRAY(char, size + 1); + memcpy(path, rawBytes, size); + path[size] = '\0'; + // Locate resource location data. + ImageLocation location; + bool found = reader->find_location(path, location); + // Resource not found. + if (!found) return NULL; + // Expand stream into array. + image_expand_location(env, rawAttributes, location); + return rawAttributes; +} +JVM_END + +// Java entry for retrieving all the attribute stream offsets from an image. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(jint*, JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id)) { + JVMWrapper("JVM_ImageAttributeOffsets"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return NULL; + // Determine endian for reader. + Endian* endian = reader->endian(); + // Get base address of attribute stream offsets table. + u4* offsets_table = reader->offsets_table(); + // Allocate int array result. + // Copy values to result (converting endian.) + for (u4 i = 0; i < length; i++) { + rawOffsets[i] = endian->get(offsets_table[i]); + } + return rawOffsets; +} +JVM_END + +// Java entry for retrieving all the attribute stream offsets length from an image. +// WARNING: This API is experimental and temporary during JDK 9 development +// cycle. It will not be supported in the eventual JDK 9 release. +JVM_ENTRY(unsigned int, JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id)) { + JVMWrapper("JVM_ImageAttributeOffsetsLength"); + // Convert image ID to image reader structure. + ImageFileReader* reader = ImageFileReader::idToReader(id); + // Fail if not valid reader. + if (reader == NULL) return 0; + // Get perfect hash table length. + u4 length = reader->table_length(); + return (jint) length; +} +JVM_END diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/jvm.h --- a/hotspot/src/share/vm/prims/jvm.h Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/jvm.h Thu Jul 09 22:46:16 2015 -0700 @@ -571,6 +571,52 @@ JNIEXPORT jboolean JNICALL JVM_SupportsCX8(void); +/* + * jdk.internal.jimage + * WARNING: This API is experimental and temporary during JDK 9 development + * cycle. It will not be supported in the eventual JDK 9 release. + */ + +JNIEXPORT jlong JNICALL +JVM_ImageOpen(JNIEnv *env, const char *nativePath, jboolean big_endian); + +JNIEXPORT void JNICALL +JVM_ImageClose(JNIEnv *env, jlong id); + +JNIEXPORT jlong JNICALL +JVM_ImageGetIndexAddress(JNIEnv *env, jlong id); + +JNIEXPORT jlong JNICALL +JVM_ImageGetDataAddress(JNIEnv *env,jlong id); + +JNIEXPORT jboolean JNICALL +JVM_ImageRead(JNIEnv *env, jlong id, jlong offset, + unsigned char* uncompressedAddress, jlong uncompressed_size); + + +JNIEXPORT jboolean JNICALL +JVM_ImageReadCompressed(JNIEnv *env, jlong id, jlong offset, + unsigned char* compressedBuffer, jlong compressed_size, + unsigned char* uncompressedBuffer, jlong uncompressed_size); + +JNIEXPORT const char* JNICALL +JVM_ImageGetStringBytes(JNIEnv *env, jlong id, jint offset); + +JNIEXPORT jlong* JNICALL +JVM_ImageGetAttributes(JNIEnv *env, jlong* rawAttributes, jlong id, jint offset); + +JNIEXPORT jsize JNICALL +JVM_ImageGetAttributesCount(JNIEnv *env); + +JNIEXPORT jlong* JNICALL +JVM_ImageFindAttributes(JNIEnv *env, jlong* rawAttributes, jbyte* rawBytes, jsize size, jlong id); + +JNIEXPORT jint* JNICALL +JVM_ImageAttributeOffsets(JNIEnv *env, jint* rawOffsets, unsigned int length, jlong id); + +JNIEXPORT unsigned int JNICALL +JVM_ImageAttributeOffsetsLength(JNIEnv *env, jlong id); + /************************************************************************* PART 2: Support for the Verifier and Class File Format Checker ************************************************************************/ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/methodHandles.cpp --- a/hotspot/src/share/vm/prims/methodHandles.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/methodHandles.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -26,6 +26,7 @@ #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "code/codeCache.hpp" +#include "code/codeCacheExtensions.hpp" #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/oopMapCache.hpp" @@ -100,6 +101,7 @@ StubCodeMark mark(this, "MethodHandle::interpreter_entry", vmIntrinsics::name_at(iid)); address entry = MethodHandles::generate_method_handle_interpreter_entry(_masm, iid); if (entry != NULL) { + CodeCacheExtensions::handle_generated_pc(entry, vmIntrinsics::name_at(iid)); Interpreter::set_entry_for_kind(mk, entry); } // If the entry is not set, it will throw AbstractMethodError. @@ -1389,41 +1391,41 @@ #define LANG "Ljava/lang/" #define JLINV "Ljava/lang/invoke/" -#define OBJ LANG"Object;" -#define CLS LANG"Class;" -#define STRG LANG"String;" -#define CS JLINV"CallSite;" -#define MT JLINV"MethodType;" -#define MH JLINV"MethodHandle;" -#define MEM JLINV"MemberName;" -#define CTX JLINV"MethodHandleNatives$CallSiteContext;" +#define OBJ LANG "Object;" +#define CLS LANG "Class;" +#define STRG LANG "String;" +#define CS JLINV "CallSite;" +#define MT JLINV "MethodType;" +#define MH JLINV "MethodHandle;" +#define MEM JLINV "MemberName;" +#define CTX JLINV "MethodHandleNatives$CallSiteContext;" #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) // These are the native methods on java.lang.invoke.MethodHandleNatives. static JNINativeMethod MHN_methods[] = { - {CC"init", CC"("MEM""OBJ")V", FN_PTR(MHN_init_Mem)}, - {CC"expand", CC"("MEM")V", FN_PTR(MHN_expand_Mem)}, - {CC"resolve", CC"("MEM""CLS")"MEM, FN_PTR(MHN_resolve_Mem)}, + {CC "init", CC "(" MEM "" OBJ ")V", FN_PTR(MHN_init_Mem)}, + {CC "expand", CC "(" MEM ")V", FN_PTR(MHN_expand_Mem)}, + {CC "resolve", CC "(" MEM "" CLS ")" MEM, FN_PTR(MHN_resolve_Mem)}, // static native int getNamedCon(int which, Object[] name) - {CC"getNamedCon", CC"(I["OBJ")I", FN_PTR(MHN_getNamedCon)}, + {CC "getNamedCon", CC "(I[" OBJ ")I", FN_PTR(MHN_getNamedCon)}, // static native int getMembers(Class defc, String matchName, String matchSig, // int matchFlags, Class caller, int skip, MemberName[] results); - {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)}, - {CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)}, - {CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)}, - {CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)}, - {CC"clearCallSiteContext", CC"("CTX")V", FN_PTR(MHN_clearCallSiteContext)}, - {CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)}, - {CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)}, - {CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)} + {CC "getMembers", CC "(" CLS "" STRG "" STRG "I" CLS "I[" MEM ")I", FN_PTR(MHN_getMembers)}, + {CC "objectFieldOffset", CC "(" MEM ")J", FN_PTR(MHN_objectFieldOffset)}, + {CC "setCallSiteTargetNormal", CC "(" CS "" MH ")V", FN_PTR(MHN_setCallSiteTargetNormal)}, + {CC "setCallSiteTargetVolatile", CC "(" CS "" MH ")V", FN_PTR(MHN_setCallSiteTargetVolatile)}, + {CC "clearCallSiteContext", CC "(" CTX ")V", FN_PTR(MHN_clearCallSiteContext)}, + {CC "staticFieldOffset", CC "(" MEM ")J", FN_PTR(MHN_staticFieldOffset)}, + {CC "staticFieldBase", CC "(" MEM ")" OBJ, FN_PTR(MHN_staticFieldBase)}, + {CC "getMemberVMInfo", CC "(" MEM ")" OBJ, FN_PTR(MHN_getMemberVMInfo)} }; static JNINativeMethod MH_methods[] = { // UnsupportedOperationException throwers - {CC"invoke", CC"(["OBJ")"OBJ, FN_PTR(MH_invoke_UOE)}, - {CC"invokeExact", CC"(["OBJ")"OBJ, FN_PTR(MH_invokeExact_UOE)} + {CC "invoke", CC "([" OBJ ")" OBJ, FN_PTR(MH_invoke_UOE)}, + {CC "invokeExact", CC "([" OBJ ")" OBJ, FN_PTR(MH_invokeExact_UOE)} }; /** diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/perf.cpp --- a/hotspot/src/share/vm/prims/perf.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/perf.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -295,17 +295,17 @@ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) #define BB "Ljava/nio/ByteBuffer;" #define JLS "Ljava/lang/String;" -#define CL_ARGS CC"("JLS"IIJ)"BB -#define CBA_ARGS CC"("JLS"II[BI)"BB +#define CL_ARGS CC "(" JLS "IIJ)" BB +#define CBA_ARGS CC "(" JLS "II[BI)" BB static JNINativeMethod perfmethods[] = { - {CC"attach", CC"("JLS"II)"BB, FN_PTR(Perf_Attach)}, - {CC"detach", CC"("BB")V", FN_PTR(Perf_Detach)}, - {CC"createLong", CL_ARGS, FN_PTR(Perf_CreateLong)}, - {CC"createByteArray", CBA_ARGS, FN_PTR(Perf_CreateByteArray)}, - {CC"highResCounter", CC"()J", FN_PTR(Perf_HighResCounter)}, - {CC"highResFrequency", CC"()J", FN_PTR(Perf_HighResFrequency)} + {CC "attach", CC "(" JLS "II)" BB, FN_PTR(Perf_Attach)}, + {CC "detach", CC "(" BB ")V", FN_PTR(Perf_Detach)}, + {CC "createLong", CL_ARGS, FN_PTR(Perf_CreateLong)}, + {CC "createByteArray", CBA_ARGS, FN_PTR(Perf_CreateByteArray)}, + {CC "highResCounter", CC "()J", FN_PTR(Perf_HighResCounter)}, + {CC "highResFrequency", CC "()J", FN_PTR(Perf_HighResFrequency)} }; #undef CBA_ARGS diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/unsafe.cpp --- a/hotspot/src/share/vm/prims/unsafe.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/unsafe.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1206,39 +1206,39 @@ #define LANG "Ljava/lang/" -#define OBJ LANG"Object;" -#define CLS LANG"Class;" -#define FLD LANG"reflect/Field;" -#define THR LANG"Throwable;" +#define OBJ LANG "Object;" +#define CLS LANG "Class;" +#define FLD LANG "reflect/Field;" +#define THR LANG "Throwable;" -#define DC_Args LANG"String;[BII" LANG"ClassLoader;" "Ljava/security/ProtectionDomain;" -#define DAC_Args CLS"[B["OBJ +#define DC_Args LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;" +#define DAC_Args CLS "[B[" OBJ #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) #define DECLARE_GETPUTOOP(Boolean, Z) \ - {CC"get"#Boolean, CC"("OBJ"J)"#Z, FN_PTR(Unsafe_Get##Boolean)}, \ - {CC"put"#Boolean, CC"("OBJ"J"#Z")V", FN_PTR(Unsafe_Set##Boolean)}, \ - {CC"get"#Boolean"Volatile", CC"("OBJ"J)"#Z, FN_PTR(Unsafe_Get##Boolean##Volatile)}, \ - {CC"put"#Boolean"Volatile", CC"("OBJ"J"#Z")V", FN_PTR(Unsafe_Set##Boolean##Volatile)} + {CC "get" #Boolean, CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean)}, \ + {CC "put" #Boolean, CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean)}, \ + {CC "get" #Boolean "Volatile", CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean##Volatile)}, \ + {CC "put" #Boolean "Volatile", CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean##Volatile)} #define DECLARE_GETPUTNATIVE(Byte, B) \ - {CC"get"#Byte, CC"("ADR")"#B, FN_PTR(Unsafe_GetNative##Byte)}, \ - {CC"put"#Byte, CC"("ADR#B")V", FN_PTR(Unsafe_SetNative##Byte)} + {CC "get" #Byte, CC "(" ADR ")" #B, FN_PTR(Unsafe_GetNative##Byte)}, \ + {CC "put" #Byte, CC "(" ADR#B ")V", FN_PTR(Unsafe_SetNative##Byte)} static JNINativeMethod methods[] = { - {CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)}, - {CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)}, - {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObjectVolatile)}, - {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObjectVolatile)}, + {CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)}, + {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)}, + {CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)}, + {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObjectVolatile)}, - {CC"getUncompressedObject", CC"("ADR")"OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, - {CC"getJavaMirror", CC"("ADR")"CLS, FN_PTR(Unsafe_GetJavaMirror)}, - {CC"getKlassPointer", CC"("OBJ")"ADR, FN_PTR(Unsafe_GetKlassPointer)}, + {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, + {CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)}, + {CC "getKlassPointer", CC "(" OBJ ")" ADR, FN_PTR(Unsafe_GetKlassPointer)}, DECLARE_GETPUTOOP(Boolean, Z), DECLARE_GETPUTOOP(Byte, B), @@ -1257,49 +1257,49 @@ DECLARE_GETPUTNATIVE(Float, F), DECLARE_GETPUTNATIVE(Double, D), - {CC"getAddress", CC"("ADR")"ADR, FN_PTR(Unsafe_GetNativeAddress)}, - {CC"putAddress", CC"("ADR""ADR")V", FN_PTR(Unsafe_SetNativeAddress)}, + {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)}, + {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)}, - {CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)}, - {CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)}, - {CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)}, + {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)}, + {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)}, + {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)}, - {CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)}, - {CC"staticFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_StaticFieldOffset)}, - {CC"staticFieldBase", CC"("FLD")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)}, - {CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)}, - {CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)}, - {CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)}, - {CC"addressSize", CC"()I", FN_PTR(Unsafe_AddressSize)}, - {CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)}, + {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)}, + {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)}, + {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)}, + {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)}, + {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)}, + {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)}, + {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)}, + {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)}, - {CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)}, - {CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)}, - {CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}, - {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, - {CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)}, - {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)}, - {CC"putOrderedObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetOrderedObject)}, - {CC"putOrderedInt", CC"("OBJ"JI)V", FN_PTR(Unsafe_SetOrderedInt)}, - {CC"putOrderedLong", CC"("OBJ"JJ)V", FN_PTR(Unsafe_SetOrderedLong)}, - {CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)}, - {CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}, + {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)}, + {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)}, + {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}, + {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, + {CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)}, + {CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)}, + {CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)}, + {CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)}, + {CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)}, + {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)}, + {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}, - {CC"getLoadAverage", CC"([DI)I", FN_PTR(Unsafe_Loadavg)}, + {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)}, - {CC"copyMemory", CC"("OBJ"J"OBJ"JJ)V", FN_PTR(Unsafe_CopyMemory)}, - {CC"setMemory", CC"("OBJ"JJB)V", FN_PTR(Unsafe_SetMemory)}, + {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)}, + {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)}, - {CC"defineAnonymousClass", CC"("DAC_Args")"CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, + {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, - {CC"shouldBeInitialized",CC"("CLS")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, + {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, - {CC"loadFence", CC"()V", FN_PTR(Unsafe_LoadFence)}, - {CC"storeFence", CC"()V", FN_PTR(Unsafe_StoreFence)}, - {CC"fullFence", CC"()V", FN_PTR(Unsafe_FullFence)}, + {CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)}, + {CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)}, + {CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)}, - {CC"isBigEndian0", CC"()Z", FN_PTR(Unsafe_isBigEndian0)}, - {CC"unalignedAccess0", CC"()Z", FN_PTR(Unsafe_unalignedAccess0)} + {CC "isBigEndian0", CC "()Z", FN_PTR(Unsafe_isBigEndian0)}, + {CC "unalignedAccess0", CC "()Z", FN_PTR(Unsafe_unalignedAccess0)} }; #undef CC diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/prims/whitebox.cpp --- a/hotspot/src/share/vm/prims/whitebox.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/prims/whitebox.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -27,6 +27,7 @@ #include #include "classfile/classLoaderData.hpp" +#include "classfile/imageFile.hpp" #include "classfile/stringTable.hpp" #include "code/codeCache.hpp" #include "jvmtifiles/jvmtiEnv.hpp" @@ -159,8 +160,8 @@ WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) { CollectorPolicy * p = Universe::heap()->collector_policy(); - gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap " - SIZE_FORMAT" Maximum heap "SIZE_FORMAT" Space alignment "SIZE_FORMAT" Heap alignment "SIZE_FORMAT, + gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " + SIZE_FORMAT " Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT, p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(), p->space_alignment(), p->heap_alignment()); } @@ -195,8 +196,8 @@ Universe::narrow_oop_use_implicit_null_checks() )) { tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n " "\tUseCompressedOops is %d\n" - "\trhs.base() is "PTR_FORMAT"\n" - "\tUniverse::narrow_oop_base() is "PTR_FORMAT"\n" + "\trhs.base() is " PTR_FORMAT "\n" + "\tUniverse::narrow_oop_base() is " PTR_FORMAT "\n" "\tUniverse::narrow_oop_use_implicit_null_checks() is %d", UseCompressedOops, rhs.base(), @@ -249,8 +250,8 @@ WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o, jlong reserved_space_size, jlong magnitude, jlong iterations)) - tty->print_cr("reservedSpaceSize="JLONG_FORMAT", magnitude="JLONG_FORMAT", " - "iterations="JLONG_FORMAT"\n", reserved_space_size, magnitude, + tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", " + "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude, iterations); if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) { tty->print_cr("One of variables printed above is negative. Can't proceed.\n"); @@ -1125,6 +1126,132 @@ return (jlong) MetaspaceGC::capacity_until_GC(); WB_END +WB_ENTRY(jboolean, WB_ReadImageFile(JNIEnv* env, jobject wb, jstring imagefile)) + const char* filename = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(imagefile)); + return ImageFileReader::open(filename) != NULL; +WB_END + +WB_ENTRY(jlong, WB_imageOpenImage(JNIEnv *env, jobject wb, jstring path, jboolean big_endian)) + ThreadToNativeFromVM ttn(thread); + const char *nativePath = env->GetStringUTFChars(path, NULL); + jlong ret = JVM_ImageOpen(env, nativePath, big_endian); + + env->ReleaseStringUTFChars(path, nativePath); + return ret; +WB_END + +WB_ENTRY(void, WB_imageCloseImage(JNIEnv *env, jobject wb, jlong id)) + ThreadToNativeFromVM ttn(thread); + JVM_ImageClose(env, id); +WB_END + +WB_ENTRY(jlong, WB_imageGetIndexAddress(JNIEnv *env, jobject wb, jlong id)) + ThreadToNativeFromVM ttn(thread); + return JVM_ImageGetIndexAddress(env, id); +WB_END + +WB_ENTRY(jlong, WB_imageGetDataAddress(JNIEnv *env, jobject wb, jlong id)) + ThreadToNativeFromVM ttn(thread); + return JVM_ImageGetDataAddress(env, id); +WB_END + +WB_ENTRY(jboolean, WB_imageRead(JNIEnv *env, jobject wb, jlong id, jlong offset, jobject uncompressedBuffer, jlong uncompressed_size)) + ThreadToNativeFromVM ttn(thread); + if (uncompressedBuffer == NULL) { + return JNI_FALSE; + } + unsigned char* uncompressedAddress = + (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer); + return JVM_ImageRead(env, id, offset, uncompressedAddress, uncompressed_size); +WB_END + +WB_ENTRY(jboolean, WB_imageReadCompressed(JNIEnv *env, jobject wb, jlong id, jlong offset, jobject compressedBuffer, jlong compressed_size, jobject uncompressedBuffer, jlong uncompressed_size)) + ThreadToNativeFromVM ttn(thread); + if (uncompressedBuffer == NULL || compressedBuffer == NULL) { + return false; + } + // Get address of read direct buffer. + unsigned char* compressedAddress = + (unsigned char*) env->GetDirectBufferAddress(compressedBuffer); + // Get address of decompression direct buffer. + unsigned char* uncompressedAddress = + (unsigned char*) env->GetDirectBufferAddress(uncompressedBuffer); + return JVM_ImageReadCompressed(env, id, offset, compressedAddress, compressed_size, uncompressedAddress, uncompressed_size); +WB_END + +WB_ENTRY(jbyteArray, WB_imageGetStringBytes(JNIEnv *env, jobject wb, jlong id, jlong offset)) + ThreadToNativeFromVM ttn(thread); + const char* data = JVM_ImageGetStringBytes(env, id, offset); + // Determine String length. + size_t size = strlen(data); + // Allocate byte array. + jbyteArray byteArray = env->NewByteArray((jsize) size); + // Get array base address. + jbyte* rawBytes = env->GetByteArrayElements(byteArray, NULL); + // Copy bytes from image string table. + memcpy(rawBytes, data, size); + // Release byte array base address. + env->ReleaseByteArrayElements(byteArray, rawBytes, 0); + return byteArray; +WB_END + +WB_ENTRY(jlong, WB_imageGetStringsSize(JNIEnv *env, jobject wb, jlong id)) + ImageFileReader* reader = ImageFileReader::idToReader(id); + return reader? reader->strings_size() : 0L; +WB_END + +WB_ENTRY(jlongArray, WB_imageGetAttributes(JNIEnv *env, jobject wb, jlong id, jint offset)) + ThreadToNativeFromVM ttn(thread); + // Allocate a jlong large enough for all location attributes. + jlongArray attributes = env->NewLongArray(JVM_ImageGetAttributesCount(env)); + // Get base address for jlong array. + jlong* rawAttributes = env->GetLongArrayElements(attributes, NULL); + jlong* ret = JVM_ImageGetAttributes(env, rawAttributes, id, offset); + // Release jlong array base address. + env->ReleaseLongArrayElements(attributes, rawAttributes, 0); + return ret == NULL ? NULL : attributes; +WB_END + +WB_ENTRY(jlongArray, WB_imageFindAttributes(JNIEnv *env, jobject wb, jlong id, jbyteArray utf8)) + ThreadToNativeFromVM ttn(thread); + // Allocate a jlong large enough for all location attributes. + jlongArray attributes = env->NewLongArray(JVM_ImageGetAttributesCount(env)); + // Get base address for jlong array. + jlong* rawAttributes = env->GetLongArrayElements(attributes, NULL); + jsize size = env->GetArrayLength(utf8); + jbyte* rawBytes = env->GetByteArrayElements(utf8, NULL); + jlong* ret = JVM_ImageFindAttributes(env, rawAttributes, rawBytes, size, id); + env->ReleaseByteArrayElements(utf8, rawBytes, 0); + env->ReleaseLongArrayElements(attributes, rawAttributes, 0); + return ret == NULL ? NULL : attributes; +WB_END + +WB_ENTRY(jintArray, WB_imageAttributeOffsets(JNIEnv *env, jobject wb, jlong id)) + ThreadToNativeFromVM ttn(thread); + unsigned int length = JVM_ImageAttributeOffsetsLength(env, id); + if (length == 0) { + return NULL; + } + jintArray offsets = env->NewIntArray(length); + // Get base address of result. + jint* rawOffsets = env->GetIntArrayElements(offsets, NULL); + jint* ret = JVM_ImageAttributeOffsets(env, rawOffsets, length, id); + // Release result base address. + env->ReleaseIntArrayElements(offsets, rawOffsets, 0); + return ret == NULL ? NULL : offsets; +WB_END + +WB_ENTRY(jint, WB_imageGetIntAtAddress(JNIEnv *env, jobject wb, jlong address, jint offset, jboolean big_endian)) + unsigned char* arr = (unsigned char*) address + offset; + jint uraw; + if (big_endian) { + uraw = arr[0] << 24 | arr[1]<<16 | (arr[2]<<8) | arr[3]; + } else { + uraw = arr[0] | arr[1]<<8 | (arr[2]<<16) | arr[3]<<24; + } + return uraw; +WB_END + WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue)) Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ? Monitor::_safepoint_check_always : @@ -1428,8 +1555,23 @@ {CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob }, {CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize }, {CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize }, + {CC"readImageFile", CC"(Ljava/lang/String;)Z", (void*)&WB_ReadImageFile }, + {CC"imageOpenImage", CC"(Ljava/lang/String;Z)J",(void*)&WB_imageOpenImage }, + {CC"imageCloseImage", CC"(J)V", (void*)&WB_imageCloseImage }, + {CC"imageGetIndexAddress",CC"(J)J", (void*)&WB_imageGetIndexAddress}, + {CC"imageGetDataAddress",CC"(J)J", (void*)&WB_imageGetDataAddress}, + {CC"imageRead", CC"(JJLjava/nio/ByteBuffer;J)Z", + (void*)&WB_imageRead }, + {CC"imageReadCompressed",CC"(JJLjava/nio/ByteBuffer;JLjava/nio/ByteBuffer;J)Z", + (void*)&WB_imageReadCompressed}, + {CC"imageGetStringBytes",CC"(JI)[B", (void*)&WB_imageGetStringBytes}, + {CC"imageGetStringsSize",CC"(J)J", (void*)&WB_imageGetStringsSize}, + {CC"imageGetAttributes", CC"(JI)[J", (void*)&WB_imageGetAttributes}, + {CC"imageFindAttributes",CC"(J[B)[J", (void*)&WB_imageFindAttributes}, + {CC"imageAttributeOffsets",CC"(J)[I", (void*)&WB_imageAttributeOffsets}, + {CC"imageGetIntAtAddress",CC"(JIZ)I", (void*)&WB_imageGetIntAtAddress}, {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, - {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, + {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, {CC"getMethodBooleanOption", CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;", diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/arguments.cpp --- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -27,6 +27,7 @@ #include "classfile/javaAssertions.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" +#include "code/codeCacheExtensions.hpp" #include "compiler/compilerOracle.hpp" #include "gc/shared/cardTableRS.hpp" #include "gc/shared/genCollectedHeap.hpp" @@ -275,6 +276,7 @@ { "AdaptiveSizePausePolicy", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "ParallelGCRetainPLAB", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "ThreadSafetyMargin", JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "LazyBootClassLoader", JDK_Version::jdk(9), JDK_Version::jdk(10) }, { NULL, JDK_Version(0), JDK_Version(0) } }; @@ -835,16 +837,19 @@ arg_len = equal_sign - argname; } - // Construct a string which consists only of the argument name without '+', '-', or '='. - char stripped_argname[256]; - strncpy(stripped_argname, argname, arg_len); - stripped_argname[arg_len] = '\0'; //strncpy doesn't null terminate. - - if (is_newly_obsolete(stripped_argname, &since)) { - char version[256]; - since.to_string(version, sizeof(version)); - warning("ignoring option %s; support was removed in %s", stripped_argname, version); - return true; + // Only make the obsolete check for valid arguments. + if (arg_len <= BUFLEN) { + // Construct a string which consists only of the argument name without '+', '-', or '='. + char stripped_argname[BUFLEN+1]; + strncpy(stripped_argname, argname, arg_len); + stripped_argname[arg_len] = '\0'; // strncpy may not null terminate. + + if (is_newly_obsolete(stripped_argname, &since)) { + char version[256]; + since.to_string(version, sizeof(version)); + warning("ignoring option %s; support was removed in %s", stripped_argname, version); + return true; + } } // For locked flags, report a custom error message if available. @@ -1582,6 +1587,11 @@ // in vm_version initialization code. #endif // _LP64 #endif // !ZERO + + // Set up runtime image flags. + set_runtime_image_flags(); + + CodeCacheExtensions::set_ergonomics_flags(); } void Arguments::set_parallel_gc_flags() { @@ -1837,6 +1847,16 @@ } } + // Set up runtime image flags +void Arguments::set_runtime_image_flags() { +#ifdef _LP64 + // Memory map image file by default on 64 bit machines. + if (FLAG_IS_DEFAULT(MemoryMapImage)) { + FLAG_SET_ERGO(bool, MemoryMapImage, true); + } +#endif +} + // This must be called after ergonomics. void Arguments::set_bytecode_flags() { if (!RewriteBytecodes) { @@ -2558,9 +2578,15 @@ round_to((int)long_ThreadStackSize, K) / K) != Flag::SUCCESS) { return JNI_EINVAL; } - // -Xoss - } else if (match_option(option, "-Xoss", &tail)) { - // HotSpot does not have separate native and Java stacks, ignore silently for compatibility + // -Xoss, -Xsqnopause, -Xoptimize, -Xboundthreads + } else if (match_option(option, "-Xoss", &tail) || + match_option(option, "-Xsqnopause") || + match_option(option, "-Xoptimize") || + match_option(option, "-Xboundthreads")) { + // All these options are deprecated in JDK 9 and will be removed in a future release + char version[256]; + JDK_Version::jdk(9).to_string(version, sizeof(version)); + warning("ignoring option %s; support was removed in %s", option->optionString, version); } else if (match_option(option, "-XX:CodeCacheExpansionSize=", &tail)) { julong long_CodeCacheExpansionSize = 0; ArgsRange errcode = parse_memory_size(tail, &long_CodeCacheExpansionSize, os::vm_page_size()); @@ -2633,9 +2659,6 @@ // -native } else if (match_option(option, "-native")) { // HotSpot always uses native threads, ignore silently for compatibility - // -Xsqnopause - } else if (match_option(option, "-Xsqnopause")) { - // EVM option, ignore silently for compatibility // -Xrs } else if (match_option(option, "-Xrs")) { // Classic/EVM option, new functionality @@ -2647,9 +2670,6 @@ if (FLAG_SET_CMDLINE(bool, UseAltSigs, true) != Flag::SUCCESS) { return JNI_EINVAL; } - // -Xoptimize - } else if (match_option(option, "-Xoptimize")) { - // EVM option, ignore silently for compatibility // -Xprof } else if (match_option(option, "-Xprof")) { #if INCLUDE_FPROF @@ -2795,8 +2815,6 @@ // -Xnoagent } else if (match_option(option, "-Xnoagent")) { // For compatibility with classic. HotSpot refuses to load the old style agent.dll. - } else if (match_option(option, "-Xboundthreads")) { - // Ignore silently for compatibility } else if (match_option(option, "-Xloggc:", &tail)) { // Redirect GC output to the file. -Xloggc: // ostream_init_log(), when called will use this filename diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/arguments.hpp --- a/hotspot/src/share/vm/runtime/arguments.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/arguments.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -224,6 +224,7 @@ class Arguments : AllStatic { friend class VMStructs; friend class JvmtiExport; + friend class CodeCacheExtensions; public: // Operation modi enum Mode { @@ -347,6 +348,8 @@ static julong limit_by_allocatable_memory(julong size); // Setup heap size static void set_heap_size(); + // Set up runtime image flags + static void set_runtime_image_flags(); // Based on automatic selection criteria, should the // low pause collector be used. static bool should_auto_select_low_pause_collector(); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp --- a/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/commandLineFlagRangeList.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -84,7 +84,7 @@ } void print(outputStream* st) { - st->print("[ "INTX_FORMAT_W(-25)" ... "INTX_FORMAT_W(25)" ]", _min, _max); + st->print("[ " INTX_FORMAT_W(-25) " ... " INTX_FORMAT_W(25) " ]", _min, _max); } }; @@ -140,7 +140,7 @@ } void print(outputStream* st) { - st->print("[ "UINTX_FORMAT_W(-25)" ... "UINTX_FORMAT_W(25)" ]", _min, _max); + st->print("[ " UINTX_FORMAT_W(-25) " ... " UINTX_FORMAT_W(25) " ]", _min, _max); } }; @@ -168,7 +168,7 @@ } void print(outputStream* st) { - st->print("[ "UINT64_FORMAT_W(-25)" ... "UINT64_FORMAT_W(25)" ]", _min, _max); + st->print("[ " UINT64_FORMAT_W(-25) " ... " UINT64_FORMAT_W(25) " ]", _min, _max); } }; @@ -196,7 +196,7 @@ } void print(outputStream* st) { - st->print("[ "SIZE_FORMAT_W(-25)" ... "SIZE_FORMAT_W(25)" ]", _min, _max); + st->print("[ " SIZE_FORMAT_W(-25) " ... " SIZE_FORMAT_W(25) " ]", _min, _max); } }; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/deoptimization.cpp --- a/hotspot/src/share/vm/runtime/deoptimization.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1340,7 +1340,7 @@ ttyLocker ttyl; char buf[100]; if (xtty != NULL) { - xtty->begin_head("uncommon_trap thread='" UINTX_FORMAT"' %s", + xtty->begin_head("uncommon_trap thread='" UINTX_FORMAT "' %s", os::current_thread_id(), format_trap_request(buf, sizeof(buf), trap_request)); nm->log_identity(xtty); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/globals.cpp --- a/hotspot/src/share/vm/runtime/globals.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/globals.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1240,7 +1240,7 @@ size_ranges += sizeof(CommandLineFlagRange*); } } - fprintf(stderr, "Size of %d ranges: "SIZE_FORMAT" bytes\n", + fprintf(stderr, "Size of %d ranges: " SIZE_FORMAT " bytes\n", CommandLineFlagRangeList::length(), size_ranges); } { @@ -1270,7 +1270,7 @@ size_constraints += sizeof(CommandLineFlagConstraint*); } } - fprintf(stderr, "Size of %d constraints: "SIZE_FORMAT" bytes\n", + fprintf(stderr, "Size of %d constraints: " SIZE_FORMAT " bytes\n", CommandLineFlagConstraintList::length(), size_constraints); } #endif // PRINT_RANGES_AND_CONSTRAINTS_SIZES diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/globals.hpp --- a/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/globals.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -728,7 +728,8 @@ "Control whether AES instructions can be used on x86/x64") \ \ product(bool, UseSHA, false, \ - "Control whether SHA instructions can be used on SPARC") \ + "Control whether SHA instructions can be used " \ + "on SPARC and on ARM") \ \ product(bool, UseGHASHIntrinsics, false, \ "Use intrinsics for GHASH versions of crypto") \ @@ -837,13 +838,16 @@ "Use intrinsics for AES versions of crypto") \ \ product(bool, UseSHA1Intrinsics, false, \ - "Use intrinsics for SHA-1 crypto hash function") \ + "Use intrinsics for SHA-1 crypto hash function. " \ + "Requires that UseSHA is enabled.") \ \ product(bool, UseSHA256Intrinsics, false, \ - "Use intrinsics for SHA-224 and SHA-256 crypto hash functions") \ + "Use intrinsics for SHA-224 and SHA-256 crypto hash functions. " \ + "Requires that UseSHA is enabled.") \ \ product(bool, UseSHA512Intrinsics, false, \ - "Use intrinsics for SHA-384 and SHA-512 crypto hash functions") \ + "Use intrinsics for SHA-384 and SHA-512 crypto hash functions. " \ + "Requires that UseSHA is enabled.") \ \ product(bool, UseCRC32Intrinsics, false, \ "use intrinsics for java.util.zip.CRC32") \ @@ -1032,6 +1036,10 @@ product(bool, CreateCoredumpOnCrash, true, \ "Create core/mini dump on VM fatal error") \ \ + product(uintx, ErrorLogTimeout, 2 * 60, \ + "Timeout, in seconds, to limit the time spent on writing an " \ + "error log in case of a crash.") \ + \ product_pd(bool, UseOSErrorReporting, \ "Let VM fatal error propagate to the OS (ie. WER on Windows)") \ \ @@ -1099,6 +1107,9 @@ product(bool, AlwaysRestoreFPU, false, \ "Restore the FPU control word after every JNI call (expensive)") \ \ + product(bool, MemoryMapImage, false, \ + "Memory map entire runtime image") \ + \ diagnostic(bool, PrintCompilation2, false, \ "Print additional statistics per compilation") \ \ @@ -1361,9 +1372,6 @@ develop(uintx, PreallocatedOutOfMemoryErrorCount, 4, \ "Number of OutOfMemoryErrors preallocated with backtrace") \ \ - product(bool, LazyBootClassLoader, true, \ - "Enable/disable lazy opening of boot class path entries") \ - \ product(bool, UseXMMForArrayCopy, false, \ "Use SSE2 MOVQ instruction for Arraycopy") \ \ @@ -4120,7 +4128,16 @@ \ product_pd(bool, PreserveFramePointer, \ "Use the FP register for holding the frame pointer " \ - "and not as a general purpose register.") + "and not as a general purpose register.") \ + \ + diagnostic(bool, CheckIntrinsics, trueInDebug, \ + "When a class C is loaded, check that " \ + "(1) all intrinsics defined by the VM for class C are present "\ + "in the loaded class file and are marked with the " \ + "@HotSpotIntrinsicCandidate annotation and also that " \ + "(2) there is an intrinsic registered for all loaded methods " \ + "that are annotated with the @HotSpotIntrinsicCandidate " \ + "annotation.") /* * Macros for factoring of globals diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/init.cpp --- a/hotspot/src/share/vm/runtime/init.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/init.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/stringTable.hpp" +#include "code/codeCacheExtensions.hpp" #include "code/icBuffer.hpp" #include "gc/shared/collectedHeap.hpp" #include "interpreter/bytecodes.hpp" @@ -82,6 +83,7 @@ // during VM shutdown void perfMemory_exit(); void ostream_exit(); +bool image_decompressor_init(); void vm_init_globals() { check_ThreadShadow(); @@ -100,21 +102,29 @@ classLoader_init(); compilationPolicy_init(); codeCache_init(); + CodeCacheExtensions::initialize(); VM_Version_init(); + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::VMVersion); os_init_globals(); stubRoutines_init1(); + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::StubRoutines1); jint status = universe_init(); // dependent on codeCache_init and // stubRoutines_init1 and metaspace_init. if (status != JNI_OK) return status; + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Universe); interpreter_init(); // before any methods loaded + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::Interpreter); invocationCounter_init(); // before any methods loaded marksweep_init(); accessFlags_init(); templateTable_init(); InterfaceSupport_init(); SharedRuntime::generate_stubs(); + if (!image_decompressor_init()) { + return JNI_ERR; + } universe2_init(); // dependent on codeCache_init and stubRoutines_init1 referenceProcessor_init(); jni_handles_init(); @@ -133,6 +143,7 @@ } javaClasses_init(); // must happen after vtable initialization stubRoutines_init2(); // note: StubRoutines need 2-phase init + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::StubRoutines2); #if INCLUDE_NMT // Solaris stack is walkable only after stubRoutines are set up. @@ -146,6 +157,7 @@ CommandLineFlags::printFlags(tty, false, PrintFlagsRanges); } + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::InitGlobals); return JNI_OK; } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/mutexLocker.cpp --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -100,6 +100,8 @@ Mutex* ExceptionCache_lock = NULL; Monitor* ObjAllocPost_lock = NULL; Mutex* OsrList_lock = NULL; +Mutex* ImageFileReaderTable_lock = NULL; + #ifndef PRODUCT Mutex* FullGCALot_lock = NULL; #endif @@ -227,6 +229,7 @@ def(ProfilePrint_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing def(ExceptionCache_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing def(OsrList_lock , Mutex , leaf, true, Monitor::_safepoint_check_never); + def(ImageFileReaderTable_lock , Mutex , nonleaf, false, Monitor::_safepoint_check_always); // synchronize image readers open/close def(Debug1_lock , Mutex , leaf, true, Monitor::_safepoint_check_never); #ifndef PRODUCT def(FullGCALot_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/mutexLocker.hpp --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -102,6 +102,7 @@ extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues +extern Mutex* ImageFileReaderTable_lock; // a lock used to synchronize image readers open/close #ifndef PRODUCT extern Mutex* FullGCALot_lock; // a lock to make FullGCALot MT safe diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/os.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1237,7 +1237,7 @@ struct stat st; // modular image if bootmodules.jimage exists - char* jimage = format_boot_path("%/lib/modules/bootmodules.jimage", home, home_len, fileSep, pathSep); + char* jimage = format_boot_path("%/lib/modules/" BOOT_IMAGE_NAME, home, home_len, fileSep, pathSep); if (jimage == NULL) return false; bool has_jimage = (os::stat(jimage, &st) == 0); if (has_jimage) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/reflection.cpp --- a/hotspot/src/share/vm/runtime/reflection.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/reflection.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1002,8 +1002,9 @@ vmSymbols::throwable_void_signature(), &args); } else { - if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) + if (rtype == T_BOOLEAN || rtype == T_BYTE || rtype == T_CHAR || rtype == T_SHORT) { narrow((jvalue*) result.get_value_addr(), rtype, CHECK_NULL); + } return box((jvalue*) result.get_value_addr(), rtype, THREAD); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/safepoint.cpp --- a/hotspot/src/share/vm/runtime/safepoint.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/safepoint.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -894,7 +894,7 @@ case _running: default: - tty->print_cr("restart thread "INTPTR_FORMAT" with state %d", + tty->print_cr("restart thread " INTPTR_FORMAT " with state %d", _thread, _type); _thread->print(); ShouldNotReachHere(); @@ -1193,7 +1193,7 @@ sstats = &_safepoint_stats[index]; tty->print("%.3f: ", sstats->_time_stamp); tty->print("%-26s [" - INT32_FORMAT_W(8)INT32_FORMAT_W(11)INT32_FORMAT_W(15) + INT32_FORMAT_W(8) INT32_FORMAT_W(11) INT32_FORMAT_W(15) " ] ", sstats->_vmop_type == -1 ? "no vm operation" : VM_Operation::name(sstats->_vmop_type), @@ -1202,9 +1202,9 @@ sstats->_nof_threads_wait_to_block); // "/ MICROUNITS " is to convert the unit from nanos to millis. tty->print(" [" - INT64_FORMAT_W(6)INT64_FORMAT_W(6) - INT64_FORMAT_W(6)INT64_FORMAT_W(6) - INT64_FORMAT_W(6)" ] ", + INT64_FORMAT_W(6) INT64_FORMAT_W(6) + INT64_FORMAT_W(6) INT64_FORMAT_W(6) + INT64_FORMAT_W(6) " ] ", sstats->_time_to_spin / MICROUNITS, sstats->_time_to_wait_to_block / MICROUNITS, sstats->_time_to_sync / MICROUNITS, @@ -1212,9 +1212,9 @@ sstats->_time_to_exec_vmop / MICROUNITS); if (need_to_track_page_armed_status) { - tty->print(INT32_FORMAT" ", sstats->_page_armed); + tty->print(INT32_FORMAT " ", sstats->_page_armed); } - tty->print_cr(INT32_FORMAT" ", sstats->_nof_threads_hit_page_trap); + tty->print_cr(INT32_FORMAT " ", sstats->_nof_threads_hit_page_trap); } } @@ -1249,17 +1249,17 @@ for (int index = 0; index < VM_Operation::VMOp_Terminating; index++) { if (_safepoint_reasons[index] != 0) { - tty->print_cr("%-26s"UINT64_FORMAT_W(10), VM_Operation::name(index), + tty->print_cr("%-26s" UINT64_FORMAT_W(10), VM_Operation::name(index), _safepoint_reasons[index]); } } - tty->print_cr(UINT64_FORMAT_W(5)" VM operations coalesced during safepoint", + tty->print_cr(UINT64_FORMAT_W(5) " VM operations coalesced during safepoint", _coalesced_vmop_count); - tty->print_cr("Maximum sync time "INT64_FORMAT_W(5)" ms", + tty->print_cr("Maximum sync time " INT64_FORMAT_W(5) " ms", _max_sync_time / MICROUNITS); tty->print_cr("Maximum vm operation time (except for Exit VM operation) " - INT64_FORMAT_W(5)" ms", + INT64_FORMAT_W(5) " ms", _max_vmop_time / MICROUNITS); } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/semaphore.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/runtime/semaphore.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 "utilities/debug.hpp" +#include "runtime/semaphore.hpp" + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +static void test_semaphore_single_separate(uint count) { + Semaphore sem(0); + + for (uint i = 0; i < count; i++) { + sem.signal(); + } + + for (uint i = 0; i < count; i++) { + sem.wait(); + } +} + +static void test_semaphore_single_combined(uint count) { + Semaphore sem(0); + + for (uint i = 0; i < count; i++) { + sem.signal(); + sem.wait(); + } +} + +static void test_semaphore_many(uint value, uint max, uint increments) { + Semaphore sem(value); + + uint total = value; + + for (uint i = value; i + increments <= max; i += increments) { + sem.signal(increments); + + total += increments; + } + + for (uint i = 0; i < total; i++) { + sem.wait(); + } +} + +static void test_semaphore_many() { + for (uint max = 0; max < 10; max++) { + for (uint value = 0; value < max; value++) { + for (uint inc = 1; inc <= max - value; inc++) { + test_semaphore_many(value, max, inc); + } + } + } +} + +void test_semaphore() { + for (uint i = 1; i < 10; i++) { + test_semaphore_single_separate(i); + } + + for (uint i = 0; i < 10; i++) { + test_semaphore_single_combined(i); + } + + test_semaphore_many(); +} + +#endif // PRODUCT + diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/semaphore.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/runtime/semaphore.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_SEMAPHORE_HPP +#define SHARE_VM_RUNTIME_SEMAPHORE_HPP + +#include "memory/allocation.hpp" + +#if defined(TARGET_OS_FAMILY_linux) || defined(TARGET_OS_FAMILY_solaris) || defined(TARGET_OS_FAMILY_aix) +# include "semaphore_posix.hpp" +#elif defined(TARGET_OS_FAMILY_bsd) +# include "semaphore_bsd.hpp" +#elif defined(TARGET_OS_FAMILY_windows) +# include "semaphore_windows.hpp" +#else +# error "No semaphore implementation provided for this OS" +#endif + +// Implements the limited, platform independent Semaphore API. +class Semaphore : public CHeapObj { + SemaphoreImpl _impl; + + // Prevent copying and assignment of Semaphore instances. + Semaphore(const Semaphore&); + Semaphore& operator=(const Semaphore&); + + public: + Semaphore(uint value = 0) : _impl(value) {} + ~Semaphore() {} + + void signal(uint count = 1) { _impl.signal(count); } + + void wait() { _impl.wait(); } +}; + + +#endif // SHARE_VM_RUNTIME_SEMAPHORE_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/sharedRuntime.cpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -27,6 +27,7 @@ #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" +#include "code/codeCacheExtensions.hpp" #include "code/scopeDesc.hpp" #include "code/vtableStubs.hpp" #include "compiler/abstractCompiler.hpp" @@ -2307,19 +2308,35 @@ return _buffer; } +extern "C" void unexpected_adapter_call() { + ShouldNotCallThis(); +} + void AdapterHandlerLibrary::initialize() { if (_adapters != NULL) return; _adapters = new AdapterHandlerTable(); - // Create a special handler for abstract methods. Abstract methods - // are never compiled so an i2c entry is somewhat meaningless, but - // throw AbstractMethodError just in case. - // Pass wrong_method_abstract for the c2i transitions to return - // AbstractMethodError for invalid invocations. - address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub(); - _abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL), - StubRoutines::throw_AbstractMethodError_entry(), - wrong_method_abstract, wrong_method_abstract); + if (!CodeCacheExtensions::skip_compiler_support()) { + // Create a special handler for abstract methods. Abstract methods + // are never compiled so an i2c entry is somewhat meaningless, but + // throw AbstractMethodError just in case. + // Pass wrong_method_abstract for the c2i transitions to return + // AbstractMethodError for invalid invocations. + address wrong_method_abstract = SharedRuntime::get_handle_wrong_method_abstract_stub(); + _abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL), + StubRoutines::throw_AbstractMethodError_entry(), + wrong_method_abstract, wrong_method_abstract); + } else { + // Adapters are not supposed to be used. + // Generate a special one to cause an error if used (and store this + // singleton in place of the useless _abstract_method_error adapter). + address entry = (address) &unexpected_adapter_call; + _abstract_method_handler = AdapterHandlerLibrary::new_entry(new AdapterFingerPrint(0, NULL), + entry, + entry, + entry); + + } } AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint, @@ -2346,6 +2363,15 @@ // make sure data structure is initialized initialize(); + if (CodeCacheExtensions::skip_compiler_support()) { + // adapters are useless and should not be used, including the + // abstract_method_handler. However, some callers check that + // an adapter was installed. + // Return the singleton adapter, stored into _abstract_method_handler + // and modified to cause an error if we ever call it. + return _abstract_method_handler; + } + if (method->is_abstract()) { return _abstract_method_handler; } @@ -2616,71 +2642,6 @@ GC_locker::unlock_critical(thread); JRT_END -int SharedRuntime::convert_ints_to_longints_argcnt(int in_args_count, BasicType* in_sig_bt) { - int argcnt = in_args_count; - if (CCallingConventionRequiresIntsAsLongs) { - for (int in = 0; in < in_args_count; in++) { - BasicType bt = in_sig_bt[in]; - switch (bt) { - case T_BOOLEAN: - case T_CHAR: - case T_BYTE: - case T_SHORT: - case T_INT: - argcnt++; - break; - default: - break; - } - } - } else { - assert(0, "This should not be needed on this platform"); - } - - return argcnt; -} - -void SharedRuntime::convert_ints_to_longints(int i2l_argcnt, int& in_args_count, - BasicType*& in_sig_bt, VMRegPair*& in_regs) { - if (CCallingConventionRequiresIntsAsLongs) { - VMRegPair *new_in_regs = NEW_RESOURCE_ARRAY(VMRegPair, i2l_argcnt); - BasicType *new_in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, i2l_argcnt); - - int argcnt = 0; - for (int in = 0; in < in_args_count; in++, argcnt++) { - BasicType bt = in_sig_bt[in]; - VMRegPair reg = in_regs[in]; - switch (bt) { - case T_BOOLEAN: - case T_CHAR: - case T_BYTE: - case T_SHORT: - case T_INT: - // Convert (bt) to (T_LONG,bt). - new_in_sig_bt[argcnt] = T_LONG; - new_in_sig_bt[argcnt+1] = bt; - assert(reg.first()->is_valid() && !reg.second()->is_valid(), ""); - new_in_regs[argcnt].set2(reg.first()); - new_in_regs[argcnt+1].set_bad(); - argcnt++; - break; - default: - // No conversion needed. - new_in_sig_bt[argcnt] = bt; - new_in_regs[argcnt] = reg; - break; - } - } - assert(argcnt == i2l_argcnt, "must match"); - - in_regs = new_in_regs; - in_sig_bt = new_in_sig_bt; - in_args_count = i2l_argcnt; - } else { - assert(0, "This should not be needed on this platform"); - } -} - // ------------------------------------------------------------------------- // Java-Java calling convention // (what you use when Java calls Java) diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/sharedRuntime.hpp --- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -145,6 +145,12 @@ static double dsqrt(double f); #endif + // Montgomery multiplication + static void montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints, + jint len, jlong inv, jint *m_ints); + static void montgomery_square(jint *a_ints, jint *n_ints, + jint len, jlong inv, jint *m_ints); + #ifdef __SOFTFP__ // C++ compiler generates soft float instructions as well as passing // float and double in registers. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/stubCodeGenerator.cpp --- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "code/codeCache.hpp" +#include "code/codeCacheExtensions.hpp" #include "compiler/disassembler.hpp" #include "oops/oop.inline.hpp" #include "prims/forte.hpp" diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/stubCodeGenerator.hpp --- a/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,14 +67,14 @@ static StubCodeDesc* desc_for_index(int); // returns the code descriptor for the index or NULL static const char* name_for(address pc); // returns the name of the code containing pc or NULL - StubCodeDesc(const char* group, const char* name, address begin) { + StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) { assert(name != NULL, "no name specified"); _next = _list; _group = group; _name = name; _index = ++_count; // (never zero) _begin = begin; - _end = NULL; + _end = end; _list = this; }; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/stubRoutines.cpp --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/codeBuffer.hpp" +#include "code/codeCacheExtensions.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/interfaceSupport.hpp" @@ -142,6 +143,8 @@ address StubRoutines::_multiplyToLen = NULL; address StubRoutines::_squareToLen = NULL; address StubRoutines::_mulAdd = NULL; +address StubRoutines::_montgomeryMultiply = NULL; +address StubRoutines::_montgomerySquare = NULL; double (* StubRoutines::_intrinsic_log )(double) = NULL; double (* StubRoutines::_intrinsic_log10 )(double) = NULL; @@ -188,6 +191,12 @@ // simple tests of generated arraycopy functions static void test_arraycopy_func(address func, int alignment) { + if (CodeCacheExtensions::use_pregenerated_interpreter() || !CodeCacheExtensions::is_executable(func)) { + // Exit safely if stubs were generated but cannot be used. + // Also excluding pregenerated interpreter since the code may depend on + // some registers being properly initialized (for instance Rthread) + return; + } int v = 0xcc; int v2 = 0x11; jlong lbuffer[8]; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/stubRoutines.hpp --- a/hotspot/src/share/vm/runtime/stubRoutines.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -202,6 +202,8 @@ static address _multiplyToLen; static address _squareToLen; static address _mulAdd; + static address _montgomeryMultiply; + static address _montgomerySquare; // These are versions of the java.lang.Math methods which perform // the same operations as the intrinsic version. They are used for @@ -366,6 +368,8 @@ static address multiplyToLen() {return _multiplyToLen; } static address squareToLen() {return _squareToLen; } static address mulAdd() {return _mulAdd; } + static address montgomeryMultiply() { return _montgomeryMultiply; } + static address montgomerySquare() { return _montgomerySquare; } static address select_fill_function(BasicType t, bool aligned, const char* &name); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/thread.cpp --- a/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/thread.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" +#include "code/codeCacheExtensions.hpp" #include "code/scopeDesc.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/gcLocker.inline.hpp" @@ -1291,7 +1292,7 @@ if (!ShowMessageBoxOnError && (OnError == NULL || OnError[0] == '\0') && Arguments::abort_hook() == NULL) { - os::sleep(this, 2 * 60 * 1000, false); + os::sleep(this, ErrorLogTimeout * 60 * 1000, false); fdStream err(defaultStream::output_fd()); err.print_raw_cr("# [ timer expired, abort... ]"); // skip atexit/vm_exit/vm_abort hooks @@ -3587,6 +3588,8 @@ } } + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::CreateVM); + create_vm_timer.end(); #ifdef ASSERT _vm_complete = true; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/unhandledOops.cpp --- a/hotspot/src/share/vm/runtime/unhandledOops.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/unhandledOops.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -105,7 +105,7 @@ _level --; if (unhandled_oop_print) { for (int i=0; i<_level; i++) tty->print(" "); - tty->print_cr("u "INTPTR_FORMAT, op); + tty->print_cr("u " INTPTR_FORMAT, op); } int i = _oop_list->find_from_end(op, match_oop_entry); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/vmStructs.cpp --- a/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -182,6 +182,8 @@ #include "runtime/vmStructs_trace.hpp" #endif +#include "runtime/vmStructs_ext.hpp" + #ifdef COMPILER2 #include "opto/addnode.hpp" #include "opto/block.hpp" @@ -2963,6 +2965,9 @@ GENERATE_STATIC_VM_STRUCT_ENTRY) #endif + VM_STRUCTS_EXT(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_STATIC_VM_STRUCT_ENTRY) + VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, GENERATE_UNCHECKED_NONSTATIC_VM_STRUCT_ENTRY, @@ -3013,6 +3018,9 @@ GENERATE_TOPLEVEL_VM_TYPE_ENTRY) #endif + VM_TYPES_EXT(GENERATE_VM_TYPE_ENTRY, + GENERATE_TOPLEVEL_VM_TYPE_ENTRY) + VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, GENERATE_OOP_VM_TYPE_ENTRY, @@ -3122,6 +3130,9 @@ CHECK_STATIC_VM_STRUCT_ENTRY); #endif + VM_STRUCTS_EXT(CHECK_NONSTATIC_VM_STRUCT_ENTRY, + CHECK_STATIC_VM_STRUCT_ENTRY); + VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, CHECK_NO_OP, @@ -3168,6 +3179,9 @@ CHECK_SINGLE_ARG_VM_TYPE_NO_OP); #endif + VM_TYPES_EXT(CHECK_VM_TYPE_ENTRY, + CHECK_SINGLE_ARG_VM_TYPE_NO_OP); + VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -3236,6 +3250,9 @@ ENSURE_FIELD_TYPE_PRESENT)); #endif + debug_only(VM_STRUCTS_EXT(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT)); + debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, CHECK_NO_OP, diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/vmStructs_ext.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/runtime/vmStructs_ext.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_VMSTRUCTS_EXT_HPP +#define SHARE_VM_RUNTIME_VMSTRUCTS_EXT_HPP + +#define VM_STRUCTS_EXT(a, b) + +#define VM_TYPES_EXT(a, b) + + +#endif // SHARE_VM_RUNTIME_VMSTRUCTS_EXT_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/vm_operations.cpp --- a/hotspot/src/share/vm/runtime/vm_operations.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -26,6 +26,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" +#include "code/codeCacheExtensions.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerOracle.hpp" #include "gc/shared/isGCActiveMark.hpp" @@ -369,6 +370,8 @@ Thread * VM_Exit::_shutdown_thread = NULL; int VM_Exit::set_vm_exited() { + CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::LastStep); + Thread * thr_cur = ThreadLocalStorage::get_thread_slow(); assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint already"); diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/runtime/vm_version.cpp --- a/hotspot/src/share/vm/runtime/vm_version.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/runtime/vm_version.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "code/codeCacheExtensions.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/arguments.hpp" @@ -155,6 +156,9 @@ const char* Abstract_VM_Version::vm_info_string() { + if (CodeCacheExtensions::use_pregenerated_interpreter()) { + return "interpreted mode, pregenerated"; + } switch (Arguments::mode()) { case Arguments::_int: return UseSharedSpaces ? "interpreted mode, sharing" : "interpreted mode"; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/services/diagnosticArgument.cpp --- a/hotspot/src/share/vm/services/diagnosticArgument.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -89,7 +89,7 @@ size_t len, TRAPS) { int scanned = -1; if (str == NULL - || sscanf(str, JLONG_FORMAT"%n", &_value, &scanned) != 1 + || sscanf(str, JLONG_FORMAT "%n", &_value, &scanned) != 1 || (size_t)scanned != len) { ResourceMark rm; diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/services/threadService.cpp --- a/hotspot/src/share/vm/services/threadService.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/services/threadService.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -888,7 +888,7 @@ st->print(" waiting to lock monitor " INTPTR_FORMAT, waitingToLockMonitor); oop obj = (oop)waitingToLockMonitor->object(); if (obj != NULL) { - st->print(" (object "INTPTR_FORMAT ", a %s)", (address)obj, + st->print(" (object " INTPTR_FORMAT ", a %s)", (address)obj, (InstanceKlass::cast(obj->klass()))->external_name()); if (!currentThread->current_pending_monitor_is_from_java()) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/trace/trace.xml --- a/hotspot/src/share/vm/trace/trace.xml Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/trace/trace.xml Thu Jul 09 22:46:16 2015 -0700 @@ -305,6 +305,13 @@ + + + + + + + diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/trace/traceStream.hpp --- a/hotspot/src/share/vm/trace/traceStream.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/trace/traceStream.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -40,31 +40,31 @@ TraceStream(outputStream& stream): _st(stream) {} void print_val(const char* label, u1 val) { - _st.print("%s = "UINT32_FORMAT, label, val); + _st.print("%s = " UINT32_FORMAT, label, val); } void print_val(const char* label, u2 val) { - _st.print("%s = "UINT32_FORMAT, label, val); + _st.print("%s = " UINT32_FORMAT, label, val); } void print_val(const char* label, s2 val) { - _st.print("%s = "INT32_FORMAT, label, val); + _st.print("%s = " INT32_FORMAT, label, val); } void print_val(const char* label, u4 val) { - _st.print("%s = "UINT32_FORMAT, label, val); + _st.print("%s = " UINT32_FORMAT, label, val); } void print_val(const char* label, s4 val) { - _st.print("%s = "INT32_FORMAT, label, val); + _st.print("%s = " INT32_FORMAT, label, val); } void print_val(const char* label, u8 val) { - _st.print("%s = "UINT64_FORMAT, label, val); + _st.print("%s = " UINT64_FORMAT, label, val); } void print_val(const char* label, s8 val) { - _st.print("%s = "INT64_FORMAT, label, (int64_t) val); + _st.print("%s = " INT64_FORMAT, label, (int64_t) val); } void print_val(const char* label, bool val) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/utilities/endian.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/endian.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 "utilities/endian.hpp" +#include "utilities/bytes.hpp" + +#ifndef bswap_16 +extern "C" inline u2 bswap_16(u2 x) { + return ((x & 0xFF) << 8) | + ((x >> 8) & 0xFF); +} +#endif + +#ifndef bswap_32 +extern "C" inline u4 bswap_32(u4 x) { + return ((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x >> 8) & 0xFF00) | + ((x >> 24) & 0xFF); +} +#endif + +#ifndef bswap_64 +extern "C" inline u8 bswap_64(u8 x) { + return (u8)bswap_32((u4)x) << 32 | + (u8)bswap_32((u4)(x >> 32)); +} +#endif + +u2 NativeEndian::get(u2 x) { return x; } +u4 NativeEndian::get(u4 x) { return x; } +u8 NativeEndian::get(u8 x) { return x; } +s2 NativeEndian::get(s2 x) { return x; } +s4 NativeEndian::get(s4 x) { return x; } +s8 NativeEndian::get(s8 x) { return x; } + +void NativeEndian::set(u2& x, u2 y) { x = y; } +void NativeEndian::set(u4& x, u4 y) { x = y; } +void NativeEndian::set(u8& x, u8 y) { x = y; } +void NativeEndian::set(s2& x, s2 y) { x = y; } +void NativeEndian::set(s4& x, s4 y) { x = y; } +void NativeEndian::set(s8& x, s8 y) { x = y; } + +NativeEndian NativeEndian::_native; + +u2 SwappingEndian::get(u2 x) { return bswap_16(x); } +u4 SwappingEndian::get(u4 x) { return bswap_32(x); } +u8 SwappingEndian::get(u8 x) { return bswap_64(x); } +s2 SwappingEndian::get(s2 x) { return bswap_16(x); } +s4 SwappingEndian::get(s4 x) { return bswap_32(x); } +s8 SwappingEndian::get(s8 x) { return bswap_64(x); } + +void SwappingEndian::set(u2& x, u2 y) { x = bswap_16(y); } +void SwappingEndian::set(u4& x, u4 y) { x = bswap_32(y); } +void SwappingEndian::set(u8& x, u8 y) { x = bswap_64(y); } +void SwappingEndian::set(s2& x, s2 y) { x = bswap_16(y); } +void SwappingEndian::set(s4& x, s4 y) { x = bswap_32(y); } +void SwappingEndian::set(s8& x, s8 y) { x = bswap_64(y); } + +SwappingEndian SwappingEndian::_swapping; + +Endian* Endian::get_handler(bool big_endian) { + // If requesting little endian on a little endian machine or + // big endian on a big endian machine use native handler + if (big_endian == is_big_endian()) { + return NativeEndian::get_native(); + } else { + // Use swapping handler. + return SwappingEndian::get_swapping(); + } +} + +Endian* Endian::get_native_handler() { + return NativeEndian::get_native(); +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/utilities/endian.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/src/share/vm/utilities/endian.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_ENDIAN_HPP +#define SHARE_VM_UTILITIES_ENDIAN_HPP + +#include "utilities/globalDefinitions.hpp" + +// Selectable endian handling. Endian handlers are used when accessing values +// that are of unknown (until runtime) endian. The only requirement of the values +// accessed are that they are aligned to proper size boundaries (no misalignment.) +// To select an endian handler, one should call Endian::get_handler(big_endian); +// Where big_endian is true if big endian is required and false otherwise. The +// native endian handler can be fetched with Endian::get_native_handler(); +// To retrieve a value using the approprate endian, use one of the overloaded +// calls to get. To set a value, then use one of the overloaded set calls. +// Ex. +// s4 value; // Imported value; +// ... +// Endian* endian = Endian::get_handler(true); // Use big endian +// s4 corrected = endian->get(value); +// endian->set(value, 1); +// +class Endian { +public: + virtual u2 get(u2 x) = 0; + virtual u4 get(u4 x) = 0; + virtual u8 get(u8 x) = 0; + virtual s2 get(s2 x) = 0; + virtual s4 get(s4 x) = 0; + virtual s8 get(s8 x) = 0; + + virtual void set(u2& x, u2 y) = 0; + virtual void set(u4& x, u4 y) = 0; + virtual void set(u8& x, u8 y) = 0; + virtual void set(s2& x, s2 y) = 0; + virtual void set(s4& x, s4 y) = 0; + virtual void set(s8& x, s8 y) = 0; + + // Quick little endian test. + static bool is_little_endian() { u4 x = 1; return *(u1 *)&x != 0; } + + // Quick big endian test. + static bool is_big_endian() { return !is_little_endian(); } + + // Select an appropriate endian handler. + static Endian* get_handler(bool big_endian); + + // Return the native endian handler. + static Endian* get_native_handler(); +}; + +// Normal endian handling. +class NativeEndian : public Endian { +private: + static NativeEndian _native; + +public: + u2 get(u2 x); + u4 get(u4 x); + u8 get(u8 x); + s2 get(s2 x); + s4 get(s4 x); + s8 get(s8 x); + + void set(u2& x, u2 y); + void set(u4& x, u4 y); + void set(u8& x, u8 y); + void set(s2& x, s2 y); + void set(s4& x, s4 y); + void set(s8& x, s8 y); + + static Endian* get_native() { return &_native; } +}; + +// Swapping endian handling. +class SwappingEndian : public Endian { +private: + static SwappingEndian _swapping; + +public: + u2 get(u2 x); + u4 get(u4 x); + u8 get(u8 x); + s2 get(s2 x); + s4 get(s4 x); + s8 get(s8 x); + + void set(u2& x, u2 y); + void set(u4& x, u4 y); + void set(u8& x, u8 y); + void set(s2& x, s2 y); + void set(s4& x, s4 y); + void set(s8& x, s8 y); + + static Endian* get_swapping() { return &_swapping; } +}; +#endif // SHARE_VM_UTILITIES_ENDIAN_HPP diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/utilities/globalDefinitions.hpp --- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Jul 09 22:46:16 2015 -0700 @@ -1367,6 +1367,7 @@ #define UINT32_FORMAT_W(width) "%" #width PRIu32 #define PTR32_FORMAT "0x%08" PRIx32 +#define PTR32_FORMAT_W(width) "0x%" #width PRIx32 // Format 64-bit quantities. #define INT64_FORMAT "%" PRId64 diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/utilities/ostream.cpp --- a/hotspot/src/share/vm/utilities/ostream.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/utilities/ostream.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -274,7 +274,7 @@ size_t limit = (len + 16) / 16 * 16; for (size_t i = 0; i < limit; ++i) { if (i % 16 == 0) { - indent().print(INTPTR_FORMAT_W(07)":", i); + indent().print(INTPTR_FORMAT_W(07) ":", i); } if (i % 2 == 0) { print(" "); @@ -946,7 +946,7 @@ // %%% Should be: jlong time_ms = os::start_time_milliseconds(), if // we ever get round to introduce that method on the os class xs->head("hotspot_log version='%d %d'" - " process='%d' time_ms='"INT64_FORMAT"'", + " process='%d' time_ms='" INT64_FORMAT "'", LOG_MAJOR_VERSION, LOG_MINOR_VERSION, os::current_process_id(), (int64_t)time_ms); // Write VM version header immediately. diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/src/share/vm/utilities/vmError.cpp --- a/hotspot/src/share/vm/utilities/vmError.cpp Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Thu Jul 09 22:46:16 2015 -0700 @@ -411,9 +411,10 @@ } st->cr(); } else { - if (_message != NULL) + if (_message != NULL) { st->print("# "); st->print_cr("%s", _message); + } } // In error file give some solutions if (_verbose) { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/TEST.groups --- a/hotspot/test/TEST.groups Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/TEST.groups Thu Jul 09 22:46:16 2015 -0700 @@ -241,7 +241,7 @@ gc/arguments/TestParallelGCThreads.java \ gc/arguments/TestUseCompressedOopsErgo.java \ gc/class_unloading/TestG1ClassUnloadingHWM.java \ - gc/ergonomics/TestDynamicNumberOfGCThreads.java + gc/ergonomics/TestDynamicNumberOfGCThreads.java \ gc/g1/ \ gc/metaspace/G1AddMetaspaceDependency.java \ gc/metaspace/TestMetaspacePerfCounters.java \ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java --- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java Thu Jul 09 22:46:16 2015 -0700 @@ -34,6 +34,7 @@ * @library /testlibrary * @modules java.base/sun.misc * java.management + * java.base/jdk.internal * @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java * @run main TestMonomorphicObjectCall */ diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java --- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/java/lang/Object.java Thu Jul 09 22:46:16 2015 -0700 @@ -25,25 +25,33 @@ package java.lang; +import jdk.internal.HotSpotIntrinsicCandidate; + /** * Slightly modified version of java.lang.Object that replaces * finalize() by finalizeObject() to avoid overriding in subclasses. */ public class Object { + @HotSpotIntrinsicCandidate + public Object() {} + private static native void registerNatives(); static { registerNatives(); } + @HotSpotIntrinsicCandidate public final native Class getClass(); + @HotSpotIntrinsicCandidate public native int hashCode(); public boolean equals(Object obj) { return (this == obj); } + @HotSpotIntrinsicCandidate protected native Object clone() throws CloneNotSupportedException; public String toString() { diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/intrinsics/montgomerymultiply/MontgomeryMultiplyTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,277 @@ +// +// Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2015, Red Hat Inc. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// +// + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Random; + +/** + * @test + * @bug 8130150 + * @library /testlibrary + * @summary Verify that the Montgomery multiply intrinsic works and correctly checks its arguments. + */ + +public class MontgomeryMultiplyTest { + + static final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + static final MethodHandle montgomeryMultiplyHandle, montgomerySquareHandle; + static final MethodHandle bigIntegerConstructorHandle; + static final Field bigIntegerMagField; + + static { + // Use reflection to gain access to the methods we want to test. + try { + Method m = BigInteger.class.getDeclaredMethod("montgomeryMultiply", + /*a*/int[].class, /*b*/int[].class, /*n*/int[].class, /*len*/int.class, + /*inv*/long.class, /*product*/int[].class); + m.setAccessible(true); + montgomeryMultiplyHandle = lookup.unreflect(m); + + m = BigInteger.class.getDeclaredMethod("montgomerySquare", + /*a*/int[].class, /*n*/int[].class, /*len*/int.class, + /*inv*/long.class, /*product*/int[].class); + m.setAccessible(true); + montgomerySquareHandle = lookup.unreflect(m); + + Constructor c + = BigInteger.class.getDeclaredConstructor(int.class, int[].class); + c.setAccessible(true); + bigIntegerConstructorHandle = lookup.unreflectConstructor(c); + + bigIntegerMagField = BigInteger.class.getDeclaredField("mag"); + bigIntegerMagField.setAccessible(true); + + } catch (Throwable ex) { + throw new RuntimeException(ex); + } + } + + // Invoke either BigInteger.montgomeryMultiply or BigInteger.montgomerySquare. + int[] montgomeryMultiply(int[] a, int[] b, int[] n, int len, long inv, + int[] product) throws Throwable { + int[] result = + (a == b) ? (int[]) montgomerySquareHandle.invokeExact(a, n, len, inv, product) + : (int[]) montgomeryMultiplyHandle.invokeExact(a, b, n, len, inv, product); + return Arrays.copyOf(result, len); + } + + // Invoke the private constructor BigInteger(int[]). + BigInteger newBigInteger(int[] val) throws Throwable { + return (BigInteger) bigIntegerConstructorHandle.invokeExact(1, val); + } + + // Get the private field BigInteger.mag + int[] mag(BigInteger n) { + try { + return (int[]) bigIntegerMagField.get(n); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + // Montgomery multiplication + // Calculate a * b * r^-1 mod n) + // + // R is a power of the word size + // N' = R^-1 mod N + // + // T := ab + // m := (T mod R)N' mod R [so 0 <= m < R] + // t := (T + mN)/R + // if t >= N then return t - N else return t + // + BigInteger montgomeryMultiply(BigInteger a, BigInteger b, BigInteger N, + int len, BigInteger n_prime) + throws Throwable { + BigInteger T = a.multiply(b); + BigInteger R = BigInteger.ONE.shiftLeft(len*32); + BigInteger mask = R.subtract(BigInteger.ONE); + BigInteger m = (T.and(mask)).multiply(n_prime); + m = m.and(mask); // i.e. m.mod(R) + T = T.add(m.multiply(N)); + T = T.shiftRight(len*32); // i.e. T.divide(R) + if (T.compareTo(N) > 0) { + T = T.subtract(N); + } + return T; + } + + // Call the Montgomery multiply intrinsic. + BigInteger montgomeryMultiply(int[] a_words, int[] b_words, int[] n_words, + int len, BigInteger inv) + throws Throwable { + BigInteger t = montgomeryMultiply( + newBigInteger(a_words), + newBigInteger(b_words), + newBigInteger(n_words), + len, inv); + return t; + } + + // Check that the Montgomery multiply intrinsic returns the same + // result as the longhand calculation. + void check(int[] a_words, int[] b_words, int[] n_words, int len, BigInteger inv) + throws Throwable { + BigInteger n = newBigInteger(n_words); + BigInteger slow = montgomeryMultiply(a_words, b_words, n_words, len, inv); + BigInteger fast + = newBigInteger(montgomeryMultiply + (a_words, b_words, n_words, len, inv.longValue(), null)); + // The intrinsic may not return the same value as the longhand + // calculation but they must have the same residue mod N. + if (!slow.mod(n).equals(fast.mod(n))) { + throw new RuntimeException(); + } + } + + Random rnd = new Random(0); + + // Return a random value of length <= bits in an array of even length + int[] random_val(int bits) { + int len = (bits+63)/64; // i.e. length in longs + int[] val = new int[len*2]; + for (int i = 0; i < val.length; i++) + val[i] = rnd.nextInt(); + int leadingZeros = 64 - (bits & 64); + if (leadingZeros >= 32) { + val[0] = 0; + val[1] &= ~(-1l << (leadingZeros & 31)); + } else { + val[0] &= ~(-1l << leadingZeros); + } + return val; + } + + void testOneLength(int lenInBits, int lenInInts) throws Throwable { + BigInteger mod = new BigInteger(lenInBits, 2, rnd); + BigInteger r = BigInteger.ONE.shiftLeft(lenInInts * 32); + BigInteger n_prime = mod.modInverse(r).negate(); + + // Make n.length even, padding with a zero if necessary + int[] n = mag(mod); + if (n.length < lenInInts) { + int[] x = new int[lenInInts]; + System.arraycopy(n, 0, x, lenInInts-n.length, n.length); + n = x; + } + + for (int i = 0; i < 10000; i++) { + // multiply + check(random_val(lenInBits), random_val(lenInBits), n, lenInInts, n_prime); + // square + int[] tmp = random_val(lenInBits); + check(tmp, tmp, n, lenInInts, n_prime); + } + } + + // Test the Montgomery multiply intrinsic with a bunch of random + // values of varying lengths. Do this for long enough that the + // caller of the intrinsic is C2-compiled. + void testResultValues() throws Throwable { + // Test a couple of interesting edge cases. + testOneLength(1024, 32); + testOneLength(1025, 34); + for (int j = 10; j > 0; j--) { + // Construct a random prime whose length in words is even + int lenInBits = rnd.nextInt(2048) + 64; + int lenInInts = (lenInBits + 63)/64*2; + testOneLength(lenInBits, lenInInts); + } + } + + // Range checks + void testOneMontgomeryMultiplyCheck(int[] a, int[] b, int[] n, int len, long inv, + int[] product, Class klass) { + try { + montgomeryMultiply(a, b, n, len, inv, product); + } catch (Throwable ex) { + if (klass.isAssignableFrom(ex.getClass())) + return; + throw new RuntimeException(klass + " expected, " + ex + " was thrown"); + } + throw new RuntimeException(klass + " expected, was not thrown"); + } + + void testOneMontgomeryMultiplyCheck(int[] a, int[] b, BigInteger n, int len, BigInteger inv, + Class klass) { + testOneMontgomeryMultiplyCheck(a, b, mag(n), len, inv.longValue(), null, klass); + } + + void testOneMontgomeryMultiplyCheck(int[] a, int[] b, BigInteger n, int len, BigInteger inv, + int[] product, Class klass) { + testOneMontgomeryMultiplyCheck(a, b, mag(n), len, inv.longValue(), product, klass); + } + + void testMontgomeryMultiplyChecks() { + int[] blah = random_val(40); + int[] small = random_val(39); + BigInteger mod = new BigInteger(40*32 , 2, rnd); + BigInteger r = BigInteger.ONE.shiftLeft(40*32); + BigInteger n_prime = mod.modInverse(r).negate(); + + // Length out of range: square + testOneMontgomeryMultiplyCheck(blah, blah, mod, 41, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, blah, mod, 0, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, blah, mod, -1, n_prime, IllegalArgumentException.class); + // As above, but for multiply + testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 41, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 0, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 0, n_prime, IllegalArgumentException.class); + + // Length odd + testOneMontgomeryMultiplyCheck(small, small, mod, 39, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(small, small, mod, 0, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(small, small, mod, -1, n_prime, IllegalArgumentException.class); + // As above, but for multiply + testOneMontgomeryMultiplyCheck(small, small.clone(), mod, 39, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(small, small.clone(), mod, 0, n_prime, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(small, small.clone(), mod, -1, n_prime, IllegalArgumentException.class); + + // array too small + testOneMontgomeryMultiplyCheck(blah, blah, mod, 40, n_prime, small, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, blah.clone(), mod, 40, n_prime, small, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(small, blah, mod, 40, n_prime, blah, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, small, mod, 40, n_prime, blah, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(blah, blah, mod, 40, n_prime, small, IllegalArgumentException.class); + testOneMontgomeryMultiplyCheck(small, small, mod, 40, n_prime, blah, IllegalArgumentException.class); + } + + public static void main(String args[]) { + try { + new MontgomeryMultiplyTest().testMontgomeryMultiplyChecks(); + new MontgomeryMultiplyTest().testResultValues(); + } catch (Throwable ex) { + throw new RuntimeException(ex); + } + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/intrinsics/sha/cli/SHAOptionsBase.java --- a/hotspot/test/compiler/intrinsics/sha/cli/SHAOptionsBase.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/compiler/intrinsics/sha/cli/SHAOptionsBase.java Thu Jul 09 22:46:16 2015 -0700 @@ -47,16 +47,12 @@ // expressions, not just a plain strings. protected static final String SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE = "SHA instructions are not available on this CPU"; - protected static final String SHA1_INSTRUCTION_IS_NOT_AVAILABLE - = "SHA1 instruction is not available on this CPU\\."; - protected static final String SHA256_INSTRUCTION_IS_NOT_AVAILABLE - = "SHA256 instruction \\(for SHA-224 and SHA-256\\) " - + "is not available on this CPU\\."; - protected static final String SHA512_INSTRUCTION_IS_NOT_AVAILABLE - = "SHA512 instruction \\(for SHA-384 and SHA-512\\) " - + "is not available on this CPU\\."; - protected static final String SHA_INTRINSICS_ARE_NOT_AVAILABLE - = "SHA intrinsics are not available on this CPU"; + protected static final String SHA1_INTRINSICS_ARE_NOT_AVAILABLE + = "Intrinsics for SHA-1 crypto hash functions not available on this CPU."; + protected static final String SHA256_INTRINSICS_ARE_NOT_AVAILABLE + = "Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."; + protected static final String SHA512_INTRINSICS_ARE_NOT_AVAILABLE + = "Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."; private final TestCase[] testCases; @@ -71,33 +67,23 @@ * instructions required by the option are not supported. */ protected static String getWarningForUnsupportedCPU(String optionName) { - if (Platform.isSparc() || Platform.isAArch64()) { + if (Platform.isSparc() || Platform.isAArch64() || + Platform.isX64() || Platform.isX86()) { switch (optionName) { - case SHAOptionsBase.USE_SHA_OPTION: - return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE; - case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION: - return SHAOptionsBase.SHA1_INSTRUCTION_IS_NOT_AVAILABLE; - case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION: - return SHAOptionsBase.SHA256_INSTRUCTION_IS_NOT_AVAILABLE; - case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION: - return SHAOptionsBase.SHA512_INSTRUCTION_IS_NOT_AVAILABLE; - default: - throw new Error("Unexpected option " + optionName); - } - } else if (Platform.isX64() || Platform.isX86()) { - switch (optionName) { - case SHAOptionsBase.USE_SHA_OPTION: - return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE; - case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION: - case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION: - case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION: - return SHAOptionsBase.SHA_INTRINSICS_ARE_NOT_AVAILABLE; - default: - throw new Error("Unexpected option " + optionName); + case SHAOptionsBase.USE_SHA_OPTION: + return SHAOptionsBase.SHA_INSTRUCTIONS_ARE_NOT_AVAILABLE; + case SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION: + return SHAOptionsBase.SHA1_INTRINSICS_ARE_NOT_AVAILABLE; + case SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION: + return SHAOptionsBase.SHA256_INTRINSICS_ARE_NOT_AVAILABLE; + case SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION: + return SHAOptionsBase.SHA512_INTRINSICS_ARE_NOT_AVAILABLE; + default: + throw new Error("Unexpected option " + optionName); } } else { - throw new Error("Support for CPUs other then X86 or SPARC is not " - + "implemented."); + throw new Error("Support for CPUs different fromn X86, SPARC, and AARCH64 " + + "is not implemented"); } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedCPU.java Thu Jul 09 22:46:16 2015 -0700 @@ -64,18 +64,20 @@ SHAOptionsBase.USE_SHA_OPTION, true), CommandLineOptionTest.prepareBooleanFlag(optionName, false)); - // Verify that it is possible to enable the tested option and disable - // all SHA intrinsics via -UseSHA without any warnings. - CommandLineOptionTest.verifySameJVMStartup(null, new String[] { - SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, shouldPassMessage, String.format("It should be able to " - + "enable option '%s' even if %s was passed to JVM", - optionName, CommandLineOptionTest.prepareBooleanFlag( - SHAOptionsBase.USE_SHA_OPTION, false)), - ExitCode.OK, - CommandLineOptionTest.prepareBooleanFlag( - SHAOptionsBase.USE_SHA_OPTION, false), - CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + if (!optionName.equals(SHAOptionsBase.USE_SHA_OPTION)) { + // Verify that if -XX:-UseSHA is passed to the JVM, it is not possible + // to enable the tested option and a warning is printed. + CommandLineOptionTest.verifySameJVMStartup( + new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) }, + null, + shouldPassMessage, + String.format("Enabling option '%s' should not be possible and should result in a warning if %s was passed to JVM", + optionName, + CommandLineOptionTest.prepareBooleanFlag(SHAOptionsBase.USE_SHA_OPTION, false)), + ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag(SHAOptionsBase.USE_SHA_OPTION, false), + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + } } @Override diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedAArch64CPU.java --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedAArch64CPU.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedAArch64CPU.java Thu Jul 09 22:46:16 2015 -0700 @@ -49,14 +49,22 @@ }, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); - shouldPassMessage = String.format("JVM should start with '-XX:+" - + "%s' flag, but output should contain warning.", optionName); - // Verify that when the tested option is explicitly enabled, then - // a warning will occur in VM output. - CommandLineOptionTest.verifySameJVMStartup(new String[] { - SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, - CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + shouldPassMessage = String.format("If JVM is started with '-XX:-" + + "%s' '-XX:+%s', output should contain warning.", + SHAOptionsBase.USE_SHA_OPTION, optionName); + + // Verify that when the tested option is enabled, then + // a warning will occur in VM output if UseSHA is disabled. + if (!optionName.equals(SHAOptionsBase.USE_SHA_OPTION)) { + CommandLineOptionTest.verifySameJVMStartup( + new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) }, + null, + shouldPassMessage, + shouldPassMessage, + ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag(SHAOptionsBase.USE_SHA_OPTION, false), + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + } } @Override diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java Thu Jul 09 22:46:16 2015 -0700 @@ -48,6 +48,19 @@ SHAOptionsBase.getWarningForUnsupportedCPU(optionName) }, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); + + // Verify that when the tested option is enabled, then + // a warning will occur in VM output if UseSHA is disabled. + if (!optionName.equals(SHAOptionsBase.USE_SHA_OPTION)) { + CommandLineOptionTest.verifySameJVMStartup( + new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) }, + null, + shouldPassMessage, + shouldPassMessage, + ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag(SHAOptionsBase.USE_SHA_OPTION, false), + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + } } @Override diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java --- a/hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/gc/g1/TestShrinkDefragmentedHeap.java Thu Jul 09 22:46:16 2015 -0700 @@ -23,7 +23,7 @@ /** * @test TestShrinkDefragmentedHeap - * @bug 8038423 + * @bug 8038423 8129590 * @summary Verify that heap shrinks after GC in the presence of fragmentation due to humongous objects * 1. allocate small objects mixed with humongous ones * "ssssHssssHssssHssssHssssHssssHssssH" @@ -51,12 +51,14 @@ // To avoid this the Eden needs to be big enough to fit all the small objects. private static final int INITIAL_HEAP_SIZE = 200 * 1024 * 1024; private static final int MINIMAL_YOUNG_SIZE = 190 * 1024 * 1024; + private static final int MAXIMUM_HEAP_SIZE = 256 * 1024 * 1024; private static final int REGION_SIZE = 1 * 1024 * 1024; public static void main(String[] args) throws Exception, Throwable { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:InitialHeapSize=" + INITIAL_HEAP_SIZE, "-Xmn" + MINIMAL_YOUNG_SIZE, + "-Xmx" + MAXIMUM_HEAP_SIZE, "-XX:MinHeapFreeRatio=10", "-XX:MaxHeapFreeRatio=11", "-XX:+UseG1GC", diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/gc/g1/TestSummarizeRSetStats.java --- a/hotspot/test/gc/g1/TestSummarizeRSetStats.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/gc/g1/TestSummarizeRSetStats.java Thu Jul 09 22:46:16 2015 -0700 @@ -23,7 +23,7 @@ /* * @test TestSummarizeRSetStats.java - * @bug 8013895 + * @bug 8013895 8129977 * @library /testlibrary * @modules java.base/sun.misc * java.management/sun.management diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/gc/g1/TestSummarizeRSetStatsPerRegion.java --- a/hotspot/test/gc/g1/TestSummarizeRSetStatsPerRegion.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/gc/g1/TestSummarizeRSetStatsPerRegion.java Thu Jul 09 22:46:16 2015 -0700 @@ -23,7 +23,7 @@ /* * @test TestSummarizeRSetStatsPerRegion.java - * @bug 8014078 + * @bug 8014078 8129977 * @library /testlibrary * @modules java.base/sun.misc * java.management/sun.management diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java --- a/hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java Thu Jul 09 22:46:16 2015 -0700 @@ -87,6 +87,7 @@ String[] defaultArgs = new String[] { "-XX:+UseG1GC", "-Xmn4m", + "-Xms20m", "-Xmx20m", "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking "-XX:+PrintGC", diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java Thu Jul 09 22:46:16 2015 -0700 @@ -28,6 +28,7 @@ * when their age exceeded tenuring threshold are not aligned to * SurvivorAlignmentInBytes value. * @library /testlibrary /../../test/lib + * @ignore 8130308 * @modules java.base/sun.misc * java.management * @build TestPromotionFromSurvivorToTenuredAfterMinorGC diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java --- a/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java Thu Jul 09 22:46:16 2015 -0700 @@ -31,6 +31,7 @@ * java.management * @build TestPromotionToSurvivor * SurvivorAlignmentTestMain AlignmentHelper + * @ignore 8129886 * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/DoubleJVMOption.java --- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/DoubleJVMOption.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/DoubleJVMOption.java Thu Jul 09 22:46:16 2015 -0700 @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Locale; public class DoubleJVMOption extends JVMOption { @@ -109,7 +110,7 @@ } private String formatValue(double value) { - return String.format("%f", value); + return String.format(Locale.US, "%f", value); } /** diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/CommandLine/TestLongUnrecognizedVMOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/CommandLine/TestLongUnrecognizedVMOption.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8129786 + * @summary Verify that JVM correctly processes very long unrecognized VM option + * @library /testlibrary + * @modules java.management + * @run main TestLongUnrecognizedVMOption + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class TestLongUnrecognizedVMOption { + + /* Create option with very long length(greater than 500 characters) */ + private static final String VERY_LONG_OPTION = String.format("%500s=10", "unrecognizedoption").replace(" ", "a"); + + public static void main(String[] args) throws Exception { + OutputAnalyzer output; + + output = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder("-XX:" + VERY_LONG_OPTION, "-version").start()); + output.shouldHaveExitValue(1); + output.shouldContain(String.format("Unrecognized VM option '%s'", VERY_LONG_OPTION)); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/Metaspace/FragmentMetaspaceSimple.java --- a/hotspot/test/runtime/Metaspace/FragmentMetaspaceSimple.java Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/runtime/Metaspace/FragmentMetaspaceSimple.java Thu Jul 09 22:46:16 2015 -0700 @@ -23,12 +23,15 @@ /** * @test - * @library /runtime/testlibrary * @library classes - * @build test.Empty ClassUnloadCommon + * @build test.Empty * @run main/othervm/timeout=200 FragmentMetaspaceSimple */ +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.ArrayList; /** @@ -47,8 +50,14 @@ private static void runSimple(long time) { long startTime = System.currentTimeMillis(); ArrayList cls = new ArrayList<>(); - for (int i = 0; System.currentTimeMillis() < startTime + time; ++i) { - ClassLoader ldr = ClassUnloadCommon.newClassLoader(); + char sep = File.separatorChar; + String fileName = "classes" + sep + "test" + sep + "Empty.class"; + File file = new File(System.getProperty("test.classes",".") + sep + fileName); + byte buff[] = read(file); + + int i = 0; + for (i = 0; System.currentTimeMillis() < startTime + time; ++i) { + ClassLoader ldr = new MyClassLoader(buff); if (i % 1000 == 0) { cls.clear(); } @@ -59,11 +68,43 @@ Class c = null; try { c = ldr.loadClass("test.Empty"); + c.getClass().getClassLoader(); // make sure we have a valid class. } catch (ClassNotFoundException ex) { + System.out.println("i=" + i + ", len" + buff.length); throw new RuntimeException(ex); } c = null; } cls = null; + System.out.println("Finished " + i + " iterations in " + + (System.currentTimeMillis() - startTime) + " ms"); + } + + private static byte[] read(File file) { + byte buff[] = new byte[(int)(file.length())]; + try { + DataInputStream din = new DataInputStream(new FileInputStream(file)); + din.readFully(buff); + din.close(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + return buff; + } + + static class MyClassLoader extends ClassLoader { + byte buff[]; + MyClassLoader(byte buff[]) { + this.buff = buff; + } + + public Class loadClass() throws ClassNotFoundException { + String name = "test.Empty"; + try { + return defineClass(name, buff, 0, buff.length); + } catch (Throwable e) { + throw new ClassNotFoundException(name, e); + } + } } } diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageAttributeOffsetsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageAttributeOffsetsTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/* + * Retrieves the array of offsets once with MemoryMapImage enabled once disabled. + * @test ImageAttributeOffsetsTest + * @summary Unit test for JVM_ImageAttributeOffsets() method + * @library /testlibrary /../../test/lib + * @build ImageAttributeOffsetsTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageAttributeOffsetsTest + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageAttributeOffsetsTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageAttributeOffsetsTest { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = wb.imageOpenImage(imageFile, bigEndian); + boolean passed = true; + // Get offsets + int[] array = wb.imageAttributeOffsets(id); + assertNotNull(array, "Could not retrieve offsets of array"); + + wb.imageCloseImage(id); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageCloseTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageCloseTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 closing image opened multiple time. Test closing mutiple time an image. + * @test ImageCloseTest + * @summary Unit test for JVM_ImageClose() method + * @library /testlibrary /../../test/lib + * @build ImageCloseTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageCloseTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; + +public class ImageCloseTest { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = 0; + + // too many opens + for (int i = 0; i < 100; i++) { + id = wb.imageOpenImage(imageFile, bigEndian); + } + wb.imageCloseImage(id); + + // too many closes + id = wb.imageOpenImage(imageFile, bigEndian); + for (int i = 0; i < 100; i++) { + wb.imageCloseImage(id); + } + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageFileHeaderTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageFileHeaderTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 that opening image containing wrong headers fails. + * @test ImageFileHeaderTest + * @library /testlibrary /../../test/lib + * @build ImageFileHeaderTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageFileHeaderTest + */ + +import java.nio.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageFileHeaderTest { + + public static final int MAGIC = 0xCAFEDADA; + public static final short MAJOR = 0; + public static final short MINOR = 1; + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + public static ByteBuffer buf; + + public static void main(String... args) throws Exception { + + ByteOrder endian = getEndian(); + + // Try to read a non-existing file + assertFalse(wb.readImageFile("bogus")); + + // Incomplete header, only include the correct magic + buf = ByteBuffer.allocate(100); + buf.order(endian); + buf.putInt(MAGIC); + assertFalse(testImageFile("invalidheader.jimage")); + + // Build a complete header but reverse the endian + buf = ByteBuffer.allocate(100); + buf.order(endian == ByteOrder.LITTLE_ENDIAN ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); + buf.putInt(MAGIC); + buf.putShort(MAJOR); + buf.putShort(MINOR); + assertFalse(testImageFile("wrongendian.jimage")); + + // Use the wrong magic + buf = ByteBuffer.allocate(100); + buf.order(endian); + buf.putInt(0xBEEFCACE); + buf.putShort(MAJOR); + buf.putShort(MINOR); + assertFalse(testImageFile("wrongmagic.jimage")); + + // Wrong major version (current + 1) + buf = ByteBuffer.allocate(100); + buf.order(endian); + buf.putInt(MAGIC); + buf.putShort((short)(MAJOR + 1)); + buf.putShort((short)MINOR); + assertFalse(testImageFile("wrongmajorversion.jimage")); + + // Wrong major version (negative) + buf = ByteBuffer.allocate(100); + buf.order(endian); + buf.putInt(MAGIC); + buf.putShort((short) -17); + buf.putShort((short)MINOR); + assertFalse(testImageFile("negativemajorversion.jimage")); + + // Wrong minor version (current + 1) + buf = ByteBuffer.allocate(100); + buf.order(endian); + buf.putInt(MAGIC); + buf.putShort((short)MAJOR); + buf.putShort((short)(MINOR + 1)); + assertFalse(testImageFile("wrongminorversion.jimage")); + + // Wrong minor version (negative) + buf = ByteBuffer.allocate(100); + buf.order(endian); + buf.putInt(MAGIC); + buf.putShort((short)MAJOR); + buf.putShort((short) -17); + assertFalse(testImageFile("negativeminorversion.jimage")); + } + + public static boolean testImageFile(String filename) throws Exception { + Files.write(Paths.get(filename), buf.array()); + System.out.println("Calling ReadImageFile on " + filename); + return wb.readImageFile(filename); + } + + public static ByteOrder getEndian() { + String endian = System.getProperty("sun.cpu.endian"); + if (endian.equalsIgnoreCase("little")) { + return ByteOrder.LITTLE_ENDIAN; + } else if (endian.equalsIgnoreCase("big")) { + return ByteOrder.BIG_ENDIAN; + } + throw new RuntimeException("Unexpected sun.cpu.endian value: " + endian); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageFindAttributesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageFindAttributesTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/* + * Find the attributes of existing and invalid classes. + * @test ImageFindAttributesTest + * @summary Unit test for JVM_ImageFindAttributes() method + * @library /testlibrary /../../test/lib + * @build ImageFindAttributesTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageFindAttributesTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageFindAttributesTest { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = wb.imageOpenImage(imageFile, bigEndian); + + // class resource + String className = "/java.base/java/lang/String.class"; + long[] longArr = wb.imageFindAttributes(id, className.getBytes()); + + assertNotNull(longArr, "Could not retrieve attributes of class " + className); + + // non-existent resource + String neClassName = "/java.base/java/lang/NonExistentClass.class"; + longArr = wb.imageFindAttributes(id, neClassName.getBytes()); + + assertNull(longArr, "Failed. Returned not null for non-existent " + neClassName); + + // garbage byte array + byte[] buf = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + longArr = wb.imageFindAttributes(id, buf); + + assertNull(longArr, "Found attributes for garbage class"); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageGetAttributesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageGetAttributesTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 getting all attributes, + * @test ImageGetAttributesTest + * @summary Unit test for JVM_ImageGetAttributes() method + * @library /testlibrary /../../test/lib + * @build LocationConstants ImageGetAttributesTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetAttributesTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageGetAttributesTest implements LocationConstants { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + testImageGetAttributes(imageFile); + } + + private static void testImageGetAttributes(String imageFile) { + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = wb.imageOpenImage(imageFile, bigEndian); + try { + long stringsSize = wb.imageGetStringsSize(id); + assertNE(stringsSize, 0, "strings size is 0"); + + int[] array = wb.imageAttributeOffsets(id); + assertNotNull(array, "Could not retrieve offsets of array"); + + // Get non-null attributes + boolean attFound = false; + int[] idx = {-1, -1, -1}; + // first non-null attribute + for (int i = 0; i < array.length; i++) { + if (array[i] != 0) { + attFound = true; + idx[0] = i; + break; + } + } + + // middle non-null attribute + for (int i = array.length / 2; i < array.length; i++) { + if (array[i] != 0) { + attFound = true; + idx[1] = i; + break; + } + } + + // last non-null attribute + for (int i = array.length - 1; i >= 0; i--) { + if (array[i] != 0) { + attFound = true; + idx[2] = i; + break; + } + } + assertTrue(attFound, "Failed. No non-null offset attributes"); + // test cases above + for (int i = 0; i < 3; i++) { + if (idx[i] != -1) { + long[] attrs = wb.imageGetAttributes(id, (int) array[idx[i]]); + long module = attrs[LOCATION_ATTRIBUTE_MODULE]; + long parent = attrs[LOCATION_ATTRIBUTE_PARENT]; + long base = attrs[LOCATION_ATTRIBUTE_BASE]; + long ext = attrs[LOCATION_ATTRIBUTE_EXTENSION]; + + if ((module >= 0) && (module < stringsSize) + && (parent >= 0) && (parent < stringsSize) + && (base != 0) + && (ext >= 0) && (ext < stringsSize)) { + } else { + System.out.printf("Failed. Read attribute offset %d (position %d) but wrong offsets\n", + array[idx[i]], idx[i]); + System.out.printf(" offsets: module = %d parent = %d base = %d extention = %d\n", + module, parent, base, ext); + throw new RuntimeException("Read attribute offset error"); + } + } else { + System.out.printf("Failed. Could not read attribute offset %d (position %d)\n", + array[idx[i]], idx[i]); + throw new RuntimeException("Read attribute offset error"); + } + } + } finally { + wb.imageCloseImage(id); + } + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageGetDataAddressTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageGetDataAddressTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 accessing the data address of a jimage. This only makes sense when the + * entire jimage is mapped into memory. + * @test ImageGetDataAddressTest + * @summary Unit test for JVM_ImageGetDataAddress() method + * @library /testlibrary /../../test/lib + * @build ImageGetDataAddressTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageGetDataAddressTest + + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageGetDataAddressTest - + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageGetDataAddressTest { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean isMMap = args[0].equals("+"); + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = wb.imageOpenImage(imageFile, bigEndian); + + // get data for valid id + long dataAddr = wb.imageGetDataAddress(id); + assertFalse((dataAddr == 0) && isMMap, "Failed. Data address is " + dataAddr + " for valid id\n"); + + // get data for invalid id == 0 + dataAddr = wb.imageGetDataAddress(0); + assertTrue(dataAddr == 0, "Failed. Data address is " + dataAddr + " for zero id\n"); + + wb.imageCloseImage(id); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageGetIndexAddressTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageGetIndexAddressTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 the address of the jimage index. + * @test ImageGetIndexAddressTest + * @summary Unit test for JVM_ImageGetIndexAddress() method + * @library /testlibrary /../../test/lib + * @build ImageGetIndexAddressTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetIndexAddressTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageGetIndexAddressTest { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = wb.imageOpenImage(imageFile, bigEndian); + + // get index for valid id + long indexAddr = wb.imageGetIndexAddress(id); + assertFalse(indexAddr == 0, "Failed. Index address is zero for valid id"); + + // get index for invalid id == 0 + indexAddr = wb.imageGetIndexAddress(0); + assertTrue(indexAddr == 0, "Failed. Index address is" + indexAddr + " for zero id\n"); + + wb.imageCloseImage(id); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageGetStringBytesTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageGetStringBytesTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 that the string referenced by an attribute is retrieved. + * @test ImageGetStringBytesTest + * @summary Unit test for JVM_ImageGetStringBytes() method + * @library /testlibrary /../../test/lib + * @build LocationConstants ImageGetStringBytesTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageGetStringBytesTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageGetStringBytesTest implements LocationConstants { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + long id = wb.imageOpenImage(imageFile, bigEndian); + + String className = "/java.base/java/lang/String.class"; + long[] offsetArr = wb.imageFindAttributes(id, className.getBytes()); + + // Module + assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_MODULE, "Module")); + + // Parent + assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_PARENT, "Parent")); + + // Base + assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_BASE, "Base")); + + // Extension + assertTrue(checkAttribute(id, offsetArr, LOCATION_ATTRIBUTE_EXTENSION, "Extension")); + + wb.imageCloseImage(id); + } + + private static boolean checkAttribute(long id, long[] offsetArr, int attrId, String attrName) { + long offset = offsetArr[attrId]; + return wb.imageGetStringBytes(id, (int) offset) != null; + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageOpenTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageOpenTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 image opening/closing + * @test ImageOpenTest + * @summary Unit test for JVM_ImageOpen() method + * @library /testlibrary /../../test/lib + * @build ImageOpenTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ImageOpenTest + */ + +import java.io.File; +import java.nio.ByteOrder; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageOpenTest { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String nonexistentImageFile = javaHome + "/lib/modules/nonexistent.jimage"; + String bootmodulesImageFile = javaHome + File.separator + "lib" + File.separator + + "modules" + File.separator + "bootmodules.jimage"; + + if (!(new File(bootmodulesImageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean bigEndian = ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN; + + // open nonexistent image + long id = wb.imageOpenImage(nonexistentImageFile, bigEndian); + assertTrue(id == 0L, "Failed. Get id " + id + "instead of 0 on opening nonexistent file\n"); + wb.imageCloseImage(id); + + // open bootmodules image + id = wb.imageOpenImage(bootmodulesImageFile, bigEndian); + assertFalse(id == 0, "Failed. Get id 0 on opening bootmodules.jimage"); + wb.imageCloseImage(id); + + // non-native endian + id = wb.imageOpenImage(bootmodulesImageFile, !bigEndian); + assertFalse(id == 0, "Failed. Get id 0 on opening bootmodules.jimage with non-native endian"); + wb.imageCloseImage(id); + + // + // open several times + // + id = wb.imageOpenImage(bootmodulesImageFile, bigEndian); + long id1 = wb.imageOpenImage(bootmodulesImageFile, bigEndian); + long id2 = wb.imageOpenImage(bootmodulesImageFile, bigEndian); + assertTrue((id == id1) && (id == id2), "Failed. Open thee times with ids " + id + " " + id1 + " " + id1); + + wb.imageCloseImage(id); + wb.imageCloseImage(id1); + wb.imageCloseImage(id2); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/ImageReadTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/ImageReadTest.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 reading resource content. + * @test ImageReadTest + * @summary Unit test for JVM_ImageRead() method + * @library /testlibrary /../../test/lib + * @build LocationConstants ImageReadTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+MemoryMapImage ImageReadTest + + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-MemoryMapImage ImageReadTest - + */ + +import java.io.File; +import java.nio.ByteBuffer; +import sun.hotspot.WhiteBox; +import static jdk.test.lib.Asserts.*; + +public class ImageReadTest implements LocationConstants { + + public static final WhiteBox wb = WhiteBox.getWhiteBox(); + + public static void main(String... args) throws Exception { + String javaHome = System.getProperty("java.home"); + String imageFile = javaHome + File.separator + "lib" + + File.separator + "modules" + File.separator + + "bootmodules.jimage"; + + if (!(new File(imageFile)).exists()) { + System.out.printf("Test skipped."); + return; + } + + boolean isMMap = args[0].equals("+"); + + long id = wb.imageOpenImage(imageFile, isMMap); + + final String mm = isMMap ? "-XX:+MemoryMapImage" : "-XX:-MemoryMapImage"; + final int magic = 0xCAFEBABE; + + String className = "/java.base/java/lang/String.class"; + long[] offsetArr = wb.imageFindAttributes(id, className.getBytes()); + long offset = offsetArr[LOCATION_ATTRIBUTE_OFFSET]; + long size = offsetArr[LOCATION_ATTRIBUTE_UNCOMPRESSED]; + + // positive: read + ByteBuffer buf = ByteBuffer.allocateDirect((int) size); + assertTrue(wb.imageRead(id, offset, buf, size), "Failed. Read operation returned false, should be true"); + int m = buf.getInt(); + assertTrue(m == magic, "Failed. Read operation returned true but wrong magic = " + magic); + + // positive: mmap + if (isMMap) { + long dataAddr = wb.imageGetDataAddress(id); + assertFalse(dataAddr == 0L, "Failed. Did not obtain data address on mmapped test"); + int data = wb.imageGetIntAtAddress(dataAddr, (int) offset, true); + assertTrue(data == magic, "Failed. MMap operation returned true but wrong magic = " + data); + } + + // negative: wrong offset + boolean success = wb.imageRead(id, -100, buf, size); + assertFalse(success, "Failed. Read operation (wrong offset): returned true"); + + // negative: too big offset + long filesize = new File(imageFile).length(); + success = wb.imageRead(id, filesize + 1, buf, size); + assertFalse(success, "Failed. Read operation (offset > file size) returned true"); + + // negative: negative size + success = wb.imageRead(id, offset, buf, -100); + assertFalse(success, "Failed. Read operation (negative size) returned true"); + + wb.imageCloseImage(id); + } +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/runtime/modules/ImageFile/LocationConstants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/runtime/modules/ImageFile/LocationConstants.java Thu Jul 09 22:46:16 2015 -0700 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +public interface LocationConstants { + // keep this in sync with enum in ImageLocation C++ class in the + // hotspot's C++ header file imageFile.hpp + public static final int LOCATION_ATTRIBUTE_END = 0; // End of attribute stream marker + public static final int LOCATION_ATTRIBUTE_MODULE = 1; // String table offset of module name + public static final int LOCATION_ATTRIBUTE_PARENT = 2; // String table offset of resource path parent + public static final int LOCATION_ATTRIBUTE_BASE = 3; // String table offset of resource path base + public static final int LOCATION_ATTRIBUTE_EXTENSION = 4; // String table offset of resource path extension + public static final int LOCATION_ATTRIBUTE_OFFSET = 5; // Container byte offset of resource + public static final int LOCATION_ATTRIBUTE_COMPRESSED = 6; // In image byte size of the compressed resource + public static final int LOCATION_ATTRIBUTE_UNCOMPRESSED = 7; // In memory byte size of the uncompressed resource + public static final int LOCATION_ATTRIBUTE_COUNT = 8; // Number of attribute kinds +} diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/testlibrary/ctw/Makefile --- a/hotspot/test/testlibrary/ctw/Makefile Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/testlibrary/ctw/Makefile Thu Jul 09 22:46:16 2015 -0700 @@ -8,7 +8,7 @@ # # 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 +# 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). # diff -r 9b3a9d72f07b -r 75c6dcc9351d hotspot/test/testlibrary/ctw/README --- a/hotspot/test/testlibrary/ctw/README Wed Jul 05 20:41:30 2017 +0200 +++ b/hotspot/test/testlibrary/ctw/README Thu Jul 09 22:46:16 2015 -0700 @@ -1,26 +1,26 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# 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. -# -# + +Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +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. + + DESCRIPTION