This commit is contained in:
J. Duke 2017-07-05 20:42:26 +02:00
commit aecbc4f508
820 changed files with 44331 additions and 16898 deletions

View File

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

View File

@ -315,3 +315,4 @@ de8acedcb5b5870f1dc54cba575aaa5d33897ea2 jdk9-b69
e7cf01990ed366bd493080663259281e91ce223b jdk9-b70 e7cf01990ed366bd493080663259281e91ce223b jdk9-b70
cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71 cd39ed501fb0504554a7f58ac6cf3dd2b64afec0 jdk9-b71
f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72 f9f3706bd24c42c07cb260fe05730a749b8e52f4 jdk9-b72
29096b78d93b01a2f8882509cd40755e3d6b8cd9 jdk9-b73

View File

@ -2430,8 +2430,8 @@ public class IIOPInputStream
private void throwAwayData(ValueMember[] fields, private void throwAwayData(ValueMember[] fields,
com.sun.org.omg.SendingContext.CodeBase sender) com.sun.org.omg.SendingContext.CodeBase sender)
throws InvalidClassException, StreamCorruptedException, throws InvalidClassException, StreamCorruptedException,
ClassNotFoundException, IOException ClassNotFoundException, IOException {
{
for (int i = 0; i < fields.length; ++i) { for (int i = 0; i < fields.length; ++i) {
try { try {
@ -2566,8 +2566,7 @@ public class IIOPInputStream
} }
private static void setObjectField(Object o, Class c, String fieldName, Object v) private static void setObjectField(Object o, Class c, String fieldName, Object v) {
{
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
Class fieldCl = fld.getType(); Class fieldCl = fld.getType();
@ -2577,9 +2576,15 @@ public class IIOPInputStream
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putObject( o, key, v ) ; bridge.putObject( o, key, v ) ;
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetObjectField( e, fieldName, throw utilWrapper.errorSetObjectField( e, fieldName,
o.toString(), o.toString(),
v.toString() ) ; v.toString() ) ;
} else {
throw utilWrapper.errorSetObjectField( e, fieldName,
"null " + c.getName() + " object",
v.toString() ) ;
}
} }
} }
@ -2587,12 +2592,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Boolean.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putBoolean( o, key, v ) ; bridge.putBoolean( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetBooleanField( e, fieldName, throw utilWrapper.errorSetBooleanField( e, fieldName,
o.toString(), o.toString(),
new Boolean(v) ) ; new Boolean(v) ) ;
} else {
throw utilWrapper.errorSetBooleanField( e, fieldName,
"null " + c.getName() + " object",
new Boolean(v) ) ;
}
} }
} }
@ -2600,12 +2615,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Byte.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putByte( o, key, v ) ; bridge.putByte( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetByteField( e, fieldName, throw utilWrapper.errorSetByteField( e, fieldName,
o.toString(), o.toString(),
new Byte(v) ) ; new Byte(v) ) ;
} else {
throw utilWrapper.errorSetByteField( e, fieldName,
"null " + c.getName() + " object",
new Byte(v) ) ;
}
} }
} }
@ -2613,12 +2638,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Character.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putChar( o, key, v ) ; bridge.putChar( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetCharField( e, fieldName, throw utilWrapper.errorSetCharField( e, fieldName,
o.toString(), o.toString(),
new Character(v) ) ; new Character(v) ) ;
} else {
throw utilWrapper.errorSetCharField( e, fieldName,
"null " + c.getName() + " object",
new Character(v) ) ;
}
} }
} }
@ -2626,12 +2661,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Short.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putShort( o, key, v ) ; bridge.putShort( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetShortField( e, fieldName, throw utilWrapper.errorSetShortField( e, fieldName,
o.toString(), o.toString(),
new Short(v) ) ; new Short(v) ) ;
} else {
throw utilWrapper.errorSetShortField( e, fieldName,
"null " + c.getName() + " object",
new Short(v) ) ;
}
} }
} }
@ -2639,12 +2684,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Integer.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putInt( o, key, v ) ; bridge.putInt( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetIntField( e, fieldName, throw utilWrapper.errorSetIntField( e, fieldName,
o.toString(), o.toString(),
new Integer(v) ) ; new Integer(v) ) ;
} else {
throw utilWrapper.errorSetIntField( e, fieldName,
"null " + c.getName() + " object",
new Integer(v) ) ;
}
} }
} }
@ -2652,12 +2707,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Long.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putLong( o, key, v ) ; bridge.putLong( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetLongField( e, fieldName, throw utilWrapper.errorSetLongField( e, fieldName,
o.toString(), o.toString(),
new Long(v) ) ; new Long(v) ) ;
} else {
throw utilWrapper.errorSetLongField( e, fieldName,
"null " + c.getName() + " object",
new Long(v) ) ;
}
} }
} }
@ -2665,12 +2730,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Float.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putFloat( o, key, v ) ; bridge.putFloat( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetFloatField( e, fieldName, throw utilWrapper.errorSetFloatField( e, fieldName,
o.toString(), o.toString(),
new Float(v) ) ; new Float(v) ) ;
} else {
throw utilWrapper.errorSetFloatField( e, fieldName,
"null " + c.getName() + " object",
new Float(v) ) ;
}
} }
} }
@ -2678,12 +2753,22 @@ public class IIOPInputStream
{ {
try { try {
Field fld = c.getDeclaredField( fieldName ) ; Field fld = c.getDeclaredField( fieldName ) ;
if ((fld != null) && (fld.getType() == Double.TYPE)) {
long key = bridge.objectFieldOffset( fld ) ; long key = bridge.objectFieldOffset( fld ) ;
bridge.putDouble( o, key, v ) ; bridge.putDouble( o, key, v ) ;
} else {
throw new InvalidObjectException("Field Type mismatch");
}
} catch (Exception e) { } catch (Exception e) {
if (o != null) {
throw utilWrapper.errorSetDoubleField( e, fieldName, throw utilWrapper.errorSetDoubleField( e, fieldName,
o.toString(), o.toString(),
new Double(v) ) ; new Double(v) ) ;
} else {
throw utilWrapper.errorSetDoubleField( e, fieldName,
"null " + c.getName() + " object",
new Double(v) ) ;
}
} }
} }

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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"); Type type = db.lookupType("CodeCache");
// Get array of CodeHeaps // 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"); 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"); scavengeRootNMethodsField = type.getAddressField("_scavenge_root_nmethods");
@ -180,31 +185,9 @@ public class CodeCache {
public void iterate(CodeCacheVisitor visitor) { public void iterate(CodeCacheVisitor visitor) {
visitor.prologue(lowBound(), highBound()); visitor.prologue(lowBound(), highBound());
CodeBlob lastBlob = null;
for (int i = 0; i < heapArray.length(); ++i) { for (int i = 0; i < heapArray.length(); ++i) {
CodeHeap current_heap = heapArray.at(i); CodeHeap current_heap = heapArray.at(i);
Address ptr = current_heap.begin(); current_heap.iterate(visitor, this);
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;
}
} }
visitor.epilogue(); visitor.epilogue();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
package sun.jvm.hotspot.memory; package sun.jvm.hotspot.memory;
import java.util.*; import java.util.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.types.*;
@ -90,7 +91,7 @@ public class CodeHeap extends VMObject {
return h.getAllocatedSpace(); return h.getAllocatedSpace();
} }
public Address nextBlock(Address ptr) { private Address nextBlock(Address ptr) {
Address base = blockBase(ptr); Address base = blockBase(ptr);
if (base == null) { if (base == null) {
return null; return null;
@ -99,6 +100,31 @@ public class CodeHeap extends VMObject {
return base.addOffsetTo(block.getLength() * (1 << getLog2SegmentSize())); 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 // Internals only below this point
// //

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -139,6 +139,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -139,6 +139,18 @@
_JVM_Halt _JVM_Halt
_JVM_HoldsLock _JVM_HoldsLock
_JVM_IHashCode _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_InitAgentProperties
_JVM_InitProperties _JVM_InitProperties
_JVM_InternString _JVM_InternString

View File

@ -139,6 +139,18 @@
_JVM_Halt _JVM_Halt
_JVM_HoldsLock _JVM_HoldsLock
_JVM_IHashCode _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_InitAgentProperties
_JVM_InitProperties _JVM_InitProperties
_JVM_InternString _JVM_InternString

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -118,7 +118,8 @@ SIMPLE_DIRS = \
$(PLATFORM_DIR)/generated/dependencies \ $(PLATFORM_DIR)/generated/dependencies \
$(PLATFORM_DIR)/generated/adfiles \ $(PLATFORM_DIR)/generated/adfiles \
$(PLATFORM_DIR)/generated/jvmtifiles \ $(PLATFORM_DIR)/generated/jvmtifiles \
$(PLATFORM_DIR)/generated/tracefiles $(PLATFORM_DIR)/generated/tracefiles \
$(PLATFORM_DIR)/generated/extensions
TARGETS = debug fastdebug optimized product TARGETS = debug fastdebug optimized product
SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -170,6 +170,12 @@ endif
$(QUIETLY) $(REMOVE_TARGET) $(QUIETLY) $(REMOVE_TARGET)
$(QUIETLY) $(AS.S) $(DEPFLAGS) -o $@ $< $(COMPILE_DONE) $(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 %.s: %.cpp
@echo $(LOG_INFO) Generating assembly for $< @echo $(LOG_INFO) Generating assembly for $<
$(QUIETLY) $(GENASM.CXX) -o $@ $< $(QUIETLY) $(GENASM.CXX) -o $@ $<

View File

@ -54,7 +54,7 @@ endif
# Src_Dirs_V is everything in src/share/vm/*, plus the right os/*/vm and cpu/*/vm # 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 adfiles directory contains ad_<arch>.[ch]pp.
# The jvmtifiles directory contains jvmti*.[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:%=%:) VPATH += $(Src_Dirs_V:%=%:)
# set INCLUDES for C preprocessor. # set INCLUDES for C preprocessor.
@ -161,6 +161,8 @@ CORE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \
fi) fi)
endif endif
CORE_PATHS+=$(GENERATED)/extensions
COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1) COMPILER1_PATHS := $(call altsrc,$(HS_COMMON_SRC)/share/vm/c1)
COMPILER1_PATHS += $(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\* Src_Files_EXCLUDE += \*x86_32\*
endif endif
Src_Files_BASE += \*.c \*.cpp \*.s
# Alternate vm.make # Alternate vm.make
# This has to be included here to allow changes to the source # This has to be included here to allow changes to the source
# directories and excluded files before they are expanded # 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. # Locate all source files in the given directory, excluding files in Src_Files_EXCLUDE.
define findsrc define findsrc
$(notdir $(shell find $(1)/. ! -name . -prune \ $(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)) \))) -a ! \( -name DUMMY $(addprefix -o -name ,$(Src_Files_EXCLUDE)) \)))
endef endef
Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) 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) JVM_OBJ_FILES = $(Obj_Files)
@ -244,10 +248,16 @@ VMDEF_PAT = ^_ZTV
VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT) VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT)
VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT) VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT)
VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(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 | \ $(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \
awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@ awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@
ifneq ($(VM_DEF_EXT),)
cat $(VM_DEF_EXT) >> $@
endif
mapfile_ext: mapfile_ext:
rm -f $@ rm -f $@

View File

@ -141,6 +141,18 @@ SUNWprivate_1.1 {
JVM_Halt; JVM_Halt;
JVM_HoldsLock; JVM_HoldsLock;
JVM_IHashCode; 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_InitAgentProperties;
JVM_InitProperties; JVM_InitProperties;
JVM_InternString; JVM_InternString;

View File

@ -143,7 +143,7 @@ else
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
endif # sparcWorks endif # sparcWorks
LIBS += -lkstat LIBS += -lkstat -lrt
# By default, link the *.o into the library, not the executable. # By default, link the *.o into the library, not the executable.
LINK_INTO$(LINK_INTO) = LIBJVM LINK_INTO$(LINK_INTO) = LIBJVM

View File

@ -2270,17 +2270,21 @@ public:
} }
// CRC32 instructions // CRC32 instructions
#define INSN(NAME, sf, sz) \ #define INSN(NAME, c, sf, sz) \
void NAME(Register Rd, Register Rn, Register Rm) { \ void NAME(Register Rd, Register Rn, Register Rm) { \
starti; \ starti; \
f(sf, 31), f(0b0011010110, 30, 21), f(0b0100, 15, 12), f(sz, 11, 10); \ f(sf, 31), f(0b0011010110, 30, 21), f(0b010, 15, 13), f(c, 12); \
rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \ f(sz, 11, 10), rf(Rm, 16), rf(Rn, 5), rf(Rd, 0); \
} }
INSN(crc32b, 0, 0b00); INSN(crc32b, 0, 0, 0b00);
INSN(crc32h, 0, 0b01); INSN(crc32h, 0, 0, 0b01);
INSN(crc32w, 0, 0b10); INSN(crc32w, 0, 0, 0b10);
INSN(crc32x, 1, 0b11); INSN(crc32x, 0, 1, 0b11);
INSN(crc32cb, 1, 0, 0b00);
INSN(crc32ch, 1, 0, 0b01);
INSN(crc32cw, 1, 0, 0b10);
INSN(crc32cx, 1, 1, 0b11);
#undef INSN #undef INSN

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,12 +28,6 @@
const int StackAlignmentInBytes = 16; const int StackAlignmentInBytes = 16;
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are properly extended to 64 bits.
// If set, SharedRuntime::c_calling_convention() must adapt
// signatures accordingly.
const bool CCallingConventionRequiresIntsAsLongs = true;
#define SUPPORTS_NATIVE_CX8 #define SUPPORTS_NATIVE_CX8
// The maximum B/BL offset range on AArch64 is 128MB. // The maximum B/BL offset range on AArch64 is 128MB.

View File

@ -2914,6 +2914,65 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len,
ornw(crc, zr, crc); ornw(crc, zr, crc);
} }
/**
* @param crc register containing existing CRC (32-bit)
* @param buf register pointing to input byte buffer (byte*)
* @param len register containing number of bytes
* @param table register that will contain address of CRC table
* @param tmp scratch register
*/
void MacroAssembler::kernel_crc32c(Register crc, Register buf, Register len,
Register table0, Register table1, Register table2, Register table3,
Register tmp, Register tmp2, Register tmp3) {
Label L_exit;
Label CRC_by64_loop, CRC_by4_loop, CRC_by1_loop;
subs(len, len, 64);
br(Assembler::GE, CRC_by64_loop);
adds(len, len, 64-4);
br(Assembler::GE, CRC_by4_loop);
adds(len, len, 4);
br(Assembler::GT, CRC_by1_loop);
b(L_exit);
BIND(CRC_by4_loop);
ldrw(tmp, Address(post(buf, 4)));
subs(len, len, 4);
crc32cw(crc, crc, tmp);
br(Assembler::GE, CRC_by4_loop);
adds(len, len, 4);
br(Assembler::LE, L_exit);
BIND(CRC_by1_loop);
ldrb(tmp, Address(post(buf, 1)));
subs(len, len, 1);
crc32cb(crc, crc, tmp);
br(Assembler::GT, CRC_by1_loop);
b(L_exit);
align(CodeEntryAlignment);
BIND(CRC_by64_loop);
subs(len, len, 64);
ldp(tmp, tmp3, Address(post(buf, 16)));
crc32cx(crc, crc, tmp);
crc32cx(crc, crc, tmp3);
ldp(tmp, tmp3, Address(post(buf, 16)));
crc32cx(crc, crc, tmp);
crc32cx(crc, crc, tmp3);
ldp(tmp, tmp3, Address(post(buf, 16)));
crc32cx(crc, crc, tmp);
crc32cx(crc, crc, tmp3);
ldp(tmp, tmp3, Address(post(buf, 16)));
crc32cx(crc, crc, tmp);
crc32cx(crc, crc, tmp3);
br(Assembler::GE, CRC_by64_loop);
adds(len, len, 64-4);
br(Assembler::GE, CRC_by4_loop);
adds(len, len, 4);
br(Assembler::GT, CRC_by1_loop);
BIND(L_exit);
return;
}
SkipIfEqual::SkipIfEqual( SkipIfEqual::SkipIfEqual(
MacroAssembler* masm, const bool* flag_addr, bool value) { MacroAssembler* masm, const bool* flag_addr, bool value) {
_masm = masm; _masm = masm;

View File

@ -967,6 +967,10 @@ public:
void kernel_crc32(Register crc, Register buf, Register len, void kernel_crc32(Register crc, Register buf, Register len,
Register table0, Register table1, Register table2, Register table3, Register table0, Register table1, Register table2, Register table3,
Register tmp, Register tmp2, Register tmp3); Register tmp, Register tmp2, Register tmp3);
// CRC32 code for java.util.zip.CRC32C::updateBytes() instrinsic.
void kernel_crc32c(Register crc, Register buf, Register len,
Register table0, Register table1, Register table2, Register table3,
Register tmp, Register tmp2, Register tmp3);
#undef VIRTUAL #undef VIRTUAL

View File

@ -2356,6 +2356,47 @@ class StubGenerator: public StubCodeGenerator {
return start; return start;
} }
/**
* Arguments:
*
* Inputs:
* c_rarg0 - int crc
* c_rarg1 - byte* buf
* c_rarg2 - int length
* c_rarg3 - int* table
*
* Ouput:
* rax - int crc result
*/
address generate_updateBytesCRC32C() {
assert(UseCRC32CIntrinsics, "what are we doing here?");
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "updateBytesCRC32C");
address start = __ pc();
const Register crc = c_rarg0; // crc
const Register buf = c_rarg1; // source java byte array address
const Register len = c_rarg2; // length
const Register table0 = c_rarg3; // crc_table address
const Register table1 = c_rarg4;
const Register table2 = c_rarg5;
const Register table3 = c_rarg6;
const Register tmp3 = c_rarg7;
BLOCK_COMMENT("Entry:");
__ enter(); // required for proper stackwalking of RuntimeStub frame
__ kernel_crc32c(crc, buf, len,
table0, table1, table2, table3, rscratch1, rscratch2, tmp3);
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret(lr);
return start;
}
/** /**
* Arguments: * Arguments:
* *
@ -2579,6 +2620,10 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB"); StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
} }
if (UseCRC32CIntrinsics) {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}
// Safefetch stubs. // Safefetch stubs.
generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry, generate_safefetch("SafeFetch32", sizeof(int), &StubRoutines::_safefetch32_entry,
&StubRoutines::_safefetch32_fault_pc, &StubRoutines::_safefetch32_fault_pc,

View File

@ -199,9 +199,12 @@ void VM_Version::get_processor_features() {
UseCRC32Intrinsics = true; UseCRC32Intrinsics = true;
} }
if (UseCRC32CIntrinsics) { if (auxv & HWCAP_CRC32) {
if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) {
warning("CRC32C intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true);
}
} else if (UseCRC32CIntrinsics) {
warning("CRC32C is not available on the CPU");
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
} }
@ -214,35 +217,32 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA, false); FLAG_SET_DEFAULT(UseSHA, false);
} }
if (!UseSHA) { if (UseSHA && (auxv & HWCAP_SHA1)) {
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} else {
if (auxv & HWCAP_SHA1) {
if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
} }
} else if (UseSHA1Intrinsics) { } else if (UseSHA1Intrinsics) {
warning("SHA1 instruction is not available on this CPU."); warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
} }
if (auxv & HWCAP_SHA2) {
if (UseSHA && (auxv & HWCAP_SHA2)) {
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
} }
} else if (UseSHA256Intrinsics) { } else if (UseSHA256Intrinsics) {
warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU."); warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
} }
if (UseSHA512Intrinsics) { if (UseSHA512Intrinsics) {
warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU."); warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} }
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA, false); FLAG_SET_DEFAULT(UseSHA, false);
} }
}
// This machine allows unaligned memory accesses // This machine allows unaligned memory accesses
if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) {

View File

@ -105,7 +105,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ flush(); __ flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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()), vtable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
@ -184,7 +184,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ flush(); __ flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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()), itable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2013 SAP AG. All rights reserved. * Copyright 2012, 2015 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,12 +31,6 @@ const int BytesPerInstWord = 4;
const int StackAlignmentInBytes = 16; const int StackAlignmentInBytes = 16;
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are properly extended to 64 bits.
// If set, SharedRuntime::c_calling_convention() must adapt
// signatures accordingly.
const bool CCallingConventionRequiresIntsAsLongs = true;
#define SUPPORTS_NATIVE_CX8 #define SUPPORTS_NATIVE_CX8
// The PPC CPUs are NOT multiple-copy-atomic. // The PPC CPUs are NOT multiple-copy-atomic.

View File

@ -465,7 +465,7 @@ void trace_method_handle_stub(const char* adaptername,
bool has_mh = (strstr(adaptername, "/static") == NULL && bool has_mh = (strstr(adaptername, "/static") == NULL &&
strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH
const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23"; 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)); adaptername, mh_reg_name, p2i(mh), p2i(entry_sp));
if (Verbose) { if (Verbose) {

View File

@ -731,23 +731,8 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
case T_SHORT: case T_SHORT:
case T_INT: case T_INT:
// We must cast ints to longs and use full 64 bit stack slots // We must cast ints to longs and use full 64 bit stack slots
// here. We do the cast in GraphKit::gen_stub() and just guard // here. Thus fall through, handle as long.
// here against loosing that change.
assert(CCallingConventionRequiresIntsAsLongs,
"argument of type int should be promoted to type long");
guarantee(i > 0 && sig_bt[i-1] == T_LONG,
"argument of type (bt) should have been promoted to type (T_LONG,bt) for bt in "
"{T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}");
// Do not count halves.
regs[i].set_bad();
--arg;
break;
case T_LONG: case T_LONG:
guarantee(sig_bt[i+1] == T_VOID ||
sig_bt[i+1] == T_BOOLEAN || sig_bt[i+1] == T_CHAR ||
sig_bt[i+1] == T_BYTE || sig_bt[i+1] == T_SHORT ||
sig_bt[i+1] == T_INT,
"expecting type (T_LONG,half) or type (T_LONG,bt) with bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}");
case T_OBJECT: case T_OBJECT:
case T_ARRAY: case T_ARRAY:
case T_ADDRESS: case T_ADDRESS:
@ -1273,7 +1258,7 @@ static void object_move(MacroAssembler* masm,
static void int_move(MacroAssembler*masm, static void int_move(MacroAssembler*masm,
VMRegPair src, VMRegPair dst, VMRegPair src, VMRegPair dst,
Register r_caller_sp, Register r_temp) { Register r_caller_sp, Register r_temp) {
assert(src.first()->is_valid() && src.second() == src.first()->next(), "incoming must be long-int"); assert(src.first()->is_valid(), "incoming must be int");
assert(dst.first()->is_valid() && dst.second() == dst.first()->next(), "outgoing must be long"); assert(dst.first()->is_valid() && dst.second() == dst.first()->next(), "outgoing must be long");
if (src.first()->is_stack()) { if (src.first()->is_stack()) {
@ -1762,13 +1747,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// the jni function will expect them. To figure out where they go // the jni function will expect them. To figure out where they go
// we convert the java signature to a C signature by inserting // we convert the java signature to a C signature by inserting
// the hidden arguments as arg[0] and possibly arg[1] (static method) // the hidden arguments as arg[0] and possibly arg[1] (static method)
//
// Additionally, on ppc64 we must convert integers to longs in the C
// signature. We do this in advance in order to have no trouble with
// indexes into the bt-arrays.
// So convert the signature and registers now, and adjust the total number
// of in-arguments accordingly.
int i2l_argcnt = convert_ints_to_longints_argcnt(total_in_args, in_sig_bt); // PPC64: pass ints as longs.
// Calculate the total number of C arguments and create arrays for the // Calculate the total number of C arguments and create arrays for the
// signature and the outgoing registers. // signature and the outgoing registers.
@ -1776,7 +1754,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// some floating-point arguments must be passed in registers _and_ // some floating-point arguments must be passed in registers _and_
// in stack locations. // in stack locations.
bool method_is_static = method->is_static(); bool method_is_static = method->is_static();
int total_c_args = i2l_argcnt; int total_c_args = total_in_args;
if (!is_critical_native) { if (!is_critical_native) {
int n_hidden_args = method_is_static ? 2 : 1; int n_hidden_args = method_is_static ? 2 : 1;
@ -1785,7 +1763,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// No JNIEnv*, no this*, but unpacked arrays (base+length). // No JNIEnv*, no this*, but unpacked arrays (base+length).
for (int i = 0; i < total_in_args; i++) { for (int i = 0; i < total_in_args; i++) {
if (in_sig_bt[i] == T_ARRAY) { if (in_sig_bt[i] == T_ARRAY) {
total_c_args += 2; // PPC64: T_LONG, T_INT, T_ADDRESS (see convert_ints_to_longints and c_calling_convention) total_c_args++;
} }
} }
} }
@ -1803,8 +1781,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
int argc = 0; int argc = 0;
if (!is_critical_native) { if (!is_critical_native) {
convert_ints_to_longints(i2l_argcnt, total_in_args, in_sig_bt, in_regs); // PPC64: pass ints as longs.
out_sig_bt[argc++] = T_ADDRESS; out_sig_bt[argc++] = T_ADDRESS;
if (method->is_static()) { if (method->is_static()) {
out_sig_bt[argc++] = T_OBJECT; out_sig_bt[argc++] = T_OBJECT;
@ -1815,7 +1791,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
} }
} else { } else {
Thread* THREAD = Thread::current(); Thread* THREAD = Thread::current();
in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, i2l_argcnt); in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args);
SignatureStream ss(method->signature()); SignatureStream ss(method->signature());
int o = 0; int o = 0;
for (int i = 0; i < total_in_args ; i++, o++) { for (int i = 0; i < total_in_args ; i++, o++) {
@ -1839,28 +1815,16 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
} }
} else { } else {
in_elem_bt[o] = T_VOID; in_elem_bt[o] = T_VOID;
switch(in_sig_bt[i]) { // PPC64: pass ints as longs.
case T_BOOLEAN:
case T_CHAR:
case T_BYTE:
case T_SHORT:
case T_INT: in_elem_bt[++o] = T_VOID; break;
default: break;
}
} }
if (in_sig_bt[i] != T_VOID) { if (in_sig_bt[i] != T_VOID) {
assert(in_sig_bt[i] == ss.type(), "must match"); assert(in_sig_bt[i] == ss.type(), "must match");
ss.next(); ss.next();
} }
} }
assert(i2l_argcnt==o, "must match");
convert_ints_to_longints(i2l_argcnt, total_in_args, in_sig_bt, in_regs); // PPC64: pass ints as longs.
for (int i = 0; i < total_in_args ; i++ ) { for (int i = 0; i < total_in_args ; i++ ) {
if (in_sig_bt[i] == T_ARRAY) { if (in_sig_bt[i] == T_ARRAY) {
// Arrays are passed as int, elem* pair. // Arrays are passed as int, elem* pair.
out_sig_bt[argc++] = T_LONG; // PPC64: pass ints as longs.
out_sig_bt[argc++] = T_INT; out_sig_bt[argc++] = T_INT;
out_sig_bt[argc++] = T_ADDRESS; out_sig_bt[argc++] = T_ADDRESS;
} else { } else {
@ -1921,7 +1885,8 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
case T_BYTE: case T_BYTE:
case T_SHORT: case T_SHORT:
case T_CHAR: case T_CHAR:
case T_INT: /*single_slots++;*/ break; // PPC64: pass ints as longs. case T_INT:
// Fall through.
case T_ARRAY: case T_ARRAY:
case T_LONG: double_slots++; break; case T_LONG: double_slots++; break;
default: ShouldNotReachHere(); default: ShouldNotReachHere();
@ -2098,24 +2063,16 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
case T_BYTE: case T_BYTE:
case T_SHORT: case T_SHORT:
case T_INT: case T_INT:
guarantee(in > 0 && in_sig_bt[in-1] == T_LONG, // Move int and do sign extension.
"expecting type (T_LONG,bt) for bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}"); int_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1);
break; break;
case T_LONG: case T_LONG:
if (in_sig_bt[in+1] == T_VOID) {
long_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1); long_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1);
} else {
guarantee(in_sig_bt[in+1] == T_BOOLEAN || in_sig_bt[in+1] == T_CHAR ||
in_sig_bt[in+1] == T_BYTE || in_sig_bt[in+1] == T_SHORT ||
in_sig_bt[in+1] == T_INT,
"expecting type (T_LONG,bt) for bt in {T_BOOLEAN, T_CHAR, T_BYTE, T_SHORT, T_INT}");
int_move(masm, in_regs[in], out_regs[out], r_callers_sp, r_temp_1);
}
break; break;
case T_ARRAY: case T_ARRAY:
if (is_critical_native) { if (is_critical_native) {
int body_arg = out; int body_arg = out;
out -= 2; // Point to length arg. PPC64: pass ints as longs. out -= 1; // Point to length arg.
unpack_array_argument(masm, in_regs[in], in_elem_bt[in], out_regs[body_arg], out_regs[out], unpack_array_argument(masm, in_regs[in], in_elem_bt[in], out_regs[body_arg], out_regs[out],
r_callers_sp, r_temp_1, r_temp_2); r_callers_sp, r_temp_1, r_temp_2);
break; break;
@ -2187,7 +2144,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Make sure that thread is non-volatile; it crosses a bunch of VM calls below. // Make sure that thread is non-volatile; it crosses a bunch of VM calls below.
assert(R16_thread->is_nonvolatile(), "thread must be in non-volatile register"); assert(R16_thread->is_nonvolatile(), "thread must be in non-volatile register");
# if 0 # if 0
// DTrace method entry // DTrace method entry
# endif # endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,12 +30,6 @@ const int BytesPerInstWord = 4;
const int StackAlignmentInBytes = (2*wordSize); const int StackAlignmentInBytes = (2*wordSize);
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are properly extended to 64 bits.
// If set, SharedRuntime::c_calling_convention() must adapt
// signatures accordingly.
const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8 #define SUPPORTS_NATIVE_CX8
// The expected size in bytes of a cache line, used to pad data structures. // The expected size in bytes of a cache line, used to pad data structures.

View File

@ -483,7 +483,7 @@ void trace_method_handle_stub(const char* adaptername,
bool has_mh = (strstr(adaptername, "/static") == NULL && bool has_mh = (strstr(adaptername, "/static") == NULL &&
strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH
const char* mh_reg_name = has_mh ? "G3_mh" : "G3"; 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, adaptername, mh_reg_name,
p2i(mh), p2i(saved_sp), p2i(args)); p2i(mh), p2i(saved_sp), p2i(args));

View File

@ -329,40 +329,36 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseSHA, false); FLAG_SET_DEFAULT(UseSHA, false);
} }
if (!UseSHA) { if (UseSHA && has_sha1()) {
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} else {
if (has_sha1()) {
if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
} }
} else if (UseSHA1Intrinsics) { } else if (UseSHA1Intrinsics) {
warning("SHA1 instruction is not available on this CPU."); warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
} }
if (has_sha256()) {
if (UseSHA && has_sha256()) {
if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
} }
} else if (UseSHA256Intrinsics) { } else if (UseSHA256Intrinsics) {
warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU."); warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
} }
if (has_sha512()) { if (UseSHA && has_sha512()) {
if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) { if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, true); FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
} }
} else if (UseSHA512Intrinsics) { } else if (UseSHA512Intrinsics) {
warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU."); warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} }
if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
FLAG_SET_DEFAULT(UseSHA, false); FLAG_SET_DEFAULT(UseSHA, false);
} }
}
// SPARC T4 and above should have support for CRC32C instruction // SPARC T4 and above should have support for CRC32C instruction
if (has_crc32c()) { if (has_crc32c()) {

View File

@ -110,7 +110,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
masm->flush(); masm->flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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()), vtable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
@ -205,7 +205,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
masm->flush(); masm->flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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()), itable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));

