This commit is contained in:
J. Duke 2017-07-05 20:42:14 +02:00
commit 0b14ff7e05
257 changed files with 6260 additions and 1971 deletions

View File

@ -315,3 +315,4 @@ f546760134eb861fcfecd4ce611b0040b0d25a6a jdk9-b67
eed77fcd77711fcdba05f18fc22f37d86efb243c jdk9-b70
c706ef5ea5da00078dc5e4334660315f7d99c15b jdk9-b71
8582c35016fb6211b373810b6b172feccf9c483b jdk9-b72
4c2cbaae528bce970dabbb5676005d379357f4b6 jdk9-b73

View File

@ -475,3 +475,4 @@ ff0929a59ced0e144201aa05819ae2e47d6f2c61 jdk9-b69
8672e9264db30c21504063932dbc374eabc287a1 jdk9-b70
07c6b035d68b0c41b1dcd442157b50b41a2551e9 jdk9-b71
c1b2825ef47e75cb34dd18450d1c4280b7c5853c jdk9-b72
e37d432868be0aa7cb5e0f3d7caff1e825d8ead3 jdk9-b73

View File

@ -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 @@ public class CodeCache {
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>(CodeHeap.class));
heapArray = GrowableArray.create(heapsField.getValue(), heapConstructor);
scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods");
@ -180,31 +185,9 @@ public class CodeCache {
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();
}

View File

