Merge
This commit is contained in:
commit
9b1474b512
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 $@ $<
|
||||
|
@ -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 $@
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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()));
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()));
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
63
hotspot/src/os/bsd/vm/semaphore_bsd.hpp
Normal file
63
hotspot/src/os/bsd/vm/semaphore_bsd.hpp
Normal 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
|
@ -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
|
||||
|
@ -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__
|
||||
|
61
hotspot/src/os/posix/vm/semaphore_posix.hpp
Normal file
61
hotspot/src/os/posix/vm/semaphore_posix.hpp
Normal 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
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
50
hotspot/src/os/windows/vm/semaphore_windows.hpp
Normal file
50
hotspot/src/os/windows/vm/semaphore_windows.hpp
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
121
hotspot/src/share/vm/classfile/imageDecompressor.cpp
Normal file
121
hotspot/src/share/vm/classfile/imageDecompressor.cpp
Normal 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
|
137
hotspot/src/share/vm/classfile/imageDecompressor.hpp
Normal file
137
hotspot/src/share/vm/classfile/imageDecompressor.hpp
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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;
|
||||
|
52
hotspot/src/share/vm/code/codeCacheExtensions.hpp
Normal file
52
hotspot/src/share/vm/code/codeCacheExtensions.hpp
Normal 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
|
130
hotspot/src/share/vm/code/codeCacheExtensions_ext.hpp
Normal file
130
hotspot/src/share/vm/code/codeCacheExtensions_ext.hpp
Normal 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
|
@ -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("}");
|
||||
}
|
||||
|
||||
|
@ -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 ");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)));
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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;
|
||||
|
@ -69,10 +69,10 @@ bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
|
||||
#ifdef ASSERT
|
||||
void G1BlockOffsetSharedArray::check_index(size_t index, const char* msg) const {
|
||||
assert((index) < (_reserved.word_size() >> LogN_words),
|
||||
err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT,
|
||||
err_msg("%s - index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT,
|
||||
msg, (index), (_reserved.word_size() >> LogN_words)));
|
||||
assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),
|
||||
err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT
|
||||
err_msg("Index " SIZE_FORMAT " corresponding to " PTR_FORMAT
|
||||
" (%u) is not in committed area.",
|
||||
(index),
|
||||
p2i(address_for_index_raw(index)),
|
||||
@ -430,11 +430,11 @@ void
|
||||
G1BlockOffsetArray::print_on(outputStream* out) {
|
||||
size_t from_index = _array->index_for(_bottom);
|
||||
size_t to_index = _array->index_for(_end);
|
||||
out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
|
||||
"cards ["SIZE_FORMAT","SIZE_FORMAT")",
|
||||
out->print_cr(">> BOT for area [" PTR_FORMAT "," PTR_FORMAT ") "
|
||||
"cards [" SIZE_FORMAT "," SIZE_FORMAT ")",
|
||||
p2i(_bottom), p2i(_end), from_index, to_index);
|
||||
for (size_t i = from_index; i < to_index; ++i) {
|
||||
out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
|
||||
out->print_cr(" entry " SIZE_FORMAT_W(8) " | " PTR_FORMAT " : %3u",
|
||||
i, p2i(_array->address_for_index(i)),
|
||||
(uint) _array->offset_array(i));
|
||||
}
|
||||
@ -514,7 +514,7 @@ G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
|
||||
void
|
||||
G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
|
||||
G1BlockOffsetArray::print_on(out);
|
||||
out->print_cr(" next offset threshold: "PTR_FORMAT, p2i(_next_offset_threshold));
|
||||
out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index);
|
||||
out->print_cr(" next offset threshold: " PTR_FORMAT, p2i(_next_offset_threshold));
|
||||
out->print_cr(" next offset index: " SIZE_FORMAT, _next_offset_index);
|
||||
}
|
||||
#endif // !PRODUCT
|
||||
|
@ -150,7 +150,7 @@ private:
|
||||
void check_offset(size_t offset, const char* msg) const {
|
||||
assert(offset <= N_words,
|
||||
err_msg("%s - "
|
||||
"offset: " SIZE_FORMAT", N_words: %u",
|
||||
"offset: " SIZE_FORMAT ", N_words: %u",
|
||||
msg, offset, (uint)N_words));
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ size_t G1CardCounts::heap_map_factor() {
|
||||
void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) {
|
||||
if (has_count_table()) {
|
||||
assert(from_card_num < to_card_num,
|
||||
err_msg("Wrong order? from: " SIZE_FORMAT ", to: "SIZE_FORMAT,
|
||||
err_msg("Wrong order? from: " SIZE_FORMAT ", to: " SIZE_FORMAT,
|
||||
from_card_num, to_card_num));
|
||||
Copy::fill_to_bytes(&_card_counts[from_card_num], (to_card_num - from_card_num));
|
||||
}
|
||||
@ -96,7 +96,7 @@ uint G1CardCounts::add_card_count(jbyte* card_ptr) {
|
||||
if (has_count_table()) {
|
||||
size_t card_num = ptr_2_card_num(card_ptr);
|
||||
assert(card_num < _reserved_max_card_num,
|
||||
err_msg("Card "SIZE_FORMAT" outside of card counts table (max size "SIZE_FORMAT")",
|
||||
err_msg("Card " SIZE_FORMAT " outside of card counts table (max size " SIZE_FORMAT ")",
|
||||
card_num, _reserved_max_card_num));
|
||||
count = (uint) _card_counts[card_num];
|
||||
if (count < G1ConcRSHotCardLimit) {
|
||||
|
@ -91,7 +91,7 @@ class G1CardCounts: public CHeapObj<mtGC> {
|
||||
|
||||
jbyte* card_num_2_ptr(size_t card_num) {
|
||||
assert(card_num < _reserved_max_card_num,
|
||||
err_msg("card num out of range: "SIZE_FORMAT, card_num));
|
||||
err_msg("card num out of range: " SIZE_FORMAT, card_num));
|
||||
return (jbyte*) (_ct_bot + card_num);
|
||||
}
|
||||
|
||||
|
@ -350,11 +350,11 @@ class G1CodeRootSetTest {
|
||||
assert(set1.is_empty(), "Code root set must be initially empty but is not.");
|
||||
|
||||
assert(G1CodeRootSet::static_mem_size() == sizeof(void*),
|
||||
err_msg("The code root set's static memory usage is incorrect, "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
|
||||
err_msg("The code root set's static memory usage is incorrect, " SIZE_FORMAT " bytes", G1CodeRootSet::static_mem_size()));
|
||||
|
||||
set1.add((nmethod*)1);
|
||||
assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
|
||||
SIZE_FORMAT" elements", set1.length()));
|
||||
SIZE_FORMAT " elements", set1.length()));
|
||||
|
||||
const size_t num_to_add = (size_t)G1CodeRootSet::Threshold + 1;
|
||||
|
||||
@ -363,14 +363,14 @@ class G1CodeRootSetTest {
|
||||
}
|
||||
assert(set1.length() == 1,
|
||||
err_msg("Duplicate detection should not have increased the set size but "
|
||||
"is "SIZE_FORMAT, set1.length()));
|
||||
"is " SIZE_FORMAT, set1.length()));
|
||||
|
||||
for (size_t i = 2; i <= num_to_add; i++) {
|
||||
set1.add((nmethod*)(uintptr_t)(i));
|
||||
}
|
||||
assert(set1.length() == num_to_add,
|
||||
err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
|
||||
"need to be in the set, but there are only "SIZE_FORMAT,
|
||||
err_msg("After adding in total " SIZE_FORMAT " distinct code roots, they "
|
||||
"need to be in the set, but there are only " SIZE_FORMAT,
|
||||
num_to_add, set1.length()));
|
||||
|
||||
assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
|
||||
@ -385,7 +385,7 @@ class G1CodeRootSetTest {
|
||||
}
|
||||
}
|
||||
assert(num_popped == num_to_add,
|
||||
err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
|
||||
err_msg("Managed to pop " SIZE_FORMAT " code roots, but only " SIZE_FORMAT " "
|
||||
"were added", num_popped, num_to_add));
|
||||
assert(CodeRootSetTable::_purge_list != NULL, "should have grown to large hashtable");
|
||||
|
||||
|
@ -197,7 +197,7 @@ bool YoungList::check_list_well_formed() {
|
||||
HeapRegion* last = NULL;
|
||||
while (curr != NULL) {
|
||||
if (!curr->is_young()) {
|
||||
gclog_or_tty->print_cr("### YOUNG REGION "PTR_FORMAT"-"PTR_FORMAT" "
|
||||
gclog_or_tty->print_cr("### YOUNG REGION " PTR_FORMAT "-" PTR_FORMAT " "
|
||||
"incorrectly tagged (y: %d, surv: %d)",
|
||||
p2i(curr->bottom()), p2i(curr->end()),
|
||||
curr->is_young(), curr->is_survivor());
|
||||
@ -326,7 +326,7 @@ void YoungList::print() {
|
||||
if (curr == NULL)
|
||||
gclog_or_tty->print_cr(" empty");
|
||||
while (curr != NULL) {
|
||||
gclog_or_tty->print_cr(" "HR_FORMAT", P: "PTR_FORMAT ", N: "PTR_FORMAT", age: %4d",
|
||||
gclog_or_tty->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT ", N: " PTR_FORMAT ", age: %4d",
|
||||
HR_FORMAT_PARAMS(curr),
|
||||
p2i(curr->prev_top_at_mark_start()),
|
||||
p2i(curr->next_top_at_mark_start()),
|
||||
@ -430,7 +430,7 @@ G1CollectedHeap::new_region_try_secondary_free_list(bool is_old) {
|
||||
HeapRegion* res = _hrm.allocate_free_region(is_old);
|
||||
if (G1ConcRegionFreeingVerbose) {
|
||||
gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
|
||||
"allocated "HR_FORMAT" from secondary_free_list",
|
||||
"allocated " HR_FORMAT " from secondary_free_list",
|
||||
HR_FORMAT_PARAMS(res));
|
||||
}
|
||||
return res;
|
||||
@ -1670,8 +1670,8 @@ resize_if_necessary_after_full_collection(size_t word_size) {
|
||||
// This assert only makes sense here, before we adjust them
|
||||
// with respect to the min and max heap size.
|
||||
assert(minimum_desired_capacity <= maximum_desired_capacity,
|
||||
err_msg("minimum_desired_capacity = "SIZE_FORMAT", "
|
||||
"maximum_desired_capacity = "SIZE_FORMAT,
|
||||
err_msg("minimum_desired_capacity = " SIZE_FORMAT ", "
|
||||
"maximum_desired_capacity = " SIZE_FORMAT,
|
||||
minimum_desired_capacity, maximum_desired_capacity));
|
||||
|
||||
// Should not be greater than the heap max size. No need to adjust
|
||||
@ -2332,7 +2332,7 @@ public:
|
||||
virtual bool doHeapRegion(HeapRegion* hr) {
|
||||
unsigned region_gc_time_stamp = hr->get_gc_time_stamp();
|
||||
if (_gc_time_stamp != region_gc_time_stamp) {
|
||||
gclog_or_tty->print_cr("Region "HR_FORMAT" has GC time stamp = %d, "
|
||||
gclog_or_tty->print_cr("Region " HR_FORMAT " has GC time stamp = %d, "
|
||||
"expected %d", HR_FORMAT_PARAMS(hr),
|
||||
region_gc_time_stamp, _gc_time_stamp);
|
||||
_failures = true;
|
||||
@ -2487,7 +2487,7 @@ void G1CollectedHeap::increment_old_marking_cycles_completed(bool concurrent) {
|
||||
// is set) so that if a waiter requests another System.gc() it doesn't
|
||||
// incorrectly see that a marking cycle is still in progress.
|
||||
if (concurrent) {
|
||||
_cmThread->clear_in_progress();
|
||||
_cmThread->set_idle();
|
||||
}
|
||||
|
||||
// This notify_all() will ensure that a thread that called
|
||||
@ -2926,10 +2926,10 @@ public:
|
||||
if (!oopDesc::is_null(heap_oop)) {
|
||||
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
||||
if (_g1h->is_obj_dead_cond(obj, _vo)) {
|
||||
gclog_or_tty->print_cr("Root location "PTR_FORMAT" "
|
||||
"points to dead obj "PTR_FORMAT, p2i(p), p2i(obj));
|
||||
gclog_or_tty->print_cr("Root location " PTR_FORMAT " "
|
||||
"points to dead obj " PTR_FORMAT, p2i(p), p2i(obj));
|
||||
if (_vo == VerifyOption_G1UseMarkWord) {
|
||||
gclog_or_tty->print_cr(" Mark word: "INTPTR_FORMAT, (intptr_t)obj->mark());
|
||||
gclog_or_tty->print_cr(" Mark word: " INTPTR_FORMAT, (intptr_t)obj->mark());
|
||||
}
|
||||
obj->print_on(gclog_or_tty);
|
||||
_failures = true;
|
||||
@ -2976,9 +2976,9 @@ class G1VerifyCodeRootOopClosure: public OopClosure {
|
||||
// Verify that the strong code root list for this region
|
||||
// contains the nmethod
|
||||
if (!hrrs->strong_code_roots_list_contains(_nm)) {
|
||||
gclog_or_tty->print_cr("Code root location "PTR_FORMAT" "
|
||||
"from nmethod "PTR_FORMAT" not in strong "
|
||||
"code roots for region ["PTR_FORMAT","PTR_FORMAT")",
|
||||
gclog_or_tty->print_cr("Code root location " PTR_FORMAT " "
|
||||
"from nmethod " PTR_FORMAT " not in strong "
|
||||
"code roots for region [" PTR_FORMAT "," PTR_FORMAT ")",
|
||||
p2i(p), p2i(_nm), p2i(hr->bottom()), p2i(hr->end()));
|
||||
_failures = true;
|
||||
}
|
||||
@ -3157,9 +3157,9 @@ public:
|
||||
r->object_iterate(¬_dead_yet_cl);
|
||||
if (_vo != VerifyOption_G1UseNextMarking) {
|
||||
if (r->max_live_bytes() < not_dead_yet_cl.live_bytes()) {
|
||||
gclog_or_tty->print_cr("["PTR_FORMAT","PTR_FORMAT"] "
|
||||
"max_live_bytes "SIZE_FORMAT" "
|
||||
"< calculated "SIZE_FORMAT,
|
||||
gclog_or_tty->print_cr("[" PTR_FORMAT "," PTR_FORMAT "] "
|
||||
"max_live_bytes " SIZE_FORMAT " "
|
||||
"< calculated " SIZE_FORMAT,
|
||||
p2i(r->bottom()), p2i(r->end()),
|
||||
r->max_live_bytes(),
|
||||
not_dead_yet_cl.live_bytes());
|
||||
@ -3444,7 +3444,7 @@ public:
|
||||
size_t occupied = hrrs->occupied();
|
||||
_occupied_sum += occupied;
|
||||
|
||||
gclog_or_tty->print_cr("Printing RSet for region "HR_FORMAT,
|
||||
gclog_or_tty->print_cr("Printing RSet for region " HR_FORMAT,
|
||||
HR_FORMAT_PARAMS(r));
|
||||
if (occupied == 0) {
|
||||
gclog_or_tty->print_cr(" RSet is empty");
|
||||
@ -3463,7 +3463,7 @@ public:
|
||||
}
|
||||
|
||||
~PrintRSetsClosure() {
|
||||
gclog_or_tty->print_cr("Occupied Sum: "SIZE_FORMAT, _occupied_sum);
|
||||
gclog_or_tty->print_cr("Occupied Sum: " SIZE_FORMAT, _occupied_sum);
|
||||
gclog_or_tty->print_cr("========================================");
|
||||
gclog_or_tty->cr();
|
||||
}
|
||||
@ -4308,7 +4308,7 @@ oop
|
||||
G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_state,
|
||||
oop old) {
|
||||
assert(obj_in_cs(old),
|
||||
err_msg("obj: "PTR_FORMAT" should still be in the CSet",
|
||||
err_msg("obj: " PTR_FORMAT " should still be in the CSet",
|
||||
p2i(old)));
|
||||
markOop m = old->mark();
|
||||
oop forward_ptr = old->forward_to_atomic(old);
|
||||
@ -4342,7 +4342,7 @@ G1CollectedHeap::handle_evacuation_failure_par(G1ParScanThreadState* _par_scan_s
|
||||
// space for this object (old != forward_ptr) or they beat us in
|
||||
// self-forwarding it (old == forward_ptr).
|
||||
assert(old == forward_ptr || !obj_in_cs(forward_ptr),
|
||||
err_msg("obj: "PTR_FORMAT" forwarded to: "PTR_FORMAT" "
|
||||
err_msg("obj: " PTR_FORMAT " forwarded to: " PTR_FORMAT " "
|
||||
"should not be in the CSet",
|
||||
p2i(old), p2i(forward_ptr)));
|
||||
return forward_ptr;
|
||||
@ -4730,8 +4730,8 @@ public:
|
||||
|
||||
if (G1TraceStringSymbolTableScrubbing) {
|
||||
gclog_or_tty->print_cr("Cleaned string and symbol table, "
|
||||
"strings: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed, "
|
||||
"symbols: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed",
|
||||
"strings: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed, "
|
||||
"symbols: " SIZE_FORMAT " processed, " SIZE_FORMAT " removed",
|
||||
strings_processed(), strings_removed(),
|
||||
symbols_processed(), symbols_removed());
|
||||
}
|
||||
@ -5828,13 +5828,13 @@ void G1CollectedHeap::verify_dirty_young_regions() {
|
||||
bool G1CollectedHeap::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap,
|
||||
HeapWord* tams, HeapWord* end) {
|
||||
guarantee(tams <= end,
|
||||
err_msg("tams: "PTR_FORMAT" end: "PTR_FORMAT, p2i(tams), p2i(end)));
|
||||
err_msg("tams: " PTR_FORMAT " end: " PTR_FORMAT, p2i(tams), p2i(end)));
|
||||
HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end);
|
||||
if (result < end) {
|
||||
gclog_or_tty->cr();
|
||||
gclog_or_tty->print_cr("## wrong marked address on %s bitmap: "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("## wrong marked address on %s bitmap: " PTR_FORMAT,
|
||||
bitmap_name, p2i(result));
|
||||
gclog_or_tty->print_cr("## %s tams: "PTR_FORMAT" end: "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("## %s tams: " PTR_FORMAT " end: " PTR_FORMAT,
|
||||
bitmap_name, p2i(tams), p2i(end));
|
||||
return false;
|
||||
}
|
||||
@ -5860,7 +5860,7 @@ bool G1CollectedHeap::verify_bitmaps(const char* caller, HeapRegion* hr) {
|
||||
res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end);
|
||||
}
|
||||
if (!res_p || !res_n) {
|
||||
gclog_or_tty->print_cr("#### Bitmap verification failed for "HR_FORMAT,
|
||||
gclog_or_tty->print_cr("#### Bitmap verification failed for " HR_FORMAT,
|
||||
HR_FORMAT_PARAMS(hr));
|
||||
gclog_or_tty->print_cr("#### Caller: %s", caller);
|
||||
return false;
|
||||
@ -6157,7 +6157,7 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
|
||||
!r->rem_set()->is_empty()) {
|
||||
|
||||
if (G1TraceEagerReclaimHumongousObjects) {
|
||||
gclog_or_tty->print_cr("Live humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length %u with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d reclaim candidate %d type array %d",
|
||||
gclog_or_tty->print_cr("Live humongous region %u size " SIZE_FORMAT " start " PTR_FORMAT " length %u with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d",
|
||||
region_idx,
|
||||
(size_t)obj->size() * HeapWordSize,
|
||||
p2i(r->bottom()),
|
||||
@ -6179,7 +6179,7 @@ class G1FreeHumongousRegionClosure : public HeapRegionClosure {
|
||||
p2i(r->bottom())));
|
||||
|
||||
if (G1TraceEagerReclaimHumongousObjects) {
|
||||
gclog_or_tty->print_cr("Dead humongous region %u size "SIZE_FORMAT" start "PTR_FORMAT" length %u with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d reclaim candidate %d type array %d",
|
||||
gclog_or_tty->print_cr("Dead humongous region %u size " SIZE_FORMAT " start " PTR_FORMAT " length %u with remset " SIZE_FORMAT " code roots " SIZE_FORMAT " is marked %d reclaim candidate %d type array %d",
|
||||
region_idx,
|
||||
(size_t)obj->size() * HeapWordSize,
|
||||
p2i(r->bottom()),
|
||||
@ -6333,7 +6333,7 @@ public:
|
||||
NoYoungRegionsClosure() : _success(true) { }
|
||||
bool doHeapRegion(HeapRegion* r) {
|
||||
if (r->is_young()) {
|
||||
gclog_or_tty->print_cr("Region ["PTR_FORMAT", "PTR_FORMAT") tagged as young",
|
||||
gclog_or_tty->print_cr("Region [" PTR_FORMAT ", " PTR_FORMAT ") tagged as young",
|
||||
p2i(r->bottom()), p2i(r->end()));
|
||||
_success = false;
|
||||
}
|
||||
@ -6470,7 +6470,7 @@ void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
|
||||
}
|
||||
assert(_allocator->used_unlocked() == recalculate_used(),
|
||||
err_msg("inconsistent _allocator->used_unlocked(), "
|
||||
"value: "SIZE_FORMAT" recalculated: "SIZE_FORMAT,
|
||||
"value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT,
|
||||
_allocator->used_unlocked(), recalculate_used()));
|
||||
}
|
||||
|
||||
@ -6697,8 +6697,8 @@ class RegisterNMethodOopClosure: public OopClosure {
|
||||
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
||||
HeapRegion* hr = _g1h->heap_region_containing(obj);
|
||||
assert(!hr->is_continues_humongous(),
|
||||
err_msg("trying to add code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
|
||||
" starting at "HR_FORMAT,
|
||||
err_msg("trying to add code root " PTR_FORMAT " in continuation of humongous region " HR_FORMAT
|
||||
" starting at " HR_FORMAT,
|
||||
p2i(_nm), HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
|
||||
|
||||
// HeapRegion::add_strong_code_root_locked() avoids adding duplicate entries.
|
||||
@ -6724,8 +6724,8 @@ class UnregisterNMethodOopClosure: public OopClosure {
|
||||
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
|
||||
HeapRegion* hr = _g1h->heap_region_containing(obj);
|
||||
assert(!hr->is_continues_humongous(),
|
||||
err_msg("trying to remove code root "PTR_FORMAT" in continuation of humongous region "HR_FORMAT
|
||||
" starting at "HR_FORMAT,
|
||||
err_msg("trying to remove code root " PTR_FORMAT " in continuation of humongous region " HR_FORMAT
|
||||
" starting at " HR_FORMAT,
|
||||
p2i(_nm), HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region())));
|
||||
|
||||
hr->remove_strong_code_root(_nm);
|
||||
|
@ -1109,6 +1109,8 @@ public:
|
||||
// The STW reference processor....
|
||||
ReferenceProcessor* ref_processor_stw() const { return _ref_processor_stw; }
|
||||
|
||||
G1NewTracer* gc_tracer_stw() const { return _gc_tracer_stw; }
|
||||
|
||||
// The Concurrent Marking reference processor...
|
||||
ReferenceProcessor* ref_processor_cm() const { return _ref_processor_cm; }
|
||||
|
||||
|
@ -82,7 +82,7 @@ inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrm.at
|
||||
|
||||
inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const {
|
||||
assert(is_in_reserved(addr),
|
||||
err_msg("Cannot calculate region index for address "PTR_FORMAT" that is outside of the heap ["PTR_FORMAT", "PTR_FORMAT")",
|
||||
err_msg("Cannot calculate region index for address " PTR_FORMAT " that is outside of the heap [" PTR_FORMAT ", " PTR_FORMAT ")",
|
||||
p2i(addr), p2i(reserved_region().start()), p2i(reserved_region().end())));
|
||||
return (uint)(pointer_delta(addr, reserved_region().start(), sizeof(uint8_t)) >> HeapRegion::LogOfHRGrainBytes);
|
||||
}
|
||||
@ -95,7 +95,7 @@ template <class T>
|
||||
inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const {
|
||||
assert(addr != NULL, "invariant");
|
||||
assert(is_in_g1_reserved((const void*) addr),
|
||||
err_msg("Address "PTR_FORMAT" is outside of the heap ranging from ["PTR_FORMAT" to "PTR_FORMAT")",
|
||||
err_msg("Address " PTR_FORMAT " is outside of the heap ranging from [" PTR_FORMAT " to " PTR_FORMAT ")",
|
||||
p2i((void*)addr), p2i(g1_reserved().start()), p2i(g1_reserved().end())));
|
||||
return _hrm.addr_to_region((HeapWord*) addr);
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
||||
const size_t region_size = HeapRegion::GrainWords;
|
||||
if (YoungPLABSize > region_size || OldPLABSize > region_size) {
|
||||
char buffer[128];
|
||||
jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most "SIZE_FORMAT,
|
||||
jio_snprintf(buffer, sizeof(buffer), "%sPLABSize should be at most " SIZE_FORMAT,
|
||||
OldPLABSize > region_size ? "Old" : "Young", region_size);
|
||||
vm_exit_during_initialization(buffer);
|
||||
}
|
||||
@ -821,7 +821,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) {
|
||||
update_survivors_policy();
|
||||
|
||||
assert(_g1->used() == _g1->recalculate_used(),
|
||||
err_msg("sanity, used: "SIZE_FORMAT" recalculate_used: "SIZE_FORMAT,
|
||||
err_msg("sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT,
|
||||
_g1->used(), _g1->recalculate_used()));
|
||||
|
||||
double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0;
|
||||
@ -865,7 +865,7 @@ void G1CollectorPolicy::record_concurrent_mark_remark_end() {
|
||||
_cur_mark_stop_world_time_ms += elapsed_time_ms;
|
||||
_prev_collection_pause_end_ms += elapsed_time_ms;
|
||||
|
||||
_mmu_tracker->add_pause(_mark_remark_start_sec, end_time_sec, true);
|
||||
_mmu_tracker->add_pause(_mark_remark_start_sec, end_time_sec, _g1->gc_tracer_cm()->gc_id());
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::record_concurrent_mark_cleanup_start() {
|
||||
@ -961,7 +961,7 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, Evacua
|
||||
}
|
||||
|
||||
_mmu_tracker->add_pause(end_time_sec - pause_time_ms/1000.0,
|
||||
end_time_sec, false);
|
||||
end_time_sec, _g1->gc_tracer_stw()->gc_id());
|
||||
|
||||
evacuation_info.set_collectionset_used_before(_collection_set_bytes_used_before);
|
||||
evacuation_info.set_bytes_copied(_bytes_copied_during_gc);
|
||||
@ -1216,10 +1216,10 @@ void G1CollectorPolicy::print_detailed_heap_transition(bool full) {
|
||||
(_young_list_target_length * HeapRegion::GrainBytes) - survivor_used_bytes_after_gc;
|
||||
|
||||
gclog_or_tty->print(
|
||||
" [Eden: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT") "
|
||||
"Survivors: "EXT_SIZE_FORMAT"->"EXT_SIZE_FORMAT" "
|
||||
"Heap: "EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")->"
|
||||
EXT_SIZE_FORMAT"("EXT_SIZE_FORMAT")]",
|
||||
" [Eden: " EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ")->" EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ") "
|
||||
"Survivors: " EXT_SIZE_FORMAT "->" EXT_SIZE_FORMAT " "
|
||||
"Heap: " EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ")->"
|
||||
EXT_SIZE_FORMAT "(" EXT_SIZE_FORMAT ")]",
|
||||
EXT_SIZE_PARAMS(_eden_used_bytes_before_gc),
|
||||
EXT_SIZE_PARAMS(_eden_capacity_bytes_before_gc),
|
||||
EXT_SIZE_PARAMS(eden_used_bytes_after_gc),
|
||||
@ -1597,7 +1597,7 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end() {
|
||||
_concurrent_mark_cleanup_times_ms->add(elapsed_time_ms);
|
||||
_cur_mark_stop_world_time_ms += elapsed_time_ms;
|
||||
_prev_collection_pause_end_ms += elapsed_time_ms;
|
||||
_mmu_tracker->add_pause(_mark_cleanup_start_sec, end_sec, true);
|
||||
_mmu_tracker->add_pause(_mark_cleanup_start_sec, end_sec, _g1->gc_tracer_cm()->gc_id());
|
||||
}
|
||||
|
||||
// Add the heap region at the head of the non-incremental collection set
|
||||
@ -1787,7 +1787,7 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream
|
||||
while (csr != NULL) {
|
||||
HeapRegion* next = csr->next_in_collection_set();
|
||||
assert(csr->in_collection_set(), "bad CS");
|
||||
st->print_cr(" "HR_FORMAT", P: "PTR_FORMAT "N: "PTR_FORMAT", age: %4d",
|
||||
st->print_cr(" " HR_FORMAT ", P: " PTR_FORMAT "N: " PTR_FORMAT ", age: %4d",
|
||||
HR_FORMAT_PARAMS(csr),
|
||||
p2i(csr->prev_top_at_mark_start()), p2i(csr->next_top_at_mark_start()),
|
||||
csr->age_in_surv_rate_group_cond());
|
||||
|
@ -121,15 +121,15 @@ public:
|
||||
// Single parameter format strings
|
||||
#define ergo_format_str(_name_) ", " _name_ ": %s"
|
||||
#define ergo_format_region(_name_) ", " _name_ ": %u regions"
|
||||
#define ergo_format_byte(_name_) ", " _name_ ": "SIZE_FORMAT" bytes"
|
||||
#define ergo_format_byte(_name_) ", " _name_ ": " SIZE_FORMAT " bytes"
|
||||
#define ergo_format_double(_name_) ", " _name_ ": %1.2f"
|
||||
#define ergo_format_perc(_name_) ", " _name_ ": %1.2f %%"
|
||||
#define ergo_format_ms(_name_) ", " _name_ ": %1.2f ms"
|
||||
#define ergo_format_size(_name_) ", " _name_ ": "SIZE_FORMAT
|
||||
#define ergo_format_size(_name_) ", " _name_ ": " SIZE_FORMAT
|
||||
|
||||
// Double parameter format strings
|
||||
#define ergo_format_byte_perc(_name_) \
|
||||
", " _name_ ": "SIZE_FORMAT" bytes (%1.2f %%)"
|
||||
", " _name_ ": " SIZE_FORMAT " bytes (%1.2f %%)"
|
||||
|
||||
// Generates the format string
|
||||
#define ergo_format(_extra_format_) \
|
||||
|
@ -331,7 +331,7 @@ void G1GCPhaseTimes::print_stats(int level, const char* str, double value) {
|
||||
}
|
||||
|
||||
void G1GCPhaseTimes::print_stats(int level, const char* str, size_t value) {
|
||||
LineBuffer(level).append_and_print_cr("[%s: "SIZE_FORMAT"]", str, value);
|
||||
LineBuffer(level).append_and_print_cr("[%s: " SIZE_FORMAT "]", str, value);
|
||||
}
|
||||
|
||||
void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) {
|
||||
@ -451,7 +451,7 @@ class G1GCParPhasePrinter : public StackObj {
|
||||
|
||||
if (phase->_thread_work_items != NULL) {
|
||||
LineBuffer buf2(phase->_thread_work_items->_indent_level);
|
||||
buf2.append_and_print_cr("[%s: "SIZE_FORMAT"]", phase->_thread_work_items->_title, _phase_times->sum_thread_work_items(phase_id));
|
||||
buf2.append_and_print_cr("[%s: " SIZE_FORMAT "]", phase->_thread_work_items->_title, _phase_times->sum_thread_work_items(phase_id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,18 +83,18 @@ void G1HRPrinter::print(ActionType action, RegionType type,
|
||||
|
||||
if (type_str != NULL) {
|
||||
if (top != NULL) {
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX" %s(%s) "PTR_FORMAT" "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX " %s(%s) " PTR_FORMAT " " PTR_FORMAT,
|
||||
action_str, type_str, p2i(bottom), p2i(top));
|
||||
} else {
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX" %s(%s) "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX " %s(%s) " PTR_FORMAT,
|
||||
action_str, type_str, p2i(bottom));
|
||||
}
|
||||
} else {
|
||||
if (top != NULL) {
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX" %s "PTR_FORMAT" "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX " %s " PTR_FORMAT " " PTR_FORMAT,
|
||||
action_str, p2i(bottom), p2i(top));
|
||||
} else {
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX" %s "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX " %s " PTR_FORMAT,
|
||||
action_str, p2i(bottom));
|
||||
}
|
||||
}
|
||||
@ -103,11 +103,11 @@ void G1HRPrinter::print(ActionType action, RegionType type,
|
||||
void G1HRPrinter::print(ActionType action, HeapWord* bottom, HeapWord* end) {
|
||||
const char* action_str = action_name(action);
|
||||
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX" %s ["PTR_FORMAT","PTR_FORMAT"]",
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX " %s [" PTR_FORMAT "," PTR_FORMAT "]",
|
||||
action_str, p2i(bottom), p2i(end));
|
||||
}
|
||||
|
||||
void G1HRPrinter::print(PhaseType phase, size_t phase_num) {
|
||||
const char* phase_str = phase_name(phase);
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX" #%s "SIZE_FORMAT, phase_str, phase_num);
|
||||
gclog_or_tty->print_cr(G1HR_PREFIX " #%s " SIZE_FORMAT, phase_str, phase_num);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArray<InCSet
|
||||
public:
|
||||
void set_humongous(uintptr_t index) {
|
||||
assert(get_by_index(index).is_default(),
|
||||
err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
|
||||
err_msg("State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
|
||||
set_by_index(index, InCSetState::Humongous);
|
||||
}
|
||||
|
||||
@ -114,13 +114,13 @@ class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArray<InCSet
|
||||
|
||||
void set_in_young(uintptr_t index) {
|
||||
assert(get_by_index(index).is_default(),
|
||||
err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
|
||||
err_msg("State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
|
||||
set_by_index(index, InCSetState::Young);
|
||||
}
|
||||
|
||||
void set_in_old(uintptr_t index) {
|
||||
assert(get_by_index(index).is_default(),
|
||||
err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
|
||||
err_msg("State at index " INTPTR_FORMAT " should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value()));
|
||||
set_by_index(index, InCSetState::Old);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1MMUTracker.hpp"
|
||||
#include "gc/shared/gcTrace.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
@ -75,7 +76,7 @@ double G1MMUTrackerQueue::calculate_gc_time(double current_time) {
|
||||
return gc_time;
|
||||
}
|
||||
|
||||
void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
|
||||
void G1MMUTrackerQueue::add_pause(double start, double end, const GCId& gcId) {
|
||||
double duration = end - start;
|
||||
|
||||
remove_expired_entries(end);
|
||||
@ -102,6 +103,10 @@ void G1MMUTrackerQueue::add_pause(double start, double end, bool gc_thread) {
|
||||
++_no_entries;
|
||||
}
|
||||
_array[_head_index] = G1MMUTrackerQueueElem(start, end);
|
||||
|
||||
// Current entry needs to be added before calculating the value
|
||||
double slice_time = calculate_gc_time(end);
|
||||
G1MMUTracer::report_mmu(gcId, _time_slice, slice_time, _max_gc_time);
|
||||
}
|
||||
|
||||
// basically the _internal call does not remove expired entries
|
||||
|
@ -25,6 +25,7 @@
|
||||
#ifndef SHARE_VM_GC_G1_G1MMUTRACKER_HPP
|
||||
#define SHARE_VM_GC_G1_G1MMUTRACKER_HPP
|
||||
|
||||
#include "gc/shared/gcId.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
@ -42,7 +43,7 @@ protected:
|
||||
public:
|
||||
G1MMUTracker(double time_slice, double max_gc_time);
|
||||
|
||||
virtual void add_pause(double start, double end, bool gc_thread) = 0;
|
||||
virtual void add_pause(double start, double end, const GCId& gcId) = 0;
|
||||
virtual double when_sec(double current_time, double pause_time) = 0;
|
||||
|
||||
double max_gc_time() {
|
||||
@ -126,7 +127,7 @@ private:
|
||||
public:
|
||||
G1MMUTrackerQueue(double time_slice, double max_gc_time);
|
||||
|
||||
virtual void add_pause(double start, double end, bool gc_thread);
|
||||
virtual void add_pause(double start, double end, const GCId& gcId);
|
||||
|
||||
virtual double when_sec(double current_time, double pause_time);
|
||||
};
|
||||
|
@ -118,7 +118,7 @@ inline void G1CMOopClosure::do_oop_nv(T* p) {
|
||||
oop obj = oopDesc::load_decode_heap_oop(p);
|
||||
if (_cm->verbose_high()) {
|
||||
gclog_or_tty->print_cr("[%u] we're looking at location "
|
||||
"*"PTR_FORMAT" = "PTR_FORMAT,
|
||||
"*" PTR_FORMAT " = " PTR_FORMAT,
|
||||
_task->worker_id(), p2i(p), p2i((void*) obj));
|
||||
}
|
||||
_task->deal_with_reference(obj);
|
||||
|
@ -424,7 +424,7 @@ G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
|
||||
bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
|
||||
bool check_for_refs_into_cset) {
|
||||
assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
|
||||
err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap",
|
||||
err_msg("Card at " PTR_FORMAT " index " SIZE_FORMAT " representing heap at " PTR_FORMAT " (%u) must be in committed heap",
|
||||
p2i(card_ptr),
|
||||
_ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
|
||||
p2i(_ct_bs->addr_for(card_ptr)),
|
||||
|
@ -187,22 +187,22 @@ public:
|
||||
size_t code_root_elems() const { return _code_root_elems; }
|
||||
|
||||
void print_rs_mem_info_on(outputStream * out, size_t total) {
|
||||
out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) "K (%5.1f%%) by " SIZE_FORMAT " %s regions",
|
||||
round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name);
|
||||
}
|
||||
|
||||
void print_cards_occupied_info_on(outputStream * out, size_t total) {
|
||||
out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) entries by "SIZE_FORMAT" %s regions",
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) entries by " SIZE_FORMAT " %s regions",
|
||||
cards_occupied(), cards_occupied_percent_of(total), amount(), _name);
|
||||
}
|
||||
|
||||
void print_code_root_mem_info_on(outputStream * out, size_t total) {
|
||||
out->print_cr(" "SIZE_FORMAT_W(8)"K (%5.1f%%) by "SIZE_FORMAT" %s regions",
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) "K (%5.1f%%) by " SIZE_FORMAT " %s regions",
|
||||
round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name);
|
||||
}
|
||||
|
||||
void print_code_root_elems_info_on(outputStream * out, size_t total) {
|
||||
out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) elements by "SIZE_FORMAT" %s regions",
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) elements by " SIZE_FORMAT " %s regions",
|
||||
code_root_elems(), code_root_elems_percent_of(total), amount(), _name);
|
||||
}
|
||||
};
|
||||
@ -280,19 +280,19 @@ public:
|
||||
RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL };
|
||||
|
||||
out->print_cr("\n Current rem set statistics");
|
||||
out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K."
|
||||
" Max = "SIZE_FORMAT"K.",
|
||||
out->print_cr(" Total per region rem sets sizes = " SIZE_FORMAT "K."
|
||||
" Max = " SIZE_FORMAT "K.",
|
||||
round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz()));
|
||||
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
|
||||
(*current)->print_rs_mem_info_on(out, total_rs_mem_sz());
|
||||
}
|
||||
|
||||
out->print_cr(" Static structures = "SIZE_FORMAT"K,"
|
||||
" free_lists = "SIZE_FORMAT"K.",
|
||||
out->print_cr(" Static structures = " SIZE_FORMAT "K,"
|
||||
" free_lists = " SIZE_FORMAT "K.",
|
||||
round_to_K(HeapRegionRemSet::static_mem_size()),
|
||||
round_to_K(HeapRegionRemSet::fl_mem_size()));
|
||||
|
||||
out->print_cr(" "SIZE_FORMAT" occupied cards represented.",
|
||||
out->print_cr(" " SIZE_FORMAT " occupied cards represented.",
|
||||
total_cards_occupied());
|
||||
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
|
||||
(*current)->print_cards_occupied_info_on(out, total_cards_occupied());
|
||||
@ -300,30 +300,30 @@ public:
|
||||
|
||||
// Largest sized rem set region statistics
|
||||
HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set();
|
||||
out->print_cr(" Region with largest rem set = "HR_FORMAT", "
|
||||
"size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.",
|
||||
out->print_cr(" Region with largest rem set = " HR_FORMAT ", "
|
||||
"size = " SIZE_FORMAT "K, occupied = " SIZE_FORMAT "K.",
|
||||
HR_FORMAT_PARAMS(max_rs_mem_sz_region()),
|
||||
round_to_K(rem_set->mem_size()),
|
||||
round_to_K(rem_set->occupied()));
|
||||
|
||||
// Strong code root statistics
|
||||
HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set();
|
||||
out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K."
|
||||
" Max = "SIZE_FORMAT"K.",
|
||||
out->print_cr(" Total heap region code root sets sizes = " SIZE_FORMAT "K."
|
||||
" Max = " SIZE_FORMAT "K.",
|
||||
round_to_K(total_code_root_mem_sz()),
|
||||
round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()));
|
||||
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
|
||||
(*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz());
|
||||
}
|
||||
|
||||
out->print_cr(" "SIZE_FORMAT" code roots represented.",
|
||||
out->print_cr(" " SIZE_FORMAT " code roots represented.",
|
||||
total_code_root_elems());
|
||||
for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) {
|
||||
(*current)->print_code_root_elems_info_on(out, total_code_root_elems());
|
||||
}
|
||||
|
||||
out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", "
|
||||
"size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".",
|
||||
out->print_cr(" Region with largest amount of code roots = " HR_FORMAT ", "
|
||||
"size = " SIZE_FORMAT "K, num_elems = " SIZE_FORMAT ".",
|
||||
HR_FORMAT_PARAMS(max_code_root_mem_sz_region()),
|
||||
round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()),
|
||||
round_to_K(max_code_root_rem_set->strong_code_roots_list_length()));
|
||||
@ -332,16 +332,16 @@ public:
|
||||
|
||||
void G1RemSetSummary::print_on(outputStream* out) {
|
||||
out->print_cr("\n Recent concurrent refinement statistics");
|
||||
out->print_cr(" Processed "SIZE_FORMAT" cards",
|
||||
out->print_cr(" Processed " SIZE_FORMAT " cards",
|
||||
num_concurrent_refined_cards());
|
||||
out->print_cr(" Of "SIZE_FORMAT" completed buffers:", num_processed_buf_total());
|
||||
out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by concurrent RS threads.",
|
||||
out->print_cr(" Of " SIZE_FORMAT " completed buffers:", num_processed_buf_total());
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by concurrent RS threads.",
|
||||
num_processed_buf_total(),
|
||||
percent_of(num_processed_buf_rs_threads(), num_processed_buf_total()));
|
||||
out->print_cr(" "SIZE_FORMAT_W(8)" (%5.1f%%) by mutator threads.",
|
||||
out->print_cr(" " SIZE_FORMAT_W(8) " (%5.1f%%) by mutator threads.",
|
||||
num_processed_buf_mutator(),
|
||||
percent_of(num_processed_buf_mutator(), num_processed_buf_total()));
|
||||
out->print_cr(" Did "SIZE_FORMAT" coarsenings.", num_coarsenings());
|
||||
out->print_cr(" Did " SIZE_FORMAT " coarsenings.", num_coarsenings());
|
||||
out->print_cr(" Concurrent RS threads times (s)");
|
||||
out->print(" ");
|
||||
for (uint i = 0; i < _num_vtimes; i++) {
|
||||
|
@ -155,7 +155,7 @@ void G1StringDedupQueue::unlink_or_oops_do(G1StringDedupUnlinkOrOopsDoClosure* c
|
||||
void G1StringDedupQueue::print_statistics(outputStream* st) {
|
||||
st->print_cr(
|
||||
" [Queue]\n"
|
||||
" [Dropped: "UINTX_FORMAT"]", _queue->_dropped);
|
||||
" [Dropped: " UINTX_FORMAT "]", _queue->_dropped);
|
||||
}
|
||||
|
||||
void G1StringDedupQueue::verify() {
|
||||
|
@ -80,8 +80,8 @@ void G1StringDedupStat::print_summary(outputStream* st, const G1StringDedupStat&
|
||||
st->stamp(PrintGCTimeStamps);
|
||||
st->print_cr(
|
||||
"[GC concurrent-string-deduplication, "
|
||||
G1_STRDEDUP_BYTES_FORMAT_NS"->"G1_STRDEDUP_BYTES_FORMAT_NS"("G1_STRDEDUP_BYTES_FORMAT_NS"), avg "
|
||||
G1_STRDEDUP_PERCENT_FORMAT_NS", "G1_STRDEDUP_TIME_FORMAT"]",
|
||||
G1_STRDEDUP_BYTES_FORMAT_NS "->" G1_STRDEDUP_BYTES_FORMAT_NS "(" G1_STRDEDUP_BYTES_FORMAT_NS "), avg "
|
||||
G1_STRDEDUP_PERCENT_FORMAT_NS ", " G1_STRDEDUP_TIME_FORMAT "]",
|
||||
G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes),
|
||||
G1_STRDEDUP_BYTES_PARAM(last_stat._new_bytes - last_stat._deduped_bytes),
|
||||
G1_STRDEDUP_BYTES_PARAM(last_stat._deduped_bytes),
|
||||
@ -135,22 +135,22 @@ void G1StringDedupStat::print_statistics(outputStream* st, const G1StringDedupSt
|
||||
|
||||
if (total) {
|
||||
st->print_cr(
|
||||
" [Total Exec: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT", Idle: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT", Blocked: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT"]",
|
||||
" [Total Exec: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Idle: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]",
|
||||
stat._exec, stat._exec_elapsed, stat._idle, stat._idle_elapsed, stat._block, stat._block_elapsed);
|
||||
} else {
|
||||
st->print_cr(
|
||||
" [Last Exec: "G1_STRDEDUP_TIME_FORMAT", Idle: "G1_STRDEDUP_TIME_FORMAT", Blocked: "UINTX_FORMAT"/"G1_STRDEDUP_TIME_FORMAT"]",
|
||||
" [Last Exec: " G1_STRDEDUP_TIME_FORMAT ", Idle: " G1_STRDEDUP_TIME_FORMAT ", Blocked: " UINTX_FORMAT "/" G1_STRDEDUP_TIME_FORMAT "]",
|
||||
stat._exec_elapsed, stat._idle_elapsed, stat._block, stat._block_elapsed);
|
||||
}
|
||||
st->print_cr(
|
||||
" [Inspected: "G1_STRDEDUP_OBJECTS_FORMAT"]\n"
|
||||
" [Skipped: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
|
||||
" [Hashed: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
|
||||
" [Known: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
|
||||
" [New: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"]\n"
|
||||
" [Deduplicated: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
|
||||
" [Young: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]\n"
|
||||
" [Old: "G1_STRDEDUP_OBJECTS_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT") "G1_STRDEDUP_BYTES_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT")]",
|
||||
" [Inspected: " G1_STRDEDUP_OBJECTS_FORMAT "]\n"
|
||||
" [Skipped: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n"
|
||||
" [Hashed: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n"
|
||||
" [Known: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n"
|
||||
" [New: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "]\n"
|
||||
" [Deduplicated: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n"
|
||||
" [Young: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]\n"
|
||||
" [Old: " G1_STRDEDUP_OBJECTS_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ") " G1_STRDEDUP_BYTES_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT ")]",
|
||||
stat._inspected,
|
||||
stat._skipped, skipped_percent,
|
||||
stat._hashed, hashed_percent,
|
||||
|
@ -556,12 +556,12 @@ void G1StringDedupTable::trim_entry_cache() {
|
||||
void G1StringDedupTable::print_statistics(outputStream* st) {
|
||||
st->print_cr(
|
||||
" [Table]\n"
|
||||
" [Memory Usage: "G1_STRDEDUP_BYTES_FORMAT_NS"]\n"
|
||||
" [Size: "SIZE_FORMAT", Min: "SIZE_FORMAT", Max: "SIZE_FORMAT"]\n"
|
||||
" [Entries: "UINTX_FORMAT", Load: "G1_STRDEDUP_PERCENT_FORMAT_NS", Cached: " UINTX_FORMAT ", Added: "UINTX_FORMAT", Removed: "UINTX_FORMAT"]\n"
|
||||
" [Resize Count: "UINTX_FORMAT", Shrink Threshold: "UINTX_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT_NS"), Grow Threshold: "UINTX_FORMAT"("G1_STRDEDUP_PERCENT_FORMAT_NS")]\n"
|
||||
" [Rehash Count: "UINTX_FORMAT", Rehash Threshold: "UINTX_FORMAT", Hash Seed: 0x%x]\n"
|
||||
" [Age Threshold: "UINTX_FORMAT"]",
|
||||
" [Memory Usage: " G1_STRDEDUP_BYTES_FORMAT_NS "]\n"
|
||||
" [Size: " SIZE_FORMAT ", Min: " SIZE_FORMAT ", Max: " SIZE_FORMAT "]\n"
|
||||
" [Entries: " UINTX_FORMAT ", Load: " G1_STRDEDUP_PERCENT_FORMAT_NS ", Cached: " UINTX_FORMAT ", Added: " UINTX_FORMAT ", Removed: " UINTX_FORMAT "]\n"
|
||||
" [Resize Count: " UINTX_FORMAT ", Shrink Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS "), Grow Threshold: " UINTX_FORMAT "(" G1_STRDEDUP_PERCENT_FORMAT_NS ")]\n"
|
||||
" [Rehash Count: " UINTX_FORMAT ", Rehash Threshold: " UINTX_FORMAT ", Hash Seed: 0x%x]\n"
|
||||
" [Age Threshold: " UINTX_FORMAT "]",
|
||||
G1_STRDEDUP_BYTES_PARAM(_table->_size * sizeof(G1StringDedupEntry*) + (_table->_entries + _entry_cache->size()) * sizeof(G1StringDedupEntry)),
|
||||
_table->_size, _min_size, _max_size,
|
||||
_table->_entries, (double)_table->_entries / (double)_table->_size * 100.0, _entry_cache->size(), _entries_added, _entries_removed,
|
||||
|
@ -327,7 +327,7 @@ void HeapRegion::note_self_forwarding_removal_end(bool during_initial_mark,
|
||||
bool during_conc_mark,
|
||||
size_t marked_bytes) {
|
||||
assert(marked_bytes <= used(),
|
||||
err_msg("marked: "SIZE_FORMAT" used: "SIZE_FORMAT, marked_bytes, used()));
|
||||
err_msg("marked: " SIZE_FORMAT " used: " SIZE_FORMAT, marked_bytes, used()));
|
||||
_prev_top_at_mark_start = top();
|
||||
_prev_marked_bytes = marked_bytes;
|
||||
}
|
||||
@ -504,9 +504,9 @@ class VerifyStrongCodeRootOopClosure: public OopClosure {
|
||||
// Object is in the region. Check that its less than top
|
||||
if (_hr->top() <= (HeapWord*)obj) {
|
||||
// Object is above top
|
||||
gclog_or_tty->print_cr("Object "PTR_FORMAT" in region "
|
||||
"["PTR_FORMAT", "PTR_FORMAT") is above "
|
||||
"top "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("Object " PTR_FORMAT " in region "
|
||||
"[" PTR_FORMAT ", " PTR_FORMAT ") is above "
|
||||
"top " PTR_FORMAT,
|
||||
p2i(obj), p2i(_hr->bottom()), p2i(_hr->end()), p2i(_hr->top()));
|
||||
_failures = true;
|
||||
return;
|
||||
@ -540,22 +540,22 @@ public:
|
||||
if (nm != NULL) {
|
||||
// Verify that the nemthod is live
|
||||
if (!nm->is_alive()) {
|
||||
gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has dead nmethod "
|
||||
PTR_FORMAT" in its strong code roots",
|
||||
gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] has dead nmethod "
|
||||
PTR_FORMAT " in its strong code roots",
|
||||
p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
|
||||
_failures = true;
|
||||
} else {
|
||||
VerifyStrongCodeRootOopClosure oop_cl(_hr, nm);
|
||||
nm->oops_do(&oop_cl);
|
||||
if (!oop_cl.has_oops_in_region()) {
|
||||
gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has nmethod "
|
||||
PTR_FORMAT" in its strong code roots "
|
||||
gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] has nmethod "
|
||||
PTR_FORMAT " in its strong code roots "
|
||||
"with no pointers into region",
|
||||
p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
|
||||
_failures = true;
|
||||
} else if (oop_cl.failures()) {
|
||||
gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] has other "
|
||||
"failures for nmethod "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] has other "
|
||||
"failures for nmethod " PTR_FORMAT,
|
||||
p2i(_hr->bottom()), p2i(_hr->end()), p2i(nm));
|
||||
_failures = true;
|
||||
}
|
||||
@ -589,8 +589,8 @@ void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const
|
||||
// on its strong code root list
|
||||
if (is_empty()) {
|
||||
if (strong_code_roots_length > 0) {
|
||||
gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is empty "
|
||||
"but has "SIZE_FORMAT" code root entries",
|
||||
gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] is empty "
|
||||
"but has " SIZE_FORMAT " code root entries",
|
||||
p2i(bottom()), p2i(end()), strong_code_roots_length);
|
||||
*failures = true;
|
||||
}
|
||||
@ -599,8 +599,8 @@ void HeapRegion::verify_strong_code_roots(VerifyOption vo, bool* failures) const
|
||||
|
||||
if (is_continues_humongous()) {
|
||||
if (strong_code_roots_length > 0) {
|
||||
gclog_or_tty->print_cr("region "HR_FORMAT" is a continuation of a humongous "
|
||||
"region but has "SIZE_FORMAT" code root entries",
|
||||
gclog_or_tty->print_cr("region " HR_FORMAT " is a continuation of a humongous "
|
||||
"region but has " SIZE_FORMAT " code root entries",
|
||||
HR_FORMAT_PARAMS(this), strong_code_roots_length);
|
||||
*failures = true;
|
||||
}
|
||||
@ -625,7 +625,7 @@ void HeapRegion::print_on(outputStream* st) const {
|
||||
else
|
||||
st->print(" ");
|
||||
st->print(" TS %5d", _gc_time_stamp);
|
||||
st->print(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT,
|
||||
st->print(" PTAMS " PTR_FORMAT " NTAMS " PTR_FORMAT,
|
||||
p2i(prev_top_at_mark_start()), p2i(next_top_at_mark_start()));
|
||||
G1OffsetTableContigSpace::print_on(st);
|
||||
}
|
||||
@ -686,25 +686,25 @@ public:
|
||||
}
|
||||
if (!_g1h->is_in_closed_subset(obj)) {
|
||||
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
|
||||
gclog_or_tty->print_cr("Field "PTR_FORMAT
|
||||
" of live obj "PTR_FORMAT" in region "
|
||||
"["PTR_FORMAT", "PTR_FORMAT")",
|
||||
gclog_or_tty->print_cr("Field " PTR_FORMAT
|
||||
" of live obj " PTR_FORMAT " in region "
|
||||
"[" PTR_FORMAT ", " PTR_FORMAT ")",
|
||||
p2i(p), p2i(_containing_obj),
|
||||
p2i(from->bottom()), p2i(from->end()));
|
||||
print_object(gclog_or_tty, _containing_obj);
|
||||
gclog_or_tty->print_cr("points to obj "PTR_FORMAT" not in the heap",
|
||||
gclog_or_tty->print_cr("points to obj " PTR_FORMAT " not in the heap",
|
||||
p2i(obj));
|
||||
} else {
|
||||
HeapRegion* from = _g1h->heap_region_containing((HeapWord*)p);
|
||||
HeapRegion* to = _g1h->heap_region_containing((HeapWord*)obj);
|
||||
gclog_or_tty->print_cr("Field "PTR_FORMAT
|
||||
" of live obj "PTR_FORMAT" in region "
|
||||
"["PTR_FORMAT", "PTR_FORMAT")",
|
||||
gclog_or_tty->print_cr("Field " PTR_FORMAT
|
||||
" of live obj " PTR_FORMAT " in region "
|
||||
"[" PTR_FORMAT ", " PTR_FORMAT ")",
|
||||
p2i(p), p2i(_containing_obj),
|
||||
p2i(from->bottom()), p2i(from->end()));
|
||||
print_object(gclog_or_tty, _containing_obj);
|
||||
gclog_or_tty->print_cr("points to dead obj "PTR_FORMAT" in region "
|
||||
"["PTR_FORMAT", "PTR_FORMAT")",
|
||||
gclog_or_tty->print_cr("points to dead obj " PTR_FORMAT " in region "
|
||||
"[" PTR_FORMAT ", " PTR_FORMAT ")",
|
||||
p2i(obj), p2i(to->bottom()), p2i(to->end()));
|
||||
print_object(gclog_or_tty, obj);
|
||||
}
|
||||
@ -740,14 +740,14 @@ public:
|
||||
gclog_or_tty->print_cr("----------");
|
||||
}
|
||||
gclog_or_tty->print_cr("Missing rem set entry:");
|
||||
gclog_or_tty->print_cr("Field "PTR_FORMAT" "
|
||||
"of obj "PTR_FORMAT", "
|
||||
"in region "HR_FORMAT,
|
||||
gclog_or_tty->print_cr("Field " PTR_FORMAT " "
|
||||
"of obj " PTR_FORMAT ", "
|
||||
"in region " HR_FORMAT,
|
||||
p2i(p), p2i(_containing_obj),
|
||||
HR_FORMAT_PARAMS(from));
|
||||
_containing_obj->print_on(gclog_or_tty);
|
||||
gclog_or_tty->print_cr("points to obj "PTR_FORMAT" "
|
||||
"in region "HR_FORMAT,
|
||||
gclog_or_tty->print_cr("points to obj " PTR_FORMAT " "
|
||||
"in region " HR_FORMAT,
|
||||
p2i(obj),
|
||||
HR_FORMAT_PARAMS(to));
|
||||
obj->print_on(gclog_or_tty);
|
||||
@ -783,8 +783,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
|
||||
if (is_region_humongous != g1->is_humongous(obj_size) &&
|
||||
!g1->is_obj_dead(obj, this)) { // Dead objects may have bigger block_size since they span several objects.
|
||||
gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size ("
|
||||
SIZE_FORMAT" words) in a %shumongous region",
|
||||
gclog_or_tty->print_cr("obj " PTR_FORMAT " is of %shumongous size ("
|
||||
SIZE_FORMAT " words) in a %shumongous region",
|
||||
p2i(p), g1->is_humongous(obj_size) ? "" : "non-",
|
||||
obj_size, is_region_humongous ? "" : "non-");
|
||||
*failures = true;
|
||||
@ -798,12 +798,12 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
(vo == VerifyOption_G1UsePrevMarking &&
|
||||
ClassLoaderDataGraph::unload_list_contains(klass));
|
||||
if (!is_metaspace_object) {
|
||||
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
|
||||
gclog_or_tty->print_cr("klass " PTR_FORMAT " of object " PTR_FORMAT " "
|
||||
"not metadata", p2i(klass), p2i(obj));
|
||||
*failures = true;
|
||||
return;
|
||||
} else if (!klass->is_klass()) {
|
||||
gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
|
||||
gclog_or_tty->print_cr("klass " PTR_FORMAT " of object " PTR_FORMAT " "
|
||||
"not a klass", p2i(klass), p2i(obj));
|
||||
*failures = true;
|
||||
return;
|
||||
@ -819,7 +819,7 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gclog_or_tty->print_cr(PTR_FORMAT" no an oop", p2i(obj));
|
||||
gclog_or_tty->print_cr(PTR_FORMAT " no an oop", p2i(obj));
|
||||
*failures = true;
|
||||
return;
|
||||
}
|
||||
@ -833,8 +833,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
}
|
||||
|
||||
if (p != top()) {
|
||||
gclog_or_tty->print_cr("end of last object "PTR_FORMAT" "
|
||||
"does not match top "PTR_FORMAT, p2i(p), p2i(top()));
|
||||
gclog_or_tty->print_cr("end of last object " PTR_FORMAT " "
|
||||
"does not match top " PTR_FORMAT, p2i(p), p2i(top()));
|
||||
*failures = true;
|
||||
return;
|
||||
}
|
||||
@ -849,8 +849,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
HeapWord* addr_1 = p;
|
||||
HeapWord* b_start_1 = _offsets.block_start_const(addr_1);
|
||||
if (b_start_1 != p) {
|
||||
gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" "
|
||||
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("BOT look up for top: " PTR_FORMAT " "
|
||||
" yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
|
||||
p2i(addr_1), p2i(b_start_1), p2i(p));
|
||||
*failures = true;
|
||||
return;
|
||||
@ -861,8 +861,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
if (addr_2 < the_end) {
|
||||
HeapWord* b_start_2 = _offsets.block_start_const(addr_2);
|
||||
if (b_start_2 != p) {
|
||||
gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" "
|
||||
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("BOT look up for top + 1: " PTR_FORMAT " "
|
||||
" yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
|
||||
p2i(addr_2), p2i(b_start_2), p2i(p));
|
||||
*failures = true;
|
||||
return;
|
||||
@ -875,8 +875,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
if (addr_3 < the_end) {
|
||||
HeapWord* b_start_3 = _offsets.block_start_const(addr_3);
|
||||
if (b_start_3 != p) {
|
||||
gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" "
|
||||
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("BOT look up for top + diff: " PTR_FORMAT " "
|
||||
" yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
|
||||
p2i(addr_3), p2i(b_start_3), p2i(p));
|
||||
*failures = true;
|
||||
return;
|
||||
@ -887,8 +887,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
HeapWord* addr_4 = the_end - 1;
|
||||
HeapWord* b_start_4 = _offsets.block_start_const(addr_4);
|
||||
if (b_start_4 != p) {
|
||||
gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" "
|
||||
" yielded "PTR_FORMAT", expecting "PTR_FORMAT,
|
||||
gclog_or_tty->print_cr("BOT look up for end - 1: " PTR_FORMAT " "
|
||||
" yielded " PTR_FORMAT ", expecting " PTR_FORMAT,
|
||||
p2i(addr_4), p2i(b_start_4), p2i(p));
|
||||
*failures = true;
|
||||
return;
|
||||
@ -896,8 +896,8 @@ void HeapRegion::verify(VerifyOption vo,
|
||||
}
|
||||
|
||||
if (is_region_humongous && object_num > 1) {
|
||||
gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous "
|
||||
"but has "SIZE_FORMAT", objects",
|
||||
gclog_or_tty->print_cr("region [" PTR_FORMAT "," PTR_FORMAT "] is humongous "
|
||||
"but has " SIZE_FORMAT ", objects",
|
||||
p2i(bottom()), p2i(end()), object_num);
|
||||
*failures = true;
|
||||
return;
|
||||
|
@ -51,7 +51,7 @@ class HeapRegion;
|
||||
class HeapRegionSetBase;
|
||||
class nmethod;
|
||||
|
||||
#define HR_FORMAT "%u:(%s)["PTR_FORMAT","PTR_FORMAT","PTR_FORMAT"]"
|
||||
#define HR_FORMAT "%u:(%s)[" PTR_FORMAT "," PTR_FORMAT "," PTR_FORMAT "]"
|
||||
#define HR_FORMAT_PARAMS(_hr_) \
|
||||
(_hr_)->hrm_index(), \
|
||||
(_hr_)->get_short_type_str(), \
|
||||
@ -538,8 +538,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
|
||||
void set_containing_set(HeapRegionSetBase* containing_set) {
|
||||
assert((containing_set == NULL && _containing_set != NULL) ||
|
||||
(containing_set != NULL && _containing_set == NULL),
|
||||
err_msg("containing_set: "PTR_FORMAT" "
|
||||
"_containing_set: "PTR_FORMAT,
|
||||
err_msg("containing_set: " PTR_FORMAT " "
|
||||
"_containing_set: " PTR_FORMAT,
|
||||
p2i(containing_set), p2i(_containing_set)));
|
||||
|
||||
_containing_set = containing_set;
|
||||
|
@ -113,7 +113,7 @@ HeapRegion::block_size(const HeapWord *addr) const {
|
||||
|
||||
assert(ClassUnloadingWithConcurrentMark,
|
||||
err_msg("All blocks should be objects if G1 Class Unloading isn't used. "
|
||||
"HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") "
|
||||
"HR: [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ") "
|
||||
"addr: " PTR_FORMAT,
|
||||
p2i(bottom()), p2i(top()), p2i(end()), p2i(addr)));
|
||||
|
||||
|
@ -486,7 +486,7 @@ void HeapRegionManager::verify() {
|
||||
HeapRegion* hr = _regions.get_by_index(i);
|
||||
guarantee(hr != NULL, err_msg("invariant: i: %u", i));
|
||||
guarantee(!prev_committed || hr->bottom() == prev_end,
|
||||
err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT,
|
||||
err_msg("invariant i: %u " HR_FORMAT " prev_end: " PTR_FORMAT,
|
||||
i, HR_FORMAT_PARAMS(hr), p2i(prev_end)));
|
||||
guarantee(hr->hrm_index() == i,
|
||||
err_msg("invariant: i: %u hrm_index(): %u", i, hr->hrm_index()));
|
||||
|
@ -31,9 +31,9 @@
|
||||
|
||||
inline HeapRegion* HeapRegionManager::addr_to_region(HeapWord* addr) const {
|
||||
assert(addr < heap_end(),
|
||||
err_msg("addr: "PTR_FORMAT" end: "PTR_FORMAT, p2i(addr), p2i(heap_end())));
|
||||
err_msg("addr: " PTR_FORMAT " end: " PTR_FORMAT, p2i(addr), p2i(heap_end())));
|
||||
assert(addr >= heap_bottom(),
|
||||
err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, p2i(addr), p2i(heap_bottom())));
|
||||
err_msg("addr: " PTR_FORMAT " bottom: " PTR_FORMAT, p2i(addr), p2i(heap_bottom())));
|
||||
|
||||
HeapRegion* hr = _regions.get_by_address(addr);
|
||||
return hr;
|
||||
|
@ -90,7 +90,7 @@ protected:
|
||||
// concurrency.
|
||||
|
||||
if (G1TraceHeapRegionRememberedSet) {
|
||||
gclog_or_tty->print_cr(" PRT::Add_reference_work(" PTR_FORMAT "->" PTR_FORMAT").",
|
||||
gclog_or_tty->print_cr(" PRT::Add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").",
|
||||
p2i(from),
|
||||
UseCompressedOops
|
||||
? p2i(oopDesc::load_decode_heap_oop((narrowOop*)from))
|
||||
@ -376,7 +376,7 @@ void FromCardCache::initialize(uint n_par_rs, uint max_num_regions) {
|
||||
|
||||
void FromCardCache::invalidate(uint start_idx, size_t new_num_regions) {
|
||||
guarantee((size_t)start_idx + new_num_regions <= max_uintx,
|
||||
err_msg("Trying to invalidate beyond maximum region, from %u size "SIZE_FORMAT,
|
||||
err_msg("Trying to invalidate beyond maximum region, from %u size " SIZE_FORMAT,
|
||||
start_idx, new_num_regions));
|
||||
for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
|
||||
uint end_idx = (start_idx + (uint)new_num_regions);
|
||||
@ -630,13 +630,13 @@ void OtherRegionsTable::scrub(CardTableModRefBS* ctbs,
|
||||
|
||||
assert(_coarse_map.size() == region_bm->size(), "Precondition");
|
||||
if (G1RSScrubVerbose) {
|
||||
gclog_or_tty->print(" Coarse map: before = "SIZE_FORMAT"...",
|
||||
gclog_or_tty->print(" Coarse map: before = " SIZE_FORMAT "...",
|
||||
_n_coarse_entries);
|
||||
}
|
||||
_coarse_map.set_intersection(*region_bm);
|
||||
_n_coarse_entries = _coarse_map.count_one_bits();
|
||||
if (G1RSScrubVerbose) {
|
||||
gclog_or_tty->print_cr(" after = "SIZE_FORMAT".", _n_coarse_entries);
|
||||
gclog_or_tty->print_cr(" after = " SIZE_FORMAT ".", _n_coarse_entries);
|
||||
}
|
||||
|
||||
// Now do the fine-grained maps.
|
||||
@ -1013,7 +1013,7 @@ bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) {
|
||||
|
||||
card_index = _cur_region_card_offset + _cur_card_in_prt;
|
||||
guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion,
|
||||
err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt));
|
||||
err_msg("Card index " SIZE_FORMAT " must be within the region", _cur_card_in_prt));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1182,8 +1182,8 @@ void PerRegionTable::test_fl_mem_size() {
|
||||
|
||||
size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize;
|
||||
assert(dummy->mem_size() > min_prt_size,
|
||||
err_msg("PerRegionTable memory usage is suspiciously small, only has "SIZE_FORMAT" bytes. "
|
||||
"Should be at least "SIZE_FORMAT" bytes.", dummy->mem_size(), min_prt_size));
|
||||
err_msg("PerRegionTable memory usage is suspiciously small, only has " SIZE_FORMAT " bytes. "
|
||||
"Should be at least " SIZE_FORMAT " bytes.", dummy->mem_size(), min_prt_size));
|
||||
free(dummy);
|
||||
guarantee(dummy->mem_size() == fl_mem_size(), "fl_mem_size() does not return the correct element size");
|
||||
// try to reset the state
|
||||
|
@ -30,7 +30,7 @@
|
||||
uint FreeRegionList::_unrealistically_long_length = 0;
|
||||
|
||||
void HeapRegionSetBase::fill_in_ext_msg(hrs_ext_msg* msg, const char* message) {
|
||||
msg->append("[%s] %s ln: %u cy: "SIZE_FORMAT,
|
||||
msg->append("[%s] %s ln: %u cy: " SIZE_FORMAT,
|
||||
name(), message, length(), total_capacity_bytes());
|
||||
fill_in_ext_msg_extra(msg);
|
||||
}
|
||||
@ -83,13 +83,13 @@ void HeapRegionSetBase::verify_end() {
|
||||
|
||||
void HeapRegionSetBase::print_on(outputStream* out, bool print_contents) {
|
||||
out->cr();
|
||||
out->print_cr("Set: %s ("PTR_FORMAT")", name(), p2i(this));
|
||||
out->print_cr("Set: %s (" PTR_FORMAT ")", name(), p2i(this));
|
||||
out->print_cr(" Region Assumptions");
|
||||
out->print_cr(" humongous : %s", BOOL_TO_STR(regions_humongous()));
|
||||
out->print_cr(" free : %s", BOOL_TO_STR(regions_free()));
|
||||
out->print_cr(" Attributes");
|
||||
out->print_cr(" length : %14u", length());
|
||||
out->print_cr(" total capacity : "SIZE_FORMAT_W(14)" bytes",
|
||||
out->print_cr(" total capacity : " SIZE_FORMAT_W(14) " bytes",
|
||||
total_capacity_bytes());
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ void FreeRegionList::set_unrealistically_long_length(uint len) {
|
||||
}
|
||||
|
||||
void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
|
||||
msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, p2i(_head), p2i(_tail));
|
||||
msg->append(" hd: " PTR_FORMAT " tl: " PTR_FORMAT, p2i(_head), p2i(_tail));
|
||||
}
|
||||
|
||||
void FreeRegionList::remove_all() {
|
||||
@ -276,8 +276,8 @@ void FreeRegionList::clear() {
|
||||
void FreeRegionList::print_on(outputStream* out, bool print_contents) {
|
||||
HeapRegionSetBase::print_on(out, print_contents);
|
||||
out->print_cr(" Linking");
|
||||
out->print_cr(" head : "PTR_FORMAT, p2i(_head));
|
||||
out->print_cr(" tail : "PTR_FORMAT, p2i(_tail));
|
||||
out->print_cr(" head : " PTR_FORMAT, p2i(_head));
|
||||
out->print_cr(" tail : " PTR_FORMAT, p2i(_tail));
|
||||
|
||||
if (print_contents) {
|
||||
out->print_cr(" Contents");
|
||||
@ -305,7 +305,7 @@ void FreeRegionList::verify_list() {
|
||||
|
||||
count++;
|
||||
guarantee(count < _unrealistically_long_length,
|
||||
hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: "PTR_FORMAT" prev0: "PTR_FORMAT" " "prev1: "PTR_FORMAT" length: %u",
|
||||
hrs_err_msg("[%s] the calculated length: %u seems very long, is there maybe a cycle? curr: " PTR_FORMAT " prev0: " PTR_FORMAT " " "prev1: " PTR_FORMAT " length: %u",
|
||||
name(), count, p2i(curr), p2i(prev0), p2i(prev1), length()));
|
||||
|
||||
if (curr->next() != NULL) {
|
||||
|
@ -200,8 +200,8 @@ void ObjPtrQueue::print(const char* name) {
|
||||
|
||||
void ObjPtrQueue::print(const char* name,
|
||||
void** buf, size_t index, size_t sz) {
|
||||
gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: "PTR_FORMAT" "
|
||||
"index: "SIZE_FORMAT" sz: "SIZE_FORMAT,
|
||||
gclog_or_tty->print_cr(" SATB BUFFER [%s] buf: " PTR_FORMAT " "
|
||||
"index: " SIZE_FORMAT " sz: " SIZE_FORMAT,
|
||||
name, p2i(buf), index, sz);
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
@ -85,7 +85,7 @@ void MutableNUMASpace::ensure_parsability() {
|
||||
while (words_left_to_fill > 0) {
|
||||
size_t words_to_fill = MIN2(words_left_to_fill, CollectedHeap::filler_array_max_size());
|
||||
assert(words_to_fill >= CollectedHeap::min_fill_size(),
|
||||
err_msg("Remaining size ("SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")",
|
||||
err_msg("Remaining size (" SIZE_FORMAT ") is too small to fill (based on " SIZE_FORMAT " and " SIZE_FORMAT ")",
|
||||
words_to_fill, words_left_to_fill, CollectedHeap::filler_array_max_size()));
|
||||
CollectedHeap::fill_with_object((HeapWord*)cur_top, words_to_fill);
|
||||
if (!os::numa_has_static_binding()) {
|
||||
|
@ -65,9 +65,9 @@ class PSOldGen : public CHeapObj<mtGC> {
|
||||
// Explictly capture current covered_region in a local
|
||||
MemRegion covered_region = this->start_array()->covered_region();
|
||||
assert(covered_region.contains(new_memregion),
|
||||
err_msg("new region is not in covered_region [ "PTR_FORMAT", "PTR_FORMAT" ], "
|
||||
"new region [ "PTR_FORMAT", "PTR_FORMAT" ], "
|
||||
"object space [ "PTR_FORMAT", "PTR_FORMAT" ]",
|
||||
err_msg("new region is not in covered_region [ " PTR_FORMAT ", " PTR_FORMAT " ], "
|
||||
"new region [ " PTR_FORMAT ", " PTR_FORMAT " ], "
|
||||
"object space [ " PTR_FORMAT ", " PTR_FORMAT " ]",
|
||||
p2i(covered_region.start()),
|
||||
p2i(covered_region.end()),
|
||||
p2i(new_memregion.start()),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user