View File

@ -27,12 +27,6 @@
const int StackAlignmentInBytes = 16; const int StackAlignmentInBytes = 16;
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are properly extended to 64 bits.
// If set, SharedRuntime::c_calling_convention() must adapt
// signatures accordingly.
const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8 #define SUPPORTS_NATIVE_CX8
// The expected size in bytes of a cache line, used to pad data structures. // The expected size in bytes of a cache line, used to pad data structures.

View File

@ -5152,7 +5152,7 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad
{ {
ResourceMark rm; ResourceMark rm;
stringStream ss; 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()); buf = code_string(ss.as_string());
} }
jcc(Assembler::notZero, L); jcc(Assembler::notZero, L);

View File

@ -484,7 +484,7 @@ void trace_method_handle_stub(const char* adaptername,
bool has_mh = (strstr(adaptername, "/static") == NULL && bool has_mh = (strstr(adaptername, "/static") == NULL &&
strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH
const char* mh_reg_name = has_mh ? "rcx_mh" : "rcx"; 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, adaptername, mh_reg_name,
(void *)mh, entry_sp); (void *)mh, entry_sp);

View File

@ -23,6 +23,9 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#ifndef _WINDOWS
#include "alloca.h"
#endif
#include "asm/macroAssembler.hpp" #include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp" #include "asm/macroAssembler.inline.hpp"
#include "code/debugInfoRec.hpp" #include "code/debugInfoRec.hpp"
@ -3511,6 +3514,250 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
} }
//------------------------------Montgomery multiplication------------------------
//
#ifndef _WINDOWS
#define ASM_SUBTRACT
#ifdef ASM_SUBTRACT
// Subtract 0:b from carry:a. Return carry.
static unsigned long
sub(unsigned long a[], unsigned long b[], unsigned long carry, long len) {
long i = 0, cnt = len;
unsigned long tmp;
asm volatile("clc; "
"0: ; "
"mov (%[b], %[i], 8), %[tmp]; "
"sbb %[tmp], (%[a], %[i], 8); "
"inc %[i]; dec %[cnt]; "
"jne 0b; "
"mov %[carry], %[tmp]; sbb $0, %[tmp]; "
: [i]"+r"(i), [cnt]"+r"(cnt), [tmp]"=&r"(tmp)
: [a]"r"(a), [b]"r"(b), [carry]"r"(carry)
: "memory");
return tmp;
}
#else // ASM_SUBTRACT
typedef int __attribute__((mode(TI))) int128;
// Subtract 0:b from carry:a. Return carry.
static unsigned long
sub(unsigned long a[], unsigned long b[], unsigned long carry, int len) {
int128 tmp = 0;
int i;
for (i = 0; i < len; i++) {
tmp += a[i];
tmp -= b[i];
a[i] = tmp;
tmp >>= 64;
assert(-1 <= tmp && tmp <= 0, "invariant");
}
return tmp + carry;
}
#endif // ! ASM_SUBTRACT
// Multiply (unsigned) Long A by Long B, accumulating the double-
// length result into the accumulator formed of T0, T1, and T2.
#define MACC(A, B, T0, T1, T2) \
do { \
unsigned long hi, lo; \
__asm__ ("mul %5; add %%rax, %2; adc %%rdx, %3; adc $0, %4" \
: "=&d"(hi), "=a"(lo), "+r"(T0), "+r"(T1), "+g"(T2) \
: "r"(A), "a"(B) : "cc"); \
} while(0)
// As above, but add twice the double-length result into the
// accumulator.
#define MACC2(A, B, T0, T1, T2) \
do { \
unsigned long hi, lo; \
__asm__ ("mul %5; add %%rax, %2; adc %%rdx, %3; adc $0, %4; " \
"add %%rax, %2; adc %%rdx, %3; adc $0, %4" \
: "=&d"(hi), "=a"(lo), "+r"(T0), "+r"(T1), "+g"(T2) \
: "r"(A), "a"(B) : "cc"); \
} while(0)
// Fast Montgomery multiplication. The derivation of the algorithm is
// in A Cryptographic Library for the Motorola DSP56000,
// Dusse and Kaliski, Proc. EUROCRYPT 90, pp. 230-237.
static void __attribute__((noinline))
montgomery_multiply(unsigned long a[], unsigned long b[], unsigned long n[],
unsigned long m[], unsigned long inv, int len) {
unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
int i;
assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply");
for (i = 0; i < len; i++) {
int j;
for (j = 0; j < i; j++) {
MACC(a[j], b[i-j], t0, t1, t2);
MACC(m[j], n[i-j], t0, t1, t2);
}
MACC(a[i], b[0], t0, t1, t2);
m[i] = t0 * inv;
MACC(m[i], n[0], t0, t1, t2);
assert(t0 == 0, "broken Montgomery multiply");
t0 = t1; t1 = t2; t2 = 0;
}
for (i = len; i < 2*len; i++) {
int j;
for (j = i-len+1; j < len; j++) {
MACC(a[j], b[i-j], t0, t1, t2);
MACC(m[j], n[i-j], t0, t1, t2);
}
m[i-len] = t0;
t0 = t1; t1 = t2; t2 = 0;
}
while (t0)
t0 = sub(m, n, t0, len);
}
// Fast Montgomery squaring. This uses asymptotically 25% fewer
// multiplies so it should be up to 25% faster than Montgomery
// multiplication. However, its loop control is more complex and it
// may actually run slower on some machines.
static void __attribute__((noinline))
montgomery_square(unsigned long a[], unsigned long n[],
unsigned long m[], unsigned long inv, int len) {
unsigned long t0 = 0, t1 = 0, t2 = 0; // Triple-precision accumulator
int i;
assert(inv * n[0] == -1UL, "broken inverse in Montgomery multiply");
for (i = 0; i < len; i++) {
int j;
int end = (i+1)/2;
for (j = 0; j < end; j++) {
MACC2(a[j], a[i-j], t0, t1, t2);
MACC(m[j], n[i-j], t0, t1, t2);
}
if ((i & 1) == 0) {
MACC(a[j], a[j], t0, t1, t2);
}
for (; j < i; j++) {
MACC(m[j], n[i-j], t0, t1, t2);
}
m[i] = t0 * inv;
MACC(m[i], n[0], t0, t1, t2);
assert(t0 == 0, "broken Montgomery square");
t0 = t1; t1 = t2; t2 = 0;
}
for (i = len; i < 2*len; i++) {
int start = i-len+1;
int end = start + (len - start)/2;
int j;
for (j = start; j < end; j++) {
MACC2(a[j], a[i-j], t0, t1, t2);
MACC(m[j], n[i-j], t0, t1, t2);
}
if ((i & 1) == 0) {
MACC(a[j], a[j], t0, t1, t2);
}
for (; j < len; j++) {
MACC(m[j], n[i-j], t0, t1, t2);
}
m[i-len] = t0;
t0 = t1; t1 = t2; t2 = 0;
}
while (t0)
t0 = sub(m, n, t0, len);
}
// Swap words in a longword.
static unsigned long swap(unsigned long x) {
return (x << 32) | (x >> 32);
}
// Copy len longwords from s to d, word-swapping as we go. The
// destination array is reversed.
static void reverse_words(unsigned long *s, unsigned long *d, int len) {
d += len;
while(len-- > 0) {
d--;
*d = swap(*s);
s++;
}
}
// The threshold at which squaring is advantageous was determined
// experimentally on an i7-3930K (Ivy Bridge) CPU @ 3.5GHz.
#define MONTGOMERY_SQUARING_THRESHOLD 64
void SharedRuntime::montgomery_multiply(jint *a_ints, jint *b_ints, jint *n_ints,
jint len, jlong inv,
jint *m_ints) {
assert(len % 2 == 0, "array length in montgomery_multiply must be even");
int longwords = len/2;
// Make very sure we don't use so much space that the stack might
// overflow. 512 jints corresponds to an 16384-bit integer and
// will use here a total of 8k bytes of stack space.
int total_allocation = longwords * sizeof (unsigned long) * 4;
guarantee(total_allocation <= 8192, "must be");
unsigned long *scratch = (unsigned long *)alloca(total_allocation);
// Local scratch arrays
unsigned long
*a = scratch + 0 * longwords,
*b = scratch + 1 * longwords,
*n = scratch + 2 * longwords,
*m = scratch + 3 * longwords;
reverse_words((unsigned long *)a_ints, a, longwords);
reverse_words((unsigned long *)b_ints, b, longwords);
reverse_words((unsigned long *)n_ints, n, longwords);
::montgomery_multiply(a, b, n, m, (unsigned long)inv, longwords);
reverse_words(m, (unsigned long *)m_ints, longwords);
}
void SharedRuntime::montgomery_square(jint *a_ints, jint *n_ints,
jint len, jlong inv,
jint *m_ints) {
assert(len % 2 == 0, "array length in montgomery_square must be even");
int longwords = len/2;
// Make very sure we don't use so much space that the stack might
// overflow. 512 jints corresponds to an 16384-bit integer and
// will use here a total of 6k bytes of stack space.
int total_allocation = longwords * sizeof (unsigned long) * 3;
guarantee(total_allocation <= 8192, "must be");
unsigned long *scratch = (unsigned long *)alloca(total_allocation);
// Local scratch arrays
unsigned long
*a = scratch + 0 * longwords,
*n = scratch + 1 * longwords,
*m = scratch + 2 * longwords;
reverse_words((unsigned long *)a_ints, a, longwords);
reverse_words((unsigned long *)n_ints, n, longwords);
if (len >= MONTGOMERY_SQUARING_THRESHOLD) {
::montgomery_square(a, n, m, (unsigned long)inv, longwords);
} else {
::montgomery_multiply(a, a, n, m, (unsigned long)inv, longwords);
}
reverse_words(m, (unsigned long *)m_ints, longwords);
}
#endif // WINDOWS
#ifdef COMPILER2 #ifdef COMPILER2
// This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame // This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame
// //

View File

@ -4318,7 +4318,18 @@ class StubGenerator: public StubCodeGenerator {
if (UseMulAddIntrinsic) { if (UseMulAddIntrinsic) {
StubRoutines::_mulAdd = generate_mulAdd(); StubRoutines::_mulAdd = generate_mulAdd();
} }
#endif
#ifndef _WINDOWS
if (UseMontgomeryMultiplyIntrinsic) {
StubRoutines::_montgomeryMultiply
= CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_multiply);
}
if (UseMontgomerySquareIntrinsic) {
StubRoutines::_montgomerySquare
= CAST_FROM_FN_PTR(address, SharedRuntime::montgomery_square);
}
#endif // WINDOWS
#endif // COMPILER2
} }
public: public:

View File