@ -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 @@ public class CodeHeap extends VMObject {
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 @@ public class CodeHeap extends VMObject {
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
//

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
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;

View File

@ -139,6 +139,18 @@ SUNWprivate_1.1 {
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;

View File

@ -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

View File

@ -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

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
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;

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
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;

View File

@ -118,7 +118,8 @@ SIMPLE_DIRS = \
$(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))

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
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;

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
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;

View File

@ -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 @@ DEMANGLE = $(DEMANGLER) < $@ > .$@ && $(MV) -f .$@ $@
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 @@ endif
$(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 $@ $<

View File

@ -54,7 +54,7 @@ endif
# Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm
# The adfiles directory contains ad_<arch>.[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 @@ CORE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
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 @@ ifeq ($(Platform_arch_model), x86_64)
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 @@ endif
# 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 = ^_ZTV
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 $@

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
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;

View File

@ -143,7 +143,7 @@ else
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

View File

@ -2270,17 +2270,21 @@ public:
}
// 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

View File

@ -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.

View File

@ -2914,6 +2914,65 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
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;

View File

@ -967,6 +967,10 @@ public:
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

View File

@ -2356,6 +2356,47 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
/**
* 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:
*
@ -2579,6 +2620,10 @@ class StubGenerator: public StubCodeGenerator {
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,

View File

@ -199,9 +199,12 @@ void VM_Version::get_processor_features() {
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 @@ void VM_Version::get_processor_features() {
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);
}
if (UseSHA && (auxv & HWCAP_SHA2)) {
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
}
} 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);
} 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 (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);
}
}
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA, false);
}
// This machine allows unaligned memory accesses

View File

@ -105,7 +105,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ 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 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ 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()));

View File

@ -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 BytesPerInstWord = 4;
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.

View File

@ -465,7 +465,7 @@ void trace_method_handle_stub(const char* adaptername,
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) {

View File

@ -731,23 +731,8 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
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 object_move(MacroAssembler* masm,
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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// 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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// 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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// 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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
}
} 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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
}
} 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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ 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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
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 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// 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

View File

@ -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 BytesPerInstWord = 4;
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.

View File

@ -483,7 +483,7 @@ void trace_method_handle_stub(const char* adaptername,
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));

View File

@ -329,39 +329,35 @@ void VM_Version::initialize() {
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 (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);
}
}
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_sha256()) {
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
}
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(UseSHA256Intrinsics, false);
}
if (UseSHA && has_sha512()) {
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
}
} 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

View File

@ -110,7 +110,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
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 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
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()));

View File

@ -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.

View File

@ -5152,7 +5152,7 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad
{
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);

View File

@ -484,7 +484,7 @@ void trace_method_handle_stub(const char* adaptername,
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);

View File

@ -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 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
}
//------------------------------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
//

View File

@ -4318,7 +4318,18 @@ class StubGenerator: public StubCodeGenerator {
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:

View File

@ -692,10 +692,19 @@ void VM_Version::get_processor_features() {
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 @@ void VM_Version::get_processor_features() {
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 @@ void VM_Version::get_processor_features() {
}
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");

View File

@ -117,7 +117,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
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 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
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()));

View File

@ -112,7 +112,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ 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 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ 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()));

View File

@ -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 <ffi.h>
// 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

View File

@ -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 void signal_unlock() {
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 @@ static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
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 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
bool sigused;
struct sigaction oldAct;
if (reentry) {
return call_os_sigaction(sig, act, oact);
}
signal_lock();
sigused = (MASK(sig) & jvmsigs) != 0;

View File

@ -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 @@ typedef sem_t os_semaphore_t;
#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;
};
#ifdef __APPLE__
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
Semaphore::Semaphore() : _semaphore(0) {
SEM_INIT(_semaphore, 0);
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 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) {
}
#else
// Use POSIX implementation of semaphores.
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;
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

View File

@ -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 <mach/semaphore.h>
class OSXSemaphore : public CHeapObj<mtInternal>{
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

View File

@ -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 @@ void* os::user_handler() {
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 @@ bool Semaphore::timedwait(unsigned int sec, int 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;
}
extern "C" {
@ -2416,7 +2373,7 @@ static volatile jint pending_signals[NSIG+1] = { 0 };
// 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

View File

@ -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 <sys/resource.h>
#include <sys/utsname.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@ -1015,3 +1017,73 @@ void os::WatcherThreadCrashProtection::check_crash_protection(int sig,
}
}
}
#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__

View File

@ -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 <semaphore.h>
class PosixSemaphore : public CHeapObj<mtInternal> {
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

View File

@ -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 @@ void* os::user_handler() {
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 @@ static void suspend_save_context(OSThread *osthread, ucontext_t* context) {
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

View File

@ -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 @@ int os::get_last_error() {
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 @@ void TestReserveMemorySpecial_test() {
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 @@ void TestReserveMemorySpecial_test() {
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 @@ void TestReserveMemorySpecial_test() {
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));
}
}

View File

@ -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 <windef.h>
class WindowsSemaphore : public CHeapObj<mtInternal> {
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

View File

@ -191,7 +191,7 @@ public:
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 @@ public:
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 @@ int VM_Version::platform_features(int features) {
}
// 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();

View File

@ -70,7 +70,8 @@ CONFIGURE_ARGS= --host=$(MINGW) --target=$(MINGW)
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

View File

@ -1093,9 +1093,11 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) {
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 @@ void CodeStrings::copy(CodeStrings& other) {
}
}
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();
}

View File

@ -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 @@ private:
// 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,11 +290,18 @@ public:
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
}
};
@ -379,6 +387,7 @@ class CodeBuffer: public StackObj {
_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 @@ class CodeBuffer: public StackObj {
// 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);

View File

@ -161,7 +161,7 @@ void CFGPrinterOutput::print_compilation() {
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");
}

View File

@ -3157,6 +3157,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
// 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 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
// 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 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co
}
// 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 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
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();

View File

@ -2208,7 +2208,15 @@ void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) {
if (log2_scale != 0) {
// temporary fix (platform dependent code without shift on Intel would be better)
// TODO: ARM also allows embedded shift in the address
__ shift_left(index_op, log2_scale, index_op);
LIR_Opr tmp = new_pointer_register();
if (TwoOperandLIRForm) {
__ move(index_op, tmp);
index_op = tmp;
}
__ shift_left(index_op, log2_scale, tmp);
if (!TwoOperandLIRForm) {
index_op = tmp;
}
}
LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());

View File

@ -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 @@ void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
// create code buffer for code storage
CodeBuffer code(buffer_blob);
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
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");
int frame_size;
bool must_gc_arguments;
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 @@ void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
#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 @@ static nmethod* counter_overflow_helper(JavaThread* THREAD, int branch_bci, Meth
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;

View File

@ -1185,7 +1185,6 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
vmIntrinsics::ID iid = method()->intrinsic_id();
if (iid == vmIntrinsics::_getClass ||
iid == vmIntrinsics::_fillInStackTrace ||
iid == vmIntrinsics::_hashCode)
return iid;
else
@ -1199,10 +1198,6 @@ bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
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;

View File

@ -178,9 +178,10 @@ class ciMethod : public ciMetadata {
// 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();

View File

@ -1751,6 +1751,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
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 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
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 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// (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));
}
}
}
}
}

View File

@ -130,6 +130,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
_method_InjectedProfile,
_method_LambdaForm_Compiled,
_method_LambdaForm_Hidden,
_method_HotSpotIntrinsicCandidate,
_sun_misc_Contended,
_field_Stable,
_annotation_LIMIT

View File

@ -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 @@ ClassPathEntry::ClassPathEntry() {
}
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 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi
}
}
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;
}
ClassPathImageEntry::ClassPathImageEntry(ImageFileReader* image) :
ClassPathEntry(),
_image(image),
_module_data(NULL) {
guarantee(image != NULL, "image file is null");
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;
}
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 @@ const char* ClassPathImageEntry::name() {
}
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 (buffer) {
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) {
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 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
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 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
}
bool ClassPathImageEntry::is_jrt() {
return string_ends_with(name(), "bootmodules.jimage");
return string_ends_with(name(), BOOT_IMAGE_NAME);
}
#endif
@ -539,11 +486,8 @@ void ClassLoader::setup_search_path(const char *class_path) {
}
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,39 +501,39 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
return NULL;
}
}
// TODO - add proper criteria for selecting image file
ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path);
if (entry->is_open()) {
new_entry = entry;
ImageFileReader* image = ImageFileReader::open(canonical_path);
if (image != NULL) {
new_entry = new ClassPathImageEntry(image);
} 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);
} 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);
} 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);
char* error_msg = NULL;
jzfile* zip;
{
// enable call to C land
ThreadToNativeFromVM ttn(thread);
HandleMark hm(thread);
zip = (*ZipOpen)(canonical_path, &error_msg);
}
if (throw_exception) {
THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL);
if (zip != NULL && error_msg == NULL) {
new_entry = new ClassPathZipEntry(zip, path);
} else {
return NULL;
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 (TraceClassLoading || TraceClassPaths) {
tty->print_cr("[Opened %s]", path);
}
@ -666,7 +610,7 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
// 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 @@ bool ClassPathZipEntry::is_jrt() {
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);

View File

@ -32,9 +32,14 @@
// The VM class loader.
#include <sys/stat.h>
// 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<mtClass> {
private:
ClassPathEntry* _next;
@ -47,7 +52,7 @@ class ClassPathEntry: public CHeapObj<mtClass> {
}
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 @@ class ClassPathDirEntry: public ClassPathEntry {
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 @@ class ClassPathZipEntry: public ClassPathEntry {
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 @@ class ClassPathZipEntry: public ClassPathEntry {
};
// 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 @@ class ClassLoader: AllStatic {
package_hash_table_size = 31 // Number of buckets
};
protected:
friend class LazyClassPathEntry;
// Performance counters
static PerfCounter* _perf_accumulated_time;
@ -222,7 +207,7 @@ class ClassLoader: AllStatic {
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

View File

@ -494,7 +494,7 @@ const char* ClassLoaderData::loader_name() {
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 @@ void ClassLoaderData::dump(outputStream * const out) {
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();

View File

@ -557,7 +557,7 @@ void ProtectionDomainCacheTable::print() {
}
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

View File

@ -370,7 +370,7 @@ class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
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) {

View File

@ -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*>* ImageDecompressor::_decompressors =
new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageDecompressor*>(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

View File

@ -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<mtClass> {
private:
const Symbol* _name;
/*
* Array of concrete decompressors. This array is used to retrieve the decompressor
* that can handle resource decompression.
*/
static GrowableArray<ImageDecompressor*>* _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

View File

@ -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"
// 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 string.
u4 ImageStrings::hash_code(const char* string, u4 seed) {
// 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) {
// Copy the image file name.
_name = NEW_C_HEAP_ARRAY(char, strlen(name)+1, mtClass);
strcpy(_name, 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<const char*>* 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<const char*>* packages = new GrowableArray<const char*>();
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*>* ImageFileReader::_reader_table =
new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageFileReader*>(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);
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 @@ bool ImageFile::open() {
(_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;
}
}
// 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;
}
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;
// 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;
}
// 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.
// 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);
}
return false;
}
// 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++ = '/';
}
// Get parent (package) string.
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.
// 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);
next = ImageStrings::starts_with(next, base);
// Continue only if a complete match.
if (!next) return false;
// Match up path extension.
// 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);
next = ImageStrings::starts_with(next, extension);
// 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';
}
// 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 && *next == '\0';
return *next == '\0';
}
// Return the resource for the supplied location.
u1* ImageFile::get_resource(ImageLocation& location) const {
// 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 = _index_size + location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
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);
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;
}
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;
}
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);
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");
}
}
GrowableArray<const char*>* 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<const char*>* pkgs = new GrowableArray<const char*>();
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 pkgs;
}

View File

@ -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 <package>/<base>.<extension> return the resource location
// in the form /<module>/<package>/<base>.<extension> 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 @@ public:
// 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 @@ public:
// 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 @@ private:
// 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 @@ public:
}
};
// Manage the image file.
class ImageFile: public CHeapObj<mtClass> {
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;
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.
//
// 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<mtClass> {
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); }
};
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
// 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); }
};
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<const char*>* 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<mtClass> {
private:
// Manage a number of image files such that an image can be shared across
// multiple uses (ex. loader.)
static GrowableArray<ImageFileReader*>* _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 image file for access.
// Open an image file, reuse structure if file already open.
static ImageFileReader* open(const char* name, bool big_endian = Endian::is_big_endian());
// 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 for location i.
inline u1* get_location_data(u4 i) const {
u4 offset = _offsets_table[i];
// 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 the attribute stream for a named resourced.
u1* find_location_data(const char* path) const;
// Return location attribute stream for location 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 get_location_offset_data(offset);
}
// 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<const char*>* 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

View File

@ -1707,8 +1707,7 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle met
// - 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;
}

View File

@ -2346,9 +2346,6 @@ methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name,
assert(!THREAD->is_Compiler_thread(), "");
Handle method_type =
SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty));
if (false) { // FIXME: Decide if the Java upcall should resolve signatures.
method_type = java_lang_String::create_from_symbol(signature, CHECK_(empty));
}
KlassHandle mh_klass = SystemDictionary::MethodHandle_klass();
int ref_kind = JVM_REF_invokeVirtual;
@ -2380,6 +2377,24 @@ methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name,
return unpack_method_and_appendix(mname, accessing_klass, appendix_box, appendix_result, THREAD);
}
// Decide if we can globally cache a lookup of this class, to be returned to any client that asks.
// We must ensure that all class loaders everywhere will reach this class, for any client.
// This is a safe bet for public classes in java.lang, such as Object and String.
// We also include public classes in java.lang.invoke, because they appear frequently in system-level method types.
// Out of an abundance of caution, we do not include any other classes, not even for packages like java.util.
static bool is_always_visible_class(oop mirror) {
Klass* klass = java_lang_Class::as_Klass(mirror);
if (klass->oop_is_objArray()) {
klass = ObjArrayKlass::cast(klass)->bottom_klass(); // check element type
}
if (klass->oop_is_typeArray()) {
return true; // primitive array
}
assert(klass->oop_is_instance(), klass->external_name());
return klass->is_public() &&
(InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::Object_klass()) || // java.lang
InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass())); // java.lang.invoke
}
// Ask Java code to find or construct a java.lang.invoke.MethodType for the given
// signature, as interpreted relative to the given class loader.
@ -2402,32 +2417,33 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
}
Handle class_loader, protection_domain;
bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader
if (accessing_klass.not_null()) {
class_loader = Handle(THREAD, InstanceKlass::cast(accessing_klass())->class_loader());
protection_domain = Handle(THREAD, InstanceKlass::cast(accessing_klass())->protection_domain());
}
bool can_be_cached = true;
int npts = ArgumentCount(signature).size();
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
int arg = 0;
Handle rt; // the return type from the signature
Handle rt; // the return type from the signature
ResourceMark rm(THREAD);
for (SignatureStream ss(signature); !ss.is_done(); ss.next()) {
oop mirror = NULL;
if (is_on_bcp) {
// Note: class_loader & protection_domain are both null at this point.
mirror = ss.as_java_mirror(class_loader, protection_domain,
if (can_be_cached) {
// Use neutral class loader to lookup candidate classes to be placed in the cache.
mirror = ss.as_java_mirror(Handle(), Handle(),
SignatureStream::ReturnNull, CHECK_(empty));
if (mirror == NULL) {
// fall back from BCP to accessing_klass
if (accessing_klass.not_null()) {
class_loader = Handle(THREAD, InstanceKlass::cast(accessing_klass())->class_loader());
protection_domain = Handle(THREAD, InstanceKlass::cast(accessing_klass())->protection_domain());
}
is_on_bcp = false;
if (mirror == NULL || (ss.is_object() && !is_always_visible_class(mirror))) {
// Fall back to accessing_klass context.
can_be_cached = false;
}
}
if (!is_on_bcp) {
if (!can_be_cached) {
// Resolve, throwing a real error if it doesn't work.
mirror = ss.as_java_mirror(class_loader, protection_domain,
SignatureStream::NCDFError, CHECK_(empty));
}
assert(!oopDesc::is_null(mirror), ss.as_symbol(THREAD)->as_C_string());
if (ss.at_return_type())
rt = Handle(THREAD, mirror);
else
@ -2459,7 +2475,7 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
&args, CHECK_(empty));
Handle method_type(THREAD, (oop) result.get_jobject());
if (is_on_bcp) {
if (can_be_cached) {
// We can cache this MethodType inside the JVM.
MutexLocker ml(SystemDictionary_lock, THREAD);
spe = invoke_method_table()->find_entry(index, hash, signature, null_iid);

View File

@ -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 */ \
\
do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \
\
/* (2) Bytecode intrinsics */ \
\
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) \

View File

@ -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 @@ CodeBlob::CodeBlob(const char* name, int header_size, int size, int frame_comple
_data_offset = size;
_frame_size = 0;
set_oop_maps(NULL);
_strings = CodeStrings();
}
@ -114,6 +116,7 @@ CodeBlob::CodeBlob(
_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* BufferBlob::create(const char* name, int buffer_size) {
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* MethodHandlesAdapterBlob::create(int buffer_size) {
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* RuntimeStub::new_runtime_stub(const char* stub_name,
{
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);

View File

@ -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 @@ struct CodeBlobType {
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 DeoptimizationBlob;
class CodeBlob VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
friend class CodeCacheDumper;
private:
const char* _name;
@ -206,6 +208,14 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
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;

View File

@ -409,7 +409,7 @@ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool strict) {
}
if (PrintCodeCacheExtension) {
ResourceMark rm;
if (SegmentedCodeCache) {
if (_heaps->length() >= 1) {
tty->print("%s", heap->name());
} else {
tty->print("CodeCache");
@ -1211,7 +1211,7 @@ void CodeCache::print_internals() {
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 @@ void CodeCache::print_summary(outputStream* st, bool detailed) {
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 @@ void CodeCache::print_codelist(outputStream* st) {
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());
}

View File

@ -78,6 +78,7 @@ class CodeCache : AllStatic {
friend class VMStructs;
friend class NMethodIterator;
friend class WhiteBox;
friend class CodeCacheLoader;
private:
// CodeHeaps of the cache
static GrowableArray<CodeHeap*>* _heaps;

View File

@ -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

View File

@ -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

View File

@ -186,7 +186,7 @@ uint ImplicitExceptionTable::at( uint exec_off ) const {
void ImplicitExceptionTable::print(address base) const {
tty->print("{");
for( uint i=0; i<len(); i++ )
tty->print("< "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("}");
}

View File

@ -2118,7 +2118,7 @@ public:
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 @@ public:
_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 @@ public:
_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 @@ void nmethod::print() const {
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 ");

View File

@ -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 @@ void StubQueue::print() {
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;
}

View File

@ -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 @@ class StubQueue: public CHeapObj<mtCode> {
// 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

View File

@ -172,7 +172,7 @@ class CompilationLog : public StringEventLog {
}
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()));
}

View File

@ -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 @@ static bool scan_line(const char * line,
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 @@ static bool scan_line(const char * line,
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 @@ static MethodMatcher* scan_flag_and_value(const char* type, const char* line, in
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 @@ static MethodMatcher* scan_flag_and_value(const char* type, const char* line, in
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;
}

View File

@ -65,7 +65,7 @@ bool Disassembler::_tried_to_load_library = false;
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;

View File

@ -688,18 +688,18 @@ void ConcurrentMarkSweepGeneration::printOccupancy(const char *s) {
"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 ConcurrentMarkSweepGeneration::promotion_attempt_is_safe(size_t max_promoti
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 @@ void ConcurrentMarkSweepGeneration::compute_new_size_free_list() {
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 @@ bool CMSCollector::shouldConcurrentCollect() {
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 @@ void ConcurrentMarkSweepGeneration::gc_prologue_work(bool full,
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 @@ void ConcurrentMarkSweepGeneration::gc_epilogue_work(bool full) {
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 @@ void ConcurrentMarkSweepGeneration::gc_epilogue_work(bool full) {
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 @@ class VerifyMarkedClosure: public BitMapClosure {
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 @@ void CMSCollector::setup_cms_unloading_and_verification_state() {
// 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 @@ void CMSCollector::checkpointRootsFinal() {
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 @@ void CMSCollector::checkpointRootsFinalWork() {
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 @@ void CMSCollector::checkpointRootsFinalWork() {
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 @@ void CMSCollector::checkpointRootsFinalWork() {
}
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 @@ void CMSCollector::do_remark_non_parallel() {
&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 @@ void CMSMarkStack::expand() {
} 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 @@ SweepClosure::~SweepClosure() {
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 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) {
// 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);

View File

@ -1021,7 +1021,7 @@ void ParNewGeneration::collect(bool full,
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 @@ void ParNewGeneration::collect(bool full,
_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++) {

View File

@ -411,9 +411,7 @@ class ParNewGeneration: public DefNewGeneration {
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;

View File

@ -119,7 +119,7 @@ void CollectionSetChooser::verify() {
}
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

View File

@ -92,7 +92,7 @@ public:
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;

View File

@ -307,7 +307,7 @@ void CMMarkStack::expand() {
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 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev
_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 @@ void ConcurrentMark::set_concurrency_and_phase(uint active_tasks, bool concurren
// 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 @@ public:
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 @@ class FinalCountDataUpdateClosure: public CMCountDataClosureBase {
}
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 @@ class G1CMKeepAliveAndDrainClosure: public OopClosure {
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 @@ ConcurrentMark::claim_region(uint worker_id) {
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 @@ ConcurrentMark::claim_region(uint worker_id) {
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 @@ ConcurrentMark::claim_region(uint worker_id) {
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 @@ ConcurrentMark::claim_region(uint worker_id) {
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 @@ private:
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 @@ void ConcurrentMark::verify_no_cset_oops() {
// 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 @@ void ConcurrentMark::verify_no_cset_oops() {
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 @@ class AggregateCountDataHRClosure: public HeapRegionClosure {
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 @@ bool ConcurrentMark::do_yield_check(uint worker_id) {
#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 @@ void CMTask::setup_for_region(HeapRegion* hr) {
"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 @@ void CMTask::update_region_limit() {
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::update_region_limit() {
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 @@ void CMTask::regular_clock_call() {
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 @@ void CMTask::drain_local_queue(bool partially) {
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 @@ void CMTask::do_marking_step(double time_target_ms,
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 @@ void CMTask::do_marking_step(double time_target_ms,
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 @@ void CMTask::do_marking_step(double time_target_ms,
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 @@ CMTask::CMTask(uint worker_id,
// 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 @@ CMTask::CMTask(uint worker_id,
// 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)

View File

@ -197,8 +197,8 @@ inline bool CMBitMapRO::iterate(BitMapClosure* cl) {
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::make_reference_grey(oop obj, HeapRegion* hr) {
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 @@ inline void ConcurrentMark::grayRoot(oop obj, size_t word_size,
// 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)));

View File

@ -44,8 +44,7 @@ SurrogateLockerThread*
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 @@ void ConcurrentMarkThread::sleepBeforeNextCycle() {
if (started()) {
set_in_progress();
clear_started();
}
}

View File

@ -47,8 +47,14 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
private:
ConcurrentMark* _cm;
volatile bool _started;
volatile bool _in_progress;
enum State {
Idle,
Started,
InProgress
};
volatile State _state;
void sleepBeforeNextCycle();
@ -68,23 +74,22 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
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();

View File

@ -140,7 +140,7 @@ HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size,
}
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 @@ void G1AllocRegion::trace(const char* str, size_t word_size, HeapWord* result) {
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);

View File

@ -86,7 +86,7 @@ void G1DefaultAllocator::init_gc_alloc_regions(EvacuationInfo& evacuation_info)
&_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 @@ void G1DefaultAllocator::release_gc_alloc_regions(uint no_of_gc_workers, Evacuat
}
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();
}
}

View File

@ -53,7 +53,7 @@ public:
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 @@ public:
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 @@ public:
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) {

View File

@ -36,19 +36,19 @@ address G1BiasedMappedArrayBase::create_new_base_array(size_t length, size_t ele
#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<int> {

View File

@ -71,10 +71,10 @@ protected:
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;

Some files were not shown because too many files have changed in this diff Show More