@ -692,10 +692,19 @@ void VM_Version::get_processor_features() {
warning("SHA instructions are not available on this CPU"); warning("SHA instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseSHA, false); FLAG_SET_DEFAULT(UseSHA, false);
} }
if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
warning("SHA intrinsics are not available on this CPU"); if (UseSHA1Intrinsics) {
warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
}
if (UseSHA256Intrinsics) {
warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
if (UseSHA512Intrinsics) {
warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
} }
@ -813,6 +822,12 @@ void VM_Version::get_processor_features() {
if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) { if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
UseMulAddIntrinsic = true; UseMulAddIntrinsic = true;
} }
if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
UseMontgomeryMultiplyIntrinsic = true;
}
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
UseMontgomerySquareIntrinsic = true;
}
#else #else
if (UseMultiplyToLenIntrinsic) { if (UseMultiplyToLenIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
@ -820,6 +835,18 @@ void VM_Version::get_processor_features() {
} }
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false); FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
} }
if (UseMontgomeryMultiplyIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
warning("montgomeryMultiply intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
}
if (UseMontgomerySquareIntrinsic) {
if (!FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
warning("montgomerySquare intrinsic is not available in 32-bit VM");
}
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
}
if (UseSquareToLenIntrinsic) { if (UseSquareToLenIntrinsic) {
if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
warning("squareToLen intrinsic is not available in 32-bit VM"); warning("squareToLen intrinsic is not available in 32-bit VM");

View File

@ -117,7 +117,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
masm->flush(); masm->flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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()), vtable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
@ -198,7 +198,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
masm->flush(); masm->flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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()), itable_index, p2i(s->entry_point()),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));

View File

@ -112,7 +112,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
__ flush(); __ flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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(), vtable_index, s->entry_point(),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));
@ -205,7 +205,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
__ flush(); __ flush();
if (PrintMiscellaneous && (WizardMode || Verbose)) { 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(), itable_index, s->entry_point(),
(int)(s->code_end() - s->entry_point()), (int)(s->code_end() - s->entry_point()),
(int)(s->code_end() - __ pc())); (int)(s->code_end() - __ pc()));

View File

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2009 Red Hat, Inc. * Copyright 2009, 2015, Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -28,10 +28,4 @@
#include <ffi.h> #include <ffi.h>
// Indicates whether the C calling conventions require that
// 32-bit integer argument values are properly extended to 64 bits.
// If set, SharedRuntime::c_calling_convention() must adapt
// signatures accordingly.
const bool CCallingConventionRequiresIntsAsLongs = false;
#endif // CPU_ZERO_VM_GLOBALDEFINITIONS_ZERO_HPP #endif // CPU_ZERO_VM_GLOBALDEFINITIONS_ZERO_HPP

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 struct sigaction sact[MAXSIGNUM]; /* saved signal handlers */
static unsigned int jvmsigs = 0; /* signals used by jvm */ 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 */ /* used to synchronize the installation of signal handlers */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 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, static sa_handler_t call_os_signal(int sig, sa_handler_t disp,
bool is_sigset) { bool is_sigset) {
sa_handler_t res;
if (os_signal == NULL) { if (os_signal == NULL) {
if (!is_sigset) { if (!is_sigset) {
os_signal = (signal_t)dlsym(RTLD_NEXT, "signal"); 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); 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) { 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; bool sigused;
struct sigaction oldAct; struct sigaction oldAct;
if (reentry) {
return call_os_sigaction(sig, act, oact);
}
signal_lock(); signal_lock();
sigused = (MASK(sig) & jvmsigs) != 0; sigused = (MASK(sig) & jvmsigs) != 0;

View File

@ -59,6 +59,7 @@
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/threadCritical.hpp" #include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp" #include "runtime/timer.hpp"
#include "semaphore_bsd.hpp"
#include "services/attachListener.hpp" #include "services/attachListener.hpp"
#include "services/memTracker.hpp" #include "services/memTracker.hpp"
#include "services/runtimeService.hpp" #include "services/runtimeService.hpp"
@ -1940,47 +1941,54 @@ typedef sem_t os_semaphore_t;
#define SEM_DESTROY(sem) sem_destroy(&sem) #define SEM_DESTROY(sem) sem_destroy(&sem)
#endif #endif
class Semaphore : public StackObj { #ifdef __APPLE__
public: // OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
Semaphore();
~Semaphore();
void signal();
void wait();
bool trywait();
bool timedwait(unsigned int sec, int nsec);
private:
jlong currenttime() const;
os_semaphore_t _semaphore;
};
Semaphore::Semaphore() : _semaphore(0) { static const char* sem_init_strerror(kern_return_t value) {
SEM_INIT(_semaphore, 0); 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); SEM_DESTROY(_semaphore);
} }
void Semaphore::signal() { void OSXSemaphore::signal(uint count) {
SEM_POST(_semaphore); 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() { void OSXSemaphore::wait() {
SEM_WAIT(_semaphore); 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; struct timeval tv;
gettimeofday(&tv, NULL); gettimeofday(&tv, NULL);
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
} }
#ifdef __APPLE__ bool OSXSemaphore::trywait() {
bool Semaphore::trywait() {
return timedwait(0, 0); 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; kern_return_t kr = KERN_ABORTED;
mach_timespec_t waitspec; mach_timespec_t waitspec;
waitspec.tv_sec = sec; waitspec.tv_sec = sec;
@ -2011,33 +2019,24 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) {
} }
#else #else
// Use POSIX implementation of semaphores.
bool Semaphore::trywait() { struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
return sem_trywait(&_semaphore) == 0;
}
bool Semaphore::timedwait(unsigned int sec, int nsec) {
struct timespec ts; struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
while (1) { return ts;
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;
}
}
} }
#endif // __APPLE__ #endif // __APPLE__
static os_semaphore_t sig_sem; 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() { void os::signal_init_pd() {
// Initialize signal structures // Initialize signal structures

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef OS_BSD_VM_SEMAPHORE_BSD_HPP
#define OS_BSD_VM_SEMAPHORE_BSD_HPP
#ifndef __APPLE__
// Use POSIX semaphores.
# include "semaphore_posix.hpp"
#else
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
# include "memory/allocation.hpp"
# include <mach/semaphore.h>
class OSXSemaphore : public CHeapObj<mtInternal>{
semaphore_t _semaphore;
// Prevent copying and assignment.
OSXSemaphore(const OSXSemaphore&);
OSXSemaphore& operator=(const OSXSemaphore&);
public:
OSXSemaphore(uint value = 0);
~OSXSemaphore();
void signal(uint count = 1);
void wait();
bool trywait();
bool timedwait(unsigned int sec, int nsec);
private:
static jlong currenttime();
};
typedef OSXSemaphore SemaphoreImpl;
#endif // __APPLE__
#endif // OS_BSD_VM_SEMAPHORE_BSD_HPP

View File

@ -60,6 +60,7 @@
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/threadCritical.hpp" #include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp" #include "runtime/timer.hpp"
#include "semaphore_posix.hpp"
#include "services/attachListener.hpp" #include "services/attachListener.hpp"
#include "services/memTracker.hpp" #include "services/memTracker.hpp"
#include "services/runtimeService.hpp" #include "services/runtimeService.hpp"
@ -2315,40 +2316,7 @@ void* os::user_handler() {
return CAST_FROM_FN_PTR(void*, UserHandler); return CAST_FROM_FN_PTR(void*, UserHandler);
} }
class Semaphore : public StackObj { struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
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 ts; struct timespec ts;
// Semaphore's are always associated with CLOCK_REALTIME // Semaphore's are always associated with CLOCK_REALTIME
os::Linux::clock_gettime(CLOCK_REALTIME, &ts); os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
@ -2365,18 +2333,7 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) {
} }
} }
while (1) { return ts;
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;
}
}
} }
extern "C" { extern "C" {
@ -2416,7 +2373,7 @@ static volatile jint pending_signals[NSIG+1] = { 0 };
// Linux(POSIX) specific hand shaking semaphore. // Linux(POSIX) specific hand shaking semaphore.
static sem_t sig_sem; static sem_t sig_sem;
static Semaphore sr_semaphore; static PosixSemaphore sr_semaphore;
void os::signal_init_pd() { void os::signal_init_pd() {
// Initialize signal structures // Initialize signal structures

View File

@ -24,6 +24,7 @@
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
#include "prims/jvm.h" #include "prims/jvm.h"
#include "semaphore_posix.hpp"
#include "runtime/frame.inline.hpp" #include "runtime/frame.inline.hpp"
#include "runtime/interfaceSupport.hpp" #include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
@ -34,6 +35,7 @@
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h>
#include <signal.h> #include <signal.h>
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@ -1015,3 +1017,73 @@ void os::WatcherThreadCrashProtection::check_crash_protection(int sig,
} }
} }
} }
#define check_with_errno(check_type, cond, msg) \
do { \
int err = errno; \
check_type(cond, err_msg("%s; error='%s' (errno=%d)", msg, strerror(err), err)); \
} while (false)
#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg)
#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
// POSIX unamed semaphores are not supported on OS X.
#ifndef __APPLE__
PosixSemaphore::PosixSemaphore(uint value) {
int ret = sem_init(&_semaphore, 0, value);
guarantee_with_errno(ret == 0, "Failed to initialize semaphore");
}
PosixSemaphore::~PosixSemaphore() {
sem_destroy(&_semaphore);
}
void PosixSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
int ret = sem_post(&_semaphore);
assert_with_errno(ret == 0, "sem_post failed");
}
}
void PosixSemaphore::wait() {
int ret;
do {
ret = sem_wait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0, "sem_wait failed");
}
bool PosixSemaphore::trywait() {
int ret;
do {
ret = sem_trywait(&_semaphore);
} while (ret != 0 && errno == EINTR);
assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed");
return ret == 0;
}
bool PosixSemaphore::timedwait(const struct timespec ts) {
while (true) {
int result = sem_timedwait(&_semaphore, &ts);
if (result == 0) {
return true;
} else if (errno == EINTR) {
continue;
} else if (errno == ETIMEDOUT) {
return false;
} else {
assert_with_errno(false, "timedwait failed");
return false;
}
}
}
#endif // __APPLE__

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef OS_POSIX_VM_SEMAPHORE_POSIX_HPP
#define OS_POSIX_VM_SEMAPHORE_POSIX_HPP
#include "memory/allocation.hpp"
#include <semaphore.h>
class PosixSemaphore : public CHeapObj<mtInternal> {
sem_t _semaphore;
// Prevent copying and assignment.
PosixSemaphore(const PosixSemaphore&);
PosixSemaphore& operator=(const PosixSemaphore&);
public:
PosixSemaphore(uint value = 0);
~PosixSemaphore();
void signal(uint count = 1);
void wait();
bool trywait();
bool timedwait(unsigned int sec, int nsec) {
return timedwait(create_timespec(sec, nsec));
}
private:
bool timedwait(struct timespec ts);
// OS specific implementation to create a timespec suitable for semaphores.
struct timespec create_timespec(unsigned int set, int nsec);
};
typedef PosixSemaphore SemaphoreImpl;
#endif // OS_POSIX_VM_SEMAPHORE_POSIX_HPP

View File

@ -60,6 +60,7 @@
#include "runtime/threadCritical.hpp" #include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp" #include "runtime/timer.hpp"
#include "runtime/vm_version.hpp" #include "runtime/vm_version.hpp"
#include "semaphore_posix.hpp"
#include "services/attachListener.hpp" #include "services/attachListener.hpp"
#include "services/memTracker.hpp" #include "services/memTracker.hpp"
#include "services/runtimeService.hpp" #include "services/runtimeService.hpp"
@ -2263,55 +2264,11 @@ void* os::user_handler() {
return CAST_FROM_FN_PTR(void*, UserHandler); return CAST_FROM_FN_PTR(void*, UserHandler);
} }
class Semaphore : public StackObj { struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
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 ts; struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
while (1) { return ts;
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;
}
}
} }
extern "C" { extern "C" {
@ -3711,7 +3668,7 @@ static void suspend_save_context(OSThread *osthread, ucontext_t* context) {
osthread->set_ucontext(context); osthread->set_ucontext(context);
} }
static Semaphore sr_semaphore; static PosixSemaphore sr_semaphore;
void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
// Save and restore errno to avoid confusing native code with EINTR // Save and restore errno to avoid confusing native code with EINTR

View File

@ -63,6 +63,7 @@
#include "runtime/threadCritical.hpp" #include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp" #include "runtime/timer.hpp"
#include "runtime/vm_version.hpp" #include "runtime/vm_version.hpp"
#include "semaphore_windows.hpp"
#include "services/attachListener.hpp" #include "services/attachListener.hpp"
#include "services/memTracker.hpp" #include "services/memTracker.hpp"
#include "services/runtimeService.hpp" #include "services/runtimeService.hpp"
@ -1901,6 +1902,30 @@ int os::get_last_error() {
return (int)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 // sun.misc.Signal
// NOTE that this is a workaround for an apparent kernel bug where if // NOTE that this is a workaround for an apparent kernel bug where if
// a signal handler for SIGBREAK is installed then that signal handler // 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); char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), NULL, false);
if (result == NULL) { if (result == NULL) {
if (VerboseInternalVMTests) { 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); large_allocation_size);
} }
} else { } 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); char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), expected_location, false);
if (actual_location == NULL) { if (actual_location == NULL) {
if (VerboseInternalVMTests) { 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); expected_location, large_allocation_size);
} }
} else { } else {
@ -5911,7 +5936,7 @@ void TestReserveMemorySpecial_test() {
os::release_memory_special(actual_location, expected_allocation_size); os::release_memory_special(actual_location, expected_allocation_size);
// only now check, after releasing any memory to avoid any leaks. // only now check, after releasing any memory to avoid any leaks.
assert(actual_location == expected_location, 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)); expected_location, expected_allocation_size, actual_location));
} }
} }

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP
#define OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP
#include "memory/allocation.hpp"
#include <windef.h>
class WindowsSemaphore : public CHeapObj<mtInternal> {
HANDLE _semaphore;
// Prevent copying and assignment.
WindowsSemaphore(const WindowsSemaphore&);
WindowsSemaphore& operator=(const WindowsSemaphore&);
public:
WindowsSemaphore(uint value = 0);
~WindowsSemaphore();
void signal(uint count = 1);
void wait();
};
typedef WindowsSemaphore SemaphoreImpl;
#endif // OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP

View File

@ -191,7 +191,7 @@ public:
return CPUVisitor::visit(nodeh, state); return CPUVisitor::visit(nodeh, state);
} }
PICL(bool is_fujitsu) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) { PICL(bool is_fujitsu, bool is_sun4v) : _L1_data_cache_line_size(0), _L2_data_cache_line_size(0), _dl_handle(NULL) {
if (!open_library()) { if (!open_library()) {
return; return;
} }
@ -203,7 +203,7 @@ public:
if (is_fujitsu) { if (is_fujitsu) {
cpu_class = "core"; cpu_class = "core";
} }
CPUVisitor cpu_visitor(this, os::processor_count()); CPUVisitor cpu_visitor(this, (is_sun4v && !is_fujitsu) ? 1 : os::processor_count());
_picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper); _picl_walk_tree_by_class(rooth, cpu_class, &cpu_visitor, PICL_visit_cpu_helper);
if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value? if (cpu_visitor.l1_visitor()->is_assigned()) { // Is there a value?
_L1_data_cache_line_size = cpu_visitor.l1_visitor()->value(); _L1_data_cache_line_size = cpu_visitor.l1_visitor()->value();
@ -447,7 +447,7 @@ int VM_Version::platform_features(int features) {
} }
// Figure out cache line sizes using PICL // Figure out cache line sizes using PICL
PICL picl((features & sparc64_family_m) != 0); PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0);
_L1_data_cache_line_size = picl.L1_data_cache_line_size(); _L1_data_cache_line_size = picl.L1_data_cache_line_size();
_L2_data_cache_line_size = picl.L2_data_cache_line_size(); _L2_data_cache_line_size = picl.L2_data_cache_line_size();

View File

@ -70,7 +70,8 @@ CONFIGURE_ARGS= --host=$(MINGW) --target=$(MINGW)
else #linux else #linux
CPU = $(shell uname -m) CPU = $(shell uname -m)
ARCH1=$(CPU:x86_64=amd64) ARCH1=$(CPU:x86_64=amd64)
ARCH=$(ARCH1:i686=i386) ARCH2=$(ARCH1:i686=i386)
ARCH=$(ARCH2:ppc64le=ppc64)
ifdef LP64 ifdef LP64
CFLAGS/sparcv9 += -m64 CFLAGS/sparcv9 += -m64
CFLAGS/amd64 += -m64 CFLAGS/amd64 += -m64

View File

@ -1093,9 +1093,11 @@ void CodeStrings::add_comment(intptr_t offset, const char * comment) {
void CodeStrings::assign(CodeStrings& other) { void CodeStrings::assign(CodeStrings& other) {
other.check_valid(); other.check_valid();
// Cannot do following because CodeStrings constructor is not alway run!
assert(is_null(), "Cannot assign onto non-empty CodeStrings"); assert(is_null(), "Cannot assign onto non-empty CodeStrings");
_strings = other._strings; _strings = other._strings;
#ifdef ASSERT
_defunct = false;
#endif
other.set_null_and_invalidate(); 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 { void CodeStrings::print_block_comment(outputStream* stream, intptr_t offset) const {
check_valid(); check_valid();
if (_strings != NULL) { if (_strings != NULL) {
CodeString* c = find(offset); CodeString* c = find(offset);
while (c && c->offset() == offset) { while (c && c->offset() == offset) {
stream->bol(); stream->bol();
stream->print(" ;; "); stream->print("%s", _prefix);
stream->print_cr("%s", c->string()); stream->print_cr("%s", c->string());
c = c->next_comment(); c = c->next_comment();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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. // Becomes true after copy-out, forbids further use.
bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env bool _defunct; // Zero bit pattern is "valid", see memset call in decode_env::decode_env
#endif #endif
static const char* _prefix; // defaults to " ;; "
#endif #endif
CodeString* find(intptr_t offset) const; CodeString* find(intptr_t offset) const;
@ -289,11 +290,18 @@ public:
void assign(CodeStrings& other) PRODUCT_RETURN; void assign(CodeStrings& other) PRODUCT_RETURN;
// COPY strings from other to this; leave other valid. // COPY strings from other to this; leave other valid.
void copy(CodeStrings& other) PRODUCT_RETURN; void copy(CodeStrings& other) PRODUCT_RETURN;
// FREE strings; invalidate this.
void free() PRODUCT_RETURN; 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 { inline void check_valid() const {
#ifdef ASSERT #ifdef ASSERT
assert(!_defunct, "Use of invalid CodeStrings"); assert(!_defunct, "Use of invalid CodeStrings");
#endif
}
static void set_prefix(const char *prefix) {
#ifndef PRODUCT
_prefix = prefix;
#endif #endif
} }
}; };
@ -379,6 +387,7 @@ class CodeBuffer: public StackObj {
_oop_recorder = NULL; _oop_recorder = NULL;
_decode_begin = NULL; _decode_begin = NULL;
_overflow_arena = NULL; _overflow_arena = NULL;
_code_strings = CodeStrings();
} }
void initialize(address code_start, csize_t code_size) { void initialize(address code_start, csize_t code_size) {
@ -495,6 +504,7 @@ class CodeBuffer: public StackObj {
// Properties // Properties
const char* name() const { return _name; } const char* name() const { return _name; }
void set_name(const char* name) { _name = name; }
CodeBuffer* before_expand() const { return _before_expand; } CodeBuffer* before_expand() const { return _before_expand; }
BufferBlob* blob() const { return _blob; } BufferBlob* blob() const { return _blob; }
void set_blob(BufferBlob* blob); void set_blob(BufferBlob* blob);

View File

@ -161,7 +161,7 @@ void CFGPrinterOutput::print_compilation() {
print("name \"%s\"", method_name(_compilation->method(), true)); print("name \"%s\"", method_name(_compilation->method(), true));
print("method \"%s\"", method_name(_compilation->method())); 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"); print_end("compilation");
} }

View File

@ -3157,6 +3157,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
// code for the inlined version will be different than the root // code for the inlined version will be different than the root
// compiled version which could lead to monotonicity problems on // compiled version which could lead to monotonicity problems on
// intel. // intel.
if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) {
BAILOUT("failed to inline intrinsic, method not annotated");
}
// Set up a stream so that appending instructions works properly. // Set up a stream so that appending instructions works properly.
ciBytecodeStream s(scope->method()); ciBytecodeStream s(scope->method());
@ -3197,6 +3200,9 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
// result in the referent being marked live and the reference // result in the referent being marked live and the reference
// object removed from the list of discovered references during // object removed from the list of discovered references during
// reference processing. // reference processing.
if (CheckIntrinsics && !scope->method()->intrinsic_candidate()) {
BAILOUT("failed to inline intrinsic, method not annotated");
}
// Also we need intrinsic to prevent commoning reads from this field // Also we need intrinsic to prevent commoning reads from this field
// across safepoint since GC can change its value. // across safepoint since GC can change its value.
@ -3317,7 +3323,8 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Bytecodes::Co
} }
// handle intrinsics // handle intrinsics
if (callee->intrinsic_id() != vmIntrinsics::_none) { if (callee->intrinsic_id() != vmIntrinsics::_none &&
(CheckIntrinsics ? callee->intrinsic_candidate() : true)) {
if (try_inline_intrinsics(callee)) { if (try_inline_intrinsics(callee)) {
print_inlining(callee, "intrinsic"); print_inlining(callee, "intrinsic");
return true; return true;
@ -4278,7 +4285,7 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
assert(result_type->is_int(), "int result"); assert(result_type->is_int(), "int result");
Values* args = state()->pop_arguments(callee->arg_size()); Values* args = state()->pop_arguments(callee->arg_size());
// Pop off some args to speically handle, then push back // Pop off some args to specially handle, then push back
Value newval = args->pop(); Value newval = args->pop();
Value cmpval = args->pop(); Value cmpval = args->pop();
Value offset = args->pop(); Value offset = args->pop();

View File

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

View File

@ -33,6 +33,7 @@
#include "classfile/systemDictionary.hpp" #include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "code/codeBlob.hpp" #include "code/codeBlob.hpp"
#include "code/codeCacheExtensions.hpp"
#include "code/compiledIC.hpp" #include "code/compiledIC.hpp"
#include "code/pcDesc.hpp" #include "code/pcDesc.hpp"
#include "code/scopeDesc.hpp" #include "code/scopeDesc.hpp"
@ -183,12 +184,17 @@ void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
// create code buffer for code storage // create code buffer for code storage
CodeBuffer code(buffer_blob); CodeBuffer code(buffer_blob);
OopMapSet* oop_maps;
int frame_size;
bool must_gc_arguments;
if (!CodeCacheExtensions::skip_compiler_support()) {
// bypass useless code generation
Compilation::setup_code_buffer(&code, 0); Compilation::setup_code_buffer(&code, 0);
// create assembler for code generation // create assembler for code generation
StubAssembler* sasm = new StubAssembler(&code, name_for(id), id); StubAssembler* sasm = new StubAssembler(&code, name_for(id), id);
// generate code for runtime stub // generate code for runtime stub
OopMapSet* oop_maps;
oop_maps = generate_code_for(id, sasm); oop_maps = generate_code_for(id, sasm);
assert(oop_maps == NULL || sasm->frame_size() != no_frame_size, assert(oop_maps == NULL || sasm->frame_size() != no_frame_size,
"if stub has an oop map it must have a valid frame size"); "if stub has an oop map it must have a valid frame size");
@ -219,13 +225,22 @@ void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
sasm->align(BytesPerWord); sasm->align(BytesPerWord);
// make sure all code is in code buffer // make sure all code is in code buffer
sasm->flush(); 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 // create blob - distinguish a few special cases
CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id), CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id),
&code, &code,
CodeOffsets::frame_never_safe, CodeOffsets::frame_never_safe,
sasm->frame_size(), frame_size,
oop_maps, oop_maps,
sasm->must_gc_arguments()); must_gc_arguments);
// install blob // install blob
assert(blob != NULL, "blob must exist"); assert(blob != NULL, "blob must exist");
_blobs[id] = blob; _blobs[id] = blob;
@ -399,7 +414,7 @@ static nmethod* counter_overflow_helper(JavaThread* THREAD, int branch_bci, Meth
CompLevel level = (CompLevel)nm->comp_level(); CompLevel level = (CompLevel)nm->comp_level();
int bci = InvocationEntryBci; int bci = InvocationEntryBci;
if (branch_bci != InvocationEntryBci) { if (branch_bci != InvocationEntryBci) {
// Compute desination bci // Compute destination bci
address pc = method()->code_base() + branch_bci; address pc = method()->code_base() + branch_bci;
Bytecodes::Code branch = Bytecodes::code_at(method(), pc); Bytecodes::Code branch = Bytecodes::code_at(method(), pc);
int offset = 0; int offset = 0;

View File

@ -1185,7 +1185,6 @@ vmIntrinsics::ID BCEscapeAnalyzer::known_intrinsic() {
vmIntrinsics::ID iid = method()->intrinsic_id(); vmIntrinsics::ID iid = method()->intrinsic_id();
if (iid == vmIntrinsics::_getClass || if (iid == vmIntrinsics::_getClass ||
iid == vmIntrinsics::_fillInStackTrace ||
iid == vmIntrinsics::_hashCode) iid == vmIntrinsics::_hashCode)
return iid; return iid;
else else
@ -1199,10 +1198,6 @@ bool BCEscapeAnalyzer::compute_escape_for_intrinsic(vmIntrinsics::ID iid) {
case vmIntrinsics::_getClass: case vmIntrinsics::_getClass:
_return_local = false; _return_local = false;
break; break;
case vmIntrinsics::_fillInStackTrace:
arg.set(0); // 'this'
set_returned(arg);
break;
case vmIntrinsics::_hashCode: case vmIntrinsics::_hashCode:
// initialized state is correct // initialized state is correct
break; break;

View File

@ -181,6 +181,7 @@ class ciMethod : public ciMetadata {
bool caller_sensitive() const { return get_Method()->caller_sensitive(); } bool caller_sensitive() const { return get_Method()->caller_sensitive(); }
bool force_inline() const { return get_Method()->force_inline(); } bool force_inline() const { return get_Method()->force_inline(); }
bool dont_inline() const { return get_Method()->dont_inline(); } bool dont_inline() const { return get_Method()->dont_inline(); }
bool intrinsic_candidate() const { return get_Method()->intrinsic_candidate(); }
int comp_level(); int comp_level();
int highest_osr_comp_level(); int highest_osr_comp_level();

View File

@ -1751,6 +1751,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
if (_location != _in_method) break; // only allow for methods if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code if (!privileged) break; // only allow in privileged code
return _method_LambdaForm_Hidden; return _method_LambdaForm_Hidden;
case vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_HotSpotIntrinsicCandidate_signature):
if (_location != _in_method) break; // only allow for methods
if (!privileged) break; // only allow in privileged code
return _method_HotSpotIntrinsicCandidate;
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature): case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_Stable_signature):
if (_location != _in_field) break; // only allow for fields if (_location != _in_field) break; // only allow for fields
if (!privileged) break; // only allow in privileged code if (!privileged) break; // only allow in privileged code
@ -1790,6 +1794,8 @@ void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm); m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm);
if (has_annotation(_method_LambdaForm_Hidden)) if (has_annotation(_method_LambdaForm_Hidden))
m->set_hidden(true); m->set_hidden(true);
if (has_annotation(_method_HotSpotIntrinsicCandidate) && !m->is_synthetic())
m->set_intrinsic_candidate(true);
} }
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) { void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
@ -4132,9 +4138,78 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// (We used to do this lazily, but now we query it in Rewriter, // (We used to do this lazily, but now we query it in Rewriter,
// which is eagerly done for every method, so we might as well do it now, // which is eagerly done for every method, so we might as well do it now,
// when everything is fresh in memory.) // when everything is fresh in memory.)
if (Method::klass_id_for_intrinsics(this_klass()) != vmSymbols::NO_SID) { vmSymbols::SID klass_id = Method::klass_id_for_intrinsics(this_klass());
if (klass_id != vmSymbols::NO_SID) {
for (int j = 0; j < methods->length(); j++) { for (int j = 0; j < methods->length(); j++) {
methods->at(j)->init_intrinsic_id(); Method* method = methods->at(j);
method->init_intrinsic_id();
if (CheckIntrinsics) {
// Check if an intrinsic is defined for method 'method',
// but the method is not annotated with @HotSpotIntrinsicCandidate.
if (method->intrinsic_id() != vmIntrinsics::_none &&
!method->intrinsic_candidate()) {
tty->print("Compiler intrinsic is defined for method [%s], "
"but the method is not annotated with @HotSpotIntrinsicCandidate.%s",
method->name_and_sig_as_C_string(),
NOT_DEBUG(" Method will not be inlined.") DEBUG_ONLY(" Exiting.")
);
tty->cr();
DEBUG_ONLY(vm_exit(1));
}
// Check is the method 'method' is annotated with @HotSpotIntrinsicCandidate,
// but there is no intrinsic available for it.
if (method->intrinsic_candidate() &&
method->intrinsic_id() == vmIntrinsics::_none) {
tty->print("Method [%s] is annotated with @HotSpotIntrinsicCandidate, "
"but no compiler intrinsic is defined for the method.%s",
method->name_and_sig_as_C_string(),
NOT_DEBUG("") DEBUG_ONLY(" Exiting.")
);
tty->cr();
DEBUG_ONLY(vm_exit(1));
}
}
}
if (CheckIntrinsics) {
// Check for orphan methods in the current class. A method m
// of a class C is orphan if an intrinsic is defined for method m,
// but class C does not declare m.
for (int id = vmIntrinsics::FIRST_ID; id < (int)vmIntrinsics::ID_LIMIT; id++) {
if (id == vmIntrinsics::_compiledLambdaForm) {
// The _compiledLamdbdaForm intrinsic is a special marker for bytecode
// generated for the JVM from a LambdaForm and therefore no method
// is defined for it.
continue;
}
if (vmIntrinsics::class_for(vmIntrinsics::ID_from(id)) == klass_id) {
// Check if the current class contains a method with the same
// name, flags, signature.
bool match = false;
for (int j = 0; j < methods->length(); j++) {
Method* method = methods->at(j);
if (id == method->intrinsic_id()) {
match = true;
break;
}
}
if (!match) {
char buf[1000];
tty->print("Compiler intrinsic is defined for method [%s], "
"but the method is not available in class [%s].%s",
vmIntrinsics::short_name_as_C_string(vmIntrinsics::ID_from(id), buf, sizeof(buf)),
this_klass->name()->as_C_string(),
NOT_DEBUG("") DEBUG_ONLY(" Exiting.")
);
tty->cr();
DEBUG_ONLY(vm_exit(1));
}
}
}
} }
} }

View File

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

View File

@ -68,7 +68,6 @@
#include "classfile/sharedPathsMiscInfo.hpp" #include "classfile/sharedPathsMiscInfo.hpp"
#endif #endif
// Entry points in zip.dll for loading zip/jar file entries and image file entries // 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); 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() { ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass); char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
strcpy(copy, dir); strcpy(copy, dir);
_dir = copy; _dir = copy;
} }
ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) { ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
// construct full path name // construct full path name
char path[JVM_MAXPATHLEN]; 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() { ClassPathImageEntry::ClassPathImageEntry(ImageFileReader* image) :
_path = os::strdup_check_oom(path); ClassPathEntry(),
_st = *st; _image(image),
_resolved_entry = NULL; _module_data(NULL) {
_has_error = false; guarantee(image != NULL, "image file is null");
_throw_exception = throw_exception;
}
LazyClassPathEntry::~LazyClassPathEntry() { char module_data_name[JVM_MAXPATHLEN];
os::free((void*)_path); ImageModuleData::module_data_name(module_data_name, _image->name());
} _module_data = new ImageModuleData(_image, module_data_name);
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;
}
} }
ClassPathImageEntry::~ClassPathImageEntry() { ClassPathImageEntry::~ClassPathImageEntry() {
if (_image) { if (_module_data != NULL) {
_image->close(); delete _module_data;
_module_data = NULL;
}
if (_image != NULL) {
ImageFileReader::close(_image);
_image = NULL; _image = NULL;
} }
} }
@ -371,15 +300,39 @@ const char* ClassPathImageEntry::name() {
} }
ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) { ClassFileStream* ClassPathImageEntry::open_stream(const char* name, TRAPS) {
u1* buffer; ImageLocation location;
u8 size; bool found = _image->find_location(name, location);
_image->get_resource(name, buffer, size);
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) { if (UsePerfData) {
ClassLoader::perf_sys_classfile_bytes_read()->inc(size); 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; return NULL;
@ -391,20 +344,14 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
tty->cr(); tty->cr();
const ImageStrings strings = _image->get_strings(); const ImageStrings strings = _image->get_strings();
// Retrieve each path component string. // Retrieve each path component string.
u4 count = _image->get_location_count(); u4 length = _image->table_length();
for (u4 i = 0; i < count; i++) { for (u4 i = 0; i < length; i++) {
u1* location_data = _image->get_location_data(i); u1* location_data = _image->get_location_data(i);
if (location_data) { if (location_data != NULL) {
ImageLocation location(location_data); ImageLocation location(location_data);
const char* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings); char path[IMAGE_MAX_PATH];
const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings); _image->location_path(location, path, IMAGE_MAX_PATH);
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);
ClassLoader::compile_the_world_in(path, loader, CHECK); ClassLoader::compile_the_world_in(path, loader, CHECK);
} }
} }
@ -420,7 +367,7 @@ void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
} }
bool ClassPathImageEntry::is_jrt() { bool ClassPathImageEntry::is_jrt() {
return string_ends_with(name(), "bootmodules.jimage"); return string_ends_with(name(), BOOT_IMAGE_NAME);
} }
#endif #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, 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(); JavaThread* thread = JavaThread::current();
if (lazy) {
return new LazyClassPathEntry(path, st, throw_exception);
}
ClassPathEntry* new_entry = NULL; ClassPathEntry* new_entry = NULL;
if ((st->st_mode & S_IFREG) == S_IFREG) { if ((st->st_mode & S_IFREG) == S_IFREG) {
// Regular file, should be a zip or image file // Regular file, should be a zip or image file
@ -557,10 +501,9 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
return NULL; return NULL;
} }
} }
// TODO - add proper criteria for selecting image file ImageFileReader* image = ImageFileReader::open(canonical_path);
ClassPathImageEntry* entry = new ClassPathImageEntry(canonical_path); if (image != NULL) {
if (entry->is_open()) { new_entry = new ClassPathImageEntry(image);
new_entry = entry;
} else { } else {
char* error_msg = NULL; char* error_msg = NULL;
jzfile* zip; jzfile* zip;
@ -583,7 +526,8 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
msg = NEW_RESOURCE_ARRAY(char, len); ; msg = NEW_RESOURCE_ARRAY(char, len); ;
jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path);
} }
if (throw_exception) { // 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); THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL);
} else { } else {
return NULL; return NULL;
@ -666,7 +610,7 @@ bool ClassLoader::update_class_path_entry_list(const char *path,
// File or directory found // File or directory found
ClassPathEntry* new_entry = NULL; ClassPathEntry* new_entry = NULL;
Thread* THREAD = Thread::current(); 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) { if (new_entry == NULL) {
return false; return false;
} }
@ -1319,19 +1263,6 @@ bool ClassPathZipEntry::is_jrt() {
return false; 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() { void ClassLoader::compile_the_world() {
EXCEPTION_MARK; EXCEPTION_MARK;
HandleMark hm(THREAD); HandleMark hm(THREAD);

View File

@ -32,9 +32,14 @@
// The VM class loader. // The VM class loader.
#include <sys/stat.h> #include <sys/stat.h>
// Name of boot module image
#define BOOT_IMAGE_NAME "bootmodules.jimage"
// Class path entry (directory or zip file) // Class path entry (directory or zip file)
class ImageFileReader;
class ImageModuleData;
class ClassPathEntry: public CHeapObj<mtClass> { class ClassPathEntry: public CHeapObj<mtClass> {
private: private:
ClassPathEntry* _next; ClassPathEntry* _next;
@ -47,7 +52,7 @@ class ClassPathEntry: public CHeapObj<mtClass> {
} }
virtual bool is_jar_file() = 0; virtual bool is_jar_file() = 0;
virtual const char* name() = 0; virtual const char* name() = 0;
virtual bool is_lazy(); virtual ImageFileReader* image() = 0;
// Constructor // Constructor
ClassPathEntry(); ClassPathEntry();
// Attempt to locate file_name through this class path entry. // Attempt to locate file_name through this class path entry.
@ -65,6 +70,7 @@ class ClassPathDirEntry: public ClassPathEntry {
public: public:
bool is_jar_file() { return false; } bool is_jar_file() { return false; }
const char* name() { return _dir; } const char* name() { return _dir; }
ImageFileReader* image() { return NULL; }
ClassPathDirEntry(const char* dir); ClassPathDirEntry(const char* dir);
ClassFileStream* open_stream(const char* name, TRAPS); ClassFileStream* open_stream(const char* name, TRAPS);
// Debugging // Debugging
@ -94,6 +100,7 @@ class ClassPathZipEntry: public ClassPathEntry {
public: public:
bool is_jar_file() { return true; } bool is_jar_file() { return true; }
const char* name() { return _zip_name; } const char* name() { return _zip_name; }
ImageFileReader* image() { return NULL; }
ClassPathZipEntry(jzfile* zip, const char* zip_name); ClassPathZipEntry(jzfile* zip, const char* zip_name);
~ClassPathZipEntry(); ~ClassPathZipEntry();
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); 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 // For java image files
class ImageFile;
class ClassPathImageEntry: public ClassPathEntry { class ClassPathImageEntry: public ClassPathEntry {
private: private:
ImageFile *_image; ImageFileReader* _image;
ImageModuleData* _module_data;
public: public:
bool is_jar_file() { return false; } bool is_jar_file() { return false; }
bool is_open() { return _image != NULL; } bool is_open() { return _image != NULL; }
const char* name(); const char* name();
ClassPathImageEntry(char* name); ImageFileReader* image() { return _image; }
ImageModuleData* module_data() { return _module_data; }
ClassPathImageEntry(ImageFileReader* image);
~ClassPathImageEntry(); ~ClassPathImageEntry();
ClassFileStream* open_stream(const char* name, TRAPS); ClassFileStream* open_stream(const char* name, TRAPS);
@ -157,7 +143,6 @@ class ClassLoader: AllStatic {
package_hash_table_size = 31 // Number of buckets package_hash_table_size = 31 // Number of buckets
}; };
protected: protected:
friend class LazyClassPathEntry;
// Performance counters // Performance counters
static PerfCounter* _perf_accumulated_time; static PerfCounter* _perf_accumulated_time;
@ -222,7 +207,7 @@ class ClassLoader: AllStatic {
static void load_zip_library(); static void load_zip_library();
static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st, 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 // Canonicalizes path names, so strcmp will work properly. This is mainly
// to avoid confusing the zip library // to avoid confusing the zip library

View File

@ -494,7 +494,7 @@ const char* ClassLoaderData::loader_name() {
void ClassLoaderData::dump(outputStream * const out) { void ClassLoaderData::dump(outputStream * const out) {
ResourceMark rm; 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(this), p2i((void *)class_loader()),
p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name()); p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name());
if (claimed()) out->print(" claimed "); if (claimed()) out->print(" claimed ");
@ -513,7 +513,7 @@ void ClassLoaderData::dump(outputStream * const out) {
ResourceMark rm; ResourceMark rm;
Klass* k = _klasses; Klass* k = _klasses;
while (k != NULL) { 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()); k->has_modified_oops(), k->has_accumulated_modified_oops());
assert(k != k->next_link(), "no loops!"); assert(k != k->next_link(), "no loops!");
k = k->next_link(); k = k->next_link();

View File

@ -557,7 +557,7 @@ void ProtectionDomainCacheTable::print() {
} }
void ProtectionDomainCacheEntry::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()); this, (void*)literal(), _strongly_reachable, next());
} }
#endif #endif

View File

@ -370,7 +370,7 @@ class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
void print_on(outputStream* st) const { void print_on(outputStream* st) const {
symbol()->print_value_on(st); symbol()->print_value_on(st);
st->print("/mode="INTX_FORMAT, symbol_mode()); st->print("/mode=" INTX_FORMAT, symbol_mode());
st->print(" -> "); st->print(" -> ");
bool printed = false; bool printed = false;
if (method() != NULL) { if (method() != NULL) {

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "runtime/thread.inline.hpp"
#include "precompiled.hpp"
#include "classfile/imageDecompressor.hpp"
#include "runtime/thread.hpp"
#include "utilities/bytes.hpp"
/*
* Allocate in C Heap not in resource area, otherwise JVM crashes.
* This array life time is the VM life time. Array is never freed and
* is not expected to contain more than few references.
*/
GrowableArray<ImageDecompressor*>* ImageDecompressor::_decompressors =
new(ResourceObj::C_HEAP, mtInternal) GrowableArray<ImageDecompressor*>(2, true);
static Symbol* createSymbol(const char* str) {
Thread* THREAD = Thread::current();
Symbol* sym = SymbolTable::lookup(str, (int) strlen(str), THREAD);
if (HAS_PENDING_EXCEPTION) {
warning("can't create symbol\n");
CLEAR_PENDING_EXCEPTION;
return NULL;
}
return sym;
}
/*
* Initialize the array of decompressors.
*/
bool image_decompressor_init() {
Symbol* zipSymbol = createSymbol("zip");
if (zipSymbol == NULL) {
return false;
}
ImageDecompressor::add_decompressor(new ZipDecompressor(zipSymbol));
return true;
}
/*
* Decompression entry point. Called from ImageFileReader::get_resource.
*/
void ImageDecompressor::decompress_resource(u1* compressed, u1* uncompressed,
u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap) {
bool has_header = false;
u1* decompressed_resource = compressed;
u1* compressed_resource = compressed;
// Resource could have been transformed by a stack of decompressors.
// Iterate and decompress resources until there is no more header.
do {
ResourceHeader _header;
memcpy(&_header, compressed_resource, sizeof (ResourceHeader));
has_header = _header._magic == ResourceHeader::resource_header_magic;
if (has_header) {
// decompressed_resource array contains the result of decompression
// when a resource content is terminal, it means that it is an actual resource,
// not an intermediate not fully uncompressed content. In this case
// the resource is allocated as an mtClass, otherwise as an mtOther
decompressed_resource = is_C_heap && _header._is_terminal ?
NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtClass) :
NEW_C_HEAP_ARRAY(u1, _header._uncompressed_size, mtOther);
// Retrieve the decompressor name
const char* decompressor_name = strings->get(_header._decompressor_name_offset);
if (decompressor_name == NULL) warning("image decompressor not found\n");
guarantee(decompressor_name, "image decompressor not found");
// Retrieve the decompressor instance
ImageDecompressor* decompressor = get_decompressor(decompressor_name);
if (decompressor == NULL) {
warning("image decompressor %s not found\n", decompressor_name);
}
guarantee(decompressor, "image decompressor not found");
u1* compressed_resource_base = compressed_resource;
compressed_resource += ResourceHeader::resource_header_length;
// Ask the decompressor to decompress the compressed content
decompressor->decompress_resource(compressed_resource, decompressed_resource,
&_header, strings);
if (compressed_resource_base != compressed) {
FREE_C_HEAP_ARRAY(char, compressed_resource_base);
}
compressed_resource = decompressed_resource;
}
} while (has_header);
memcpy(uncompressed, decompressed_resource, uncompressed_size);
}
// Zip decompressor
void ZipDecompressor::decompress_resource(u1* data, u1* uncompressed,
ResourceHeader* header, const ImageStrings* strings) {
char* msg = NULL;
jboolean res = ClassLoader::decompress(data, header->_size, uncompressed,
header->_uncompressed_size, &msg);
if (!res) warning("decompression failed due to %s\n", msg);
guarantee(res, "decompression failed");
}
// END Zip Decompressor

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
#define SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP
#include "runtime/thread.inline.hpp"
#include "precompiled.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/imageFile.hpp"
#include "classfile/symbolTable.hpp"
#include "oops/symbol.hpp"
#include "utilities/growableArray.hpp"
/*
* Compressed resources located in image have an header.
* This header contains:
* - _magic: A magic u4, required to retrieved the header in the compressed content
* - _size: The size of the compressed resource.
* - _uncompressed_size: The uncompressed size of the compressed resource.
* - _decompressor_name_offset: The ImageDecompressor instance name StringsTable offset.
* - _decompressor_config_offset: StringsTable offset of configuration that could be needed by
* the decompressor in order to decompress.
* - _is_terminal: 1: the compressed content is terminal. Uncompressing it would
* create the actual resource. 0: the compressed content is not terminal. Uncompressing it
* will result in a compressed content to be decompressed (This occurs when a stack of compressors
* have been used to compress the resource.
*/
struct ResourceHeader {
/* Length of header, needed to retrieve content offset */
static const u1 resource_header_length = 21;
/* magic bytes that identifies a compressed resource header*/
static const u4 resource_header_magic = 0xCAFEFAFA;
u4 _magic; // Resource header
u4 _size; // Resource size
u4 _uncompressed_size; // Expected uncompressed size
u4 _decompressor_name_offset; // Strings table decompressor offset
u4 _decompressor_config_offset; // Strings table config offset
u1 _is_terminal; // Last decompressor 1, otherwise 0.
};
/*
* Resources located in jimage file can be compressed. Compression occurs at
* jimage file creation time. When compressed a resource is added an header that
* contains the name of the compressor that compressed it.
* Various compression strategies can be applied to compress a resource.
* The same resource can even be compressed multiple time by a stack of compressors.
* At runtime, a resource is decompressed in a loop until there is no more header
* meaning that the resource is equivalent to the not compressed resource.
* In each iteration, the name of the compressor located in the current header
* is used to retrieve the associated instance of ImageDecompressor.
* For example zip is the name of the compressor that compresses resources
* using the zip algorithm. The ZipDecompressor class name is also zip.
* ImageDecompressor instances are retrieved from a static array in which
* they are registered.
*/
class ImageDecompressor: public CHeapObj<mtClass> {
private:
const Symbol* _name;
/*
* Array of concrete decompressors. This array is used to retrieve the decompressor
* that can handle resource decompression.
*/
static GrowableArray<ImageDecompressor*>* _decompressors;
/*
* Identifier of a decompressor. This name is the identification key to retrieve
* decompressor from a resource header.
*/
inline const Symbol* get_name() const { return _name; }
protected:
ImageDecompressor(const Symbol* name) : _name(name) {
}
virtual void decompress_resource(u1* data, u1* uncompressed,
ResourceHeader* header, const ImageStrings* strings) = 0;
public:
inline static void add_decompressor(ImageDecompressor* decompressor) {
_decompressors->append(decompressor);
}
inline static ImageDecompressor* get_decompressor(const char * decompressor_name) {
Thread* THREAD = Thread::current();
TempNewSymbol sym = SymbolTable::new_symbol(decompressor_name,
(int) strlen(decompressor_name), CHECK_NULL);
if (HAS_PENDING_EXCEPTION) {
warning("can't create symbol\n");
CLEAR_PENDING_EXCEPTION;
return NULL;
}
for (int i = 0; i < _decompressors->length(); i++) {
ImageDecompressor* decompressor = _decompressors->at(i);
if (decompressor->get_name()->fast_compare(sym) == 0) {
return decompressor;
}
}
guarantee(false, "No decompressor found.");
return NULL;
}
static void decompress_resource(u1* compressed, u1* uncompressed,
u4 uncompressed_size, const ImageStrings* strings, bool is_C_heap);
};
/**
* Zip decompressor.
*/
class ZipDecompressor : public ImageDecompressor {
public:
ZipDecompressor(const Symbol* sym) : ImageDecompressor(sym) { }
void decompress_resource(u1* data, u1* uncompressed, ResourceHeader* header,
const ImageStrings* strings);
};
#endif // SHARE_VM_CLASSFILE_IMAGEDECOMPRESSOR_HPP

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,77 +23,311 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/imageDecompressor.hpp"
#include "classfile/imageFile.hpp" #include "classfile/imageFile.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/mutex.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.inline.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. // Compute the Perfect Hashing hash code for the supplied UTF-8 string.
u4 ImageStrings::hash_code(const char* string, u4 seed) { s4 ImageStrings::hash_code(const char* string, s4 seed) {
// Access bytes as unsigned.
u1* bytes = (u1*)string; u1* bytes = (u1*)string;
// Compute hash code. // Compute hash code.
for (u1 byte = *bytes++; byte; byte = *bytes++) { for (u1 byte = *bytes++; byte; byte = *bytes++) {
seed = (seed * HASH_MULTIPLIER) ^ byte; seed = (seed * HASH_MULTIPLIER) ^ byte;
} }
// Ensure the result is not signed.
// Ensure the result is unsigned.
return seed & 0x7FFFFFFF; return seed & 0x7FFFFFFF;
} }
// Test to see if string begins with start. If so returns remaining portion // Match up a string in a perfect hash table. Result still needs validation
// of string. Otherwise, NULL. // 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) { const char* ImageStrings::starts_with(const char* string, const char* start) {
char ch1, ch2; char ch1, ch2;
// Match up the strings the best we can. // Match up the strings the best we can.
while ((ch1 = *string) && (ch2 = *start)) { while ((ch1 = *string) && (ch2 = *start)) {
if (ch1 != ch2) { if (ch1 != ch2) {
// Mismatch, return NULL. // Mismatch, return NULL.
return NULL; return NULL;
} }
// Next characters.
string++, start++; string++, start++;
} }
// Return remainder of string. // Return remainder of string.
return 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. // Deflate the attribute stream into an array of attributes.
memset(_attributes, 0, sizeof(_attributes));
u1 byte; u1 byte;
// Repeat until end header is found.
while ((byte = *data) != ATTRIBUTE_END) { while ((byte = *data)) {
// Extract kind from header byte.
u1 kind = attribute_kind(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); 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); _attributes[kind] = attribute_value(data + 1, n);
// Position to next attribute by skipping attribute header and data bytes.
data += n + 1; data += n + 1;
} }
} }
ImageFile::ImageFile(const char* name) { // Zero all attribute values.
// Copy the image file name. void ImageLocation::clear_data() {
_name = NEW_C_HEAP_ARRAY(char, strlen(name)+1, mtClass); // Set defaults to zero.
strcpy(_name, name); 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. // Initialize for a closed file.
_fd = -1; _fd = -1;
_memory_mapped = true; _endian = Endian::get_handler(big_endian);
_index_data = NULL; _index_data = NULL;
} }
ImageFile::~ImageFile() { // Close image and free up data structures.
ImageFileReader::~ImageFileReader() {
// Ensure file is closed. // Ensure file is closed.
close(); close();
// Free up name. // Free up name.
if (_name != NULL) {
FREE_C_HEAP_ARRAY(char, _name); 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. // If file exists open for reading.
struct stat st; struct stat st;
if (os::stat(_name, &st) != 0 || if (os::stat(_name, &st) != 0 ||
@ -101,186 +335,212 @@ bool ImageFile::open() {
(_fd = os::open(_name, 0, O_RDONLY)) == -1) { (_fd = os::open(_name, 0, O_RDONLY)) == -1) {
return false; return false;
} }
// Retrieve the file size.
// Read image file header and verify. _file_size = (u8)st.st_size;
u8 header_size = sizeof(ImageHeader); // Read image file header and verify it has a valid header.
if (os::read(_fd, &_header, header_size) != header_size || size_t header_size = sizeof(ImageHeader);
_header._magic != IMAGE_MAGIC || if (_file_size < header_size ||
_header._major_version != MAJOR_VERSION || !read_at((u1*)&_header, header_size, 0) ||
_header._minor_version != MINOR_VERSION) { _header.magic(_endian) != IMAGE_MAGIC ||
_header.major_version(_endian) != MAJOR_VERSION ||
_header.minor_version(_endian) != MINOR_VERSION) {
close(); close();
return false; return false;
} }
// Size of image index.
// Memory map index.
_index_size = index_size(); _index_size = index_size();
_index_data = (u1*)os::map_memory(_fd, _name, 0, NULL, _index_size, true, false); // Make sure file is large enough to contain the index.
if (_file_size < _index_size) {
// 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; return false;
} }
// Determine how much of the image is memory mapped.
if (os::read(_fd, _index_data, _index_size) != _index_size) { off_t map_size = (off_t)(MemoryMapImage ? _file_size : _index_size);
close(); // Memory map image (minimally the index.)
return false; _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.
return true; u4 length = table_length();
} // Compute offset of the perfect hash table redirect table.
u4 redirect_table_offset = (u4)header_size;
// Used to advance a pointer, unstructured. // Compute offset of index attribute offsets.
#undef nextPtr u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
#define nextPtr(base, fromType, count, toType) (toType*)((fromType*)(base) + (count)) // Compute offset of index location attribute data.
// Pull tables out from the index. u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
_redirect_table = nextPtr(_index_data, u1, header_size, s4); // Compute offset of index string table.
_offsets_table = nextPtr(_redirect_table, s4, _header._location_count, u4); u4 string_bytes_offset = location_bytes_offset + locations_size();
_location_bytes = nextPtr(_offsets_table, u4, _header._location_count, u1); // Compute address of the perfect hash table redirect table.
_string_bytes = nextPtr(_location_bytes, u1, _header._locations_size, u1); _redirect_table = (s4*)(_index_data + redirect_table_offset);
#undef nextPtr // 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. // Successful open.
return true; return true;
} }
void ImageFile::close() { // Close image file.
void ImageFileReader::close() {
// Dealllocate the index. // Dealllocate the index.
if (_index_data) { if (_index_data != NULL) {
if (_memory_mapped) {
os::unmap_memory((char*)_index_data, _index_size); os::unmap_memory((char*)_index_data, _index_size);
} else {
FREE_RESOURCE_ARRAY(u1, _index_data, _index_size);
}
_index_data = NULL; _index_data = NULL;
} }
// Close file.
// close file.
if (_fd != -1) { if (_fd != -1) {
os::close(_fd); os::close(_fd);
_fd = -1; _fd = -1;
} }
} }
// Return the attribute stream for a named resourced. // Read directly from the file.
u1* ImageFile::find_location_data(const char* path) const { bool ImageFileReader::read_at(u1* data, u8 size, u8 offset) const {
// Compute hash. return os::read_at(_fd, data, size, offset) == size;
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;
} }
// Verify that a found location matches the supplied path. // Find the location attributes associated with the path. Returns true if
bool ImageFile::verify_location(ImageLocation& location, const char* path) const { // the location is found, false otherwise.
// Retrieve each path component string. bool ImageFileReader::find_location(const char* path, ImageLocation& location) const {
ImageStrings strings(_string_bytes, _header._strings_size); // Locate the entry in the index perfect hash table.
// Match a path with each subcomponent without concatenation (copy). s4 index = ImageStrings::find(_endian, path, _redirect_table, table_length());
// Match up path parent. // 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* parent = location.get_attribute(ImageLocation::ATTRIBUTE_PARENT, strings);
const char* next = ImageStrings::starts_with(path, parent); // If parent string is not empty string.
// Continue only if a complete match. if (*parent != '\0') {
if (!next) return false; // Get length of module string.
// Match up path base. 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); const char* base = location.get_attribute(ImageLocation::ATTRIBUTE_BASE, strings);
next = ImageStrings::starts_with(next, base); // Get length of base name.
// Continue only if a complete match. length = strlen(base);
if (!next) return false; // Make sure there is no buffer overflow.
// Match up path extension. 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); 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. // True only if complete match and no more characters.
return next && *next == '\0'; return *next == '\0';
} }
// Return the resource for the supplied location. // Return the resource data for the supplied location.
u1* ImageFile::get_resource(ImageLocation& location) const { void ImageFileReader::get_resource(ImageLocation& location, u1* uncompressed_data) const {
// Retrieve the byte offset and size of the resource. // Retrieve the byte offset and size of the resource.
u8 offset = _index_size + location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET); u8 offset = location.get_attribute(ImageLocation::ATTRIBUTE_OFFSET);
u8 size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED); u8 uncompressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED); u8 compressed_size = location.get_attribute(ImageLocation::ATTRIBUTE_COMPRESSED);
u8 read_size = compressed_size ? compressed_size : size; if (compressed_size != 0) {
ResourceMark rm;
// Allocate space for the resource. u1* compressed_data;
u1* data = NEW_RESOURCE_ARRAY(u1, read_size); // If not memory mapped read in bytes.
if (!MemoryMapImage) {
bool is_read = os::read_at(_fd, data, read_size, offset) == read_size; // 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"); guarantee(is_read, "error reading from image or short read");
} else {
// If not compressed, just return the data. compressed_data = get_data_address() + offset;
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);
} }
// Get image string table.
const ImageStrings strings = get_strings();
// Decompress resource.
ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size,
&strings, false);
} else {
// Read bytes from offset beyond the image index.
bool is_read = read_at(uncompressed_data, uncompressed_size, _index_size + offset);
guarantee(is_read, "error reading from image or short read");
} }
} }
GrowableArray<const char*>* ImageFile::packages(const char* name) {
char entry[JVM_MAXPATHLEN];
bool overflow = jio_snprintf(entry, sizeof(entry), "%s/packages.offsets", name) == -1;
guarantee(!overflow, "package name overflow");
u1* buffer;
u8 size;
get_resource(entry, buffer, size);
guarantee(buffer, "missing module packages reource");
ImageStrings strings(_string_bytes, _header._strings_size);
GrowableArray<const char*>* pkgs = new GrowableArray<const char*>();
int count = size / 4;
for (int i = 0; i < count; i++) {
u4 offset = Bytes::get_Java_u4(buffer + (i*4));
const char* p = strings.get(offset);
pkgs->append(p);
}
return pkgs;
}

View File

@ -28,13 +28,15 @@
#include "classfile/classLoader.hpp" #include "classfile/classLoader.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "utilities/endian.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
#include "utilities/growableArray.hpp"
// Image files are an alternate file format for storing classes and resources. The // 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. // 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 // 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 format. This allows the image to be mapped into memory without endian
// endian translation. This also means that images are platform dependent. // translation. This also means that images are platform dependent.
// //
// Image files are structured as three sections; // Image files are structured as three sections;
// //
@ -42,7 +44,7 @@
// | Header | // | Header |
// +-----------+ // +-----------+
// | | // | |
// | Directory | // | Index |
// | | // | |
// +-----------+ // +-----------+
// | | // | |
@ -60,7 +62,11 @@
// +------------+------------+ // +------------+------------+
// | Major Vers | Minor Vers | // | Major Vers | Minor Vers |
// +------------+------------+ // +------------+------------+
// | Location Count | // | Flags |
// +-------------------------+
// | Resource Count |
// +-------------------------+
// | Table Length |
// +-------------------------+ // +-------------------------+
// | Attributes Size | // | Attributes Size |
// +-------------------------+ // +-------------------------+
@ -71,23 +77,24 @@
// special file extension. // special file extension.
// Major vers, minor vers - differences in version numbers indicate structural // Major vers, minor vers - differences in version numbers indicate structural
// changes in the image. // changes in the image.
// Location count - number of locations/resources in the file. This count is also // Flags - various image wide flags (future).
// the length of lookup tables used in the directory. // 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 // Attributes size - number of bytes in the region used to store location attribute
// streams. // streams.
// Strings size - the size of the region used to store strings used by the // 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" // used for lookup is "A Practical Minimal Perfect Hashing Method"
// (http://homepages.dcc.ufmg.br/~nivio/papers/wea05.pdf). Given a path string // (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; // information;
// //
// redirectIndex = hash(path, DEFAULT_SEED) % count; // redirectIndex = hash(path, DEFAULT_SEED) % table_length;
// redirect = redirectTable[redirectIndex]; // redirect = redirectTable[redirectIndex];
// if (redirect == 0) return not found; // 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]; // location = locationTable[locationIndex];
// if (!verify(location, path)) return not found; // if (!verify(location, path)) return not found;
// return location; // return location;
@ -97,7 +104,7 @@
// other seeds. The verify function guarantees the found resource location is // other seeds. The verify function guarantees the found resource location is
// indeed the resource we are looking for. // 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 | // | Redirect Table |
@ -117,54 +124,74 @@
// offsets. Zero indicates not found. // offsets. Zero indicates not found.
// Attribute Offsets - Array of 32-bit unsigned values representing offsets into // Attribute Offsets - Array of 32-bit unsigned values representing offsets into
// attribute data. Attribute offsets can be iterated to do a // 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 // Attribute Data - Bytes representing compact attribute data for locations. (See
// comments in ImageLocation.) // 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 // image meta data. Each string is accessed by offset. Each string is
// unique. Offset zero is reserved for the empty string. // unique. Offset zero is reserved for the empty string.
// //
// Note that the memory mapped directory assumes 32 bit alignment of the image // Note that the memory mapped index assumes 32 bit alignment of each component
// header, the redirect table and the attribute offsets. // 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. // Manage image file string table.
class ImageStrings { class ImageStrings VALUE_OBJ_CLASS_SPEC {
private: private:
// Data bytes for strings. u1* _data; // Data bytes for strings.
u1* _data; u4 _size; // Number of bytes in the string table.
// Number of bytes in the string table.
u4 _size;
public: public:
enum {
// Not found result from find routine.
NOT_FOUND = -1,
// Prime used to generate hash for Perfect Hashing. // Prime used to generate hash for Perfect Hashing.
static const u4 HASH_MULTIPLIER = 0x01000193; HASH_MULTIPLIER = 0x01000193
};
ImageStrings(u1* data, u4 size) : _data(data), _size(size) {} ImageStrings(u1* data, u4 size) : _data(data), _size(size) {}
// Return the UTF-8 string beginning at offset. // Return the UTF-8 string beginning at offset.
inline const char* get(u4 offset) const { 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); 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) { inline static u4 hash_code(const char* string) {
return hash_code(string, HASH_MULTIPLIER); return hash_code(string, HASH_MULTIPLIER);
} }
// Compute the Perfect Hashing hash code for the supplied string, starting at seed. // 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 // Match up a string in a perfect hash table. Result still needs validation
// of string. Otherwise, NULL. Used to test sections of a path without // for precise match.
// copying. 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); 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 // attributes are compressed into a stream of bytes. An attribute stream is
// composed of individual attribute sequences. Each attribute sequence begins with // composed of individual attribute sequences. Each attribute sequence begins with
// a header byte containing the attribute 'kind' (upper 5 bits of header) and the // a header byte containing the attribute 'kind' (upper 5 bits of header) and the
@ -188,7 +215,7 @@ public:
// stream. // stream.
// - ATTRIBUTE_OFFSET represents the number of bytes from the beginning of the region // - 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 // 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 // - Currently, compressed resources are represented by having a non-zero
// ATTRIBUTE_COMPRESSED value. This represents the number of bytes stored in the // 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 // image, and the value of ATTRIBUTE_UNCOMPRESSED represents number of bytes of the
@ -198,17 +225,19 @@ public:
// represented differently. // represented differently.
// - Package strings include trailing slash and extensions include prefix period. // - Package strings include trailing slash and extensions include prefix period.
// //
class ImageLocation { class ImageLocation VALUE_OBJ_CLASS_SPEC {
public: public:
// Attribute kind enumeration. enum {
static const u1 ATTRIBUTE_END = 0; // End of attribute stream marker ATTRIBUTE_END, // End of attribute stream marker
static const u1 ATTRIBUTE_BASE = 1; // String table offset of resource path base ATTRIBUTE_MODULE, // String table offset of module name
static const u1 ATTRIBUTE_PARENT = 2; // String table offset of resource path parent ATTRIBUTE_PARENT, // String table offset of resource path parent
static const u1 ATTRIBUTE_EXTENSION = 3; // String table offset of resource path extension ATTRIBUTE_BASE, // String table offset of resource path base
static const u1 ATTRIBUTE_OFFSET = 4; // Container byte offset of resource ATTRIBUTE_EXTENSION, // String table offset of resource path extension
static const u1 ATTRIBUTE_COMPRESSED = 5; // In image byte size of the compressed resource ATTRIBUTE_OFFSET, // Container byte offset of resource
static const u1 ATTRIBUTE_UNCOMPRESSED = 6; // In memory byte size of the uncompressed resource ATTRIBUTE_COMPRESSED, // In image byte size of the compressed resource
static const u1 ATTRIBUTE_COUNT = 7; // Number of attribute kinds ATTRIBUTE_UNCOMPRESSED, // In memory byte size of the uncompressed resource
ATTRIBUTE_COUNT // Number of attribute kinds
};
private: private:
// Values of inflated attributes. // Values of inflated attributes.
@ -222,30 +251,43 @@ private:
// Return the attribute kind. // Return the attribute kind.
inline static u1 attribute_kind(u1 data) { inline static u1 attribute_kind(u1 data) {
u1 kind = data >> 3; u1 kind = data >> 3;
assert(kind < ATTRIBUTE_COUNT, "invalid attribute kind"); guarantee(kind < ATTRIBUTE_COUNT, "invalid attribute kind");
return kind; return kind;
} }
// Return the attribute length. // Return the attribute length.
inline static u8 attribute_value(u1* data, u1 n) { 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; u8 value = 0;
// Most significant bytes first. // Most significant bytes first.
for (u1 i = 0; i < n; i++) { for (u1 i = 0; i < n; i++) {
value <<= 8; value <<= 8;
value |= data[i]; value |= data[i];
} }
return value; return value;
} }
public: 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. // Retrieve an attribute value from the inflated array.
inline u8 get_attribute(u1 kind) const { 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]; return _attributes[kind];
} }
@ -255,89 +297,306 @@ public:
} }
}; };
// Manage the image file. //
class ImageFile: public CHeapObj<mtClass> { // NOTE: needs revision.
private: // Each loader requires set of module meta data to identify which modules and
// Image file marker. // packages are managed by that loader. Currently, there is one image file per
static const u4 IMAGE_MAGIC = 0xCAFEDADA; // builtin loader, so only one module meta data resource per file.
// Image file major version number. //
static const u2 MAJOR_VERSION = 0; // Each element in the module meta data is a native endian 4 byte integer. Note
// Image file minor version number. // that entries with zero offsets for string table entries should be ignored (
static const u2 MINOR_VERSION = 1; // padding for hash table lookup.)
//
struct ImageHeader { // Format:
u4 _magic; // Image file marker // Count of package to module entries
u2 _major_version; // Image file major version number // Count of module to package entries
u2 _minor_version; // Image file minor version number // Perfect Hash redirect table[Count of package to module entries]
u4 _location_count; // Number of locations managed in index. // Package to module entries[Count of package to module entries]
u4 _locations_size; // Number of bytes in attribute table. // Offset to package name in string table
u4 _strings_size; // Number of bytes 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); }
}; };
// 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 char* _name; // Name of image
s4 _use; // Use count
int _fd; // File descriptor int _fd; // File descriptor
bool _memory_mapped; // Is file memory mapped Endian* _endian; // Endian handler
u8 _file_size; // File size in bytes
ImageHeader _header; // Image header ImageHeader _header; // Image header
u8 _index_size; // Total size of index size_t _index_size; // Total size of index
u1* _index_data; // Raw index data u1* _index_data; // Raw index data
s4* _redirect_table; // Perfect hash redirect table s4* _redirect_table; // Perfect hash redirect table
u4* _offsets_table; // Location offset table u4* _offsets_table; // Location offset table
u1* _location_bytes; // Location attributes u1* _location_bytes; // Location attributes
u1* _string_bytes; // String table u1* _string_bytes; // String table
ImageFileReader(const char* name, bool big_endian);
~ImageFileReader();
// Compute number of bytes in image file index. // Compute number of bytes in image file index.
inline u8 index_size() { inline u8 index_size() {
return sizeof(ImageHeader) + return sizeof(ImageHeader) +
_header._location_count * sizeof(u4) * 2 + table_length() * sizeof(u4) * 2 + locations_size() + strings_size();
_header._locations_size +
_header._strings_size;
} }
public: public:
ImageFile(const char* name); enum {
~ImageFile(); // 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(); bool open();
// Close image file. // Close image file.
void close(); 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. // Retrieve name of image file.
inline const char* name() const { inline const char* name() const {
return _name; 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. // Return a string table accessor.
inline const ImageStrings get_strings() const { 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. // Return location attribute stream at offset.
inline u4 get_location_count() const { inline u1* get_location_offset_data(u4 offset) const {
return _header._location_count; guarantee((u4)offset < _header.locations_size(_endian),
} "offset exceeds location attributes size");
// Return location attribute stream for location i.
inline u1* get_location_data(u4 i) const {
u4 offset = _offsets_table[i];
return offset != 0 ? _location_bytes + offset : NULL; return offset != 0 ? _location_bytes + offset : NULL;
} }
// Return the attribute stream for a named resourced. // Return location attribute stream for location i.
u1* find_location_data(const char* path) const; 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. // Verify that a found location matches the supplied path.
bool verify_location(ImageLocation& location, const char* path) const; bool verify_location(ImageLocation& location, const char* path) const;
// Return the resource for the supplied location info. // Return the resource for the supplied path.
u1* get_resource(ImageLocation& location) const; void get_resource(ImageLocation& location, u1* uncompressed_data) 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);
}; };
#endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP #endif // SHARE_VM_CLASSFILE_IMAGEFILE_HPP

View File

@ -1707,8 +1707,7 @@ void java_lang_Throwable::fill_in_stack_trace(Handle throwable, methodHandle met
// - rest of the stack // - rest of the stack
if (!skip_fillInStackTrace_check) { if (!skip_fillInStackTrace_check) {
if ((method->name() == vmSymbols::fillInStackTrace_name() || if (method->name() == vmSymbols::fillInStackTrace_name() &&
method->name() == vmSymbols::fillInStackTrace0_name()) &&
throwable->is_a(method->method_holder())) { throwable->is_a(method->method_holder())) {
continue; continue;
} }

View File

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

View File

@ -258,6 +258,8 @@
/* Type Annotations (JDK 8 and above) */ \ /* Type Annotations (JDK 8 and above) */ \
template(type_annotations_name, "typeAnnotations") \ template(type_annotations_name, "typeAnnotations") \
\ \
/* Intrinsic Annotation (JDK 9 and above) */ \
template(jdk_internal_HotSpotIntrinsicCandidate_signature, "Ljdk/internal/HotSpotIntrinsicCandidate;") \
\ \
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \ template(java_lang_invoke_CallSite, "java/lang/invoke/CallSite") \
@ -345,7 +347,6 @@
template(dispatch_name, "dispatch") \ template(dispatch_name, "dispatch") \
template(getSystemClassLoader_name, "getSystemClassLoader") \ template(getSystemClassLoader_name, "getSystemClassLoader") \
template(fillInStackTrace_name, "fillInStackTrace") \ template(fillInStackTrace_name, "fillInStackTrace") \
template(fillInStackTrace0_name, "fillInStackTrace0") \
template(getCause_name, "getCause") \ template(getCause_name, "getCause") \
template(initCause_name, "initCause") \ template(initCause_name, "initCause") \
template(setProperty_name, "setProperty") \ template(setProperty_name, "setProperty") \
@ -635,7 +636,43 @@
// The F_xx is one of the Flags enum; see below. // The F_xx is one of the Flags enum; see below.
// //
// for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t)) // for Emacs: (let ((c-backslash-column 120) (c-backslash-max-column 120)) (c-backslash-region (point) (point-max) nil t))
//
//
// There are two types of intrinsic methods: (1) Library intrinsics and (2) bytecode intrinsics.
//
// (1) A library intrinsic method may be replaced with hand-crafted assembly code,
// with hand-crafted compiler IR, or with a combination of the two. The semantics
// of the replacement code may differ from the semantics of the replaced code.
//
// (2) Bytecode intrinsic methods are not replaced by special code, but they are
// treated in some other special way by the compiler. For example, the compiler
// may delay inlining for some String-related intrinsic methods (e.g., some methods
// defined in the StringBuilder and StringBuffer classes, see
// Compile::should_delay_string_inlining() for more details).
//
// Due to the difference between the semantics of an intrinsic method as defined
// in the (Java) source code and the semantics of the method as defined
// by the code in the VM, intrinsic methods must be explicitly marked.
//
// Intrinsic methods are marked by the jdk.internal.HotSpotIntrinsicCandidate
// annotation. If CheckIntrinsics is enabled, the VM performs the following
// checks when a class C is loaded: (1) all intrinsics defined by the VM for
// class C are present in the loaded class file and are marked;
// (2) an intrinsic is defined by the VM for all marked methods of class C.
//
// If a mismatch is detected for a method, the VM behaves differently depending
// on the type of build. A fastdebug build exits and reports an error on a mismatch.
// A product build will not replace an unmarked library intrinsic method with
// hand-crafted code, that is, unmarked library intrinsics are treated as ordinary
// methods in a product build. The special treatment of a bytecode intrinsic method
// persists even if the method not marked.
//
// When adding an intrinsic for a method, please make sure to appropriately
// annotate the method in the source code. The list below contains all
// library intrinsics followed by bytecode intrinsics. Please also make sure to
// add the declaration of the intrinsic to the approriate section of the list.
#define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \ #define VM_INTRINSICS_DO(do_intrinsic, do_class, do_name, do_signature, do_alias) \
/* (1) Library intrinsics */ \
do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \ do_intrinsic(_hashCode, java_lang_Object, hashCode_name, void_int_signature, F_R) \
do_name( hashCode_name, "hashCode") \ do_name( hashCode_name, "hashCode") \
do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \ do_intrinsic(_getClass, java_lang_Object, getClass_name, void_class_signature, F_R) \
@ -792,12 +829,12 @@
\ \
do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \ do_class(sun_nio_cs_iso8859_1_Encoder, "sun/nio/cs/ISO_8859_1$Encoder") \
do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \ do_intrinsic(_encodeISOArray, sun_nio_cs_iso8859_1_Encoder, encodeISOArray_name, encodeISOArray_signature, F_S) \
do_name( encodeISOArray_name, "encodeISOArray") \ do_name( encodeISOArray_name, "implEncodeISOArray") \
do_signature(encodeISOArray_signature, "([CI[BII)I") \ do_signature(encodeISOArray_signature, "([CI[BII)I") \
\ \
do_class(java_math_BigInteger, "java/math/BigInteger") \ do_class(java_math_BigInteger, "java/math/BigInteger") \
do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_R) \ do_intrinsic(_multiplyToLen, java_math_BigInteger, multiplyToLen_name, multiplyToLen_signature, F_S) \
do_name( multiplyToLen_name, "multiplyToLen") \ do_name( multiplyToLen_name, "implMultiplyToLen") \
do_signature(multiplyToLen_signature, "([II[II[I)[I") \ do_signature(multiplyToLen_signature, "([II[II[I)[I") \
\ \
do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \ do_intrinsic(_squareToLen, java_math_BigInteger, squareToLen_name, squareToLen_signature, F_S) \
@ -808,6 +845,14 @@
do_name( mulAdd_name, "implMulAdd") \ do_name( mulAdd_name, "implMulAdd") \
do_signature(mulAdd_signature, "([I[IIII)I") \ do_signature(mulAdd_signature, "([I[IIII)I") \
\ \
do_intrinsic(_montgomeryMultiply, java_math_BigInteger, montgomeryMultiply_name, montgomeryMultiply_signature, F_S) \
do_name( montgomeryMultiply_name, "implMontgomeryMultiply") \
do_signature(montgomeryMultiply_signature, "([I[I[IIJ[I)[I") \
\
do_intrinsic(_montgomerySquare, java_math_BigInteger, montgomerySquare_name, montgomerySquare_signature, F_S) \
do_name( montgomerySquare_name, "implMontgomerySquare") \
do_signature(montgomerySquare_signature, "([I[IIJ[I)[I") \
\
/* java/lang/ref/Reference */ \ /* java/lang/ref/Reference */ \
do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \
\ \
@ -815,21 +860,21 @@
do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \ do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \
do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \
do_name( encryptBlock_name, "encryptBlock") \ do_name( encryptBlock_name, "implEncryptBlock") \
do_name( decryptBlock_name, "decryptBlock") \ do_name( decryptBlock_name, "implDecryptBlock") \
do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \ do_signature(byteArray_int_byteArray_int_signature, "([BI[BI)V") \
\ \
do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \ do_class(com_sun_crypto_provider_cipherBlockChaining, "com/sun/crypto/provider/CipherBlockChaining") \
do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ do_intrinsic(_cipherBlockChaining_encryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, encrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \ do_intrinsic(_cipherBlockChaining_decryptAESCrypt, com_sun_crypto_provider_cipherBlockChaining, decrypt_name, byteArray_int_int_byteArray_int_signature, F_R) \
do_name( encrypt_name, "encrypt") \ do_name( encrypt_name, "implEncrypt") \
do_name( decrypt_name, "decrypt") \ do_name( decrypt_name, "implDecrypt") \
do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \ do_signature(byteArray_int_int_byteArray_int_signature, "([BII[BI)I") \
\ \
/* support for sun.security.provider.SHA */ \ /* support for sun.security.provider.SHA */ \
do_class(sun_security_provider_sha, "sun/security/provider/SHA") \ do_class(sun_security_provider_sha, "sun/security/provider/SHA") \
do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \ do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R) \
do_name( implCompress_name, "implCompress") \ do_name( implCompress_name, "implCompress0") \
do_signature(implCompress_signature, "([BI)V") \ do_signature(implCompress_signature, "([BI)V") \
\ \
/* support for sun.security.provider.SHA2 */ \ /* support for sun.security.provider.SHA2 */ \
@ -843,7 +888,7 @@
/* support for sun.security.provider.DigestBase */ \ /* support for sun.security.provider.DigestBase */ \
do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \ do_class(sun_security_provider_digestbase, "sun/security/provider/DigestBase") \
do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \ do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R) \
do_name( implCompressMB_name, "implCompressMultiBlock") \ do_name( implCompressMB_name, "implCompressMultiBlock0") \
do_signature(implCompressMB_signature, "([BII)I") \ do_signature(implCompressMB_signature, "([BII)I") \
\ \
/* support for com.sun.crypto.provider.GHASH */ \ /* support for com.sun.crypto.provider.GHASH */ \
@ -857,17 +902,18 @@
do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \ do_intrinsic(_updateCRC32, java_util_zip_CRC32, update_name, int2_int_signature, F_SN) \
do_name( update_name, "update") \ do_name( update_name, "update") \
do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \ do_intrinsic(_updateBytesCRC32, java_util_zip_CRC32, updateBytes_name, updateBytes_signature, F_SN) \
do_name( updateBytes_name, "updateBytes") \ do_name( updateBytes_name, "updateBytes0") \
do_signature(updateBytes_signature, "(I[BII)I") \ do_signature(updateBytes_signature, "(I[BII)I") \
do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \ do_intrinsic(_updateByteBufferCRC32, java_util_zip_CRC32, updateByteBuffer_name, updateByteBuffer_signature, F_SN) \
do_name( updateByteBuffer_name, "updateByteBuffer") \ do_name( updateByteBuffer_name, "updateByteBuffer0") \
do_signature(updateByteBuffer_signature, "(IJII)I") \ do_signature(updateByteBuffer_signature, "(IJII)I") \
\ \
/* support for java.util.zip.CRC32C */ \ /* support for java.util.zip.CRC32C */ \
do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \ do_class(java_util_zip_CRC32C, "java/util/zip/CRC32C") \
do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_name, updateBytes_signature, F_S) \ do_intrinsic(_updateBytesCRC32C, java_util_zip_CRC32C, updateBytes_C_name, updateBytes_signature, F_S) \
do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_name, updateByteBuffer_signature, F_S) \ do_name( updateBytes_C_name, "updateBytes") \
do_name( updateDirectByteBuffer_name, "updateDirectByteBuffer") \ do_intrinsic(_updateDirectByteBufferCRC32C, java_util_zip_CRC32C, updateDirectByteBuffer_C_name, updateByteBuffer_signature, F_S) \
do_name( updateDirectByteBuffer_C_name, "updateDirectByteBuffer") \
\ \
/* support for sun.misc.Unsafe */ \ /* support for sun.misc.Unsafe */ \
do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \
@ -878,12 +924,6 @@
do_intrinsic(_copyMemory, sun_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ do_intrinsic(_copyMemory, sun_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \
do_name( copyMemory_name, "copyMemory") \ do_name( copyMemory_name, "copyMemory") \
do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \
do_intrinsic(_park, sun_misc_Unsafe, park_name, park_signature, F_RN) \
do_name( park_name, "park") \
do_signature(park_signature, "(ZJ)V") \
do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \
do_name( unpark_name, "unpark") \
do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \
do_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ do_intrinsic(_loadFence, sun_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \
do_name( loadFence_name, "loadFence") \ do_name( loadFence_name, "loadFence") \
do_alias( loadFence_signature, void_method_signature) \ do_alias( loadFence_signature, void_method_signature) \
@ -1066,11 +1106,15 @@
do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\ do_intrinsic(_getAndSetObject, sun_misc_Unsafe, getAndSetObject_name, getAndSetObject_signature, F_R)\
do_name( getAndSetObject_name, "getAndSetObject") \ do_name( getAndSetObject_name, "getAndSetObject") \
do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \ do_signature(getAndSetObject_signature, "(Ljava/lang/Object;JLjava/lang/Object;)Ljava/lang/Object;" ) \
/*== LAST_COMPILER_INLINE*/ \
/*the compiler does have special inlining code for these; bytecode inline is just fine */ \
\ \
do_intrinsic(_fillInStackTrace, java_lang_Throwable, fillInStackTrace_name, void_throwable_signature, F_RNY) \ /* (2) Bytecode intrinsics */ \
\ \
do_intrinsic(_park, sun_misc_Unsafe, park_name, park_signature, F_RN) \
do_name( park_name, "park") \
do_signature(park_signature, "(ZJ)V") \
do_intrinsic(_unpark, sun_misc_Unsafe, unpark_name, unpark_signature, F_RN) \
do_name( unpark_name, "unpark") \
do_alias( unpark_signature, /*(LObject;)V*/ object_void_signature) \
do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \ do_intrinsic(_StringBuilder_void, java_lang_StringBuilder, object_initializer_name, void_method_signature, F_R) \
do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \ do_intrinsic(_StringBuilder_int, java_lang_StringBuilder, object_initializer_name, int_void_signature, F_R) \
do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \ do_intrinsic(_StringBuilder_String, java_lang_StringBuilder, object_initializer_name, string_void_signature, F_R) \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "code/codeBlob.hpp" #include "code/codeBlob.hpp"
#include "code/codeCache.hpp" #include "code/codeCache.hpp"
#include "code/codeCacheExtensions.hpp"
#include "code/relocInfo.hpp" #include "code/relocInfo.hpp"
#include "compiler/disassembler.hpp" #include "compiler/disassembler.hpp"
#include "interpreter/bytecode.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; _data_offset = size;
_frame_size = 0; _frame_size = 0;
set_oop_maps(NULL); set_oop_maps(NULL);
_strings = CodeStrings();
} }
@ -114,6 +116,7 @@ CodeBlob::CodeBlob(
_code_offset = _content_offset + cb->total_offset_of(cb->insts()); _code_offset = _content_offset + cb->total_offset_of(cb->insts());
_data_offset = _content_offset + round_to(cb->total_content_size(), oopSize); _data_offset = _content_offset + round_to(cb->total_content_size(), oopSize);
assert(_data_offset <= size, "codeBlob is too small"); assert(_data_offset <= size, "codeBlob is too small");
_strings = CodeStrings();
cb->copy_code_and_locs_to(this); cb->copy_code_and_locs_to(this);
set_oop_maps(oop_maps); set_oop_maps(oop_maps);
@ -192,6 +195,7 @@ BufferBlob* BufferBlob::create(const char* name, int buffer_size) {
BufferBlob* blob = NULL; BufferBlob* blob = NULL;
unsigned int size = sizeof(BufferBlob); unsigned int size = sizeof(BufferBlob);
CodeCacheExtensions::size_blob(name, &buffer_size);
// align the size to CodeEntryAlignment // align the size to CodeEntryAlignment
size = align_code_offset(size); size = align_code_offset(size);
size += round_to(buffer_size, oopSize); size += round_to(buffer_size, oopSize);
@ -275,6 +279,7 @@ MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) {
MethodHandlesAdapterBlob* blob = NULL; MethodHandlesAdapterBlob* blob = NULL;
unsigned int size = sizeof(MethodHandlesAdapterBlob); unsigned int size = sizeof(MethodHandlesAdapterBlob);
CodeCacheExtensions::size_blob("MethodHandles adapters", &buffer_size);
// align the size to CodeEntryAlignment // align the size to CodeEntryAlignment
size = align_code_offset(size); size = align_code_offset(size);
size += round_to(buffer_size, oopSize); size += round_to(buffer_size, oopSize);
@ -315,11 +320,13 @@ RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name,
{ {
RuntimeStub* stub = NULL; RuntimeStub* stub = NULL;
ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock 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); MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
unsigned int size = allocation_size(cb, sizeof(RuntimeStub)); 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 = 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); trace_new_stub(stub, "RuntimeStub - ", stub_name);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 MethodProfiled = 1, // Execution level 2 and 3 (profiled) nmethods
NonNMethod = 2, // Non-nmethods like Buffers, Adapters and Runtime Stubs NonNMethod = 2, // Non-nmethods like Buffers, Adapters and Runtime Stubs
All = 3, // All types (No code cache segmentation) 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 { class CodeBlob VALUE_OBJ_CLASS_SPEC {
friend class VMStructs; friend class VMStructs;
friend class CodeCacheDumper;
private: private:
const char* _name; const char* _name;
@ -206,6 +208,14 @@ class CodeBlob VALUE_OBJ_CLASS_SPEC {
void set_strings(CodeStrings& strings) { void set_strings(CodeStrings& strings) {
_strings.assign(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; class WhiteBox;

View File

@ -409,7 +409,7 @@ CodeBlob* CodeCache::allocate(int size, int code_blob_type, bool strict) {
} }
if (PrintCodeCacheExtension) { if (PrintCodeCacheExtension) {
ResourceMark rm; ResourceMark rm;
if (SegmentedCodeCache) { if (_heaps->length() >= 1) {
tty->print("%s", heap->name()); tty->print("%s", heap->name());
} else { } else {
tty->print("CodeCache"); tty->print("CodeCache");
@ -1211,7 +1211,7 @@ void CodeCache::print_internals() {
int i = 0; int i = 0;
FOR_ALL_HEAPS(heap) { FOR_ALL_HEAPS(heap) {
if (SegmentedCodeCache && Verbose) { if ((_heaps->length() >= 1) && Verbose) {
tty->print_cr("-- %s --", (*heap)->name()); tty->print_cr("-- %s --", (*heap)->name());
} }
FOR_ALL_BLOBS(cb, *heap) { FOR_ALL_BLOBS(cb, *heap) {
@ -1360,7 +1360,7 @@ void CodeCache::print_summary(outputStream* st, bool detailed) {
FOR_ALL_HEAPS(heap_iterator) { FOR_ALL_HEAPS(heap_iterator) {
CodeHeap* heap = (*heap_iterator); CodeHeap* heap = (*heap_iterator);
size_t total = (heap->high_boundary() - heap->low_boundary()); size_t total = (heap->high_boundary() - heap->low_boundary());
if (SegmentedCodeCache) { if (_heaps->length() >= 1) {
st->print("%s:", heap->name()); st->print("%s:", heap->name());
} else { } else {
st->print("CodeCache:"); st->print("CodeCache:");
@ -1397,7 +1397,7 @@ void CodeCache::print_codelist(outputStream* st) {
nmethod* nm = iter.method(); nmethod* nm = iter.method();
ResourceMark rm; ResourceMark rm;
char *method_name = nm->method()->name_and_sig_as_C_string(); 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(), nm->compile_id(), nm->comp_level(), method_name, (intptr_t)nm->header_begin(),
(intptr_t)nm->code_begin(), (intptr_t)nm->code_end()); (intptr_t)nm->code_begin(), (intptr_t)nm->code_end());
} }

View File

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

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_HPP
#define SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_HPP
#include "memory/allocation.hpp"
class CodeCacheExtensionsSteps: AllStatic {
public:
enum Step {
// Support for optional fine grain initialization hooks
// Note: these hooks must support refining the granularity
// (e.g. adding intermediate steps in the ordered enum
// if needed for future features)
Start,
VMVersion,
StubRoutines1,
Universe,
TemplateInterpreter,
Interpreter,
StubRoutines2,
InitGlobals,
CreateVM,
LastStep
};
};
#include "code/codeCacheExtensions_ext.hpp"
#endif // SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_HPP

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_EXT_HPP
#define SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_EXT_HPP
#include "utilities/macros.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"
#include "interpreter/bytecodes.hpp"
class AdapterHandlerEntry;
class CodeBlob;
class CodeBuffer;
class InterpreterMacroAssembler;
class Template;
// All the methods defined here are placeholders for possible extensions.
class CodeCacheExtensions: AllStatic {
friend class CodeCacheDumper;
public:
// init both code saving and loading
// Must be called very early, before any code is generated.
static void initialize() {}
// Check whether the generated interpreter will be saved.
static bool saving_generated_interpreter() { return false; }
// Check whether a pregenerated interpreter is used.
static bool use_pregenerated_interpreter() { return false; }
// Placeholder for additional VM initialization code
static void complete_step(CodeCacheExtensionsSteps::Step phase) {}
// Return false for newly generated code, on systems where it is not
// executable.
static bool is_executable(void *pc) { return true; }
// Return whether dynamically generated code can be executable
static bool support_dynamic_code() { return true; }
// Skip new code generation when known to be useless.
static bool skip_code_generation() { return false; }
// Skip stubs used only for compiled code support.
static bool skip_compiler_support() { return false; }
// Ignore UseFastSignatureHandlers when returning false
static bool support_fast_signature_handlers() { return true; }
/////////////////////////
// Handle generated code:
// - allow newly generated code to be shared
// - allow pregenerated code to be used in place of the newly generated one
// (modifying pc).
// - support remapping when doing both save and load
// 'remap' can be set to false if the addresses handled are not referenced
// from code generated later.
// Associate a name to a generated codelet and possibly modify the pc
// Note: use instead the specialized versions when they exist:
// - handle_generated_blob for CodeBlob
// - handle_generated_handler for SignatureHandlers
// See also the optimized calls below that handle several PCs at once.
static void handle_generated_pc(address &pc, const char *name) {}
// Adds a safe definition of the codelet, for codelets used right after
// generation (else we would need to immediately stop the JVM and convert
// the generated code to executable format before being able to go further).
static void handle_generated_pc(address &pc, const char *name, address default_entry) {}
// Special cases
// Special case for CodeBlobs, which may require blob specific actions.
static CodeBlob* handle_generated_blob(CodeBlob* blob, const char *name = NULL) { return blob; }
// Special case for Signature Handlers.
static void handle_generated_handler(address &handler_start, const char *name, address handler_end) {}
// Support for generating different variants of the interpreter
// that can be dynamically selected after reload.
//
// - init_interpreter_assembler allows to configure the assembler for
// the current variant
//
// - needs_other_interpreter_variant returns true as long as other
// variants are needed.
//
// - skip_template_interpreter_entries returns true if new entries
// need not be generated for this masm setup and this bytecode
//
// - completed_template_interpreter_entries is called after new
// entries have been generated and installed, for any non skipped
// bytecode.
static void init_interpreter_assembler(InterpreterMacroAssembler* masm, CodeBuffer* code) {}
static bool needs_other_interpreter_variant() { return false; }
static bool skip_template_interpreter_entries(Bytecodes::Code code) { return false; }
static void completed_template_interpreter_entries(InterpreterMacroAssembler* masm, Bytecodes::Code code) {}
// Code size optimization. May optimize the requested size.
static void size_blob(const char* name, int *updatable_size) {}
// ergonomics
static void set_ergonomics_flags() {}
};
#endif // SHARE_VM_CODE_CODE_CACHE_EXTENSIONS_EXT_HPP

View File

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

View File

@ -2118,7 +2118,7 @@ public:
void maybe_print(oop* p) { void maybe_print(oop* p) {
if (_print_nm == NULL) return; if (_print_nm == NULL) return;
if (!_detected_scavenge_root) _print_nm->print_on(tty, "new scavenge root"); 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), _print_nm, (int)((intptr_t)p - (intptr_t)_print_nm),
(void *)(*p), (intptr_t)p); (void *)(*p), (intptr_t)p);
(*p)->print(); (*p)->print();
@ -2518,7 +2518,7 @@ public:
_nm->print_nmethod(true); _nm->print_nmethod(true);
_ok = false; _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)); (void *)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
} }
virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); } virtual void do_oop(narrowOop* p) { ShouldNotReachHere(); }
@ -2642,7 +2642,7 @@ public:
_nm->print_nmethod(true); _nm->print_nmethod(true);
_ok = false; _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)); (void *)(*p), (intptr_t)p, (int)((intptr_t)p - (intptr_t)_nm));
(*p)->print(); (*p)->print();
} }
@ -2687,7 +2687,7 @@ void nmethod::print() const {
print_on(tty, NULL); print_on(tty, NULL);
if (WizardMode) { if (WizardMode) {
tty->print("((nmethod*) "INTPTR_FORMAT ") ", this); tty->print("((nmethod*) " INTPTR_FORMAT ") ", this);
tty->print(" for method " INTPTR_FORMAT , (address)method()); tty->print(" for method " INTPTR_FORMAT , (address)method());
tty->print(" { "); tty->print(" { ");
if (is_in_use()) tty->print("in_use "); if (is_in_use()) tty->print("in_use ");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -261,3 +261,17 @@ void StubQueue::print() {
stub_print(s); stub_print(s);
} }
} }
// Fixup for pregenerated code
void StubQueue::fix_buffer(address buffer, address queue_end, address buffer_end, int number_of_stubs) {
const int extra_bytes = CodeEntryAlignment;
_stub_buffer = buffer;
_queue_begin = 0;
_queue_end = queue_end - buffer;
_number_of_stubs = number_of_stubs;
int size = buffer_end - buffer;
// Note: _buffer_limit must differ from _queue_end in the iteration loops
// => add extra space at the end (preserving alignment for asserts) if needed
if (buffer_end == queue_end) size += extra_bytes;
_buffer_limit = _buffer_size = size;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -216,6 +216,9 @@ class StubQueue: public CHeapObj<mtCode> {
// Debugging/printing // Debugging/printing
void verify(); // verifies the stub queue void verify(); // verifies the stub queue
void print(); // prints information about 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 #endif // SHARE_VM_CODE_STUBS_HPP

View File

@ -172,7 +172,7 @@ class CompilationLog : public StringEventLog {
} }
void log_nmethod(JavaThread* thread, nmethod* nm) { 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() ? "%" : "", nm->compile_id(), nm->is_osr_method() ? "%" : "",
p2i(nm), p2i(nm->code_begin()), p2i(nm->code_end())); p2i(nm), p2i(nm->code_begin()), p2i(nm->code_end()));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -586,8 +586,6 @@ static bool scan_line(const char * line,
return false; return false;
} }
// Scan next flag and value in line, return MethodMatcher object on success, NULL on failure. // 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. // On failure, error_msg contains description for the first error.
// For future extensions: set error_msg on 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); jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
} }
} else { } 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) { } else if (strcmp(type, "double") == 0) {
char buffer[2][256]; 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); jio_snprintf(errorbuf, buf_size, " Value cannot be read for flag %s of type %s", flag, type);
} }
} else { } else {
jio_snprintf(errorbuf, sizeof(errorbuf), " Type %s not supported ", type); jio_snprintf(errorbuf, buf_size, " Type %s not supported ", type);
} }
} else { } 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; return NULL;
} }

View File

@ -65,7 +65,7 @@ bool Disassembler::_tried_to_load_library = false;
Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL; Disassembler::decode_func_virtual Disassembler::_decode_instructions_virtual = NULL;
Disassembler::decode_func Disassembler::_decode_instructions = 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_virtual_name[] = "decode_instructions_virtual";
static const char decode_instructions_name[] = "decode_instructions"; static const char decode_instructions_name[] = "decode_instructions";
static bool use_new_version = true; static bool use_new_version = true;

View File

@ -688,18 +688,18 @@ void ConcurrentMarkSweepGeneration::printOccupancy(const char *s) {
"The CMS generation should be the old generation"); "The CMS generation should be the old generation");
uint level = 1; uint level = 1;
if (Verbose) { 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()); level, short_name(), s, used(), capacity());
} else { } 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); level, short_name(), s, used() / K, capacity() / K);
} }
} }
if (Verbose) { if (Verbose) {
gclog_or_tty->print(" "SIZE_FORMAT"("SIZE_FORMAT")", gclog_or_tty->print(" " SIZE_FORMAT "(" SIZE_FORMAT ")",
gch->used(), gch->capacity()); gch->used(), gch->capacity());
} else { } 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); 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); bool res = (available >= av_promo) || (available >= max_promotion_in_bytes);
if (Verbose && PrintGCDetails) { if (Verbose && PrintGCDetails) {
gclog_or_tty->print_cr( gclog_or_tty->print_cr(
"CMS: promo attempt is%s safe: available("SIZE_FORMAT") %s av_promo("SIZE_FORMAT")," "CMS: promo attempt is%s safe: available(" SIZE_FORMAT ") %s av_promo(" SIZE_FORMAT "),"
"max_promo("SIZE_FORMAT")", "max_promo(" SIZE_FORMAT ")",
res? "":" not", available, res? ">=":"<", res? "":" not", available, res? ">=":"<",
av_promo, max_promotion_in_bytes); av_promo, max_promotion_in_bytes);
} }
@ -805,18 +805,18 @@ void ConcurrentMarkSweepGeneration::compute_new_size_free_list() {
desired_free_percentage); desired_free_percentage);
gclog_or_tty->print_cr(" Maximum free fraction %f", gclog_or_tty->print_cr(" Maximum free fraction %f",
maximum_free_percentage); maximum_free_percentage);
gclog_or_tty->print_cr(" Capacity "SIZE_FORMAT, capacity()/1000); gclog_or_tty->print_cr(" Capacity " SIZE_FORMAT, capacity()/1000);
gclog_or_tty->print_cr(" Desired capacity "SIZE_FORMAT, gclog_or_tty->print_cr(" Desired capacity " SIZE_FORMAT,
desired_capacity/1000); desired_capacity/1000);
GenCollectedHeap* gch = GenCollectedHeap::heap(); GenCollectedHeap* gch = GenCollectedHeap::heap();
assert(gch->is_old_gen(this), "The CMS generation should always be the old generation"); assert(gch->is_old_gen(this), "The CMS generation should always be the old generation");
size_t young_size = gch->young_gen()->capacity(); 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(" 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); 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); 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); expand_bytes);
} }
// safe if expansion fails // safe if expansion fails
@ -1182,8 +1182,8 @@ bool CMSCollector::shouldConcurrentCollect() {
stats().print_on(gclog_or_tty); stats().print_on(gclog_or_tty);
gclog_or_tty->print_cr("time_until_cms_gen_full %3.7f", gclog_or_tty->print_cr("time_until_cms_gen_full %3.7f",
stats().time_until_cms_gen_full()); stats().time_until_cms_gen_full());
gclog_or_tty->print_cr("free="SIZE_FORMAT, _cmsGen->free()); gclog_or_tty->print_cr("free=" SIZE_FORMAT, _cmsGen->free());
gclog_or_tty->print_cr("contiguous_available="SIZE_FORMAT, gclog_or_tty->print_cr("contiguous_available=" SIZE_FORMAT,
_cmsGen->contiguous_available()); _cmsGen->contiguous_available());
gclog_or_tty->print_cr("promotion_rate=%g", stats().promotion_rate()); gclog_or_tty->print_cr("promotion_rate=%g", stats().promotion_rate());
gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_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(_numObjectsPromoted == 0, "check");
assert(_numWordsPromoted == 0, "check"); assert(_numWordsPromoted == 0, "check");
if (Verbose && PrintGC) { if (Verbose && PrintGC) {
gclog_or_tty->print("Allocated "SIZE_FORMAT" objects, " gclog_or_tty->print("Allocated " SIZE_FORMAT " objects, "
SIZE_FORMAT" bytes concurrently", SIZE_FORMAT " bytes concurrently",
_numObjectsAllocated, _numWordsAllocated*sizeof(HeapWord)); _numObjectsAllocated, _numWordsAllocated*sizeof(HeapWord));
} }
_numObjectsAllocated = 0; _numObjectsAllocated = 0;
@ -2241,8 +2241,8 @@ void ConcurrentMarkSweepGeneration::gc_epilogue_work(bool full) {
assert(_numObjectsAllocated == 0, "check"); assert(_numObjectsAllocated == 0, "check");
assert(_numWordsAllocated == 0, "check"); assert(_numWordsAllocated == 0, "check");
if (Verbose && PrintGC) { if (Verbose && PrintGC) {
gclog_or_tty->print("Promoted "SIZE_FORMAT" objects, " gclog_or_tty->print("Promoted " SIZE_FORMAT " objects, "
SIZE_FORMAT" bytes", SIZE_FORMAT " bytes",
_numObjectsPromoted, _numWordsPromoted*sizeof(HeapWord)); _numObjectsPromoted, _numWordsPromoted*sizeof(HeapWord));
} }
_numObjectsPromoted = 0; _numObjectsPromoted = 0;
@ -2252,7 +2252,7 @@ void ConcurrentMarkSweepGeneration::gc_epilogue_work(bool full) {
if (PrintGC && Verbose) { if (PrintGC && Verbose) {
// Call down the chain in contiguous_available needs the freelistLock // Call down the chain in contiguous_available needs the freelistLock
// so print this out before releasing 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()); contiguous_available());
} }
} }
@ -2340,7 +2340,7 @@ class VerifyMarkedClosure: public BitMapClosure {
HeapWord* addr = _marks->offsetToHeapWord(offset); HeapWord* addr = _marks->offsetToHeapWord(offset);
if (!_marks->isMarked(addr)) { if (!_marks->isMarked(addr)) {
oop(addr)->print_on(gclog_or_tty); 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; _failed = true;
} }
return true; return true;
@ -2702,9 +2702,11 @@ void CMSCollector::setup_cms_unloading_and_verification_state() {
// Not unloading classes this cycle // Not unloading classes this cycle
assert(!should_unload_classes(), "Inconsistency!"); assert(!should_unload_classes(), "Inconsistency!");
if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) { // If we are not unloading classes then add SO_AllCodeCache to root
// Include symbols, strings and code cache elements to prevent their resurrection. // scanning options.
add_root_scanning_option(rso); add_root_scanning_option(rso);
if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) {
set_verifying(true); set_verifying(true);
} else if (verifying() && !should_verify) { } else if (verifying() && !should_verify) {
// We were verifying, but some verification flags got disabled. // We were verifying, but some verification flags got disabled.
@ -4269,7 +4271,7 @@ void CMSCollector::checkpointRootsFinal() {
verify_overflow_empty(); verify_overflow_empty();
if (PrintGCDetails) { 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->used() / K,
_young_gen->capacity() / K); _young_gen->capacity() / K);
} }
@ -4381,8 +4383,8 @@ void CMSCollector::checkpointRootsFinalWork() {
if (ser_ovflw > 0) { if (ser_ovflw > 0) {
if (PrintCMSStatistics != 0) { if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Marking stack overflow (benign) " gclog_or_tty->print_cr("Marking stack overflow (benign) "
"(pmc_pc="SIZE_FORMAT", pmc_rm="SIZE_FORMAT", kac="SIZE_FORMAT "(pmc_pc=" SIZE_FORMAT ", pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT
", kac_preclean="SIZE_FORMAT")", ", kac_preclean=" SIZE_FORMAT ")",
_ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw, _ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
_ser_kac_ovflw, _ser_kac_preclean_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 (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
if (PrintCMSStatistics != 0) { if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Work queue overflow (benign) " 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, _par_kac_ovflw);
} }
_par_pmc_remark_ovflw = 0; _par_pmc_remark_ovflw = 0;
@ -4403,12 +4405,12 @@ void CMSCollector::checkpointRootsFinalWork() {
} }
if (PrintCMSStatistics != 0) { if (PrintCMSStatistics != 0) {
if (_markStack._hit_limit > 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); _markStack._hit_limit);
} }
if (_markStack._failed_double > 0) { if (_markStack._failed_double > 0) {
gclog_or_tty->print_cr(" (benign) Failed stack doubling ("SIZE_FORMAT")," gclog_or_tty->print_cr(" (benign) Failed stack doubling (" SIZE_FORMAT "),"
" current capacity "SIZE_FORMAT, " current capacity " SIZE_FORMAT,
_markStack._failed_double, _markStack._failed_double,
_markStack.capacity()); _markStack.capacity());
} }
@ -5161,7 +5163,7 @@ void CMSCollector::do_remark_non_parallel() {
&markFromDirtyCardsClosure); &markFromDirtyCardsClosure);
verify_work_stacks_empty(); verify_work_stacks_empty();
if (PrintCMSStatistics != 0) { 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()); markFromDirtyCardsClosure.num_dirty_cards());
} }
} }
@ -6035,8 +6037,8 @@ void CMSMarkStack::expand() {
} else if (_failed_double++ == 0 && !CMSConcurrentMTEnabled && PrintGCDetails) { } else if (_failed_double++ == 0 && !CMSConcurrentMTEnabled && PrintGCDetails) {
// Failed to double capacity, continue; // Failed to double capacity, continue;
// we print a detail message only once per CMS cycle. // 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 " gclog_or_tty->print(" (benign) Failed to expand marking stack from " SIZE_FORMAT "K to "
SIZE_FORMAT"K", SIZE_FORMAT "K",
_capacity / K, new_capacity / K); _capacity / K, new_capacity / K);
} }
} }
@ -7335,25 +7337,25 @@ SweepClosure::~SweepClosure() {
ShouldNotReachHere(); ShouldNotReachHere();
} }
if (Verbose && PrintGC) { 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)); _numObjectsFreed, _numWordsFreed*sizeof(HeapWord));
gclog_or_tty->print_cr("\nLive "SIZE_FORMAT" objects, " gclog_or_tty->print_cr("\nLive " SIZE_FORMAT " objects, "
SIZE_FORMAT" bytes " SIZE_FORMAT " bytes "
"Already free "SIZE_FORMAT" objects, "SIZE_FORMAT" bytes", "Already free " SIZE_FORMAT " objects, " SIZE_FORMAT " bytes",
_numObjectsLive, _numWordsLive*sizeof(HeapWord), _numObjectsLive, _numWordsLive*sizeof(HeapWord),
_numObjectsAlreadyFree, _numWordsAlreadyFree*sizeof(HeapWord)); _numObjectsAlreadyFree, _numWordsAlreadyFree*sizeof(HeapWord));
size_t totalBytes = (_numWordsFreed + _numWordsLive + _numWordsAlreadyFree) size_t totalBytes = (_numWordsFreed + _numWordsLive + _numWordsAlreadyFree)
* sizeof(HeapWord); * 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) { if (PrintCMSStatistics && CMSVerifyReturnedBytes) {
size_t indexListReturnedBytes = _sp->sumIndexedFreeListArrayReturnedBytes(); size_t indexListReturnedBytes = _sp->sumIndexedFreeListArrayReturnedBytes();
size_t dict_returned_bytes = _sp->dictionary()->sum_dict_returned_bytes(); size_t dict_returned_bytes = _sp->dictionary()->sum_dict_returned_bytes();
size_t returned_bytes = indexListReturnedBytes + 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("Returned " SIZE_FORMAT " bytes", returned_bytes);
gclog_or_tty->print(" Indexed List Returned "SIZE_FORMAT" bytes", gclog_or_tty->print(" Indexed List Returned " SIZE_FORMAT " bytes",
indexListReturnedBytes); indexListReturnedBytes);
gclog_or_tty->print_cr(" Dictionary Returned "SIZE_FORMAT" bytes", gclog_or_tty->print_cr(" Dictionary Returned " SIZE_FORMAT " bytes",
dict_returned_bytes); dict_returned_bytes);
} }
} }
@ -7432,12 +7434,12 @@ size_t SweepClosure::do_blk_careful(HeapWord* addr) {
// coalesced chunk to the appropriate free list. // coalesced chunk to the appropriate free list.
if (inFreeRange()) { if (inFreeRange()) {
assert(freeFinger() >= _sp->bottom() && freeFinger() < _limit, 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(), flush_cur_free_chunk(freeFinger(),
pointer_delta(addr, freeFinger())); pointer_delta(addr, freeFinger()));
if (CMSTraceSweeper) { if (CMSTraceSweeper) {
gclog_or_tty->print("Sweep: last chunk: "); 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", "[coalesced:%d]\n",
p2i(freeFinger()), pointer_delta(addr, freeFinger()), p2i(freeFinger()), pointer_delta(addr, freeFinger()),
lastFreeRangeCoalesced() ? 1 : 0); lastFreeRangeCoalesced() ? 1 : 0);

View File

@ -1021,7 +1021,7 @@ void ParNewGeneration::collect(bool full,
to()->set_concurrent_iteration_safe_limit(to()->top()); to()->set_concurrent_iteration_safe_limit(to()->top());
if (ResizePLAB) { if (ResizePLAB) {
plab_stats()->adjust_desired_plab_sz(active_workers); plab_stats()->adjust_desired_plab_sz();
} }
if (PrintGC && !PrintGCDetails) { if (PrintGC && !PrintGCDetails) {
@ -1059,6 +1059,10 @@ void ParNewGeneration::collect(bool full,
_gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); _gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
} }
size_t ParNewGeneration::desired_plab_sz() {
return _plab_stats.desired_plab_sz(GenCollectedHeap::heap()->workers()->active_workers());
}
static int sum; static int sum;
void ParNewGeneration::waste_some_time() { void ParNewGeneration::waste_some_time() {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {

View File

@ -411,9 +411,7 @@ class ParNewGeneration: public DefNewGeneration {
return &_plab_stats; return &_plab_stats;
} }
size_t desired_plab_sz() { size_t desired_plab_sz();
return _plab_stats.desired_plab_sz();
}
const ParNewTracer* gc_tracer() const { const ParNewTracer* gc_tracer() const {
return &_gc_tracer; return &_gc_tracer;

View File

@ -119,7 +119,7 @@ void CollectionSetChooser::verify() {
} }
guarantee(sum_of_reclaimable_bytes == _remaining_reclaimable_bytes, guarantee(sum_of_reclaimable_bytes == _remaining_reclaimable_bytes,
err_msg("reclaimable bytes inconsistent, " err_msg("reclaimable bytes inconsistent, "
"remaining: "SIZE_FORMAT" sum: "SIZE_FORMAT, "remaining: " SIZE_FORMAT " sum: " SIZE_FORMAT,
_remaining_reclaimable_bytes, sum_of_reclaimable_bytes)); _remaining_reclaimable_bytes, sum_of_reclaimable_bytes));
} }
#endif // !PRODUCT #endif // !PRODUCT

View File

@ -92,7 +92,7 @@ public:
regions_at_put(_curr_index, NULL); regions_at_put(_curr_index, NULL);
assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes, assert(hr->reclaimable_bytes() <= _remaining_reclaimable_bytes,
err_msg("remaining reclaimable bytes inconsistent " 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)); hr->reclaimable_bytes(), _remaining_reclaimable_bytes));
_remaining_reclaimable_bytes -= hr->reclaimable_bytes(); _remaining_reclaimable_bytes -= hr->reclaimable_bytes();
_curr_index += 1; _curr_index += 1;

View File

@ -307,7 +307,7 @@ void CMMarkStack::expand() {
if (PrintGCDetails && Verbose) { if (PrintGCDetails && Verbose) {
// Failed to double capacity, continue; // Failed to double capacity, continue;
gclog_or_tty->print(" (benign) Failed to expand marking stack capacity from " 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); _capacity / K, new_capacity / K);
} }
} }
@ -555,7 +555,7 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev
_verbose_level = verbose_level; _verbose_level = verbose_level;
if (verbose_low()) { 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)); "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. // in a STW phase.
assert(!concurrent_marking_in_progress(), "invariant"); assert(!concurrent_marking_in_progress(), "invariant");
assert(out_of_regions(), 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))); p2i(_finger), p2i(_heap_end)));
} }
} }
@ -1424,7 +1424,7 @@ public:
assert(start <= hr->end() && start <= ntams && ntams <= hr->end(), assert(start <= hr->end() && start <= ntams && ntams <= hr->end(),
err_msg("Preconditions not met - " 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()))); p2i(start), p2i(ntams), p2i(hr->end())));
// Find the first marked object at or after "start". // Find the first marked object at or after "start".
@ -1725,10 +1725,10 @@ class FinalCountDataUpdateClosure: public CMCountDataClosureBase {
} }
assert(end_idx <= _card_bm->size(), 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())); end_idx, _card_bm->size()));
assert(start_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())); start_idx, _card_bm->size()));
_cm->set_card_bitmap_range(_card_bm, start_idx, end_idx, true /* is_par */); _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); oop obj = oopDesc::load_decode_heap_oop(p);
if (_cm->verbose_high()) { if (_cm->verbose_high()) {
gclog_or_tty->print_cr("\t[%u] we're looking at location " 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)); _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(); HeapWord* limit = curr_region->next_top_at_mark_start();
if (verbose_low()) { if (verbose_low()) {
gclog_or_tty->print_cr("[%u] curr_region = "PTR_FORMAT" " gclog_or_tty->print_cr("[%u] curr_region = " PTR_FORMAT " "
"["PTR_FORMAT", "PTR_FORMAT"), " "[" PTR_FORMAT ", " PTR_FORMAT "), "
"limit = "PTR_FORMAT, "limit = " PTR_FORMAT,
worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit)); 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 (limit > bottom) {
if (verbose_low()) { 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)); "returning it ", worker_id, p2i(curr_region));
} }
return curr_region; return curr_region;
@ -2685,7 +2685,7 @@ ConcurrentMark::claim_region(uint worker_id) {
assert(limit == bottom, assert(limit == bottom,
"the region limit should be at bottom"); "the region limit should be at bottom");
if (verbose_low()) { 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)); "returning NULL", worker_id, p2i(curr_region));
} }
// we return NULL and the caller should try calling // we return NULL and the caller should try calling
@ -2697,13 +2697,13 @@ ConcurrentMark::claim_region(uint worker_id) {
if (verbose_low()) { if (verbose_low()) {
if (curr_region == NULL) { if (curr_region == NULL) {
gclog_or_tty->print_cr("[%u] found uncommitted region, moving finger, " gclog_or_tty->print_cr("[%u] found uncommitted region, moving finger, "
"global finger = "PTR_FORMAT", " "global finger = " PTR_FORMAT ", "
"our finger = "PTR_FORMAT, "our finger = " PTR_FORMAT,
worker_id, p2i(_finger), p2i(finger)); worker_id, p2i(_finger), p2i(finger));
} else { } else {
gclog_or_tty->print_cr("[%u] somebody else moved the finger, " gclog_or_tty->print_cr("[%u] somebody else moved the finger, "
"global finger = "PTR_FORMAT", " "global finger = " PTR_FORMAT ", "
"our finger = "PTR_FORMAT, "our finger = " PTR_FORMAT,
worker_id, p2i(_finger), p2i(finger)); worker_id, p2i(_finger), p2i(finger));
} }
} }
@ -2739,7 +2739,7 @@ private:
void do_object_work(oop obj) { void do_object_work(oop obj) {
guarantee(!_g1h->obj_in_cs(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)); p2i((void*) obj), phase_str(), _info));
} }
@ -2800,7 +2800,7 @@ void ConcurrentMark::verify_no_cset_oops() {
// here. // here.
HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger); HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger);
guarantee(global_hr == NULL || global_finger == global_hr->bottom(), 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))); 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); HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger);
guarantee(task_hr == NULL || task_finger == task_hr->bottom() || guarantee(task_hr == NULL || task_finger == task_hr->bottom() ||
!task_hr->in_collection_set(), !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))); 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(), assert(start <= limit && limit <= hr->top() && hr->top() <= hr->end(),
err_msg("Preconditions not met - " err_msg("Preconditions not met - "
"start: "PTR_FORMAT", limit: "PTR_FORMAT", " "start: " PTR_FORMAT ", limit: " PTR_FORMAT ", "
"top: "PTR_FORMAT", end: "PTR_FORMAT, "top: " PTR_FORMAT ", end: " PTR_FORMAT,
p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end()))); p2i(start), p2i(limit), p2i(hr->top()), p2i(hr->end())));
assert(hr->next_marked_bytes() == 0, "Precondition"); assert(hr->next_marked_bytes() == 0, "Precondition");
@ -3118,7 +3118,7 @@ bool ConcurrentMark::do_yield_check(uint worker_id) {
#ifndef PRODUCT #ifndef PRODUCT
// for debugging purposes // for debugging purposes
void ConcurrentMark::print_finger() { 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)); p2i(_heap_start), p2i(_heap_end), p2i(_finger));
for (uint i = 0; i < _max_worker_id; ++i) { for (uint i = 0; i < _max_worker_id; ++i) {
gclog_or_tty->print(" %u: " PTR_FORMAT, i, p2i(_tasks[i]->finger())); 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"); "claim_region() should have filtered out continues humongous regions");
if (_cm->verbose_low()) { 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)); _worker_id, p2i(hr));
} }
@ -3220,7 +3220,7 @@ void CMTask::update_region_limit() {
if (limit == bottom) { if (limit == bottom) {
if (_cm->verbose_low()) { if (_cm->verbose_low()) {
gclog_or_tty->print_cr("[%u] found an empty region " gclog_or_tty->print_cr("[%u] found an empty region "
"["PTR_FORMAT", "PTR_FORMAT")", "[" PTR_FORMAT ", " PTR_FORMAT ")",
_worker_id, p2i(bottom), p2i(limit)); _worker_id, p2i(bottom), p2i(limit));
} }
// The region was collected underneath our feet. // The region was collected underneath our feet.
@ -3252,7 +3252,7 @@ void CMTask::update_region_limit() {
void CMTask::giveup_current_region() { void CMTask::giveup_current_region() {
assert(_curr_region != NULL, "invariant"); assert(_curr_region != NULL, "invariant");
if (_cm->verbose_low()) { 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)); _worker_id, p2i(_curr_region));
} }
clear_region_fields(); clear_region_fields();
@ -3374,7 +3374,7 @@ void CMTask::regular_clock_call() {
if (_cm->verbose_medium()) { if (_cm->verbose_medium()) {
gclog_or_tty->print_cr("[%u] regular clock, interval = %1.2lfms, " 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, _worker_id, last_interval_ms,
_words_scanned, _words_scanned,
(_words_scanned >= _words_scanned_limit) ? " (*)" : "", (_words_scanned >= _words_scanned_limit) ? " (*)" : "",
@ -3543,7 +3543,7 @@ void CMTask::drain_local_queue(bool partially) {
statsOnly( ++_local_pops ); statsOnly( ++_local_pops );
if (_cm->verbose_high()) { 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)); p2i((void*) obj));
} }
@ -3900,8 +3900,8 @@ void CMTask::do_marking_step(double time_target_ms,
if (_cm->verbose_low()) { if (_cm->verbose_low()) {
gclog_or_tty->print_cr("[%u] we're scanning part " gclog_or_tty->print_cr("[%u] we're scanning part "
"["PTR_FORMAT", "PTR_FORMAT") " "[" PTR_FORMAT ", " PTR_FORMAT ") "
"of region "HR_FORMAT, "of region " HR_FORMAT,
_worker_id, p2i(_finger), p2i(_region_limit), _worker_id, p2i(_finger), p2i(_region_limit),
HR_FORMAT_PARAMS(_curr_region)); HR_FORMAT_PARAMS(_curr_region));
} }
@ -3988,7 +3988,7 @@ void CMTask::do_marking_step(double time_target_ms,
if (_cm->verbose_low()) { if (_cm->verbose_low()) {
gclog_or_tty->print_cr("[%u] we successfully claimed " gclog_or_tty->print_cr("[%u] we successfully claimed "
"region "PTR_FORMAT, "region " PTR_FORMAT,
_worker_id, p2i(claimed_region)); _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->try_stealing(_worker_id, &_hash_seed, obj)) {
if (_cm->verbose_medium()) { 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)); _worker_id, p2i((void*) obj));
} }
@ -4257,7 +4257,7 @@ CMTask::CMTask(uint worker_id,
// identify them easily in a large log file. // identify them easily in a large log file.
#define G1PPRL_LINE_PREFIX "###" #define G1PPRL_LINE_PREFIX "###"
#define G1PPRL_ADDR_BASE_FORMAT " "PTR_FORMAT"-"PTR_FORMAT #define G1PPRL_ADDR_BASE_FORMAT " " PTR_FORMAT "-" PTR_FORMAT
#ifdef _LP64 #ifdef _LP64
#define G1PPRL_ADDR_BASE_H_FORMAT " %37s" #define G1PPRL_ADDR_BASE_H_FORMAT " %37s"
#else // _LP64 #else // _LP64
@ -4267,16 +4267,16 @@ CMTask::CMTask(uint worker_id,
// For per-region info // For per-region info
#define G1PPRL_TYPE_FORMAT " %-4s" #define G1PPRL_TYPE_FORMAT " %-4s"
#define G1PPRL_TYPE_H_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_BYTE_H_FORMAT " %9s"
#define G1PPRL_DOUBLE_FORMAT " %14.1f" #define G1PPRL_DOUBLE_FORMAT " %14.1f"
#define G1PPRL_DOUBLE_H_FORMAT " %14s" #define G1PPRL_DOUBLE_H_FORMAT " %14s"
// For summary info // For summary info
#define G1PPRL_SUM_ADDR_FORMAT(tag) " "tag":"G1PPRL_ADDR_BASE_FORMAT #define G1PPRL_SUM_ADDR_FORMAT(tag) " " tag ":" G1PPRL_ADDR_BASE_FORMAT
#define G1PPRL_SUM_BYTE_FORMAT(tag) " "tag": "SIZE_FORMAT #define G1PPRL_SUM_BYTE_FORMAT(tag) " " tag ": " SIZE_FORMAT
#define G1PPRL_SUM_MB_FORMAT(tag) " "tag": %1.2f MB" #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_MB_PERC_FORMAT(tag) G1PPRL_SUM_MB_FORMAT(tag) " / %1.2f %%"
G1PrintRegionLivenessInfoClosure:: G1PrintRegionLivenessInfoClosure::
G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name) G1PrintRegionLivenessInfoClosure(outputStream* out, const char* phase_name)

View File

@ -197,8 +197,8 @@ inline bool CMBitMapRO::iterate(BitMapClosure* cl) {
assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \ assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize), \
"outside underlying space?"); \ "outside underlying space?"); \
assert(G1CollectedHeap::heap()->is_in_exact(addr), \ assert(G1CollectedHeap::heap()->is_in_exact(addr), \
err_msg("Trying to access not available bitmap "PTR_FORMAT \ err_msg("Trying to access not available bitmap " PTR_FORMAT \
" corresponding to "PTR_FORMAT" (%u)", \ " corresponding to " PTR_FORMAT " (%u)", \
p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr))); p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr)));
inline void CMBitMap::mark(HeapWord* 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) { inline void CMTask::deal_with_reference(oop obj) {
if (_cm->verbose_high()) { 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)); _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 // assert that word_size is under an upper bound which is its
// containing region's capacity. // containing region's capacity.
assert(word_size * HeapWordSize <= hr->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(), word_size * HeapWordSize, hr->capacity(),
HR_FORMAT_PARAMS(hr))); HR_FORMAT_PARAMS(hr)));

View File

@ -44,8 +44,7 @@ SurrogateLockerThread*
ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) : ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) :
ConcurrentGCThread(), ConcurrentGCThread(),
_cm(cm), _cm(cm),
_started(false), _state(Idle),
_in_progress(false),
_vtime_accum(0.0), _vtime_accum(0.0),
_vtime_mark_accum(0.0) { _vtime_mark_accum(0.0) {
@ -307,7 +306,6 @@ void ConcurrentMarkThread::sleepBeforeNextCycle() {
if (started()) { if (started()) {
set_in_progress(); set_in_progress();
clear_started();
} }
} }

View File

@ -47,8 +47,14 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
private: private:
ConcurrentMark* _cm; ConcurrentMark* _cm;
volatile bool _started;
volatile bool _in_progress; enum State {
Idle,
Started,
InProgress
};
volatile State _state;
void sleepBeforeNextCycle(); void sleepBeforeNextCycle();
@ -68,23 +74,22 @@ class ConcurrentMarkThread: public ConcurrentGCThread {
ConcurrentMark* cm() { return _cm; } ConcurrentMark* cm() { return _cm; }
void set_started() { assert(!_in_progress, "cycle in progress"); _started = true; } void set_idle() { assert(_state != Started, "must not be starting a new cycle"); _state = Idle; }
void clear_started() { assert(_in_progress, "must be starting a cycle"); _started = false; } bool idle() { return _state == Idle; }
bool started() { return _started; } 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; } // Returns true from the moment a marking cycle is
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
// initiated (during the initial-mark pause when started() is set) // initiated (during the initial-mark pause when started() is set)
// to the moment when the cycle completes (just after the next // to the moment when the cycle completes (just after the next
// marking bitmap has been cleared and in_progress() is // 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() // 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 // as the CM thread might take some time to wake up before noticing
// that started() is set and set in_progress(). // that started() is set and set in_progress().
bool during_cycle() { return started() || in_progress(); } bool during_cycle() { return !idle(); }
// shutdown // shutdown
void stop(); void stop();

View File

@ -140,7 +140,7 @@ HeapWord* G1AllocRegion::new_alloc_region_and_allocate(size_t word_size,
} }
void G1AllocRegion::fill_in_ext_msg(ar_ext_msg* msg, const char* message) { 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), _name, message, _count, BOOL_TO_STR(_bot_updates),
p2i(_alloc_region), _used_bytes_before); 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 (G1_ALLOC_REGION_TRACING > 1) {
if (result != NULL) { 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); word_size, result);
} else if (word_size != 0) { } else if (word_size != 0) {
jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT, word_size); jio_snprintf(rest_buffer, buffer_length, SIZE_FORMAT, word_size);

View File

@ -86,7 +86,7 @@ void G1DefaultAllocator::init_gc_alloc_regions(EvacuationInfo& evacuation_info)
&_retained_old_gc_alloc_region); &_retained_old_gc_alloc_region);
} }
void G1DefaultAllocator::release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info) { void G1DefaultAllocator::release_gc_alloc_regions(EvacuationInfo& evacuation_info) {
AllocationContext_t context = AllocationContext::current(); AllocationContext_t context = AllocationContext::current();
evacuation_info.set_allocation_regions(survivor_gc_alloc_region(context)->count() + evacuation_info.set_allocation_regions(survivor_gc_alloc_region(context)->count() +
old_gc_alloc_region(context)->count()); old_gc_alloc_region(context)->count());
@ -102,8 +102,8 @@ void G1DefaultAllocator::release_gc_alloc_regions(uint no_of_gc_workers, Evacuat
} }
if (ResizePLAB) { if (ResizePLAB) {
_g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz(no_of_gc_workers); _g1h->alloc_buffer_stats(InCSetState::Young)->adjust_desired_plab_sz();
_g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz(no_of_gc_workers); _g1h->alloc_buffer_stats(InCSetState::Old)->adjust_desired_plab_sz();
} }
} }

View File

@ -53,7 +53,7 @@ public:
virtual void release_mutator_alloc_region() = 0; virtual void release_mutator_alloc_region() = 0;
virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0; virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0;
virtual void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info) = 0; virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0;
virtual void abandon_gc_alloc_regions() = 0; virtual void abandon_gc_alloc_regions() = 0;
virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0; virtual MutatorAllocRegion* mutator_alloc_region(AllocationContext_t context) = 0;
@ -76,7 +76,7 @@ public:
void decrease_used(size_t bytes) { void decrease_used(size_t bytes) {
assert(_summary_bytes_used >= 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));
_summary_bytes_used -= bytes; _summary_bytes_used -= bytes;
} }
@ -114,7 +114,7 @@ public:
virtual void release_mutator_alloc_region(); virtual void release_mutator_alloc_region();
virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info); virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info);
virtual void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info); virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info);
virtual void abandon_gc_alloc_regions(); virtual void abandon_gc_alloc_regions();
virtual bool is_retained_old_region(HeapRegion* hr) { virtual bool is_retained_old_region(HeapRegion* hr) {

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