mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 18:14:38 +02:00
Merge
This commit is contained in:
commit
faf9972570
53 changed files with 1152 additions and 830 deletions
|
@ -158,8 +158,8 @@ To build hotspot and import it into the JDK: "mx make hotspot import-hotspot"
|
||||||
# JDK9 must be bootstrapped with a JDK8
|
# JDK9 must be bootstrapped with a JDK8
|
||||||
compliance = mx.JavaCompliance('8')
|
compliance = mx.JavaCompliance('8')
|
||||||
jdk8 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value)
|
jdk8 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value)
|
||||||
cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--with-native-debug-symbols=external', '--disable-precompiled-headers',
|
cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--with-native-debug-symbols=external', '--disable-precompiled-headers', '--with-jvm-features=graal',
|
||||||
'--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk8.home]
|
'--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk8.home, '--with-jvm-features=graal']
|
||||||
mx.run(cmd, cwd=_jdkSourceRoot)
|
mx.run(cmd, cwd=_jdkSourceRoot)
|
||||||
cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel]
|
cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel]
|
||||||
if mx.get_opts().verbose:
|
if mx.get_opts().verbose:
|
||||||
|
@ -176,66 +176,6 @@ To build hotspot and import it into the JDK: "mx make hotspot import-hotspot"
|
||||||
|
|
||||||
mx.run(cmd, cwd=_jdkSourceRoot)
|
mx.run(cmd, cwd=_jdkSourceRoot)
|
||||||
|
|
||||||
if 'images' in cmd:
|
|
||||||
jdkImageDir = join(jdkBuildDir, 'images', 'jdk')
|
|
||||||
|
|
||||||
# The OpenJDK build creates an empty cacerts file so copy one from
|
|
||||||
# the default JDK (which is assumed to be an OracleJDK)
|
|
||||||
srcCerts = join(mx.get_jdk(tag='default').home, 'lib', 'security', 'cacerts')
|
|
||||||
if not exists(srcCerts):
|
|
||||||
# Might be building with JDK8 which has cacerts under jre/
|
|
||||||
srcCerts = join(mx.get_jdk(tag='default').home, 'jre', 'lib', 'security', 'cacerts')
|
|
||||||
dstCerts = join(jdkImageDir, 'lib', 'security', 'cacerts')
|
|
||||||
if srcCerts != dstCerts:
|
|
||||||
shutil.copyfile(srcCerts, dstCerts)
|
|
||||||
|
|
||||||
_create_jdk_bundle(jdkBuildDir, _vm.debugLevel, jdkImageDir)
|
|
||||||
|
|
||||||
def _get_jdk_bundle_arches():
|
|
||||||
"""
|
|
||||||
Gets a list of names that will be the part of a JDK bundle's file name denoting the architecture.
|
|
||||||
The first element in the list is the canonical name. Symlinks should be created for the
|
|
||||||
remaining names.
|
|
||||||
"""
|
|
||||||
cpu = mx.get_arch()
|
|
||||||
if cpu == 'amd64':
|
|
||||||
return ['x64', 'x86_64', 'amd64']
|
|
||||||
elif cpu == 'sparcv9':
|
|
||||||
return ['sparcv9']
|
|
||||||
mx.abort('Unsupported JDK bundle arch: ' + cpu)
|
|
||||||
|
|
||||||
def _create_jdk_bundle(jdkBuildDir, debugLevel, jdkImageDir):
|
|
||||||
"""
|
|
||||||
Creates a tar.gz JDK archive, an accompanying tar.gz.sha1 file with its
|
|
||||||
SHA1 signature plus symlinks to the archive for non-canonical architecture names.
|
|
||||||
"""
|
|
||||||
|
|
||||||
arches = _get_jdk_bundle_arches()
|
|
||||||
jdkTgzPath = join(_suite.get_output_root(), 'jdk-bundles', 'jdk9-{}-{}-{}.tar.gz'.format(debugLevel, _get_openjdk_os(), arches[0]))
|
|
||||||
with mx.Archiver(jdkTgzPath, kind='tgz') as arc:
|
|
||||||
mx.log('Creating ' + jdkTgzPath)
|
|
||||||
for root, _, filenames in os.walk(jdkImageDir):
|
|
||||||
for name in filenames:
|
|
||||||
f = join(root, name)
|
|
||||||
arcname = 'jdk1.9.0/' + os.path.relpath(f, jdkImageDir)
|
|
||||||
arc.zf.add(name=f, arcname=arcname, recursive=False)
|
|
||||||
|
|
||||||
with open(jdkTgzPath + '.sha1', 'w') as fp:
|
|
||||||
mx.log('Creating ' + jdkTgzPath + '.sha1')
|
|
||||||
fp.write(mx.sha1OfFile(jdkTgzPath))
|
|
||||||
|
|
||||||
def _create_link(source, link_name):
|
|
||||||
if exists(link_name):
|
|
||||||
os.remove(link_name)
|
|
||||||
mx.log('Creating ' + link_name + ' -> ' + source)
|
|
||||||
os.symlink(source, link_name)
|
|
||||||
|
|
||||||
for arch in arches[1:]:
|
|
||||||
link_name = join(_suite.get_output_root(), 'jdk-bundles', 'jdk9-{}-{}-{}.tar.gz'.format(debugLevel, _get_openjdk_os(), arch))
|
|
||||||
jdkTgzName = os.path.basename(jdkTgzPath)
|
|
||||||
_create_link(jdkTgzName, link_name)
|
|
||||||
_create_link(jdkTgzName + '.sha1', link_name + '.sha1')
|
|
||||||
|
|
||||||
def _runmultimake(args):
|
def _runmultimake(args):
|
||||||
"""run the JDK make process for one or more configurations"""
|
"""run the JDK make process for one or more configurations"""
|
||||||
|
|
||||||
|
|
|
@ -850,6 +850,12 @@ void VM_Version::get_processor_features() {
|
||||||
|
|
||||||
#if INCLUDE_RTM_OPT
|
#if INCLUDE_RTM_OPT
|
||||||
if (UseRTMLocking) {
|
if (UseRTMLocking) {
|
||||||
|
if (is_client_compilation_mode_vm()) {
|
||||||
|
// Only C2 does RTM locking optimization.
|
||||||
|
// Can't continue because UseRTMLocking affects UseBiasedLocking flag
|
||||||
|
// setting during arguments processing. See use_biased_locking().
|
||||||
|
vm_exit_during_initialization("RTM locking optimization is not supported in emulated client VM");
|
||||||
|
}
|
||||||
if (is_intel_family_core()) {
|
if (is_intel_family_core()) {
|
||||||
if ((_model == CPU_MODEL_HASWELL_E3) ||
|
if ((_model == CPU_MODEL_HASWELL_E3) ||
|
||||||
(_model == CPU_MODEL_HASWELL_E7 && _stepping < 3) ||
|
(_model == CPU_MODEL_HASWELL_E7 && _stepping < 3) ||
|
||||||
|
|
|
@ -59,12 +59,6 @@ abstract class CallSiteRelocationSymbol {
|
||||||
addExternalPltToGotRelocation(binaryContainer, symbol, relocationOffset);
|
addExternalPltToGotRelocation(binaryContainer, symbol, relocationOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void addMetaspaceGotRelocation(BinaryContainer binaryContainer, String symbolName, int symbolOffset, int relocationOffset) {
|
|
||||||
ByteContainer container = binaryContainer.getMetaspaceGotContainer();
|
|
||||||
Symbol symbol = container.createGotSymbol(symbolOffset, symbolName);
|
|
||||||
addExternalPltToGotRelocation(binaryContainer, symbol, relocationOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an {@link RelocType#EXTERNAL_GOT_TO_PLT} relocation to the
|
* Add an {@link RelocType#EXTERNAL_GOT_TO_PLT} relocation to the
|
||||||
* {@link BinaryContainer#getExtLinkageGOTContainer()}.
|
* {@link BinaryContainer#getExtLinkageGOTContainer()}.
|
||||||
|
|
|
@ -37,6 +37,7 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
|
||||||
final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
||||||
|
|
||||||
private static final byte[] zeroSlot = new byte[8];
|
private static final byte[] zeroSlot = new byte[8];
|
||||||
|
// -1 represents Universe::non_oop_word() value
|
||||||
private static final byte[] minusOneSlot = {-1, -1, -1, -1, -1, -1, -1, -1};
|
private static final byte[] minusOneSlot = {-1, -1, -1, -1, -1, -1, -1, -1};
|
||||||
|
|
||||||
public JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
|
public JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
|
||||||
|
@ -79,30 +80,39 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add relocation to GOT cell for call resolution jump.
|
// Add relocation to GOT cell for call resolution jump.
|
||||||
|
// This GOT cell will be initialized during JVM startup with address
|
||||||
|
// of JVM runtime call resolution function.
|
||||||
String gotSymbolName = "got." + getResolveSymbolName(binaryContainer, mi, call);
|
String gotSymbolName = "got." + getResolveSymbolName(binaryContainer, mi, call);
|
||||||
Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
|
Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
|
||||||
addExternalPltToGotRelocation(binaryContainer, gotSymbol, stub.getResolveJumpOffset());
|
addExternalPltToGotRelocation(binaryContainer, gotSymbol, stub.getResolveJumpOffset());
|
||||||
|
|
||||||
// Add relocation to resolve call jump instruction address for GOT cell.
|
// Add relocation to resolve call jump instruction address for GOT cell.
|
||||||
|
// This GOT cell will be initialized with address of resolution jump instruction and
|
||||||
|
// will be updated with call destination address by JVM runtime call resolution code.
|
||||||
String pltJmpSymbolName = relocationSymbolName("plt.jmp", mi, call, callSiteRelocation);
|
String pltJmpSymbolName = relocationSymbolName("plt.jmp", mi, call, callSiteRelocation);
|
||||||
addCodeContainerRelocation(binaryContainer, pltJmpSymbolName, stub.getResolveJumpStart(), gotStartOffset);
|
addCodeContainerRelocation(binaryContainer, pltJmpSymbolName, stub.getResolveJumpStart(), gotStartOffset);
|
||||||
|
|
||||||
// Add relocation to GOT cell for dispatch jump.
|
// Add relocation to GOT cell for dispatch jump.
|
||||||
|
// The dispatch jump loads destination address from this GOT cell.
|
||||||
String gotEntrySymbolName = relocationSymbolName("got.entry", mi, call, callSiteRelocation);
|
String gotEntrySymbolName = relocationSymbolName("got.entry", mi, call, callSiteRelocation);
|
||||||
addExtLinkageGotContainerRelocation(binaryContainer, gotEntrySymbolName, gotStartOffset, stub.getDispatchJumpOffset());
|
addExtLinkageGotContainerRelocation(binaryContainer, gotEntrySymbolName, gotStartOffset, stub.getDispatchJumpOffset());
|
||||||
|
|
||||||
// Virtual call needs initial -1 value.
|
// Virtual call needs initial -1 value for Klass pointer.
|
||||||
|
// Non virtual call needs initial 0 value for Method pointer to call c2i adapter.
|
||||||
byte[] slot = isVirtualCall ? minusOneSlot : zeroSlot;
|
byte[] slot = isVirtualCall ? minusOneSlot : zeroSlot;
|
||||||
final int gotMetaOffset = binaryContainer.appendMetaspaceGotBytes(slot, 0, slot.length);
|
final int gotMetaOffset = binaryContainer.appendExtLinkageGotBytes(slot, 0, slot.length);
|
||||||
|
|
||||||
// Add relocation to GOT cell for move instruction (Klass* for virtual, Method* otherwise).
|
// Add relocation to GOT cell for move instruction (Klass* for virtual, Method* otherwise).
|
||||||
String gotMoveSymbolName = relocationSymbolName("got.move", mi, call, callSiteRelocation);
|
String gotMoveSymbolName = relocationSymbolName("got.move", mi, call, callSiteRelocation);
|
||||||
addMetaspaceGotRelocation(binaryContainer, gotMoveSymbolName, gotMetaOffset, stub.getMovOffset());
|
addExtLinkageGotContainerRelocation(binaryContainer, gotMoveSymbolName, gotMetaOffset, stub.getMovOffset());
|
||||||
|
|
||||||
if (isVirtualCall) {
|
if (isVirtualCall) {
|
||||||
// Nothing.
|
// Nothing.
|
||||||
} else {
|
} else {
|
||||||
// Add relocation to GOT cell for c2i adapter jump.
|
// Add relocation to GOT cell for c2i adapter jump.
|
||||||
|
// The c2i jump instruction loads destination address from this GOT cell.
|
||||||
|
// This GOT cell is initialized with -1 and will be updated
|
||||||
|
// by JVM runtime call resolution code.
|
||||||
String gotC2ISymbolName = relocationSymbolName("got.c2i", mi, call, callSiteRelocation);
|
String gotC2ISymbolName = relocationSymbolName("got.c2i", mi, call, callSiteRelocation);
|
||||||
addExtLinkageGotContainerRelocation(binaryContainer, gotC2ISymbolName, gotStartOffset + 8, stub.getC2IJumpOffset());
|
addExtLinkageGotContainerRelocation(binaryContainer, gotC2ISymbolName, gotStartOffset + 8, stub.getC2IJumpOffset());
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,8 +278,10 @@ final class CompilerToVM {
|
||||||
* {@code info} are:
|
* {@code info} are:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* [(int) flags, // only valid if field is resolved
|
* [ flags, // fieldDescriptor::access_flags()
|
||||||
* (int) offset] // only valid if field is resolved
|
* offset, // fieldDescriptor::offset()
|
||||||
|
* index // fieldDescriptor::index()
|
||||||
|
* ]
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* The behavior of this method is undefined if {@code cpi} does not denote a
|
* The behavior of this method is undefined if {@code cpi} does not denote a
|
||||||
|
@ -288,7 +290,7 @@ final class CompilerToVM {
|
||||||
* @param info an array in which the details of the field are returned
|
* @param info an array in which the details of the field are returned
|
||||||
* @return the type defining the field if resolution is successful, 0 otherwise
|
* @return the type defining the field if resolution is successful, 0 otherwise
|
||||||
*/
|
*/
|
||||||
native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, HotSpotResolvedJavaMethodImpl method, byte opcode, long[] info);
|
native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, int cpi, HotSpotResolvedJavaMethodImpl method, byte opcode, int[] info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
|
* Converts {@code cpci} from an index into the cache for {@code constantPool} to an index
|
||||||
|
@ -631,4 +633,15 @@ final class CompilerToVM {
|
||||||
* {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
|
* {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
|
||||||
*/
|
*/
|
||||||
native void compileToBytecode(Object lambdaForm);
|
native void compileToBytecode(Object lambdaForm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the VM flag named {@code name}.
|
||||||
|
*
|
||||||
|
* @param name name of a VM option
|
||||||
|
* @return {@code this} if the named VM option doesn't exist, a {@link String} or {@code null}
|
||||||
|
* if its type is {@code ccstr} or {@code ccstrlist}, a {@link Double} if its type is
|
||||||
|
* {@code double}, a {@link Boolean} if its type is {@code bool} otherwise a
|
||||||
|
* {@link Long}
|
||||||
|
*/
|
||||||
|
native Object getFlagValue(String name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,7 +298,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||||
* @param index constant pool index
|
* @param index constant pool index
|
||||||
* @return constant pool entry
|
* @return constant pool entry
|
||||||
*/
|
*/
|
||||||
private long getEntryAt(int index) {
|
long getEntryAt(int index) {
|
||||||
assert checkBounds(index);
|
assert checkBounds(index);
|
||||||
int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
|
int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
|
||||||
return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset);
|
return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset);
|
||||||
|
@ -605,8 +605,6 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||||
public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
|
public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
|
||||||
final int index = rawIndexToConstantPoolIndex(cpi, opcode);
|
final int index = rawIndexToConstantPoolIndex(cpi, opcode);
|
||||||
final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
|
final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
|
||||||
final int nameIndex = getNameRefIndexAt(nameAndTypeIndex);
|
|
||||||
String name = lookupUtf8(nameIndex);
|
|
||||||
final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
|
final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
|
||||||
String typeName = lookupUtf8(typeIndex);
|
String typeName = lookupUtf8(typeIndex);
|
||||||
JavaType type = runtime().lookupType(typeName, getHolder(), false);
|
JavaType type = runtime().lookupType(typeName, getHolder(), false);
|
||||||
|
@ -615,7 +613,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||||
JavaType holder = lookupType(holderIndex, opcode);
|
JavaType holder = lookupType(holderIndex, opcode);
|
||||||
|
|
||||||
if (holder instanceof HotSpotResolvedObjectTypeImpl) {
|
if (holder instanceof HotSpotResolvedObjectTypeImpl) {
|
||||||
long[] info = new long[2];
|
int[] info = new int[3];
|
||||||
HotSpotResolvedObjectTypeImpl resolvedHolder;
|
HotSpotResolvedObjectTypeImpl resolvedHolder;
|
||||||
try {
|
try {
|
||||||
resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
|
resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
|
||||||
|
@ -624,14 +622,15 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject
|
||||||
* If there was an exception resolving the field we give up and return an unresolved
|
* If there was an exception resolving the field we give up and return an unresolved
|
||||||
* field.
|
* field.
|
||||||
*/
|
*/
|
||||||
return new HotSpotUnresolvedField(holder, name, type);
|
return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
|
||||||
}
|
}
|
||||||
final int flags = (int) info[0];
|
final int flags = info[0];
|
||||||
final long offset = info[1];
|
final int offset = info[1];
|
||||||
HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags);
|
final int fieldIndex = info[2];
|
||||||
|
HotSpotResolvedJavaField result = resolvedHolder.createField(type, offset, flags, fieldIndex);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
return new HotSpotUnresolvedField(holder, name, type);
|
return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -513,10 +513,6 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider {
|
||||||
for (Map.Entry<String, Long> e : constants.entrySet()) {
|
for (Map.Entry<String, Long> e : constants.entrySet()) {
|
||||||
printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
|
printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
|
||||||
}
|
}
|
||||||
TreeMap<String, Long> typeSizes = new TreeMap<>(store.getTypeSizes());
|
|
||||||
for (Map.Entry<String, Long> e : typeSizes.entrySet()) {
|
|
||||||
printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue());
|
|
||||||
}
|
|
||||||
for (VMIntrinsicMethod e : store.getIntrinsics()) {
|
for (VMIntrinsicMethod e : store.getIntrinsics()) {
|
||||||
printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
|
printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,23 +59,12 @@ abstract class HotSpotMethod implements JavaMethod, Formattable {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String name;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls whether {@link #toString()} includes the qualified or simple name of the class in
|
* Controls whether {@link #toString()} includes the qualified or simple name of the class in
|
||||||
* which the method is declared.
|
* which the method is declared.
|
||||||
*/
|
*/
|
||||||
public static final boolean FULLY_QUALIFIED_METHOD_NAME = false;
|
public static final boolean FULLY_QUALIFIED_METHOD_NAME = false;
|
||||||
|
|
||||||
protected HotSpotMethod(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final String toString() {
|
public final String toString() {
|
||||||
char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
|
char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
|
||||||
|
|
|
@ -31,15 +31,21 @@ import jdk.vm.ci.meta.Signature;
|
||||||
*/
|
*/
|
||||||
final class HotSpotMethodUnresolved extends HotSpotMethod {
|
final class HotSpotMethodUnresolved extends HotSpotMethod {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
private final Signature signature;
|
private final Signature signature;
|
||||||
protected JavaType holder;
|
protected JavaType holder;
|
||||||
|
|
||||||
HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) {
|
HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) {
|
||||||
super(name);
|
this.name = name;
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Signature getSignature() {
|
public Signature getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2017, 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,19 +38,20 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||||
class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
||||||
|
|
||||||
private final HotSpotResolvedObjectTypeImpl holder;
|
private final HotSpotResolvedObjectTypeImpl holder;
|
||||||
private final String name;
|
|
||||||
private JavaType type;
|
private JavaType type;
|
||||||
private final int offset;
|
private final int offset;
|
||||||
|
private final short index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This value contains all flags as stored in the VM including internal ones.
|
* This value contains all flags as stored in the VM including internal ones.
|
||||||
*/
|
*/
|
||||||
private final int modifiers;
|
private final int modifiers;
|
||||||
|
|
||||||
HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) {
|
HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, JavaType type, long offset, int modifiers, int index) {
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
this.name = name;
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.index = (short) index;
|
||||||
|
assert this.index == index;
|
||||||
assert offset != -1;
|
assert offset != -1;
|
||||||
assert offset == (int) offset : "offset larger than int";
|
assert offset == (int) offset : "offset larger than int";
|
||||||
this.offset = (int) offset;
|
this.offset = (int) offset;
|
||||||
|
@ -67,7 +68,6 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
||||||
if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
|
if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
|
||||||
return false;
|
return false;
|
||||||
} else if (this.holder.equals(that.holder)) {
|
} else if (this.holder.equals(that.holder)) {
|
||||||
assert this.name.equals(that.name) && this.type.equals(that.type);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return name.hashCode();
|
return offset ^ modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -109,7 +109,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return holder.createFieldInfo(index).getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -178,18 +178,12 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Field toJavaCache;
|
|
||||||
|
|
||||||
private Field toJava() {
|
private Field toJava() {
|
||||||
if (toJavaCache != null) {
|
|
||||||
return toJavaCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isInternal()) {
|
if (isInternal()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return toJavaCache = holder.mirror().getDeclaredField(name);
|
return holder.mirror().getDeclaredField(getName());
|
||||||
} catch (NoSuchFieldException | NoClassDefFoundError e) {
|
} catch (NoSuchFieldException | NoClassDefFoundError e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2017, 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
|
||||||
|
@ -75,6 +75,12 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
private byte[] code;
|
private byte[] code;
|
||||||
private Executable toJavaCache;
|
private Executable toJavaCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only 30% of {@link HotSpotResolvedJavaMethodImpl}s have their name accessed so compute it
|
||||||
|
* lazily and cache it.
|
||||||
|
*/
|
||||||
|
private String nameCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the holder of a HotSpot metaspace method native object.
|
* Gets the holder of a HotSpot metaspace method native object.
|
||||||
*
|
*
|
||||||
|
@ -106,8 +112,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
}
|
}
|
||||||
|
|
||||||
HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) {
|
HotSpotResolvedJavaMethodImpl(HotSpotResolvedObjectTypeImpl holder, long metaspaceMethod) {
|
||||||
// It would be too much work to get the method name here so we fill it in later.
|
|
||||||
super(null);
|
|
||||||
this.metaspaceMethod = metaspaceMethod;
|
this.metaspaceMethod = metaspaceMethod;
|
||||||
this.holder = holder;
|
this.holder = holder;
|
||||||
|
|
||||||
|
@ -126,9 +130,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
this.constantPool = compilerToVM().getConstantPool(this);
|
this.constantPool = compilerToVM().getConstantPool(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int nameIndex = UNSAFE.getChar(constMethod + config.constMethodNameIndexOffset);
|
|
||||||
this.name = constantPool.lookupUtf8(nameIndex);
|
|
||||||
|
|
||||||
final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset);
|
final int signatureIndex = UNSAFE.getChar(constMethod + config.constMethodSignatureIndexOffset);
|
||||||
this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
|
this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
|
||||||
}
|
}
|
||||||
|
@ -146,6 +147,15 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset);
|
return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
if (nameCache == null) {
|
||||||
|
final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
|
||||||
|
nameCache = constantPool.lookupUtf8(nameIndex);
|
||||||
|
}
|
||||||
|
return nameCache;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
@ -326,12 +336,24 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isClassInitializer() {
|
public boolean isClassInitializer() {
|
||||||
return "<clinit>".equals(name) && isStatic();
|
if (isStatic()) {
|
||||||
|
final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
|
||||||
|
long nameSymbol = constantPool.getEntryAt(nameIndex);
|
||||||
|
long clinitSymbol = config().symbolClinit;
|
||||||
|
return nameSymbol == clinitSymbol;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isConstructor() {
|
public boolean isConstructor() {
|
||||||
return "<init>".equals(name) && !isStatic();
|
if (!isStatic()) {
|
||||||
|
final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
|
||||||
|
long nameSymbol = constantPool.getEntryAt(nameIndex);
|
||||||
|
long initSymbol = config().symbolInit;
|
||||||
|
return nameSymbol == initSymbol;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -472,7 +494,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
@Override
|
@Override
|
||||||
public Annotation[][] getParameterAnnotations() {
|
public Annotation[][] getParameterAnnotations() {
|
||||||
Executable javaMethod = toJava();
|
Executable javaMethod = toJava();
|
||||||
return javaMethod == null ? null : javaMethod.getParameterAnnotations();
|
return javaMethod == null ? new Annotation[signature.getParameterCount(false)][0] : javaMethod.getParameterAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -513,9 +535,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDefault() {
|
public boolean isDefault() {
|
||||||
if (isConstructor()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Copied from java.lang.Method.isDefault()
|
// Copied from java.lang.Method.isDefault()
|
||||||
int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
|
int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
|
||||||
return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
|
return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
|
||||||
|
@ -562,7 +581,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
|
||||||
} else {
|
} else {
|
||||||
// Do not use Method.getDeclaredMethod() as it can return a bridge method
|
// Do not use Method.getDeclaredMethod() as it can return a bridge method
|
||||||
// when this.isBridge() is false and vice versa.
|
// when this.isBridge() is false and vice versa.
|
||||||
result = searchMethods(holder.mirror().getDeclaredMethods(), name, returnType, parameterTypes);
|
result = searchMethods(holder.mirror().getDeclaredMethods(), getName(), returnType, parameterTypes);
|
||||||
}
|
}
|
||||||
toJavaCache = result;
|
toJavaCache = result;
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2011, 2017, 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
|
||||||
|
@ -36,8 +36,6 @@ import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import jdk.vm.ci.common.JVMCIError;
|
import jdk.vm.ci.common.JVMCIError;
|
||||||
|
@ -59,12 +57,15 @@ import jdk.vm.ci.meta.ResolvedJavaType;
|
||||||
*/
|
*/
|
||||||
final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceWrapperObject {
|
final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implements HotSpotResolvedObjectType, MetaspaceWrapperObject {
|
||||||
|
|
||||||
|
private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
|
||||||
|
private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Java class this type represents.
|
* The Java class this type represents.
|
||||||
*/
|
*/
|
||||||
private final Class<?> javaClass;
|
private final Class<?> javaClass;
|
||||||
private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
|
private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
|
||||||
private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCache;
|
private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
|
||||||
private HotSpotResolvedJavaField[] instanceFields;
|
private HotSpotResolvedJavaField[] instanceFields;
|
||||||
private HotSpotResolvedObjectTypeImpl[] interfaces;
|
private HotSpotResolvedObjectTypeImpl[] interfaces;
|
||||||
private HotSpotConstantPool constantPool;
|
private HotSpotConstantPool constantPool;
|
||||||
|
@ -255,7 +256,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||||
* @return true if the type is a leaf class
|
* @return true if the type is a leaf class
|
||||||
*/
|
*/
|
||||||
private boolean isLeafClass() {
|
private boolean isLeafClass() {
|
||||||
return getSubklass() == null;
|
return UNSAFE.getLong(this.getMetaspaceKlass() + config().subklassOffset) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -484,18 +485,38 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
|
synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
|
||||||
HotSpotResolvedJavaMethodImpl method = null;
|
// Maintain cache as array.
|
||||||
if (methodCache == null) {
|
if (methodCacheArray == null) {
|
||||||
methodCache = new HashMap<>(8);
|
methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < methodCacheArray.length; ++i) {
|
||||||
|
HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i];
|
||||||
|
if (curMethod == null) {
|
||||||
|
HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
|
||||||
|
methodCacheArray[i] = newMethod;
|
||||||
|
context.add(newMethod);
|
||||||
|
return newMethod;
|
||||||
|
} else if (curMethod.getMetaspacePointer() == metaspaceMethod) {
|
||||||
|
return curMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall-back to hash table.
|
||||||
|
if (methodCacheHashMap == null) {
|
||||||
|
methodCacheHashMap = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod);
|
||||||
|
if (lookupResult == null) {
|
||||||
|
HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
|
||||||
|
methodCacheHashMap.put(metaspaceMethod, newMethod);
|
||||||
|
context.add(lookupResult);
|
||||||
|
return newMethod;
|
||||||
} else {
|
} else {
|
||||||
method = methodCache.get(metaspaceMethod);
|
return lookupResult;
|
||||||
}
|
}
|
||||||
if (method == null) {
|
|
||||||
method = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
|
|
||||||
methodCache.put(metaspaceMethod, method);
|
|
||||||
context.add(method);
|
|
||||||
}
|
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getVtableLength() {
|
public int getVtableLength() {
|
||||||
|
@ -509,37 +530,8 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) {
|
synchronized HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
|
||||||
HotSpotResolvedJavaField result = null;
|
return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);
|
||||||
|
|
||||||
final int flags = rawFlags & HotSpotModifiers.jvmFieldModifiers();
|
|
||||||
|
|
||||||
final long id = offset + ((long) flags << 32);
|
|
||||||
|
|
||||||
// Must cache the fields, because the local load elimination only works if the
|
|
||||||
// objects from two field lookups are identical.
|
|
||||||
if (fieldCache == null) {
|
|
||||||
fieldCache = new HashMap<>(8);
|
|
||||||
} else {
|
|
||||||
result = fieldCache.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
result = new HotSpotResolvedJavaFieldImpl(this, fieldName, type, offset, rawFlags);
|
|
||||||
fieldCache.put(id, result);
|
|
||||||
} else {
|
|
||||||
assert result.getName().equals(fieldName);
|
|
||||||
/*
|
|
||||||
* Comparing the types directly is too strict, because the type in the cache could be
|
|
||||||
* resolved while the incoming type is unresolved. The name comparison is sufficient
|
|
||||||
* because the type will always be resolved in the context of the holder.
|
|
||||||
*/
|
|
||||||
assert result.getType().getName().equals(type.getName());
|
|
||||||
assert result.offset() == offset;
|
|
||||||
assert result.getModifiers() == flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -577,11 +569,15 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FieldInfo createFieldInfo(int index) {
|
||||||
|
return new FieldInfo(index);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents the field information for one field contained in the fields array of an
|
* This class represents the field information for one field contained in the fields array of an
|
||||||
* {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
|
* {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class.
|
||||||
*/
|
*/
|
||||||
private class FieldInfo {
|
class FieldInfo {
|
||||||
/**
|
/**
|
||||||
* Native pointer into the array of Java shorts.
|
* Native pointer into the array of Java shorts.
|
||||||
*/
|
*/
|
||||||
|
@ -666,61 +662,31 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings(value = "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE", justification = "comparator is only used transiently")
|
|
||||||
private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> {
|
|
||||||
@Override
|
|
||||||
public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) {
|
|
||||||
return o1.offset() - o2.offset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
|
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
|
||||||
if (instanceFields == null) {
|
if (instanceFields == null) {
|
||||||
if (isArray() || isInterface()) {
|
if (isArray() || isInterface()) {
|
||||||
instanceFields = new HotSpotResolvedJavaField[0];
|
instanceFields = NO_FIELDS;
|
||||||
} else {
|
} else {
|
||||||
final int fieldCount = getFieldCount();
|
HotSpotResolvedJavaField[] prepend = NO_FIELDS;
|
||||||
ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
|
if (getSuperclass() != null) {
|
||||||
|
prepend = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true);
|
||||||
for (int i = 0; i < fieldCount; i++) {
|
|
||||||
FieldInfo field = new FieldInfo(i);
|
|
||||||
|
|
||||||
// We are only interested in instance fields.
|
|
||||||
if (!field.isStatic()) {
|
|
||||||
HotSpotResolvedJavaField resolvedJavaField = createField(field.getName(), field.getType(), field.getOffset(), field.getAccessFlags());
|
|
||||||
fieldsArray.add(resolvedJavaField);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
instanceFields = getFields(false, prepend);
|
||||||
fieldsArray.sort(new OffsetComparator());
|
|
||||||
|
|
||||||
HotSpotResolvedJavaField[] myFields = fieldsArray.toArray(new HotSpotResolvedJavaField[0]);
|
|
||||||
|
|
||||||
if (mirror() != Object.class) {
|
|
||||||
HotSpotResolvedJavaField[] superFields = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true);
|
|
||||||
HotSpotResolvedJavaField[] fields = Arrays.copyOf(superFields, superFields.length + myFields.length);
|
|
||||||
System.arraycopy(myFields, 0, fields, superFields.length, myFields.length);
|
|
||||||
instanceFields = fields;
|
|
||||||
} else {
|
|
||||||
assert myFields.length == 0 : "java.lang.Object has fields!";
|
|
||||||
instanceFields = myFields;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!includeSuperclasses) {
|
if (!includeSuperclasses && getSuperclass() != null) {
|
||||||
int myFieldsStart = 0;
|
int superClassFieldCount = getSuperclass().getInstanceFields(true).length;
|
||||||
while (myFieldsStart < instanceFields.length && !instanceFields[myFieldsStart].getDeclaringClass().equals(this)) {
|
if (superClassFieldCount == instanceFields.length) {
|
||||||
myFieldsStart++;
|
// This class does not have any instance fields of its own.
|
||||||
|
return NO_FIELDS;
|
||||||
|
} else if (superClassFieldCount != 0) {
|
||||||
|
HotSpotResolvedJavaField[] result = new HotSpotResolvedJavaField[instanceFields.length - superClassFieldCount];
|
||||||
|
System.arraycopy(instanceFields, superClassFieldCount, result, 0, result.length);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// The super classes of this class do not have any instance fields.
|
||||||
}
|
}
|
||||||
if (myFieldsStart == 0) {
|
|
||||||
return instanceFields;
|
|
||||||
}
|
|
||||||
if (myFieldsStart == instanceFields.length) {
|
|
||||||
return new HotSpotResolvedJavaField[0];
|
|
||||||
}
|
|
||||||
return Arrays.copyOfRange(instanceFields, myFieldsStart, instanceFields.length);
|
|
||||||
}
|
}
|
||||||
return instanceFields;
|
return instanceFields;
|
||||||
}
|
}
|
||||||
|
@ -730,45 +696,63 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||||
if (isArray()) {
|
if (isArray()) {
|
||||||
return new HotSpotResolvedJavaField[0];
|
return new HotSpotResolvedJavaField[0];
|
||||||
} else {
|
} else {
|
||||||
final int fieldCount = getFieldCount();
|
return getFields(true, NO_FIELDS);
|
||||||
ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
|
|
||||||
|
|
||||||
for (int i = 0; i < fieldCount; i++) {
|
|
||||||
FieldInfo field = new FieldInfo(i);
|
|
||||||
|
|
||||||
// We are only interested in static fields.
|
|
||||||
if (field.isStatic()) {
|
|
||||||
HotSpotResolvedJavaField resolvedJavaField = createField(field.getName(), field.getType(), field.getOffset(), field.getAccessFlags());
|
|
||||||
fieldsArray.add(resolvedJavaField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldsArray.sort(new OffsetComparator());
|
|
||||||
return fieldsArray.toArray(new HotSpotResolvedJavaField[fieldsArray.size()]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the actual field count of this class's internal {@code InstanceKlass::_fields} array
|
* Gets the instance or static fields of this class.
|
||||||
* by walking the array and discounting the generic signature slots at the end of the array.
|
|
||||||
*
|
*
|
||||||
* <p>
|
* @param retrieveStaticFields specifies whether to return instance or static fields
|
||||||
* See {@code FieldStreamBase::init_generic_signature_start_slot}
|
* @param prepend an array to be prepended to the returned result
|
||||||
*/
|
*/
|
||||||
private int getFieldCount() {
|
private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSpotResolvedJavaField[] prepend) {
|
||||||
HotSpotVMConfig config = config();
|
HotSpotVMConfig config = config();
|
||||||
final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
|
final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
|
||||||
int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
|
int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
|
||||||
int fieldCount = 0;
|
int resultCount = 0;
|
||||||
|
int index = 0;
|
||||||
for (int i = 0, index = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
|
for (int i = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
|
||||||
FieldInfo field = new FieldInfo(index);
|
FieldInfo field = new FieldInfo(index);
|
||||||
if (field.hasGenericSignature()) {
|
if (field.hasGenericSignature()) {
|
||||||
metaspaceFieldsLength--;
|
metaspaceFieldsLength--;
|
||||||
}
|
}
|
||||||
fieldCount++;
|
|
||||||
|
if (field.isStatic() == retrieveStaticFields) {
|
||||||
|
resultCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return fieldCount;
|
|
||||||
|
if (resultCount == 0) {
|
||||||
|
return prepend;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prependLength = prepend.length;
|
||||||
|
resultCount += prependLength;
|
||||||
|
|
||||||
|
HotSpotResolvedJavaField[] result = new HotSpotResolvedJavaField[resultCount];
|
||||||
|
if (prependLength != 0) {
|
||||||
|
System.arraycopy(prepend, 0, result, 0, prependLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
int resultIndex = prependLength;
|
||||||
|
for (int i = 0; i < index; ++i) {
|
||||||
|
FieldInfo field = new FieldInfo(i);
|
||||||
|
if (field.isStatic() == retrieveStaticFields) {
|
||||||
|
int offset = field.getOffset();
|
||||||
|
HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i);
|
||||||
|
|
||||||
|
// Make sure the result is sorted by offset.
|
||||||
|
int j;
|
||||||
|
for (j = resultIndex - 1; j >= prependLength && result[j].offset() > offset; j--) {
|
||||||
|
result[j + 1] = result[j];
|
||||||
|
}
|
||||||
|
result[j + 1] = resolvedJavaField;
|
||||||
|
resultIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -85,7 +85,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
final int klassLayoutHelperNeutralValue = getConstant("Klass::_lh_neutral_value", Integer.class);
|
final int klassLayoutHelperNeutralValue = getConstant("Klass::_lh_neutral_value", Integer.class);
|
||||||
final int klassLayoutHelperInstanceSlowPathBit = getConstant("Klass::_lh_instance_slow_path_bit", Integer.class);
|
final int klassLayoutHelperInstanceSlowPathBit = getConstant("Klass::_lh_instance_slow_path_bit", Integer.class);
|
||||||
|
|
||||||
final int vtableEntrySize = getTypeSize("vtableEntry");
|
final int vtableEntrySize = getFieldValue("CompilerToVM::Data::sizeof_vtableEntry", Integer.class, "int");
|
||||||
final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
|
final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
|
||||||
|
|
||||||
final int instanceKlassSourceFileNameIndexOffset = getFieldOffset("InstanceKlass::_source_file_name_index", Integer.class, "u2");
|
final int instanceKlassSourceFileNameIndexOffset = getFieldOffset("InstanceKlass::_source_file_name_index", Integer.class, "u2");
|
||||||
|
@ -192,20 +192,20 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
|
final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
|
||||||
final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
|
final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
|
||||||
|
|
||||||
final int exceptionTableElementSize = getTypeSize("ExceptionTableElement");
|
final int exceptionTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_ExceptionTableElement", Integer.class, "int");
|
||||||
final int exceptionTableElementStartPcOffset = getFieldOffset("ExceptionTableElement::start_pc", Integer.class, "u2");
|
final int exceptionTableElementStartPcOffset = getFieldOffset("ExceptionTableElement::start_pc", Integer.class, "u2");
|
||||||
final int exceptionTableElementEndPcOffset = getFieldOffset("ExceptionTableElement::end_pc", Integer.class, "u2");
|
final int exceptionTableElementEndPcOffset = getFieldOffset("ExceptionTableElement::end_pc", Integer.class, "u2");
|
||||||
final int exceptionTableElementHandlerPcOffset = getFieldOffset("ExceptionTableElement::handler_pc", Integer.class, "u2");
|
final int exceptionTableElementHandlerPcOffset = getFieldOffset("ExceptionTableElement::handler_pc", Integer.class, "u2");
|
||||||
final int exceptionTableElementCatchTypeIndexOffset = getFieldOffset("ExceptionTableElement::catch_type_index", Integer.class, "u2");
|
final int exceptionTableElementCatchTypeIndexOffset = getFieldOffset("ExceptionTableElement::catch_type_index", Integer.class, "u2");
|
||||||
|
|
||||||
final int localVariableTableElementSize = getTypeSize("LocalVariableTableElement");
|
final int localVariableTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_LocalVariableTableElement", Integer.class, "int");
|
||||||
final int localVariableTableElementStartBciOffset = getFieldOffset("LocalVariableTableElement::start_bci", Integer.class, "u2");
|
final int localVariableTableElementStartBciOffset = getFieldOffset("LocalVariableTableElement::start_bci", Integer.class, "u2");
|
||||||
final int localVariableTableElementLengthOffset = getFieldOffset("LocalVariableTableElement::length", Integer.class, "u2");
|
final int localVariableTableElementLengthOffset = getFieldOffset("LocalVariableTableElement::length", Integer.class, "u2");
|
||||||
final int localVariableTableElementNameCpIndexOffset = getFieldOffset("LocalVariableTableElement::name_cp_index", Integer.class, "u2");
|
final int localVariableTableElementNameCpIndexOffset = getFieldOffset("LocalVariableTableElement::name_cp_index", Integer.class, "u2");
|
||||||
final int localVariableTableElementDescriptorCpIndexOffset = getFieldOffset("LocalVariableTableElement::descriptor_cp_index", Integer.class, "u2");
|
final int localVariableTableElementDescriptorCpIndexOffset = getFieldOffset("LocalVariableTableElement::descriptor_cp_index", Integer.class, "u2");
|
||||||
final int localVariableTableElementSlotOffset = getFieldOffset("LocalVariableTableElement::slot", Integer.class, "u2");
|
final int localVariableTableElementSlotOffset = getFieldOffset("LocalVariableTableElement::slot", Integer.class, "u2");
|
||||||
|
|
||||||
final int constantPoolSize = getTypeSize("ConstantPool");
|
final int constantPoolSize = getFieldValue("CompilerToVM::Data::sizeof_ConstantPool", Integer.class, "int");
|
||||||
final int constantPoolTagsOffset = getFieldOffset("ConstantPool::_tags", Integer.class, "Array<u1>*");
|
final int constantPoolTagsOffset = getFieldOffset("ConstantPool::_tags", Integer.class, "Array<u1>*");
|
||||||
final int constantPoolHolderOffset = getFieldOffset("ConstantPool::_pool_holder", Integer.class, "InstanceKlass*");
|
final int constantPoolHolderOffset = getFieldOffset("ConstantPool::_pool_holder", Integer.class, "InstanceKlass*");
|
||||||
final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length", Integer.class, "int");
|
final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length", Integer.class, "int");
|
||||||
|
@ -237,12 +237,15 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
|
|
||||||
final int heapWordSize = getConstant("HeapWordSize", Integer.class);
|
final int heapWordSize = getConstant("HeapWordSize", Integer.class);
|
||||||
|
|
||||||
final int symbolPointerSize = getTypeSize("Symbol*");
|
final int symbolPointerSize = getFieldValue("CompilerToVM::Data::sizeof_SymbolPointer", Integer.class, "int");
|
||||||
|
|
||||||
final long vmSymbolsSymbols = getFieldAddress("vmSymbols::_symbols[0]", "Symbol*");
|
final long vmSymbolsSymbols = getFieldAddress("vmSymbols::_symbols[0]", "Symbol*");
|
||||||
final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
|
final int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", Integer.class);
|
||||||
final int vmSymbolsSIDLimit = getConstant("vmSymbols::SID_LIMIT", Integer.class);
|
final int vmSymbolsSIDLimit = getConstant("vmSymbols::SID_LIMIT", Integer.class);
|
||||||
|
|
||||||
|
final long symbolInit = getFieldValue("CompilerToVM::Data::symbol_init", Long.class);
|
||||||
|
final long symbolClinit = getFieldValue("CompilerToVM::Data::symbol_clinit", Long.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the symbol in the {@code vmSymbols} table at position {@code index} as a
|
* Returns the symbol in the {@code vmSymbols} table at position {@code index} as a
|
||||||
* {@link String}.
|
* {@link String}.
|
||||||
|
|
|
@ -66,21 +66,6 @@ public class HotSpotVMConfigAccess {
|
||||||
return getAddress(name, null);
|
return getAddress(name, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the size of a C++ type.
|
|
||||||
*
|
|
||||||
* @param name name of the type
|
|
||||||
* @return the size in bytes of the requested field
|
|
||||||
* @throws JVMCIError if the field is not present and {@code notPresent} is null
|
|
||||||
*/
|
|
||||||
public int getTypeSize(String name) {
|
|
||||||
Long entry = store.vmTypeSizes.get(name);
|
|
||||||
if (entry == null) {
|
|
||||||
throw new JVMCIError("expected VM type not found: " + name);
|
|
||||||
}
|
|
||||||
return (int) (long) entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value of a C++ constant.
|
* Gets the value of a C++ constant.
|
||||||
*
|
*
|
||||||
|
@ -291,13 +276,24 @@ public class HotSpotVMConfigAccess {
|
||||||
*/
|
*/
|
||||||
public <T> T getFlag(String name, Class<T> type, T notPresent) {
|
public <T> T getFlag(String name, Class<T> type, T notPresent) {
|
||||||
VMFlag entry = store.vmFlags.get(name);
|
VMFlag entry = store.vmFlags.get(name);
|
||||||
|
Object value;
|
||||||
|
String cppType;
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
if (notPresent != null) {
|
// Fall back to VM call
|
||||||
return notPresent;
|
value = store.compilerToVm.getFlagValue(name);
|
||||||
|
if (value == store.compilerToVm) {
|
||||||
|
if (notPresent != null) {
|
||||||
|
return notPresent;
|
||||||
|
}
|
||||||
|
throw new JVMCIError("expected VM flag not found: " + name);
|
||||||
|
} else {
|
||||||
|
cppType = null;
|
||||||
}
|
}
|
||||||
throw new JVMCIError("expected VM flag not found: " + name);
|
} else {
|
||||||
|
value = entry.value;
|
||||||
|
cppType = entry.type;
|
||||||
}
|
}
|
||||||
return type.cast(convertValue(name, type, entry.value, entry.type));
|
return type.cast(convertValue(name, type, value, cppType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
|
private static <T> Object convertValue(String name, Class<T> toType, Object value, String cppType) throws JVMCIError {
|
||||||
|
@ -319,6 +315,10 @@ public class HotSpotVMConfigAccess {
|
||||||
} else if (value instanceof Long) {
|
} else if (value instanceof Long) {
|
||||||
return (int) (long) value;
|
return (int) (long) value;
|
||||||
}
|
}
|
||||||
|
} else if (toType == String.class) {
|
||||||
|
if (value == null || value instanceof String) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
} else if (toType == Long.class) {
|
} else if (toType == Long.class) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,15 +46,6 @@ public final class HotSpotVMConfigStore {
|
||||||
return Collections.unmodifiableMap(vmAddresses);
|
return Collections.unmodifiableMap(vmAddresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the C++ type sizes exposed by this object.
|
|
||||||
*
|
|
||||||
* @return an unmodifiable map from C++ type names to their sizes in bytes
|
|
||||||
*/
|
|
||||||
public Map<String, Long> getTypeSizes() {
|
|
||||||
return Collections.unmodifiableMap(vmTypeSizes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the C++ constants exposed by this object.
|
* Gets the C++ constants exposed by this object.
|
||||||
*
|
*
|
||||||
|
@ -90,11 +81,11 @@ public final class HotSpotVMConfigStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
final HashMap<String, VMField> vmFields;
|
final HashMap<String, VMField> vmFields;
|
||||||
final HashMap<String, Long> vmTypeSizes;
|
|
||||||
final HashMap<String, Long> vmConstants;
|
final HashMap<String, Long> vmConstants;
|
||||||
final HashMap<String, Long> vmAddresses;
|
final HashMap<String, Long> vmAddresses;
|
||||||
final HashMap<String, VMFlag> vmFlags;
|
final HashMap<String, VMFlag> vmFlags;
|
||||||
final List<VMIntrinsicMethod> vmIntrinsics;
|
final List<VMIntrinsicMethod> vmIntrinsics;
|
||||||
|
final CompilerToVM compilerToVm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the database of VM info. The return value encodes the info in a nested object array
|
* Reads the database of VM info. The return value encodes the info in a nested object array
|
||||||
|
@ -103,7 +94,6 @@ public final class HotSpotVMConfigStore {
|
||||||
* <pre>
|
* <pre>
|
||||||
* info = [
|
* info = [
|
||||||
* VMField[] vmFields,
|
* VMField[] vmFields,
|
||||||
* [String name, Long size, ...] vmTypeSizes,
|
|
||||||
* [String name, Long value, ...] vmConstants,
|
* [String name, Long value, ...] vmConstants,
|
||||||
* [String name, Long value, ...] vmAddresses,
|
* [String name, Long value, ...] vmAddresses,
|
||||||
* VMFlag[] vmFlags
|
* VMFlag[] vmFlags
|
||||||
|
@ -113,25 +103,24 @@ public final class HotSpotVMConfigStore {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("try")
|
@SuppressWarnings("try")
|
||||||
HotSpotVMConfigStore(CompilerToVM compilerToVm) {
|
HotSpotVMConfigStore(CompilerToVM compilerToVm) {
|
||||||
|
this.compilerToVm = compilerToVm;
|
||||||
Object[] data;
|
Object[] data;
|
||||||
try (InitTimer t = timer("CompilerToVm readConfiguration")) {
|
try (InitTimer t = timer("CompilerToVm readConfiguration")) {
|
||||||
data = compilerToVm.readConfiguration();
|
data = compilerToVm.readConfiguration();
|
||||||
}
|
}
|
||||||
assert data.length == 6 : data.length;
|
assert data.length == 5 : data.length;
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
VMField[] vmFieldsInfo = (VMField[]) data[0];
|
VMField[] vmFieldsInfo = (VMField[]) data[0];
|
||||||
Object[] vmTypesSizesInfo = (Object[]) data[1];
|
Object[] vmConstantsInfo = (Object[]) data[1];
|
||||||
Object[] vmConstantsInfo = (Object[]) data[2];
|
Object[] vmAddressesInfo = (Object[]) data[2];
|
||||||
Object[] vmAddressesInfo = (Object[]) data[3];
|
VMFlag[] vmFlagsInfo = (VMFlag[]) data[3];
|
||||||
VMFlag[] vmFlagsInfo = (VMFlag[]) data[4];
|
|
||||||
|
|
||||||
vmFields = new HashMap<>(vmFieldsInfo.length);
|
vmFields = new HashMap<>(vmFieldsInfo.length);
|
||||||
vmTypeSizes = new HashMap<>(vmTypesSizesInfo.length);
|
|
||||||
vmConstants = new HashMap<>(vmConstantsInfo.length);
|
vmConstants = new HashMap<>(vmConstantsInfo.length);
|
||||||
vmAddresses = new HashMap<>(vmAddressesInfo.length);
|
vmAddresses = new HashMap<>(vmAddressesInfo.length);
|
||||||
vmFlags = new HashMap<>(vmFlagsInfo.length);
|
vmFlags = new HashMap<>(vmFlagsInfo.length);
|
||||||
vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[5]);
|
vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[4]);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
try (InitTimer t = timer("HotSpotVMConfigStore<init> fill maps")) {
|
try (InitTimer t = timer("HotSpotVMConfigStore<init> fill maps")) {
|
||||||
|
@ -139,12 +128,6 @@ public final class HotSpotVMConfigStore {
|
||||||
vmFields.put(vmField.name, vmField);
|
vmFields.put(vmField.name, vmField);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < vmTypesSizesInfo.length / 2; i++) {
|
|
||||||
String name = (String) vmTypesSizesInfo[i * 2];
|
|
||||||
Long size = (Long) vmTypesSizesInfo[i * 2 + 1];
|
|
||||||
vmTypeSizes.put(name, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < vmConstantsInfo.length / 2; i++) {
|
for (int i = 0; i < vmConstantsInfo.length / 2; i++) {
|
||||||
String name = (String) vmConstantsInfo[i * 2];
|
String name = (String) vmConstantsInfo[i * 2];
|
||||||
Long value = (Long) vmConstantsInfo[i * 2 + 1];
|
Long value = (Long) vmConstantsInfo[i * 2 + 1];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2012, 2017, 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
|
||||||
|
@ -497,9 +497,8 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value emitLoadConfigValue(int markId) {
|
public Value emitLoadConfigValue(int markId, LIRKind kind) {
|
||||||
// Globals are always full-pointer width.
|
Variable result = newVariable(kind);
|
||||||
Variable result = newVariable(LIRKind.value(target().arch.getWordKind()));
|
|
||||||
append(new AMD64HotSpotLoadConfigValueOp(markId, result));
|
append(new AMD64HotSpotLoadConfigValueOp(markId, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -24,8 +24,12 @@ package org.graalvm.compiler.hotspot.amd64;
|
||||||
|
|
||||||
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
|
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
|
||||||
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
import static jdk.vm.ci.code.ValueUtil.asRegister;
|
||||||
|
|
||||||
|
import jdk.vm.ci.amd64.AMD64Kind;
|
||||||
|
import jdk.vm.ci.code.Register;
|
||||||
import jdk.vm.ci.meta.AllocatableValue;
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.asm.amd64.AMD64Address;
|
||||||
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
|
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
|
||||||
import org.graalvm.compiler.debug.GraalError;
|
import org.graalvm.compiler.debug.GraalError;
|
||||||
import org.graalvm.compiler.lir.LIRInstructionClass;
|
import org.graalvm.compiler.lir.LIRInstructionClass;
|
||||||
|
@ -48,7 +52,25 @@ public final class AMD64HotSpotLoadConfigValueOp extends AMD64LIRInstruction {
|
||||||
@Override
|
@Override
|
||||||
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
|
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
|
||||||
if (GeneratePIC.getValue()) {
|
if (GeneratePIC.getValue()) {
|
||||||
masm.movq(asRegister(result), masm.getPlaceholder(-1));
|
AMD64Kind kind = (AMD64Kind) result.getPlatformKind();
|
||||||
|
Register reg = asRegister(result);
|
||||||
|
AMD64Address placeholder = masm.getPlaceholder(-1);
|
||||||
|
switch (kind) {
|
||||||
|
case BYTE:
|
||||||
|
masm.movsbl(reg, placeholder);
|
||||||
|
break;
|
||||||
|
case WORD:
|
||||||
|
masm.movswl(reg, placeholder);
|
||||||
|
break;
|
||||||
|
case DWORD:
|
||||||
|
masm.movl(reg, placeholder);
|
||||||
|
break;
|
||||||
|
case QWORD:
|
||||||
|
masm.movq(reg, placeholder);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw GraalError.unimplemented();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
return (int) (Math.log(objectAlignment) / Math.log(2));
|
return (int) (Math.log(objectAlignment) / Math.log(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int narrowKlassSize = getTypeSize("narrowKlass");
|
public final int narrowKlassSize = getFieldValue("CompilerToVM::Data::sizeof_narrowKlass", Integer.class, "int");
|
||||||
public final long narrowKlassBase = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_base", Long.class, "address");
|
public final long narrowKlassBase = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_base", Long.class, "address");
|
||||||
public final int narrowKlassShift = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_shift", Integer.class, "int");
|
public final int narrowKlassShift = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_shift", Integer.class, "int");
|
||||||
public final int logKlassAlignment = getConstant("LogKlassAlignmentInBytes", Integer.class);
|
public final int logKlassAlignment = getConstant("LogKlassAlignmentInBytes", Integer.class);
|
||||||
|
@ -290,7 +290,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
return (layoutHelperArrayTagTypeValue & ~layoutHelperArrayTagObjectValue) << layoutHelperArrayTagShift;
|
return (layoutHelperArrayTagTypeValue & ~layoutHelperArrayTagObjectValue) << layoutHelperArrayTagShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int vtableEntrySize = getTypeSize("vtableEntry");
|
public final int vtableEntrySize = getFieldValue("CompilerToVM::Data::sizeof_vtableEntry", Integer.class, "int");
|
||||||
public final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
|
public final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*");
|
||||||
|
|
||||||
public final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
|
public final int instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
|
||||||
|
@ -302,7 +302,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
public final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
|
public final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", Integer.class);
|
||||||
public final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
|
public final int instanceKlassStateFullyInitialized = getConstant("InstanceKlass::fully_initialized", Integer.class);
|
||||||
|
|
||||||
public final int arrayOopDescSize = getTypeSize("arrayOopDesc");
|
public final int arrayOopDescSize = getFieldValue("CompilerToVM::Data::sizeof_arrayOopDesc", Integer.class, "int");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The offset of the array length word in an array object's header.
|
* The offset of the array length word in an array object's header.
|
||||||
|
@ -496,7 +496,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
public final int compilationLevelFullOptimization = getConstant("CompLevel_full_optimization",
|
public final int compilationLevelFullOptimization = getConstant("CompLevel_full_optimization",
|
||||||
Integer.class);
|
Integer.class);
|
||||||
|
|
||||||
public final int constantPoolSize = getTypeSize("ConstantPool");
|
public final int constantPoolSize = getFieldValue("CompilerToVM::Data::sizeof_ConstantPool", Integer.class, "int");
|
||||||
public final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length",
|
public final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length",
|
||||||
Integer.class, "int");
|
Integer.class, "int");
|
||||||
|
|
||||||
|
@ -553,7 +553,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||||
public final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
|
public final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
|
||||||
public final int arrayKlassOffset = getFieldValue("java_lang_Class::_array_klass_offset", Integer.class, "int");
|
public final int arrayKlassOffset = getFieldValue("java_lang_Class::_array_klass_offset", Integer.class, "int");
|
||||||
|
|
||||||
public final int basicLockSize = getTypeSize("BasicLock");
|
public final int basicLockSize = getFieldValue("CompilerToVM::Data::sizeof_BasicLock", Integer.class, "int");
|
||||||
public final int basicLockDisplacedHeaderOffset = getFieldOffset("BasicLock::_displaced_header", Integer.class, "markOop");
|
public final int basicLockDisplacedHeaderOffset = getFieldOffset("BasicLock::_displaced_header", Integer.class, "markOop");
|
||||||
|
|
||||||
public final int threadAllocatedBytesOffset = getFieldOffset("Thread::_allocated_bytes", Integer.class, "jlong");
|
public final int threadAllocatedBytesOffset = getFieldOffset("Thread::_allocated_bytes", Integer.class, "jlong");
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package org.graalvm.compiler.hotspot;
|
package org.graalvm.compiler.hotspot;
|
||||||
|
|
||||||
|
import org.graalvm.compiler.core.common.LIRKind;
|
||||||
import org.graalvm.compiler.debug.GraalError;
|
import org.graalvm.compiler.debug.GraalError;
|
||||||
import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
|
import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
|
||||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||||
|
@ -141,10 +142,10 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
|
||||||
/**
|
/**
|
||||||
* Emits code for a {@link LoadConstantIndirectlyNode}.
|
* Emits code for a {@link LoadConstantIndirectlyNode}.
|
||||||
*
|
*
|
||||||
* @param constant
|
* @param constant original constant
|
||||||
|
* @param action action to perform on the metaspace object
|
||||||
* @return Value of loaded address in register
|
* @return Value of loaded address in register
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
default Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) {
|
default Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
@ -152,21 +153,23 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
|
||||||
/**
|
/**
|
||||||
* Emits code for a {@link GraalHotSpotVMConfigNode}.
|
* Emits code for a {@link GraalHotSpotVMConfigNode}.
|
||||||
*
|
*
|
||||||
* @param markId type of address to load
|
* @param markId id of the value to load
|
||||||
|
* @param kind type of the value to load
|
||||||
* @return value of loaded global in register
|
* @return value of loaded global in register
|
||||||
*/
|
*/
|
||||||
default Value emitLoadConfigValue(int markId) {
|
default Value emitLoadConfigValue(int markId, LIRKind kind) {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotObjectConstant}.
|
* Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotObjectConstant}.
|
||||||
*
|
*
|
||||||
|
* @param constant original constant
|
||||||
* @param constantDescription a description of the string that need to be materialized (and
|
* @param constantDescription a description of the string that need to be materialized (and
|
||||||
* interned) as java.lang.String, generated with {@link EncodedSymbolConstant}
|
* interned) as java.lang.String, generated with {@link EncodedSymbolConstant}
|
||||||
|
* @param frameState frame state for the runtime call
|
||||||
* @return Returns the address of the requested constant.
|
* @return Returns the address of the requested constant.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
default Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
|
default Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
@ -174,11 +177,12 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
|
||||||
/**
|
/**
|
||||||
* Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotMetaspaceConstant}.
|
* Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotMetaspaceConstant}.
|
||||||
*
|
*
|
||||||
|
* @param constant original constant
|
||||||
* @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant}
|
* @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant}
|
||||||
* generated by {@link EncodedSymbolConstant}
|
* generated by {@link EncodedSymbolConstant}
|
||||||
|
* @param frameState frame state for the runtime call
|
||||||
* @return Returns the address of the requested constant.
|
* @return Returns the address of the requested constant.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
default Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
|
default Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
@ -188,12 +192,13 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
|
||||||
* {@link HotSpotMetaspaceConstant} that represents a {@link ResolvedJavaMethod} and return the
|
* {@link HotSpotMetaspaceConstant} that represents a {@link ResolvedJavaMethod} and return the
|
||||||
* corresponding MethodCounters object.
|
* corresponding MethodCounters object.
|
||||||
*
|
*
|
||||||
|
* @param method original constant
|
||||||
* @param klassHint a klass in which the method is declared
|
* @param klassHint a klass in which the method is declared
|
||||||
* @param methodDescription is symbolic description of the constant generated by
|
* @param methodDescription is symbolic description of the constant generated by
|
||||||
* {@link EncodedSymbolConstant}
|
* {@link EncodedSymbolConstant}
|
||||||
|
* @param frameState frame state for the runtime call
|
||||||
* @return Returns the address of the requested constant.
|
* @return Returns the address of the requested constant.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
default Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) {
|
default Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
@ -202,11 +207,13 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
|
||||||
* Emits code for a {@link ResolveConstantNode} to resolve a klass
|
* Emits code for a {@link ResolveConstantNode} to resolve a klass
|
||||||
* {@link HotSpotMetaspaceConstant} and run static initializer.
|
* {@link HotSpotMetaspaceConstant} and run static initializer.
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* @param constant original constant
|
||||||
* @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant}
|
* @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant}
|
||||||
* generated by {@link EncodedSymbolConstant}
|
* generated by {@link EncodedSymbolConstant}
|
||||||
|
* @param frameState frame state for the runtime call
|
||||||
* @return Returns the address of the requested constant.
|
* @return Returns the address of the requested constant.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused")
|
|
||||||
default Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
|
default Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
|
||||||
throw GraalError.unimplemented();
|
throw GraalError.unimplemented();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -55,62 +55,86 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
|
||||||
private final GraalHotSpotVMConfig config;
|
private final GraalHotSpotVMConfig config;
|
||||||
protected final int markId;
|
protected final int markId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for {@link #areConfigValuesConstant()}.
|
||||||
|
*
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config) {
|
||||||
|
super(TYPE, StampFactory.forKind(JavaKind.Boolean));
|
||||||
|
this.config = config;
|
||||||
|
this.markId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for node intrinsics below.
|
||||||
|
*
|
||||||
|
* @param config
|
||||||
|
* @param markId id of the config value
|
||||||
|
*/
|
||||||
|
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
|
||||||
|
super(TYPE, StampFactory.forNodeIntrinsic());
|
||||||
|
this.config = config;
|
||||||
|
this.markId = markId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor with explicit type specification.
|
||||||
|
*
|
||||||
|
* @param config
|
||||||
|
* @param markId id of the config value
|
||||||
|
* @param kind explicit type of the node
|
||||||
|
*/
|
||||||
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) {
|
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) {
|
||||||
super(TYPE, StampFactory.forKind(kind));
|
super(TYPE, StampFactory.forKind(kind));
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.markId = markId;
|
this.markId = markId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor selected by {@link #loadConfigValue(int, JavaKind)}.
|
|
||||||
*
|
|
||||||
* @param config
|
|
||||||
* @param markId
|
|
||||||
*/
|
|
||||||
public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) {
|
|
||||||
super(TYPE, StampFactory.forKind(JavaKind.Boolean));
|
|
||||||
this.config = config;
|
|
||||||
this.markId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(NodeLIRBuilderTool generator) {
|
public void generate(NodeLIRBuilderTool generator) {
|
||||||
Value res = ((HotSpotLIRGenerator) generator.getLIRGeneratorTool()).emitLoadConfigValue(markId);
|
Value res = ((HotSpotLIRGenerator) generator.getLIRGeneratorTool()).emitLoadConfigValue(markId, generator.getLIRGeneratorTool().getLIRKind(stamp));
|
||||||
generator.setResult(this, res);
|
generator.setResult(this, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NodeIntrinsic
|
@NodeIntrinsic
|
||||||
private static native boolean isConfigValueConstant(@ConstantNodeParameter int markId);
|
private static native boolean areConfigValuesConstant();
|
||||||
|
|
||||||
@NodeIntrinsic
|
@NodeIntrinsic(setStampFromReturnType = true)
|
||||||
private static native long loadConfigValue(@ConstantNodeParameter int markId, @ConstantNodeParameter JavaKind kind);
|
private static native long loadLongConfigValue(@ConstantNodeParameter int markId);
|
||||||
|
|
||||||
|
@NodeIntrinsic(setStampFromReturnType = true)
|
||||||
|
private static native int loadIntConfigValue(@ConstantNodeParameter int markId);
|
||||||
|
|
||||||
|
@NodeIntrinsic(setStampFromReturnType = true)
|
||||||
|
private static native byte loadByteConfigValue(@ConstantNodeParameter int markId);
|
||||||
|
|
||||||
public static long cardTableAddress() {
|
public static long cardTableAddress() {
|
||||||
return loadConfigValue(cardTableAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
|
return loadLongConfigValue(cardTableAddressMark(INJECTED_VMCONFIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCardTableAddressConstant() {
|
public static boolean isCardTableAddressConstant() {
|
||||||
return isConfigValueConstant(cardTableAddressMark(INJECTED_VMCONFIG));
|
return areConfigValuesConstant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long heapTopAddress() {
|
public static long heapTopAddress() {
|
||||||
return loadConfigValue(heapTopAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
|
return loadLongConfigValue(heapTopAddressMark(INJECTED_VMCONFIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long heapEndAddress() {
|
public static long heapEndAddress() {
|
||||||
return loadConfigValue(heapEndAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
|
return loadLongConfigValue(heapEndAddressMark(INJECTED_VMCONFIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long crcTableAddress() {
|
public static long crcTableAddress() {
|
||||||
return loadConfigValue(crcTableAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
|
return loadLongConfigValue(crcTableAddressMark(INJECTED_VMCONFIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int logOfHeapRegionGrainBytes() {
|
public static int logOfHeapRegionGrainBytes() {
|
||||||
return (int) loadConfigValue(logOfHeapRegionGrainBytesMark(INJECTED_VMCONFIG), JavaKind.Byte);
|
return loadIntConfigValue(logOfHeapRegionGrainBytesMark(INJECTED_VMCONFIG));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean inlineContiguousAllocationSupported() {
|
public static boolean inlineContiguousAllocationSupported() {
|
||||||
return loadConfigValue(inlineContiguousAllocationSupportedMark(INJECTED_VMCONFIG), JavaKind.Byte) > 0;
|
return loadByteConfigValue(inlineContiguousAllocationSupportedMark(INJECTED_VMCONFIG)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Fold
|
@Fold
|
||||||
|
|
|
@ -830,38 +830,19 @@ void AOTCodeHeap::oops_do(OopClosure* f) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yes, this is faster than going through the relocations,
|
// Scan only metaspace_got cells which should have only Klass*,
|
||||||
// but there are two problems:
|
// metadata_got cells are scanned only for alive AOT methods
|
||||||
// 1) GOT slots are sometimes patched with non-Metadata values
|
// by AOTCompiledMethod::metadata_do().
|
||||||
// 2) We don't want to scan metadata for dead methods
|
|
||||||
// Unfortunately we don't know if the metadata belongs to
|
|
||||||
// live aot methods or not, so process them all. If this
|
|
||||||
// is for mark_on_stack, some old methods may stick around
|
|
||||||
// forever instead of getting cleaned up.
|
|
||||||
void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
|
void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
|
||||||
for (int i = 1; i < _metaspace_got_size; i++) {
|
for (int i = 1; i < _metaspace_got_size; i++) {
|
||||||
Metadata** p = &_metaspace_got[i];
|
Metadata** p = &_metaspace_got[i];
|
||||||
Metadata* md = *p;
|
Metadata* md = *p;
|
||||||
if (md == NULL) continue; // skip non-oops
|
if (md == NULL) continue; // skip non-oops
|
||||||
intptr_t meta = (intptr_t)md;
|
|
||||||
if (meta == -1) continue; // skip non-oops
|
|
||||||
if (Metaspace::contains(md)) {
|
if (Metaspace::contains(md)) {
|
||||||
f(md);
|
f(md);
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 1; i < _metadata_got_size; i++) {
|
|
||||||
Metadata** p = &_metadata_got[i];
|
|
||||||
Metadata* md = *p;
|
|
||||||
intptr_t meta = (intptr_t)md;
|
|
||||||
if ((meta & 1) == 1) {
|
|
||||||
// already resolved
|
|
||||||
md = (Metadata*)(meta & ~1);
|
|
||||||
} else {
|
} else {
|
||||||
continue;
|
intptr_t meta = (intptr_t)md;
|
||||||
}
|
fatal("Invalid value in _metaspace_got[%d] = " INTPTR_FORMAT, i, meta);
|
||||||
if (md == NULL) continue; // skip non-oops
|
|
||||||
if (Metaspace::contains(md)) {
|
|
||||||
f(md);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -910,8 +891,6 @@ void AOTCodeHeap::metadata_do(void f(Metadata*)) {
|
||||||
aot->metadata_do(f);
|
aot->metadata_do(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 0
|
// Scan metaspace_got cells.
|
||||||
// With the marking above, this call doesn't seem to be needed
|
|
||||||
got_metadata_do(f);
|
got_metadata_do(f);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,15 +71,6 @@ static void metadata_oops_do(Metadata** metadata_begin, Metadata **metadata_end,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void AOTCompiledMethod::oops_do(OopClosure* f) {
|
|
||||||
if (_oop != NULL) {
|
|
||||||
f->do_oop(&_oop);
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
metadata_oops_do(metadata_begin(), metadata_end(), f);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AOTCompiledMethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred) {
|
bool AOTCompiledMethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -161,9 +152,6 @@ Metadata* AOTCompiledMethod::metadata_at(int index) const {
|
||||||
*entry = (Metadata*)meta; // Should be atomic on x64
|
*entry = (Metadata*)meta; // Should be atomic on x64
|
||||||
return (Metadata*)m;
|
return (Metadata*)m;
|
||||||
}
|
}
|
||||||
// need to resolve it here..., patching of GOT need to be CAS or atomic operation.
|
|
||||||
// FIXIT: need methods for debuginfo.
|
|
||||||
// return _method;
|
|
||||||
}
|
}
|
||||||
ShouldNotReachHere(); return NULL;
|
ShouldNotReachHere(); return NULL;
|
||||||
}
|
}
|
||||||
|
@ -288,11 +276,19 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
|
||||||
f(cichk->holder_method());
|
f(cichk->holder_method());
|
||||||
f(cichk->holder_klass());
|
f(cichk->holder_klass());
|
||||||
} else {
|
} else {
|
||||||
|
// Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
|
||||||
Metadata* ic_oop = ic->cached_metadata();
|
Metadata* ic_oop = ic->cached_metadata();
|
||||||
if (ic_oop != NULL) {
|
if (ic_oop != NULL) {
|
||||||
f(ic_oop);
|
f(ic_oop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (iter.type() == relocInfo::static_call_type ||
|
||||||
|
iter.type() == relocInfo::opt_virtual_call_type){
|
||||||
|
// Check Method* in AOT c2i stub for other calls.
|
||||||
|
Metadata* meta = (Metadata*)nativeLoadGot_at(nativePltCall_at(iter.addr())->plt_c2i_stub())->data();
|
||||||
|
if (meta != NULL) {
|
||||||
|
f(meta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,7 +328,12 @@ void AOTCompiledMethod::print_on(outputStream* st, const char* msg) const {
|
||||||
st->print("%4d ", _aot_id); // print compilation number
|
st->print("%4d ", _aot_id); // print compilation number
|
||||||
st->print(" aot[%2d]", _heap->dso_id());
|
st->print(" aot[%2d]", _heap->dso_id());
|
||||||
// Stubs have _method == NULL
|
// Stubs have _method == NULL
|
||||||
st->print(" %s", (_method == NULL ? _name : _method->name_and_sig_as_C_string()));
|
if (_method == NULL) {
|
||||||
|
st->print(" %s", _name);
|
||||||
|
} else {
|
||||||
|
ResourceMark m;
|
||||||
|
st->print(" %s", _method->name_and_sig_as_C_string());
|
||||||
|
}
|
||||||
if (Verbose) {
|
if (Verbose) {
|
||||||
st->print(" entry at " INTPTR_FORMAT, p2i(_code));
|
st->print(" entry at " INTPTR_FORMAT, p2i(_code));
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,8 +257,6 @@ private:
|
||||||
return (int) (*_state_adr);
|
return (int) (*_state_adr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void oops_do(OopClosure* f);
|
|
||||||
|
|
||||||
// inlined and non-virtual for AOTCodeHeap::oops_do
|
// inlined and non-virtual for AOTCodeHeap::oops_do
|
||||||
void do_oops(OopClosure* f) {
|
void do_oops(OopClosure* f) {
|
||||||
assert(_is_alive(), "");
|
assert(_is_alive(), "");
|
||||||
|
|
|
@ -704,16 +704,17 @@ ciField* ciEnv::get_field_by_index(ciInstanceKlass* accessor,
|
||||||
//
|
//
|
||||||
// Perform an appropriate method lookup based on accessor, holder,
|
// Perform an appropriate method lookup based on accessor, holder,
|
||||||
// name, signature, and bytecode.
|
// name, signature, and bytecode.
|
||||||
Method* ciEnv::lookup_method(InstanceKlass* accessor,
|
Method* ciEnv::lookup_method(ciInstanceKlass* accessor,
|
||||||
InstanceKlass* holder,
|
ciKlass* holder,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Symbol* sig,
|
Symbol* sig,
|
||||||
Bytecodes::Code bc,
|
Bytecodes::Code bc,
|
||||||
constantTag tag) {
|
constantTag tag) {
|
||||||
EXCEPTION_CONTEXT;
|
// Accessibility checks are performed in ciEnv::get_method_by_index_impl.
|
||||||
KlassHandle h_accessor(THREAD, accessor);
|
assert(check_klass_accessibility(accessor, holder->get_Klass()), "holder not accessible");
|
||||||
KlassHandle h_holder(THREAD, holder);
|
|
||||||
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
|
KlassHandle h_accessor(accessor->get_instanceKlass());
|
||||||
|
KlassHandle h_holder(holder->get_Klass());
|
||||||
methodHandle dest_method;
|
methodHandle dest_method;
|
||||||
LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
|
LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
|
||||||
switch (bc) {
|
switch (bc) {
|
||||||
|
@ -772,7 +773,6 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
|
||||||
const int holder_index = cpool->klass_ref_index_at(index);
|
const int holder_index = cpool->klass_ref_index_at(index);
|
||||||
bool holder_is_accessible;
|
bool holder_is_accessible;
|
||||||
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
|
ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
|
||||||
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
|
||||||
|
|
||||||
// Get the method's name and signature.
|
// Get the method's name and signature.
|
||||||
Symbol* name_sym = cpool->name_ref_at(index);
|
Symbol* name_sym = cpool->name_ref_at(index);
|
||||||
|
@ -800,10 +800,9 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holder_is_accessible) { // Our declared holder is loaded.
|
if (holder_is_accessible) { // Our declared holder is loaded.
|
||||||
InstanceKlass* lookup = declared_holder->get_instanceKlass();
|
|
||||||
constantTag tag = cpool->tag_ref_at(index);
|
constantTag tag = cpool->tag_ref_at(index);
|
||||||
assert(accessor->get_instanceKlass() == cpool->pool_holder(), "not the pool holder?");
|
assert(accessor->get_instanceKlass() == cpool->pool_holder(), "not the pool holder?");
|
||||||
Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc, tag);
|
Method* m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag);
|
||||||
if (m != NULL &&
|
if (m != NULL &&
|
||||||
(bc == Bytecodes::_invokestatic
|
(bc == Bytecodes::_invokestatic
|
||||||
? m->method_holder()->is_not_initialized()
|
? m->method_holder()->is_not_initialized()
|
||||||
|
@ -826,7 +825,7 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
|
||||||
// lookup.
|
// lookup.
|
||||||
ciSymbol* name = get_symbol(name_sym);
|
ciSymbol* name = get_symbol(name_sym);
|
||||||
ciSymbol* signature = get_symbol(sig_sym);
|
ciSymbol* signature = get_symbol(sig_sym);
|
||||||
return get_unloaded_method(declared_holder, name, signature, accessor);
|
return get_unloaded_method(holder, name, signature, accessor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,12 +153,12 @@ private:
|
||||||
// Helper methods
|
// Helper methods
|
||||||
bool check_klass_accessibility(ciKlass* accessing_klass,
|
bool check_klass_accessibility(ciKlass* accessing_klass,
|
||||||
Klass* resolved_klass);
|
Klass* resolved_klass);
|
||||||
Method* lookup_method(InstanceKlass* accessor,
|
Method* lookup_method(ciInstanceKlass* accessor,
|
||||||
InstanceKlass* holder,
|
ciKlass* holder,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Symbol* sig,
|
Symbol* sig,
|
||||||
Bytecodes::Code bc,
|
Bytecodes::Code bc,
|
||||||
constantTag tag);
|
constantTag tag);
|
||||||
|
|
||||||
// Get a ciObject from the object factory. Ensures uniqueness
|
// Get a ciObject from the object factory. Ensures uniqueness
|
||||||
// of ciObjects.
|
// of ciObjects.
|
||||||
|
@ -227,11 +227,12 @@ private:
|
||||||
// Get a ciMethod representing either an unfound method or
|
// Get a ciMethod representing either an unfound method or
|
||||||
// a method with an unloaded holder. Ensures uniqueness of
|
// a method with an unloaded holder. Ensures uniqueness of
|
||||||
// the result.
|
// the result.
|
||||||
ciMethod* get_unloaded_method(ciInstanceKlass* holder,
|
ciMethod* get_unloaded_method(ciKlass* holder,
|
||||||
ciSymbol* name,
|
ciSymbol* name,
|
||||||
ciSymbol* signature,
|
ciSymbol* signature,
|
||||||
ciInstanceKlass* accessor) {
|
ciInstanceKlass* accessor) {
|
||||||
return _factory->get_unloaded_method(holder, name, signature, accessor);
|
ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
|
||||||
|
return _factory->get_unloaded_method(declared_holder, name, signature, accessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a ciKlass representing an unloaded klass.
|
// Get a ciKlass representing an unloaded klass.
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "runtime/vframe.hpp"
|
#include "runtime/vframe.hpp"
|
||||||
#include "runtime/vframe_hp.hpp"
|
#include "runtime/vframe_hp.hpp"
|
||||||
#include "runtime/vmStructs.hpp"
|
#include "runtime/vmStructs.hpp"
|
||||||
|
#include "utilities/resourceHash.hpp"
|
||||||
|
|
||||||
|
|
||||||
// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
|
// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
|
||||||
|
@ -120,6 +121,15 @@ int CompilerToVM::Data::cardtable_shift;
|
||||||
|
|
||||||
int CompilerToVM::Data::vm_page_size;
|
int CompilerToVM::Data::vm_page_size;
|
||||||
|
|
||||||
|
int CompilerToVM::Data::sizeof_vtableEntry = sizeof(vtableEntry);
|
||||||
|
int CompilerToVM::Data::sizeof_ExceptionTableElement = sizeof(ExceptionTableElement);
|
||||||
|
int CompilerToVM::Data::sizeof_LocalVariableTableElement = sizeof(LocalVariableTableElement);
|
||||||
|
int CompilerToVM::Data::sizeof_ConstantPool = sizeof(ConstantPool);
|
||||||
|
int CompilerToVM::Data::sizeof_SymbolPointer = sizeof(Symbol*);
|
||||||
|
int CompilerToVM::Data::sizeof_narrowKlass = sizeof(narrowKlass);
|
||||||
|
int CompilerToVM::Data::sizeof_arrayOopDesc = sizeof(arrayOopDesc);
|
||||||
|
int CompilerToVM::Data::sizeof_BasicLock = sizeof(BasicLock);
|
||||||
|
|
||||||
address CompilerToVM::Data::dsin;
|
address CompilerToVM::Data::dsin;
|
||||||
address CompilerToVM::Data::dcos;
|
address CompilerToVM::Data::dcos;
|
||||||
address CompilerToVM::Data::dtan;
|
address CompilerToVM::Data::dtan;
|
||||||
|
@ -128,7 +138,10 @@ address CompilerToVM::Data::dlog;
|
||||||
address CompilerToVM::Data::dlog10;
|
address CompilerToVM::Data::dlog10;
|
||||||
address CompilerToVM::Data::dpow;
|
address CompilerToVM::Data::dpow;
|
||||||
|
|
||||||
void CompilerToVM::Data::initialize() {
|
address CompilerToVM::Data::symbol_init;
|
||||||
|
address CompilerToVM::Data::symbol_clinit;
|
||||||
|
|
||||||
|
void CompilerToVM::Data::initialize(TRAPS) {
|
||||||
Klass_vtable_start_offset = in_bytes(Klass::vtable_start_offset());
|
Klass_vtable_start_offset = in_bytes(Klass::vtable_start_offset());
|
||||||
Klass_vtable_length_offset = in_bytes(Klass::vtable_length_offset());
|
Klass_vtable_length_offset = in_bytes(Klass::vtable_length_offset());
|
||||||
|
|
||||||
|
@ -160,6 +173,9 @@ void CompilerToVM::Data::initialize() {
|
||||||
assert(OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index)), "should be valid");
|
assert(OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index)), "should be valid");
|
||||||
assert(!OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index + 1)), "should be invalid");
|
assert(!OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index + 1)), "should be invalid");
|
||||||
|
|
||||||
|
symbol_init = (address) vmSymbols::object_initializer_name();
|
||||||
|
symbol_clinit = (address) vmSymbols::class_initializer_name();
|
||||||
|
|
||||||
BarrierSet* bs = Universe::heap()->barrier_set();
|
BarrierSet* bs = Universe::heap()->barrier_set();
|
||||||
switch (bs->kind()) {
|
switch (bs->kind()) {
|
||||||
case BarrierSet::CardTableModRef:
|
case BarrierSet::CardTableModRef:
|
||||||
|
@ -179,7 +195,7 @@ void CompilerToVM::Data::initialize() {
|
||||||
// No post barriers
|
// No post barriers
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
JVMCI_ERROR("Unsupported BarrierSet kind %d", bs->kind());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,13 +253,114 @@ objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) {
|
||||||
return vmIntrinsics;
|
return vmIntrinsics;
|
||||||
}
|
}
|
||||||
|
|
||||||
C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
|
/**
|
||||||
#define BOXED_LONG(name, value) oop name; do { jvalue p; p.j = (jlong) (value); name = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL);} while(0)
|
* The set of VM flags known to be used.
|
||||||
|
*/
|
||||||
|
#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_intx_flag, do_uintx_flag) \
|
||||||
|
do_intx_flag(AllocateInstancePrefetchLines) \
|
||||||
|
do_intx_flag(AllocatePrefetchDistance) \
|
||||||
|
do_intx_flag(AllocatePrefetchInstr) \
|
||||||
|
do_intx_flag(AllocatePrefetchLines) \
|
||||||
|
do_intx_flag(AllocatePrefetchStepSize) \
|
||||||
|
do_intx_flag(AllocatePrefetchStyle) \
|
||||||
|
do_intx_flag(BciProfileWidth) \
|
||||||
|
do_bool_flag(BootstrapJVMCI) \
|
||||||
|
do_bool_flag(CITime) \
|
||||||
|
do_bool_flag(CITimeEach) \
|
||||||
|
do_uintx_flag(CodeCacheSegmentSize) \
|
||||||
|
do_intx_flag(CodeEntryAlignment) \
|
||||||
|
do_bool_flag(CompactFields) \
|
||||||
|
NOT_PRODUCT(do_intx_flag(CompileTheWorldStartAt)) \
|
||||||
|
NOT_PRODUCT(do_intx_flag(CompileTheWorldStopAt)) \
|
||||||
|
do_intx_flag(ContendedPaddingWidth) \
|
||||||
|
do_bool_flag(DontCompileHugeMethods) \
|
||||||
|
do_bool_flag(EnableContended) \
|
||||||
|
do_intx_flag(FieldsAllocationStyle) \
|
||||||
|
do_bool_flag(FoldStableValues) \
|
||||||
|
do_bool_flag(ForceUnreachable) \
|
||||||
|
do_intx_flag(HugeMethodLimit) \
|
||||||
|
do_bool_flag(Inline) \
|
||||||
|
do_intx_flag(JVMCICounterSize) \
|
||||||
|
do_bool_flag(JVMCIPrintProperties) \
|
||||||
|
do_bool_flag(JVMCIUseFastLocking) \
|
||||||
|
do_intx_flag(MethodProfileWidth) \
|
||||||
|
do_intx_flag(ObjectAlignmentInBytes) \
|
||||||
|
do_bool_flag(PrintInlining) \
|
||||||
|
do_bool_flag(ReduceInitialCardMarks) \
|
||||||
|
do_bool_flag(RestrictContended) \
|
||||||
|
do_intx_flag(StackReservedPages) \
|
||||||
|
do_intx_flag(StackShadowPages) \
|
||||||
|
do_bool_flag(TLABStats) \
|
||||||
|
do_uintx_flag(TLABWasteIncrement) \
|
||||||
|
do_intx_flag(TypeProfileWidth) \
|
||||||
|
do_bool_flag(UseAESIntrinsics) \
|
||||||
|
X86_ONLY(do_intx_flag(UseAVX)) \
|
||||||
|
do_bool_flag(UseBiasedLocking) \
|
||||||
|
do_bool_flag(UseCRC32Intrinsics) \
|
||||||
|
do_bool_flag(UseCompressedClassPointers) \
|
||||||
|
do_bool_flag(UseCompressedOops) \
|
||||||
|
do_bool_flag(UseConcMarkSweepGC) \
|
||||||
|
X86_ONLY(do_bool_flag(UseCountLeadingZerosInstruction)) \
|
||||||
|
X86_ONLY(do_bool_flag(UseCountTrailingZerosInstruction)) \
|
||||||
|
do_bool_flag(UseG1GC) \
|
||||||
|
COMPILER2_PRESENT(do_bool_flag(UseMontgomeryMultiplyIntrinsic)) \
|
||||||
|
COMPILER2_PRESENT(do_bool_flag(UseMontgomerySquareIntrinsic)) \
|
||||||
|
COMPILER2_PRESENT(do_bool_flag(UseMulAddIntrinsic)) \
|
||||||
|
COMPILER2_PRESENT(do_bool_flag(UseMultiplyToLenIntrinsic)) \
|
||||||
|
do_bool_flag(UsePopCountInstruction) \
|
||||||
|
do_bool_flag(UseSHA1Intrinsics) \
|
||||||
|
do_bool_flag(UseSHA256Intrinsics) \
|
||||||
|
do_bool_flag(UseSHA512Intrinsics) \
|
||||||
|
do_intx_flag(UseSSE) \
|
||||||
|
COMPILER2_PRESENT(do_bool_flag(UseSquareToLenIntrinsic)) \
|
||||||
|
do_bool_flag(UseStackBanging) \
|
||||||
|
do_bool_flag(UseTLAB) \
|
||||||
|
do_bool_flag(VerifyOops) \
|
||||||
|
|
||||||
|
#define BOXED_BOOLEAN(name, value) oop name = ((jboolean)(value) ? boxedTrue() : boxedFalse())
|
||||||
#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
|
#define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
|
||||||
|
#define BOXED_LONG(name, value) \
|
||||||
|
oop name; \
|
||||||
|
do { \
|
||||||
|
jvalue p; p.j = (jlong) (value); \
|
||||||
|
Handle* e = longs.get(p.j); \
|
||||||
|
if (e == NULL) { \
|
||||||
|
Handle h = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); \
|
||||||
|
longs.put(p.j, h); \
|
||||||
|
name = h(); \
|
||||||
|
} else { \
|
||||||
|
name = (*e)(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CSTRING_TO_JSTRING(name, value) \
|
||||||
|
Handle name; \
|
||||||
|
do { \
|
||||||
|
if (value != NULL) { \
|
||||||
|
Handle* e = strings.get(value); \
|
||||||
|
if (e == NULL) { \
|
||||||
|
Handle h = java_lang_String::create_from_str(value, CHECK_NULL); \
|
||||||
|
strings.put(value, h); \
|
||||||
|
name = h(); \
|
||||||
|
} else { \
|
||||||
|
name = (*e)(); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
|
|
||||||
CompilerToVM::Data::initialize();
|
// Used to canonicalize Long and String values.
|
||||||
|
ResourceHashtable<jlong, Handle> longs;
|
||||||
|
ResourceHashtable<const char*, Handle, &CompilerToVM::cstring_hash, &CompilerToVM::cstring_equals> strings;
|
||||||
|
|
||||||
|
jvalue prim;
|
||||||
|
prim.z = true; Handle boxedTrue = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
|
||||||
|
prim.z = false; Handle boxedFalse = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
|
||||||
|
|
||||||
|
CompilerToVM::Data::initialize(CHECK_NULL);
|
||||||
|
|
||||||
VMField::klass()->initialize(CHECK_NULL);
|
VMField::klass()->initialize(CHECK_NULL);
|
||||||
VMFlag::klass()->initialize(CHECK_NULL);
|
VMFlag::klass()->initialize(CHECK_NULL);
|
||||||
|
@ -257,31 +374,31 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
|
||||||
size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
|
size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */;
|
||||||
char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
|
char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1);
|
||||||
sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
|
sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
|
||||||
Handle name = java_lang_String::create_from_str(name_buf, CHECK_NULL);
|
CSTRING_TO_JSTRING(name, name_buf);
|
||||||
Handle type = java_lang_String::create_from_str(vmField.typeString, CHECK_NULL);
|
CSTRING_TO_JSTRING(type, vmField.typeString);
|
||||||
VMField::set_name(vmFieldObj, name());
|
VMField::set_name(vmFieldObj, name());
|
||||||
VMField::set_type(vmFieldObj, type());
|
VMField::set_type(vmFieldObj, type());
|
||||||
VMField::set_offset(vmFieldObj, vmField.offset);
|
VMField::set_offset(vmFieldObj, vmField.offset);
|
||||||
VMField::set_address(vmFieldObj, (jlong) vmField.address);
|
VMField::set_address(vmFieldObj, (jlong) vmField.address);
|
||||||
if (vmField.isStatic) {
|
if (vmField.isStatic && vmField.typeString != NULL) {
|
||||||
if (strcmp(vmField.typeString, "bool") == 0) {
|
if (strcmp(vmField.typeString, "bool") == 0) {
|
||||||
BOXED_LONG(value, *(jbyte*) vmField.address);
|
BOXED_BOOLEAN(box, *(jbyte*) vmField.address);
|
||||||
VMField::set_value(vmFieldObj, value);
|
VMField::set_value(vmFieldObj, box);
|
||||||
} else if (strcmp(vmField.typeString, "int") == 0 ||
|
} else if (strcmp(vmField.typeString, "int") == 0 ||
|
||||||
strcmp(vmField.typeString, "jint") == 0) {
|
strcmp(vmField.typeString, "jint") == 0) {
|
||||||
BOXED_LONG(value, *(jint*) vmField.address);
|
BOXED_LONG(box, *(jint*) vmField.address);
|
||||||
VMField::set_value(vmFieldObj, value);
|
VMField::set_value(vmFieldObj, box);
|
||||||
} else if (strcmp(vmField.typeString, "uint64_t") == 0) {
|
} else if (strcmp(vmField.typeString, "uint64_t") == 0) {
|
||||||
BOXED_LONG(value, *(uint64_t*) vmField.address);
|
BOXED_LONG(box, *(uint64_t*) vmField.address);
|
||||||
VMField::set_value(vmFieldObj, value);
|
VMField::set_value(vmFieldObj, box);
|
||||||
} else if (strcmp(vmField.typeString, "address") == 0 ||
|
} else if (strcmp(vmField.typeString, "address") == 0 ||
|
||||||
strcmp(vmField.typeString, "intptr_t") == 0 ||
|
strcmp(vmField.typeString, "intptr_t") == 0 ||
|
||||||
strcmp(vmField.typeString, "uintptr_t") == 0 ||
|
strcmp(vmField.typeString, "uintptr_t") == 0 ||
|
||||||
strcmp(vmField.typeString, "size_t") == 0 ||
|
strcmp(vmField.typeString, "size_t") == 0 ||
|
||||||
// All foo* types are addresses.
|
// All foo* types are addresses.
|
||||||
vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
|
vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
|
||||||
BOXED_LONG(value, *((address*) vmField.address));
|
BOXED_LONG(box, *((address*) vmField.address));
|
||||||
VMField::set_value(vmFieldObj, value);
|
VMField::set_value(vmFieldObj, box);
|
||||||
} else {
|
} else {
|
||||||
JVMCI_ERROR_NULL("VM field %s has unsupported type %s", name_buf, vmField.typeString);
|
JVMCI_ERROR_NULL("VM field %s has unsupported type %s", name_buf, vmField.typeString);
|
||||||
}
|
}
|
||||||
|
@ -289,16 +406,6 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
|
||||||
vmFields->obj_at_put(i, vmFieldObj());
|
vmFields->obj_at_put(i, vmFieldObj());
|
||||||
}
|
}
|
||||||
|
|
||||||
len = JVMCIVMStructs::localHotSpotVMTypes_count();
|
|
||||||
objArrayHandle vmTypes = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
|
|
||||||
for (int i = 0; i < len ; i++) {
|
|
||||||
VMTypeEntry vmType = JVMCIVMStructs::localHotSpotVMTypes[i];
|
|
||||||
Handle name = java_lang_String::create_from_str(vmType.typeName, CHECK_NULL);
|
|
||||||
BOXED_LONG(size, vmType.size);
|
|
||||||
vmTypes->obj_at_put(i * 2, name());
|
|
||||||
vmTypes->obj_at_put(i * 2 + 1, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ints_len = JVMCIVMStructs::localHotSpotVMIntConstants_count();
|
int ints_len = JVMCIVMStructs::localHotSpotVMIntConstants_count();
|
||||||
int longs_len = JVMCIVMStructs::localHotSpotVMLongConstants_count();
|
int longs_len = JVMCIVMStructs::localHotSpotVMLongConstants_count();
|
||||||
len = ints_len + longs_len;
|
len = ints_len + longs_len;
|
||||||
|
@ -306,14 +413,14 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
|
||||||
int insert = 0;
|
int insert = 0;
|
||||||
for (int i = 0; i < ints_len ; i++) {
|
for (int i = 0; i < ints_len ; i++) {
|
||||||
VMIntConstantEntry c = JVMCIVMStructs::localHotSpotVMIntConstants[i];
|
VMIntConstantEntry c = JVMCIVMStructs::localHotSpotVMIntConstants[i];
|
||||||
Handle name = java_lang_String::create_from_str(c.name, CHECK_NULL);
|
CSTRING_TO_JSTRING(name, c.name);
|
||||||
BOXED_LONG(value, c.value);
|
BOXED_LONG(value, c.value);
|
||||||
vmConstants->obj_at_put(insert++, name());
|
vmConstants->obj_at_put(insert++, name());
|
||||||
vmConstants->obj_at_put(insert++, value);
|
vmConstants->obj_at_put(insert++, value);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < longs_len ; i++) {
|
for (int i = 0; i < longs_len ; i++) {
|
||||||
VMLongConstantEntry c = JVMCIVMStructs::localHotSpotVMLongConstants[i];
|
VMLongConstantEntry c = JVMCIVMStructs::localHotSpotVMLongConstants[i];
|
||||||
Handle name = java_lang_String::create_from_str(c.name, CHECK_NULL);
|
CSTRING_TO_JSTRING(name, c.name);
|
||||||
BOXED_LONG(value, c.value);
|
BOXED_LONG(value, c.value);
|
||||||
vmConstants->obj_at_put(insert++, name());
|
vmConstants->obj_at_put(insert++, name());
|
||||||
vmConstants->obj_at_put(insert++, value);
|
vmConstants->obj_at_put(insert++, value);
|
||||||
|
@ -324,69 +431,104 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
|
||||||
objArrayHandle vmAddresses = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
|
objArrayHandle vmAddresses = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
|
||||||
for (int i = 0; i < len ; i++) {
|
for (int i = 0; i < len ; i++) {
|
||||||
VMAddressEntry a = JVMCIVMStructs::localHotSpotVMAddresses[i];
|
VMAddressEntry a = JVMCIVMStructs::localHotSpotVMAddresses[i];
|
||||||
Handle name = java_lang_String::create_from_str(a.name, CHECK_NULL);
|
CSTRING_TO_JSTRING(name, a.name);
|
||||||
BOXED_LONG(value, a.value);
|
BOXED_LONG(value, a.value);
|
||||||
vmAddresses->obj_at_put(i * 2, name());
|
vmAddresses->obj_at_put(i * 2, name());
|
||||||
vmAddresses->obj_at_put(i * 2 + 1, value);
|
vmAddresses->obj_at_put(i * 2 + 1, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The last entry is the null entry.
|
#define COUNT_FLAG(ignore) +1
|
||||||
len = (int) Flag::numFlags - 1;
|
#ifdef ASSERT
|
||||||
|
#define CHECK_FLAG(type, name) { \
|
||||||
|
Flag* flag = Flag::find_flag(#name, strlen(#name), /*allow_locked*/ true, /* return_flag */ true); \
|
||||||
|
assert(flag != NULL, "No such flag named " #name); \
|
||||||
|
assert(flag->is_##type(), "Flag " #name " is not of type " #type); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define CHECK_FLAG(type, name)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ADD_FLAG(type, name, convert) { \
|
||||||
|
CHECK_FLAG(type, name) \
|
||||||
|
instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL); \
|
||||||
|
CSTRING_TO_JSTRING(fname, #name); \
|
||||||
|
CSTRING_TO_JSTRING(ftype, #type); \
|
||||||
|
VMFlag::set_name(vmFlagObj, fname()); \
|
||||||
|
VMFlag::set_type(vmFlagObj, ftype()); \
|
||||||
|
convert(value, name); \
|
||||||
|
VMFlag::set_value(vmFlagObj, value); \
|
||||||
|
vmFlags->obj_at_put(i++, vmFlagObj()); \
|
||||||
|
}
|
||||||
|
#define ADD_BOOL_FLAG(name) ADD_FLAG(bool, name, BOXED_BOOLEAN)
|
||||||
|
#define ADD_INTX_FLAG(name) ADD_FLAG(intx, name, BOXED_LONG)
|
||||||
|
#define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG)
|
||||||
|
|
||||||
|
len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG);
|
||||||
objArrayHandle vmFlags = oopFactory::new_objArray(VMFlag::klass(), len, CHECK_NULL);
|
objArrayHandle vmFlags = oopFactory::new_objArray(VMFlag::klass(), len, CHECK_NULL);
|
||||||
for (int i = 0; i < len; i++) {
|
int i = 0;
|
||||||
Flag* flag = &Flag::flags[i];
|
PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
|
||||||
instanceHandle vmFlagObj = InstanceKlass::cast(VMFlag::klass())->allocate_instance_handle(CHECK_NULL);
|
|
||||||
Handle name = java_lang_String::create_from_str(flag->_name, CHECK_NULL);
|
|
||||||
Handle type = java_lang_String::create_from_str(flag->_type, CHECK_NULL);
|
|
||||||
VMFlag::set_name(vmFlagObj, name());
|
|
||||||
VMFlag::set_type(vmFlagObj, type());
|
|
||||||
if (flag->is_bool()) {
|
|
||||||
BOXED_LONG(value, flag->get_bool());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_ccstr()) {
|
|
||||||
Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
|
|
||||||
VMFlag::set_value(vmFlagObj, value());
|
|
||||||
} else if (flag->is_int()) {
|
|
||||||
BOXED_LONG(value, flag->get_int());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_intx()) {
|
|
||||||
BOXED_LONG(value, flag->get_intx());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_uint()) {
|
|
||||||
BOXED_LONG(value, flag->get_uint());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_uint64_t()) {
|
|
||||||
BOXED_LONG(value, flag->get_uint64_t());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_uintx()) {
|
|
||||||
BOXED_LONG(value, flag->get_uintx());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_double()) {
|
|
||||||
BOXED_DOUBLE(value, flag->get_double());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else if (flag->is_size_t()) {
|
|
||||||
BOXED_LONG(value, flag->get_size_t());
|
|
||||||
VMFlag::set_value(vmFlagObj, value);
|
|
||||||
} else {
|
|
||||||
JVMCI_ERROR_NULL("VM flag %s has unsupported type %s", flag->_name, flag->_type);
|
|
||||||
}
|
|
||||||
vmFlags->obj_at_put(i, vmFlagObj());
|
|
||||||
}
|
|
||||||
|
|
||||||
objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
|
objArrayHandle vmIntrinsics = CompilerToVM::initialize_intrinsics(CHECK_NULL);
|
||||||
|
|
||||||
objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 6, CHECK_NULL);
|
objArrayOop data = oopFactory::new_objArray(SystemDictionary::Object_klass(), 5, CHECK_NULL);
|
||||||
data->obj_at_put(0, vmFields());
|
data->obj_at_put(0, vmFields());
|
||||||
data->obj_at_put(1, vmTypes());
|
data->obj_at_put(1, vmConstants());
|
||||||
data->obj_at_put(2, vmConstants());
|
data->obj_at_put(2, vmAddresses());
|
||||||
data->obj_at_put(3, vmAddresses());
|
data->obj_at_put(3, vmFlags());
|
||||||
data->obj_at_put(4, vmFlags());
|
data->obj_at_put(4, vmIntrinsics());
|
||||||
data->obj_at_put(5, vmIntrinsics());
|
|
||||||
|
|
||||||
return (jobjectArray) JNIHandles::make_local(THREAD, data);
|
return (jobjectArray) JNIHandles::make_local(THREAD, data);
|
||||||
|
#undef COUNT_FLAG
|
||||||
|
#undef ADD_FLAG
|
||||||
|
#undef ADD_BOOL_FLAG
|
||||||
|
#undef ADD_INTX_FLAG
|
||||||
|
#undef ADD_UINTX_FLAG
|
||||||
|
#undef CHECK_FLAG
|
||||||
|
C2V_END
|
||||||
|
|
||||||
|
C2V_VMENTRY(jobject, getFlagValue, (JNIEnv *, jobject c2vm, jobject name_handle))
|
||||||
|
#define RETURN_BOXED_LONG(value) oop box; jvalue p; p.j = (jlong) (value); box = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
|
||||||
|
#define RETURN_BOXED_DOUBLE(value) oop box; jvalue p; p.d = (jdouble) (value); box = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL); return JNIHandles::make_local(THREAD, box);
|
||||||
|
Handle name = JNIHandles::resolve(name_handle);
|
||||||
|
if (name.is_null()) {
|
||||||
|
THROW_0(vmSymbols::java_lang_NullPointerException());
|
||||||
|
}
|
||||||
|
ResourceMark rm;
|
||||||
|
const char* cstring = java_lang_String::as_utf8_string(name());
|
||||||
|
Flag* flag = Flag::find_flag(cstring, strlen(cstring), /* allow_locked */ true, /* return_flag */ true);
|
||||||
|
if (flag == NULL) {
|
||||||
|
return c2vm;
|
||||||
|
}
|
||||||
|
if (flag->is_bool()) {
|
||||||
|
jvalue prim;
|
||||||
|
prim.z = flag->get_bool();
|
||||||
|
oop box = java_lang_boxing_object::create(T_BOOLEAN, &prim, CHECK_NULL);
|
||||||
|
return JNIHandles::make_local(THREAD, box);
|
||||||
|
} else if (flag->is_ccstr()) {
|
||||||
|
Handle value = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_NULL);
|
||||||
|
return JNIHandles::make_local(THREAD, value());
|
||||||
|
} else if (flag->is_intx()) {
|
||||||
|
RETURN_BOXED_LONG(flag->get_intx());
|
||||||
|
} else if (flag->is_int()) {
|
||||||
|
RETURN_BOXED_LONG(flag->get_int());
|
||||||
|
} else if (flag->is_uint()) {
|
||||||
|
RETURN_BOXED_LONG(flag->get_uint());
|
||||||
|
} else if (flag->is_uint64_t()) {
|
||||||
|
RETURN_BOXED_LONG(flag->get_uint64_t());
|
||||||
|
} else if (flag->is_size_t()) {
|
||||||
|
RETURN_BOXED_LONG(flag->get_size_t());
|
||||||
|
} else if (flag->is_uintx()) {
|
||||||
|
RETURN_BOXED_LONG(flag->get_uintx());
|
||||||
|
} else if (flag->is_double()) {
|
||||||
|
RETURN_BOXED_DOUBLE(flag->get_double());
|
||||||
|
} else {
|
||||||
|
JVMCI_ERROR_NULL("VM flag %s has unsupported type %s", flag->_name, flag->_type);
|
||||||
|
}
|
||||||
|
C2V_END
|
||||||
|
|
||||||
#undef BOXED_LONG
|
#undef BOXED_LONG
|
||||||
#undef BOXED_DOUBLE
|
#undef BOXED_DOUBLE
|
||||||
C2V_END
|
#undef CSTRING_TO_JSTRING
|
||||||
|
|
||||||
C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
|
C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
|
||||||
methodHandle method = CompilerToVM::asMethod(jvmci_method);
|
methodHandle method = CompilerToVM::asMethod(jvmci_method);
|
||||||
|
@ -743,7 +885,7 @@ C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobjec
|
||||||
return cp->remap_instruction_operand_from_cache(index);
|
return cp->remap_instruction_operand_from_cache(index);
|
||||||
C2V_END
|
C2V_END
|
||||||
|
|
||||||
C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jlongArray info_handle))
|
C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
|
constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
|
||||||
Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
|
Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
|
||||||
|
@ -751,9 +893,12 @@ C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_consta
|
||||||
LinkInfo link_info(cp, index, (jvmci_method != NULL) ? CompilerToVM::asMethod(jvmci_method) : NULL, CHECK_0);
|
LinkInfo link_info(cp, index, (jvmci_method != NULL) ? CompilerToVM::asMethod(jvmci_method) : NULL, CHECK_0);
|
||||||
LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0);
|
LinkResolver::resolve_field(fd, link_info, Bytecodes::java_code(code), false, CHECK_0);
|
||||||
typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
|
typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
|
||||||
assert(info != NULL && info->length() == 2, "must be");
|
if (info == NULL || info->length() != 3) {
|
||||||
info->long_at_put(0, (jlong) fd.access_flags().as_int());
|
JVMCI_ERROR_NULL("info must not be null and have a length of 3");
|
||||||
info->long_at_put(1, (jlong) fd.offset());
|
}
|
||||||
|
info->int_at_put(0, fd.access_flags().as_int());
|
||||||
|
info->int_at_put(1, fd.offset());
|
||||||
|
info->int_at_put(2, fd.index());
|
||||||
oop field_holder = CompilerToVM::get_jvmci_type(fd.field_holder(), CHECK_NULL);
|
oop field_holder = CompilerToVM::get_jvmci_type(fd.field_holder(), CHECK_NULL);
|
||||||
return JNIHandles::make_local(THREAD, field_holder);
|
return JNIHandles::make_local(THREAD, field_holder);
|
||||||
C2V_END
|
C2V_END
|
||||||
|
@ -1610,7 +1755,7 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||||
{CC "resolveConstantInPool", CC "(" HS_CONSTANT_POOL "I)" OBJECT, FN_PTR(resolveConstantInPool)},
|
{CC "resolveConstantInPool", CC "(" HS_CONSTANT_POOL "I)" OBJECT, FN_PTR(resolveConstantInPool)},
|
||||||
{CC "resolvePossiblyCachedConstantInPool", CC "(" HS_CONSTANT_POOL "I)" OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)},
|
{CC "resolvePossiblyCachedConstantInPool", CC "(" HS_CONSTANT_POOL "I)" OBJECT, FN_PTR(resolvePossiblyCachedConstantInPool)},
|
||||||
{CC "resolveTypeInPool", CC "(" HS_CONSTANT_POOL "I)" HS_RESOLVED_KLASS, FN_PTR(resolveTypeInPool)},
|
{CC "resolveTypeInPool", CC "(" HS_CONSTANT_POOL "I)" HS_RESOLVED_KLASS, FN_PTR(resolveTypeInPool)},
|
||||||
{CC "resolveFieldInPool", CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[J)" HS_RESOLVED_KLASS, FN_PTR(resolveFieldInPool)},
|
{CC "resolveFieldInPool", CC "(" HS_CONSTANT_POOL "I" HS_RESOLVED_METHOD "B[I)" HS_RESOLVED_KLASS, FN_PTR(resolveFieldInPool)},
|
||||||
{CC "resolveInvokeDynamicInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeDynamicInPool)},
|
{CC "resolveInvokeDynamicInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeDynamicInPool)},
|
||||||
{CC "resolveInvokeHandleInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeHandleInPool)},
|
{CC "resolveInvokeHandleInPool", CC "(" HS_CONSTANT_POOL "I)V", FN_PTR(resolveInvokeHandleInPool)},
|
||||||
{CC "resolveMethod", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
|
{CC "resolveMethod", CC "(" HS_RESOLVED_KLASS HS_RESOLVED_METHOD HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(resolveMethod)},
|
||||||
|
@ -1648,6 +1793,7 @@ JNINativeMethod CompilerToVM::methods[] = {
|
||||||
{CC "getFingerprint", CC "(J)J", FN_PTR(getFingerprint)},
|
{CC "getFingerprint", CC "(J)J", FN_PTR(getFingerprint)},
|
||||||
{CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)},
|
{CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)},
|
||||||
{CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)},
|
{CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)},
|
||||||
|
{CC "getFlagValue", CC "(" STRING ")" OBJECT, FN_PTR(getFlagValue)},
|
||||||
};
|
};
|
||||||
|
|
||||||
int CompilerToVM::methods_count() {
|
int CompilerToVM::methods_count() {
|
||||||
|
|
|
@ -66,6 +66,15 @@ class CompilerToVM {
|
||||||
|
|
||||||
static int vm_page_size;
|
static int vm_page_size;
|
||||||
|
|
||||||
|
static int sizeof_vtableEntry;
|
||||||
|
static int sizeof_ExceptionTableElement;
|
||||||
|
static int sizeof_LocalVariableTableElement;
|
||||||
|
static int sizeof_ConstantPool;
|
||||||
|
static int sizeof_SymbolPointer;
|
||||||
|
static int sizeof_narrowKlass;
|
||||||
|
static int sizeof_arrayOopDesc;
|
||||||
|
static int sizeof_BasicLock;
|
||||||
|
|
||||||
static address dsin;
|
static address dsin;
|
||||||
static address dcos;
|
static address dcos;
|
||||||
static address dtan;
|
static address dtan;
|
||||||
|
@ -74,8 +83,11 @@ class CompilerToVM {
|
||||||
static address dlog10;
|
static address dlog10;
|
||||||
static address dpow;
|
static address dpow;
|
||||||
|
|
||||||
|
static address symbol_init;
|
||||||
|
static address symbol_clinit;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void initialize();
|
static void initialize(TRAPS);
|
||||||
|
|
||||||
static int max_oop_map_stack_offset() {
|
static int max_oop_map_stack_offset() {
|
||||||
assert(_max_oop_map_stack_offset > 0, "must be initialized");
|
assert(_max_oop_map_stack_offset > 0, "must be initialized");
|
||||||
|
@ -83,6 +95,20 @@ class CompilerToVM {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool cstring_equals(const char* const& s0, const char* const& s1) {
|
||||||
|
return strcmp(s0, s1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned cstring_hash(const char* const& s) {
|
||||||
|
int h = 0;
|
||||||
|
const char* p = s;
|
||||||
|
while (*p != '\0') {
|
||||||
|
h = 31 * h + *p;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
static JNINativeMethod methods[];
|
static JNINativeMethod methods[];
|
||||||
|
|
||||||
static objArrayHandle initialize_intrinsics(TRAPS);
|
static objArrayHandle initialize_intrinsics(TRAPS);
|
||||||
|
|
|
@ -283,13 +283,14 @@ void JVMCIEnv::get_field_by_index(instanceKlassHandle accessor, fieldDescriptor&
|
||||||
// Perform an appropriate method lookup based on accessor, holder,
|
// Perform an appropriate method lookup based on accessor, holder,
|
||||||
// name, signature, and bytecode.
|
// name, signature, and bytecode.
|
||||||
methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor,
|
methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor,
|
||||||
instanceKlassHandle h_holder,
|
KlassHandle h_holder,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Symbol* sig,
|
Symbol* sig,
|
||||||
Bytecodes::Code bc,
|
Bytecodes::Code bc,
|
||||||
constantTag tag) {
|
constantTag tag) {
|
||||||
JVMCI_EXCEPTION_CONTEXT;
|
// Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl().
|
||||||
LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
|
assert(check_klass_accessibility(h_accessor, h_holder), "holder not accessible");
|
||||||
|
|
||||||
methodHandle dest_method;
|
methodHandle dest_method;
|
||||||
LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
|
LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
|
||||||
switch (bc) {
|
switch (bc) {
|
||||||
|
@ -363,9 +364,8 @@ methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (holder_is_accessible) { // Our declared holder is loaded.
|
if (holder_is_accessible) { // Our declared holder is loaded.
|
||||||
instanceKlassHandle lookup = get_instance_klass_for_declared_method_holder(holder);
|
|
||||||
constantTag tag = cpool->tag_ref_at(index);
|
constantTag tag = cpool->tag_ref_at(index);
|
||||||
methodHandle m = lookup_method(accessor, lookup, name_sym, sig_sym, bc, tag);
|
methodHandle m = lookup_method(accessor, holder, name_sym, sig_sym, bc, tag);
|
||||||
if (!m.is_null() &&
|
if (!m.is_null() &&
|
||||||
(bc == Bytecodes::_invokestatic
|
(bc == Bytecodes::_invokestatic
|
||||||
? InstanceKlass::cast(m->method_holder())->is_not_initialized()
|
? InstanceKlass::cast(m->method_holder())->is_not_initialized()
|
||||||
|
|
|
@ -127,7 +127,7 @@ private:
|
||||||
// Helper methods
|
// Helper methods
|
||||||
static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass);
|
static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass);
|
||||||
static methodHandle lookup_method(instanceKlassHandle accessor,
|
static methodHandle lookup_method(instanceKlassHandle accessor,
|
||||||
instanceKlassHandle holder,
|
KlassHandle holder,
|
||||||
Symbol* name,
|
Symbol* name,
|
||||||
Symbol* sig,
|
Symbol* sig,
|
||||||
Bytecodes::Code bc,
|
Bytecodes::Code bc,
|
||||||
|
|
|
@ -78,6 +78,15 @@
|
||||||
\
|
\
|
||||||
static_field(CompilerToVM::Data, vm_page_size, int) \
|
static_field(CompilerToVM::Data, vm_page_size, int) \
|
||||||
\
|
\
|
||||||
|
static_field(CompilerToVM::Data, sizeof_vtableEntry, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_ExceptionTableElement, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_LocalVariableTableElement, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_ConstantPool, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_SymbolPointer, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_narrowKlass, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_arrayOopDesc, int) \
|
||||||
|
static_field(CompilerToVM::Data, sizeof_BasicLock, int) \
|
||||||
|
\
|
||||||
static_field(CompilerToVM::Data, dsin, address) \
|
static_field(CompilerToVM::Data, dsin, address) \
|
||||||
static_field(CompilerToVM::Data, dcos, address) \
|
static_field(CompilerToVM::Data, dcos, address) \
|
||||||
static_field(CompilerToVM::Data, dtan, address) \
|
static_field(CompilerToVM::Data, dtan, address) \
|
||||||
|
@ -86,6 +95,9 @@
|
||||||
static_field(CompilerToVM::Data, dlog10, address) \
|
static_field(CompilerToVM::Data, dlog10, address) \
|
||||||
static_field(CompilerToVM::Data, dpow, address) \
|
static_field(CompilerToVM::Data, dpow, address) \
|
||||||
\
|
\
|
||||||
|
static_field(CompilerToVM::Data, symbol_init, address) \
|
||||||
|
static_field(CompilerToVM::Data, symbol_clinit, address) \
|
||||||
|
\
|
||||||
static_field(Abstract_VM_Version, _features, uint64_t) \
|
static_field(Abstract_VM_Version, _features, uint64_t) \
|
||||||
\
|
\
|
||||||
nonstatic_field(Array<int>, _length, int) \
|
nonstatic_field(Array<int>, _length, int) \
|
||||||
|
@ -293,7 +305,6 @@
|
||||||
static_field(StubRoutines, _crc32c_table_addr, address) \
|
static_field(StubRoutines, _crc32c_table_addr, address) \
|
||||||
static_field(StubRoutines, _updateBytesCRC32C, address) \
|
static_field(StubRoutines, _updateBytesCRC32C, address) \
|
||||||
static_field(StubRoutines, _updateBytesAdler32, address) \
|
static_field(StubRoutines, _updateBytesAdler32, address) \
|
||||||
static_field(StubRoutines, _multiplyToLen, address) \
|
|
||||||
static_field(StubRoutines, _squareToLen, address) \
|
static_field(StubRoutines, _squareToLen, address) \
|
||||||
static_field(StubRoutines, _mulAdd, address) \
|
static_field(StubRoutines, _mulAdd, address) \
|
||||||
static_field(StubRoutines, _montgomeryMultiply, address) \
|
static_field(StubRoutines, _montgomeryMultiply, address) \
|
||||||
|
|
|
@ -1889,6 +1889,12 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
bool saw_self = false;
|
bool saw_self = false;
|
||||||
for( uint i=1; i<req(); ++i ) {// For all paths in
|
for( uint i=1; i<req(); ++i ) {// For all paths in
|
||||||
Node *ii = in(i);
|
Node *ii = in(i);
|
||||||
|
// TOP inputs should not be counted as safe inputs because if the
|
||||||
|
// Phi references itself through all other inputs then splitting the
|
||||||
|
// Phi through memory merges would create dead loop at later stage.
|
||||||
|
if (ii == top) {
|
||||||
|
return NULL; // Delay optimization until graph is cleaned.
|
||||||
|
}
|
||||||
if (ii->is_MergeMem()) {
|
if (ii->is_MergeMem()) {
|
||||||
MergeMemNode* n = ii->as_MergeMem();
|
MergeMemNode* n = ii->as_MergeMem();
|
||||||
merge_width = MAX2(merge_width, n->req());
|
merge_width = MAX2(merge_width, n->req());
|
||||||
|
|
|
@ -1894,6 +1894,11 @@ void Arguments::set_jvmci_specific_flags() {
|
||||||
if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
|
if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
|
||||||
FLAG_SET_DEFAULT(NewSizeThreadIncrease, 4*K);
|
FLAG_SET_DEFAULT(NewSizeThreadIncrease, 4*K);
|
||||||
}
|
}
|
||||||
|
if (TieredStopAtLevel != CompLevel_full_optimization) {
|
||||||
|
// Currently JVMCI compiler can only work at the full optimization level
|
||||||
|
warning("forcing TieredStopAtLevel to full optimization because JVMCI is enabled");
|
||||||
|
TieredStopAtLevel = CompLevel_full_optimization;
|
||||||
|
}
|
||||||
if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
|
if (FLAG_IS_DEFAULT(TypeProfileLevel)) {
|
||||||
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
|
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
|
||||||
}
|
}
|
||||||
|
@ -2506,8 +2511,8 @@ bool Arguments::check_vm_args_consistency() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if INCLUDE_JVMCI
|
|
||||||
|
|
||||||
|
#if INCLUDE_JVMCI
|
||||||
status = status && check_jvmci_args_consistency();
|
status = status && check_jvmci_args_consistency();
|
||||||
|
|
||||||
if (EnableJVMCI) {
|
if (EnableJVMCI) {
|
||||||
|
|
|
@ -221,8 +221,9 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||||
// It is not guaranteed that we can get such information here only
|
// It is not guaranteed that we can get such information here only
|
||||||
// by analyzing bytecode in deoptimized frames. This is why this flag
|
// by analyzing bytecode in deoptimized frames. This is why this flag
|
||||||
// is set during method compilation (see Compile::Process_OopMap_Node()).
|
// is set during method compilation (see Compile::Process_OopMap_Node()).
|
||||||
// If the previous frame was popped, we don't have a result.
|
// If the previous frame was popped or if we are dispatching an exception,
|
||||||
bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution();
|
// we don't have an oop result.
|
||||||
|
bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution() && (exec_mode == Unpack_deopt);
|
||||||
Handle return_value;
|
Handle return_value;
|
||||||
if (save_oop_result) {
|
if (save_oop_result) {
|
||||||
// Reallocation may trigger GC. If deoptimization happened on return from
|
// Reallocation may trigger GC. If deoptimization happened on return from
|
||||||
|
@ -1596,9 +1597,9 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
|
||||||
get_method_data(thread, profiled_method, create_if_missing);
|
get_method_data(thread, profiled_method, create_if_missing);
|
||||||
|
|
||||||
// Log a message
|
// Log a message
|
||||||
Events::log_deopt_message(thread, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d",
|
Events::log_deopt_message(thread, "Uncommon trap: reason=%s action=%s pc=" INTPTR_FORMAT " method=%s @ %d %s",
|
||||||
trap_reason_name(reason), trap_action_name(action), p2i(fr.pc()),
|
trap_reason_name(reason), trap_action_name(action), p2i(fr.pc()),
|
||||||
trap_method->name_and_sig_as_C_string(), trap_bci);
|
trap_method->name_and_sig_as_C_string(), trap_bci, nm->compiler_name());
|
||||||
|
|
||||||
// Print a bunch of diagnostics, if requested.
|
// Print a bunch of diagnostics, if requested.
|
||||||
if (TraceDeoptimization || LogCompilation) {
|
if (TraceDeoptimization || LogCompilation) {
|
||||||
|
@ -1812,7 +1813,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
|
||||||
// aggressive optimization.
|
// aggressive optimization.
|
||||||
bool inc_recompile_count = false;
|
bool inc_recompile_count = false;
|
||||||
ProfileData* pdata = NULL;
|
ProfileData* pdata = NULL;
|
||||||
if (ProfileTraps && update_trap_state && trap_mdo != NULL) {
|
if (ProfileTraps && !is_client_compilation_mode_vm() && update_trap_state && trap_mdo != NULL) {
|
||||||
assert(trap_mdo == get_method_data(thread, profiled_method, false), "sanity");
|
assert(trap_mdo == get_method_data(thread, profiled_method, false), "sanity");
|
||||||
uint this_trap_count = 0;
|
uint this_trap_count = 0;
|
||||||
bool maybe_prior_trap = false;
|
bool maybe_prior_trap = false;
|
||||||
|
|
|
@ -657,14 +657,13 @@ public:
|
||||||
range(0, 99) \
|
range(0, 99) \
|
||||||
\
|
\
|
||||||
product(bool, UseAES, false, \
|
product(bool, UseAES, false, \
|
||||||
"Control whether AES instructions can be used on x86/x64") \
|
"Control whether AES instructions are used when available") \
|
||||||
\
|
\
|
||||||
product(bool, UseFMA, false, \
|
product(bool, UseFMA, false, \
|
||||||
"Control whether FMA instructions can be used") \
|
"Control whether FMA instructions are used when available") \
|
||||||
\
|
\
|
||||||
product(bool, UseSHA, false, \
|
product(bool, UseSHA, false, \
|
||||||
"Control whether SHA instructions can be used " \
|
"Control whether SHA instructions are used when available") \
|
||||||
"on SPARC, on ARM and on x86") \
|
|
||||||
\
|
\
|
||||||
diagnostic(bool, UseGHASHIntrinsics, false, \
|
diagnostic(bool, UseGHASHIntrinsics, false, \
|
||||||
"Use intrinsics for GHASH versions of crypto") \
|
"Use intrinsics for GHASH versions of crypto") \
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8170455
|
||||||
|
* @summary C2: Access to [].clone from interfaces fails.
|
||||||
|
* @library /test/lib /
|
||||||
|
*
|
||||||
|
* @requires vm.flavor == "server" & !vm.emulatedClient
|
||||||
|
* @build sun.hotspot.WhiteBox
|
||||||
|
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @run main/othervm -Xcomp -Xbatch -Xbootclasspath/a:. -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
|
* -XX:CompileCommand=compileonly,*TestDefaultMethodArrayCloneDeoptC2Interface::test
|
||||||
|
* compiler.arraycopy.TestDefaultMethodArrayCloneDeoptC2
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.arraycopy;
|
||||||
|
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import compiler.whitebox.CompilerWhiteBoxTest;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
interface TestDefaultMethodArrayCloneDeoptC2Interface {
|
||||||
|
default int[] test(int[] arr) {
|
||||||
|
return arr.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
default TDMACDC2InterfaceTypeTest[] test(TDMACDC2InterfaceTypeTest[] arr) {
|
||||||
|
return arr.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
default TDMACDC2ClassTypeTest[] test(TDMACDC2ClassTypeTest[] arr) {
|
||||||
|
return arr.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestDefaultMethodArrayCloneDeoptC2 implements TestDefaultMethodArrayCloneDeoptC2Interface {
|
||||||
|
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||||
|
public static TestDefaultMethodArrayCloneDeoptC2 a = new TestDefaultMethodArrayCloneDeoptC2();
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
testPrimitiveArr();
|
||||||
|
testIntfArr();
|
||||||
|
testClassArr();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testPrimitiveArr() throws Exception {
|
||||||
|
Method m = TestDefaultMethodArrayCloneDeoptC2Interface.class.getMethod("test", int[].class);
|
||||||
|
a.test(new int[1]); // Compiled
|
||||||
|
a.test(new int[1]);
|
||||||
|
if (!WB.isMethodCompiled(m)) {
|
||||||
|
WB.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
|
||||||
|
}
|
||||||
|
a.test(new int[1]);
|
||||||
|
if (!WB.isMethodCompiled(m)) {
|
||||||
|
throw new Exception("Method should be compiled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testIntfArr() throws Exception {
|
||||||
|
Method m = TestDefaultMethodArrayCloneDeoptC2Interface.class.getMethod("test", TDMACDC2InterfaceTypeTest[].class);
|
||||||
|
a.test(new TDMACDC2InterfaceTypeTest[1]); // Compiled, Decompile unloaded
|
||||||
|
a.test(new TDMACDC2InterfaceTypeTest[1]); // Compiled
|
||||||
|
a.test(new TDMACDC2InterfaceTypeTest[1]);
|
||||||
|
if (!WB.isMethodCompiled(m)) {
|
||||||
|
WB.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
|
||||||
|
}
|
||||||
|
a.test(new TDMACDC2InterfaceTypeTest[1]);
|
||||||
|
if (!WB.isMethodCompiled(m)) {
|
||||||
|
throw new Exception("Method should be compiled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void testClassArr() throws Exception {
|
||||||
|
Method m = TestDefaultMethodArrayCloneDeoptC2Interface.class.getMethod("test", TDMACDC2ClassTypeTest[].class);
|
||||||
|
a.test(new TDMACDC2ClassTypeTest[1]); // Compiled, Decompile unloaded
|
||||||
|
a.test(new TDMACDC2ClassTypeTest[1]); // Compiled
|
||||||
|
a.test(new TDMACDC2ClassTypeTest[1]);
|
||||||
|
if (!WB.isMethodCompiled(m)) {
|
||||||
|
WB.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION);
|
||||||
|
}
|
||||||
|
a.test(new TDMACDC2ClassTypeTest[1]);
|
||||||
|
if (!WB.isMethodCompiled(m)) {
|
||||||
|
throw new Exception("Method should be compiled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TDMACDC2InterfaceTypeTest {
|
||||||
|
}
|
||||||
|
|
||||||
|
class TDMACDC2ClassTypeTest {
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,10 @@ public class CompilerToVMHelper {
|
||||||
return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method);
|
return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Object getFlagValue(String name) {
|
||||||
|
return CTVM.getFlagValue(name);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isCompilable(HotSpotResolvedJavaMethod method) {
|
public static boolean isCompilable(HotSpotResolvedJavaMethod method) {
|
||||||
return CTVM.isCompilable((HotSpotResolvedJavaMethodImpl)method);
|
return CTVM.isCompilable((HotSpotResolvedJavaMethodImpl)method);
|
||||||
}
|
}
|
||||||
|
@ -128,7 +132,7 @@ public class CompilerToVMHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HotSpotResolvedObjectType resolveFieldInPool(
|
public static HotSpotResolvedObjectType resolveFieldInPool(
|
||||||
ConstantPool constantPool, int cpi, ResolvedJavaMethod method, byte opcode, long[] info) {
|
ConstantPool constantPool, int cpi, ResolvedJavaMethod method, byte opcode, int[] info) {
|
||||||
return CTVM.resolveFieldInPool((HotSpotConstantPool) constantPool, cpi, (HotSpotResolvedJavaMethodImpl) method, opcode, info);
|
return CTVM.resolveFieldInPool((HotSpotConstantPool) constantPool, cpi, (HotSpotResolvedJavaMethodImpl) method, opcode, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,13 +202,13 @@ public class ConstantPoolTestCase {
|
||||||
public final String type;
|
public final String type;
|
||||||
public final ResolvedJavaMethod[] methods;
|
public final ResolvedJavaMethod[] methods;
|
||||||
public final byte[] opcodes;
|
public final byte[] opcodes;
|
||||||
public final long accFlags;
|
public final int accFlags;
|
||||||
|
|
||||||
public TestedCPEntry(String klass, String name, String type, byte[] opcodes, long accFlags) {
|
public TestedCPEntry(String klass, String name, String type, byte[] opcodes, int accFlags) {
|
||||||
this(klass, name, type, null, opcodes, accFlags);
|
this(klass, name, type, null, opcodes, accFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TestedCPEntry(String klass, String name, String type, ResolvedJavaMethod[] methods, byte[] opcodes, long accFlags) {
|
public TestedCPEntry(String klass, String name, String type, ResolvedJavaMethod[] methods, byte[] opcodes, int accFlags) {
|
||||||
this.klass = klass;
|
this.klass = klass;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
|
@ -206,7 +206,7 @@ public class ConstantPoolTestsHelper {
|
||||||
"stringFieldEmpty",
|
"stringFieldEmpty",
|
||||||
"Ljava/lang/String;",
|
"Ljava/lang/String;",
|
||||||
new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
|
new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
|
||||||
0L),
|
0),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
CP_MAP_FOR_CLASS.put(CONSTANT_METHODREF,
|
CP_MAP_FOR_CLASS.put(CONSTANT_METHODREF,
|
||||||
|
@ -362,7 +362,7 @@ public class ConstantPoolTestsHelper {
|
||||||
"stringFieldEmpty",
|
"stringFieldEmpty",
|
||||||
"Ljava/lang/String;",
|
"Ljava/lang/String;",
|
||||||
new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
|
new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
|
||||||
0L),
|
0),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODREF,
|
CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODREF,
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8173912
|
||||||
|
* @requires vm.jvmci
|
||||||
|
* @library / /test/lib
|
||||||
|
* @library ../common/patches
|
||||||
|
* @modules jdk.vm.ci/jdk.vm.ci.hotspot:+open
|
||||||
|
* @build sun.hotspot.WhiteBox
|
||||||
|
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
|
* @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper
|
||||||
|
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
|
||||||
|
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||||
|
* compiler.jvmci.compilerToVM.GetFlagValueTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.jvmci.compilerToVM;
|
||||||
|
|
||||||
|
import jdk.test.lib.Asserts;
|
||||||
|
import jdk.vm.ci.hotspot.CompilerToVMHelper;
|
||||||
|
import jdk.test.lib.process.OutputAnalyzer;
|
||||||
|
import jdk.test.lib.process.ProcessTools;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import sun.hotspot.WhiteBox;
|
||||||
|
|
||||||
|
public class GetFlagValueTest {
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
try {
|
||||||
|
CompilerToVMHelper.getFlagValue(null);
|
||||||
|
Asserts.fail("Expected NullPointerException when calling getFlagValue(null)");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
|
Object missing = CompilerToVMHelper.getFlagValue("this is surely not a flag");
|
||||||
|
Asserts.assertEquals(CompilerToVMHelper.CTVM, missing);
|
||||||
|
|
||||||
|
ProcessBuilder pb;
|
||||||
|
OutputAnalyzer out;
|
||||||
|
|
||||||
|
String[] arguments = {"-XX:+UnlockExperimentalVMOptions", "-XX:+EnableJVMCI", "-XX:+PrintFlagsFinal", "-version"};
|
||||||
|
pb = ProcessTools.createJavaProcessBuilder(arguments);
|
||||||
|
out = new OutputAnalyzer(pb.start());
|
||||||
|
|
||||||
|
out.shouldHaveExitValue(0);
|
||||||
|
String[] lines = out.getStdout().split("\\r?\\n");
|
||||||
|
Asserts.assertTrue(lines.length > 1, "Expected output from -XX:+PrintFlagsFinal");
|
||||||
|
|
||||||
|
final WhiteBox wb = WhiteBox.getWhiteBox();
|
||||||
|
|
||||||
|
// Line example: ccstr PrintIdealGraphAddress = 127.0.0.1 {C2 notproduct} {default}
|
||||||
|
Pattern flagLine = Pattern.compile("(\\w+)\\s+(\\w+)\\s+:?= (?:(.+))\\{[^}]+\\}\\s+\\{[^}]+\\}");
|
||||||
|
for (String line : lines) {
|
||||||
|
if (line.indexOf('=') != -1) {
|
||||||
|
line = line.trim();
|
||||||
|
Matcher m = flagLine.matcher(line);
|
||||||
|
Asserts.assertTrue(m.matches(), "Unexpected line in -XX:+PrintFlagsFinal output: " + line);
|
||||||
|
String type = m.group(1);
|
||||||
|
String name = m.group(2);
|
||||||
|
String expect = m.group(3).trim();
|
||||||
|
Object value = CompilerToVMHelper.getFlagValue(name);
|
||||||
|
Object wbValue = wb.getVMFlag(name);
|
||||||
|
Asserts.assertEquals(value, wbValue, "Value of flag " + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -103,7 +103,7 @@ public class ResolveFieldInPoolTest {
|
||||||
cached = "cached ";
|
cached = "cached ";
|
||||||
}
|
}
|
||||||
for (int j = 0; j < entry.opcodes.length; j++) {
|
for (int j = 0; j < entry.opcodes.length; j++) {
|
||||||
long[] info = new long[2];
|
int[] info = new int[3];
|
||||||
HotSpotResolvedObjectType fieldToVerify
|
HotSpotResolvedObjectType fieldToVerify
|
||||||
= CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
|
= CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
|
||||||
index,
|
index,
|
||||||
|
@ -147,11 +147,11 @@ public class ResolveFieldInPoolTest {
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new Error("Unexpected exception", ex);
|
throw new Error("Unexpected exception", ex);
|
||||||
}
|
}
|
||||||
long offsetToRefer;
|
int offsetToRefer;
|
||||||
if ((entry.accFlags & Opcodes.ACC_STATIC) != 0) {
|
if ((entry.accFlags & Opcodes.ACC_STATIC) != 0) {
|
||||||
offsetToRefer = UNSAFE.staticFieldOffset(fieldToRefer);
|
offsetToRefer = (int) UNSAFE.staticFieldOffset(fieldToRefer);
|
||||||
} else {
|
} else {
|
||||||
offsetToRefer = UNSAFE.objectFieldOffset(fieldToRefer);
|
offsetToRefer = (int) UNSAFE.objectFieldOffset(fieldToRefer);
|
||||||
}
|
}
|
||||||
msg = String.format("Field offset returned by resolveFieldInPool"
|
msg = String.format("Field offset returned by resolveFieldInPool"
|
||||||
+ " method is wrong for the field %s.%s"
|
+ " method is wrong for the field %s.%s"
|
||||||
|
|
|
@ -30,6 +30,6 @@ import java.util.function.BooleanSupplier;
|
||||||
public class SupportedVM implements BooleanSupplier {
|
public class SupportedVM implements BooleanSupplier {
|
||||||
@Override
|
@Override
|
||||||
public boolean getAsBoolean() {
|
public boolean getAsBoolean() {
|
||||||
return Platform.isServer();
|
return Platform.isServer() && !Platform.isEmulatedClient();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
/*
|
/*
|
||||||
* @test CorrectnessTest
|
* @test CorrectnessTest
|
||||||
* @bug 8038418
|
* @bug 8038418
|
||||||
|
* @requires vm.flavor == "server" & !vm.emulatedClient
|
||||||
* @library /test/lib /
|
* @library /test/lib /
|
||||||
* @modules java.base/jdk.internal.misc
|
* @modules java.base/jdk.internal.misc
|
||||||
* java.management
|
* java.management
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import utils.GarbageProducer;
|
||||||
|
import common.TmTool;
|
||||||
|
import utils.JstatResults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for jstat testing which uses GarbageProducer to allocate garbage.
|
||||||
|
*/
|
||||||
|
public class GarbageProducerTest {
|
||||||
|
|
||||||
|
// Iterations of measurement to get consistent value of counters and jstat.
|
||||||
|
private final static int ITERATIONS = 10;
|
||||||
|
private final static float TARGET_MEMORY_USAGE = 0.7f;
|
||||||
|
private final static float MEASUREMENT_TOLERANCE = 0.05f;
|
||||||
|
private final GarbageProducer garbageProducer;
|
||||||
|
private final TmTool<? extends JstatResults> jstatTool;
|
||||||
|
|
||||||
|
public GarbageProducerTest(TmTool<? extends JstatResults> tool) {
|
||||||
|
garbageProducer = new GarbageProducer(TARGET_MEMORY_USAGE);
|
||||||
|
// We will be running jstat tool
|
||||||
|
jstatTool = tool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws Exception {
|
||||||
|
// Run once and get the results asserting that they are reasonable
|
||||||
|
JstatResults measurement1 = jstatTool.measure();
|
||||||
|
measurement1.assertConsistency();
|
||||||
|
// Eat metaspace and heap then run the tool again and get the results asserting that they are reasonable
|
||||||
|
System.gc();
|
||||||
|
garbageProducer.allocateMetaspaceAndHeap();
|
||||||
|
// Collect garbage. Also update VM statistics
|
||||||
|
System.gc();
|
||||||
|
int i = 0;
|
||||||
|
long collectionCountBefore = getCollectionCount();
|
||||||
|
JstatResults measurement2 = jstatTool.measure();
|
||||||
|
do {
|
||||||
|
System.out.println("Measurement #" + i);
|
||||||
|
long currentCounter = getCollectionCount();
|
||||||
|
// Check if GC cycle occured during measurement
|
||||||
|
if (currentCounter == collectionCountBefore) {
|
||||||
|
measurement2.assertConsistency();
|
||||||
|
checkOldGenMeasurement(measurement2);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
System.out.println("GC happened during measurement.");
|
||||||
|
}
|
||||||
|
collectionCountBefore = getCollectionCount();
|
||||||
|
measurement2 = jstatTool.measure();
|
||||||
|
|
||||||
|
} while (i++ < ITERATIONS);
|
||||||
|
// Checking will be performed without consistency guarantee.
|
||||||
|
checkOldGenMeasurement(measurement2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkOldGenMeasurement(JstatResults measurement2) {
|
||||||
|
float oldGenAllocationRatio = garbageProducer.getOldGenAllocationRatio() - MEASUREMENT_TOLERANCE;
|
||||||
|
// Assert that space has been utilized accordingly
|
||||||
|
JstatResults.assertSpaceUtilization(measurement2, TARGET_MEMORY_USAGE, oldGenAllocationRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getCollectionCount() {
|
||||||
|
return ManagementFactory.getGarbageCollectorMXBeans().stream()
|
||||||
|
.mapToLong(b -> b.getCollectionCount())
|
||||||
|
.sum();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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,39 +25,19 @@
|
||||||
* @test
|
* @test
|
||||||
* @summary Test checks output displayed with jstat -gccause.
|
* @summary Test checks output displayed with jstat -gccause.
|
||||||
* Test scenario:
|
* Test scenario:
|
||||||
* tests forces debuggee application eat ~70% of heap and runs jstat.
|
* test forces debuggee application eat ~70% of heap and runs jstat.
|
||||||
* jstat should show that ~70% of heap (OC/OU ~= 70%).
|
* jstat should show actual usage of old gen (OC/OU ~= old gen usage).
|
||||||
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
|
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
|
||||||
* @modules java.base/jdk.internal.misc
|
* @modules java.base/jdk.internal.misc
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @library ../share
|
* @library ../share
|
||||||
* @run main/othervm -XX:+UsePerfData -XX:InitialHeapSize=128M -XX:MaxHeapSize=128M -XX:MaxMetaspaceSize=128M GcCauseTest02
|
* @run main/othervm -XX:+UsePerfData -XX:MaxNewSize=4m -XX:MaxHeapSize=128M -XX:MaxMetaspaceSize=128M GcCauseTest02
|
||||||
*/
|
*/
|
||||||
import utils.*;
|
import utils.*;
|
||||||
|
|
||||||
public class GcCauseTest02 {
|
public class GcCauseTest02 {
|
||||||
|
|
||||||
private final static float targetMemoryUsagePercent = 0.7f;
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
new GarbageProducerTest(new JstatGcCauseTool(ProcessHandle.current().getPid())).run();
|
||||||
// We will be running "jstat -gc" tool
|
|
||||||
JstatGcCauseTool jstatGcTool = new JstatGcCauseTool(ProcessHandle.current().getPid());
|
|
||||||
|
|
||||||
// Run once and get the results asserting that they are reasonable
|
|
||||||
JstatGcCauseResults measurement1 = jstatGcTool.measure();
|
|
||||||
measurement1.assertConsistency();
|
|
||||||
|
|
||||||
GcProvoker gcProvoker = new GcProvoker();
|
|
||||||
|
|
||||||
// Eat metaspace and heap then run the tool again and get the results asserting that they are reasonable
|
|
||||||
gcProvoker.allocateAvailableMetaspaceAndHeap(targetMemoryUsagePercent);
|
|
||||||
// Collect garbage. Also update VM statistics
|
|
||||||
System.gc();
|
|
||||||
JstatGcCauseResults measurement2 = jstatGcTool.measure();
|
|
||||||
measurement2.assertConsistency();
|
|
||||||
|
|
||||||
// Assert that space has been utilized acordingly
|
|
||||||
JstatResults.assertSpaceUtilization(measurement2, targetMemoryUsagePercent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -21,43 +21,23 @@
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import utils.*;
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @summary Test checks output displayed with jstat -gc.
|
* @summary Test checks output displayed with jstat -gc.
|
||||||
* Test scenario:
|
* Test scenario:
|
||||||
* tests forces debuggee application eat ~70% of heap and runs jstat.
|
* test forces debuggee application eat ~70% of heap and runs jstat.
|
||||||
* jstat should show that ~70% of heap is utilized (OC/OU ~= 70%).
|
* jstat should show actual usage of old gen (OC/OU ~= old gen usage).
|
||||||
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
|
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
|
||||||
* @modules java.base/jdk.internal.misc
|
* @modules java.base/jdk.internal.misc
|
||||||
* @library /test/lib
|
* @library /test/lib
|
||||||
* @library ../share
|
* @library ../share
|
||||||
* @run main/othervm -XX:+UsePerfData -XX:InitialHeapSize=128M -XX:MaxHeapSize=128M -XX:MaxMetaspaceSize=128M GcTest02
|
* @run main/othervm -XX:+UsePerfData -XX:MaxNewSize=4m -XX:MaxHeapSize=128M -XX:MaxMetaspaceSize=128M GcTest02
|
||||||
*/
|
*/
|
||||||
|
import utils.*;
|
||||||
|
|
||||||
public class GcTest02 {
|
public class GcTest02 {
|
||||||
|
|
||||||
private final static float targetMemoryUsagePercent = 0.7f;
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
new GarbageProducerTest(new JstatGcTool(ProcessHandle.current().getPid())).run();
|
||||||
// We will be running "jstat -gc" tool
|
|
||||||
JstatGcTool jstatGcTool = new JstatGcTool(ProcessHandle.current().getPid());
|
|
||||||
|
|
||||||
// Run once and get the results asserting that they are reasonable
|
|
||||||
JstatGcResults measurement1 = jstatGcTool.measure();
|
|
||||||
measurement1.assertConsistency();
|
|
||||||
|
|
||||||
GcProvoker gcProvoker = new GcProvoker();
|
|
||||||
|
|
||||||
// Eat metaspace and heap then run the tool again and get the results asserting that they are reasonable
|
|
||||||
gcProvoker.allocateAvailableMetaspaceAndHeap(targetMemoryUsagePercent);
|
|
||||||
// Collect garbage. Also updates VM statistics
|
|
||||||
System.gc();
|
|
||||||
JstatGcResults measurement2 = jstatGcTool.measure();
|
|
||||||
measurement2.assertConsistency();
|
|
||||||
|
|
||||||
// Assert that space has been utilized acordingly
|
|
||||||
JstatResults.assertSpaceUtilization(measurement2, targetMemoryUsagePercent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package utils;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.MemoryMXBean;
|
||||||
|
import java.lang.management.MemoryPoolMXBean;
|
||||||
|
import java.lang.management.MemoryUsage;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is an class used to allocate specified amount of metaspace and heap.
|
||||||
|
*/
|
||||||
|
public class GarbageProducer {
|
||||||
|
|
||||||
|
// Uses fixed small objects to avoid Humongous objects allocation with G1 GC.
|
||||||
|
private static final int MEMORY_CHUNK = 2048;
|
||||||
|
|
||||||
|
public static List<Object> allocatedMetaspace;
|
||||||
|
public static List<Object> allocatedMemory;
|
||||||
|
|
||||||
|
private final MemoryMXBean memoryMXBean;
|
||||||
|
private final float targetMemoryUsagePercent;
|
||||||
|
private final long targetMemoryUsage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param targetMemoryUsagePercent how many percent of metaspace and heap to
|
||||||
|
* allocate
|
||||||
|
*/
|
||||||
|
public GarbageProducer(float targetMemoryUsagePercent) {
|
||||||
|
memoryMXBean = ManagementFactory.getMemoryMXBean();
|
||||||
|
this.targetMemoryUsagePercent = targetMemoryUsagePercent;
|
||||||
|
targetMemoryUsage = (long) (memoryMXBean.getHeapMemoryUsage().getMax() * targetMemoryUsagePercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates heap and metaspace upon exit targetMemoryUsagePercent percents
|
||||||
|
* of heap and metaspace have been consumed.
|
||||||
|
*/
|
||||||
|
public void allocateMetaspaceAndHeap() {
|
||||||
|
// Metaspace should be filled before Java Heap to prevent unexpected OOME
|
||||||
|
// in the Java Heap while filling Metaspace
|
||||||
|
allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent);
|
||||||
|
allocatedMemory = allocateGarbage(targetMemoryUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Object> eatMetaspace(float targetUsage) {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
MemoryPoolMXBean metaspacePool = getMatchedMemoryPool(".*Metaspace.*");
|
||||||
|
float currentUsage;
|
||||||
|
GeneratedClassProducer gp = new GeneratedClassProducer();
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
list.add(gp.create(0));
|
||||||
|
} catch (OutOfMemoryError oome) {
|
||||||
|
list = null;
|
||||||
|
throw new RuntimeException("Unexpected OOME '" + oome.getMessage() + "' while eating " + targetUsage + " of Metaspace.");
|
||||||
|
}
|
||||||
|
MemoryUsage memoryUsage = metaspacePool.getUsage();
|
||||||
|
currentUsage = (((float) memoryUsage.getUsed()) / memoryUsage.getMax());
|
||||||
|
} while (currentUsage < targetUsage);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemoryPoolMXBean getMatchedMemoryPool(String patternPoolName) {
|
||||||
|
return ManagementFactory.getMemoryPoolMXBeans().stream()
|
||||||
|
.filter(bean -> bean.getName().matches(patternPoolName))
|
||||||
|
.findFirst()
|
||||||
|
.orElseThrow(() -> new RuntimeException("Cannot find '" + patternPoolName + "' memory pool."));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Object> allocateGarbage(long targetMemoryUsage) {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
do {
|
||||||
|
try {
|
||||||
|
list.add(new byte[MEMORY_CHUNK]);
|
||||||
|
} catch (OutOfMemoryError e) {
|
||||||
|
list = null;
|
||||||
|
throw new RuntimeException("Unexpected OOME '" + e.getMessage() + "'");
|
||||||
|
}
|
||||||
|
} while (memoryMXBean.getHeapMemoryUsage().getUsed() < targetMemoryUsage);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns allocation rate for old gen based on appropriate MemoryPoolMXBean
|
||||||
|
* memory usage.
|
||||||
|
*
|
||||||
|
* @return allocation rate
|
||||||
|
*/
|
||||||
|
public float getOldGenAllocationRatio() {
|
||||||
|
MemoryPoolMXBean oldGenBean = getMatchedMemoryPool(".*Old.*|.*Tenured.*");
|
||||||
|
MemoryUsage usage = oldGenBean.getUsage();
|
||||||
|
System.out.format("Memory usage for %1s.\n", oldGenBean.getName());
|
||||||
|
System.out.format("Used: %1d\n", usage.getUsed());
|
||||||
|
System.out.format("Commited: %1d\n", usage.getCommitted());
|
||||||
|
System.out.format("Max: %1d\n", usage.getMax());
|
||||||
|
return ((float) usage.getUsed()) / usage.getCommitted();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -22,9 +22,6 @@
|
||||||
*/
|
*/
|
||||||
package utils;
|
package utils;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.lang.management.MemoryPoolMXBean;
|
|
||||||
import java.lang.management.MemoryUsage;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -36,11 +33,7 @@ import java.util.List;
|
||||||
public class GcProvoker{
|
public class GcProvoker{
|
||||||
|
|
||||||
// Uses fixed small objects to avoid Humongous objects allocation in G1
|
// Uses fixed small objects to avoid Humongous objects allocation in G1
|
||||||
public static final int MEMORY_CHUNK = 2048;
|
private static final int MEMORY_CHUNK = 2048;
|
||||||
public static final float ALLOCATION_TOLERANCE = 0.05f;
|
|
||||||
|
|
||||||
public static List<Object> allocatedMetaspace;
|
|
||||||
public static List<Object> allocatedMemory;
|
|
||||||
|
|
||||||
private final Runtime runtime;
|
private final Runtime runtime;
|
||||||
|
|
||||||
|
@ -61,21 +54,6 @@ public class GcProvoker{
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Object> allocateAvailableHeap(float targetUsage) {
|
|
||||||
// Calculates size of free memory after allocation with small tolerance.
|
|
||||||
long minFreeMemory = (long) ((1.0 - (targetUsage + ALLOCATION_TOLERANCE)) * runtime.maxMemory());
|
|
||||||
List<Object> list = new ArrayList<>();
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
list.add(new byte[MEMORY_CHUNK]);
|
|
||||||
} catch (OutOfMemoryError e) {
|
|
||||||
list = null;
|
|
||||||
throw new RuntimeException("Unexpected OOME '" + e.getMessage() + "' while eating " + targetUsage + " of heap memory.");
|
|
||||||
}
|
|
||||||
} while (runtime.freeMemory() > minFreeMemory);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method provokes a GC
|
* This method provokes a GC
|
||||||
*/
|
*/
|
||||||
|
@ -93,65 +71,7 @@ public class GcProvoker{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates heap and metaspace upon exit not less than targetMemoryUsagePercent percents
|
|
||||||
* of heap and metaspace have been consumed.
|
|
||||||
*
|
|
||||||
* @param targetMemoryUsagePercent how many percent of heap and metaspace to
|
|
||||||
* allocate
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void allocateMetaspaceAndHeap(float targetMemoryUsagePercent) {
|
|
||||||
// Metaspace should be filled before Java Heap to prevent unexpected OOME
|
|
||||||
// in the Java Heap while filling Metaspace
|
|
||||||
allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent);
|
|
||||||
allocatedMemory = allocateHeap(targetMemoryUsagePercent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates heap and metaspace upon exit targetMemoryUsagePercent percents
|
|
||||||
* of heap and metaspace have been consumed.
|
|
||||||
*
|
|
||||||
* @param targetMemoryUsagePercent how many percent of heap and metaspace to
|
|
||||||
* allocate
|
|
||||||
*/
|
|
||||||
public void allocateAvailableMetaspaceAndHeap(float targetMemoryUsagePercent) {
|
|
||||||
// Metaspace should be filled before Java Heap to prevent unexpected OOME
|
|
||||||
// in the Java Heap while filling Metaspace
|
|
||||||
allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent);
|
|
||||||
allocatedMemory = allocateAvailableHeap(targetMemoryUsagePercent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Object> eatMetaspace(float targetUsage) {
|
|
||||||
List<Object> list = new ArrayList<>();
|
|
||||||
final String metaspacePoolName = "Metaspace";
|
|
||||||
MemoryPoolMXBean metaspacePool = null;
|
|
||||||
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
|
|
||||||
if (pool.getName().contains(metaspacePoolName)) {
|
|
||||||
metaspacePool = pool;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (metaspacePool == null) {
|
|
||||||
throw new RuntimeException("MXBean for Metaspace pool wasn't found");
|
|
||||||
}
|
|
||||||
float currentUsage;
|
|
||||||
GeneratedClassProducer gp = new GeneratedClassProducer();
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
list.add(gp.create(0));
|
|
||||||
} catch (OutOfMemoryError oome) {
|
|
||||||
list = null;
|
|
||||||
throw new RuntimeException("Unexpected OOME '" + oome.getMessage() + "' while eating " + targetUsage + " of Metaspace.");
|
|
||||||
}
|
|
||||||
MemoryUsage memoryUsage = metaspacePool.getUsage();
|
|
||||||
currentUsage = (((float) memoryUsage.getUsed()) / memoryUsage.getMax());
|
|
||||||
} while (currentUsage < targetUsage);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GcProvoker() {
|
public GcProvoker() {
|
||||||
runtime = Runtime.getRuntime();
|
runtime = Runtime.getRuntime();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package utils;
|
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
|
||||||
import java.lang.management.MemoryPoolMXBean;
|
|
||||||
import java.lang.management.MemoryUsage;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Utilities to provoke GC in various ways
|
|
||||||
*/
|
|
||||||
public class GcProvokerImpl implements GcProvoker {
|
|
||||||
|
|
||||||
private static List<Object> eatenMetaspace;
|
|
||||||
private static List<Object> eatenMemory;
|
|
||||||
|
|
||||||
static List<Object> eatHeapMemory(float targetUsage) {
|
|
||||||
long maxMemory = Runtime.getRuntime().maxMemory();
|
|
||||||
// uses fixed small objects to avoid Humongous objects allocation in G1
|
|
||||||
int memoryChunk = 2048;
|
|
||||||
List<Object> list = new ArrayList<>();
|
|
||||||
long used = 0;
|
|
||||||
long target = (long) (maxMemory * targetUsage);
|
|
||||||
while (used < target) {
|
|
||||||
try {
|
|
||||||
list.add(new byte[memoryChunk]);
|
|
||||||
used += memoryChunk;
|
|
||||||
} catch (OutOfMemoryError e) {
|
|
||||||
list = null;
|
|
||||||
throw new RuntimeException("Unexpected OOME '" + e.getMessage() + "' while eating " + targetUsage + " of heap memory.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void provokeGc() {
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
long edenSize = Pools.getEdenCommittedSize();
|
|
||||||
long heapSize = Pools.getHeapCommittedSize();
|
|
||||||
float targetPercent = ((float) edenSize) / (heapSize);
|
|
||||||
if ((targetPercent < 0) || (targetPercent > 1.0)) {
|
|
||||||
throw new RuntimeException("Error in the percent calculation" + " (eden size: " + edenSize + ", heap size: " + heapSize + ", calculated eden percent: " + targetPercent + ")");
|
|
||||||
}
|
|
||||||
eatHeapMemory(targetPercent);
|
|
||||||
eatHeapMemory(targetPercent);
|
|
||||||
System.gc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void eatMetaspaceAndHeap(float targetMemoryUsagePercent) {
|
|
||||||
// Metaspace should be filled before Java Heap to prevent unexpected OOME
|
|
||||||
// in the Java Heap while filling Metaspace
|
|
||||||
eatenMetaspace = eatMetaspace(targetMemoryUsagePercent);
|
|
||||||
eatenMemory = eatHeapMemory(targetMemoryUsagePercent);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<Object> eatMetaspace(float targetUsage) {
|
|
||||||
List<Object> list = new ArrayList<>();
|
|
||||||
final String metaspacePoolName = "Metaspace";
|
|
||||||
MemoryPoolMXBean metaspacePool = null;
|
|
||||||
for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) {
|
|
||||||
if (pool.getName().contains(metaspacePoolName)) {
|
|
||||||
metaspacePool = pool;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (metaspacePool == null) {
|
|
||||||
throw new RuntimeException("MXBean for Metaspace pool wasn't found");
|
|
||||||
}
|
|
||||||
float currentUsage;
|
|
||||||
GeneratedClassProducer gp = new GeneratedClassProducer();
|
|
||||||
do {
|
|
||||||
try {
|
|
||||||
list.add(gp.create(0));
|
|
||||||
} catch (OutOfMemoryError oome) {
|
|
||||||
list = null;
|
|
||||||
throw new RuntimeException("Unexpected OOME '" + oome.getMessage() + "' while eating " + targetUsage + " of Metaspace.");
|
|
||||||
}
|
|
||||||
MemoryUsage memoryUsage = metaspacePool.getUsage();
|
|
||||||
currentUsage = (((float) memoryUsage.getUsed()) / memoryUsage.getMax());
|
|
||||||
} while (currentUsage < targetUsage);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GcProvokerImpl() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -62,6 +62,7 @@ public class JstatGcCapacityResults extends JstatResults {
|
||||||
/**
|
/**
|
||||||
* Checks the overall consistency of the results reported by the tool
|
* Checks the overall consistency of the results reported by the tool
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void assertConsistency() {
|
public void assertConsistency() {
|
||||||
|
|
||||||
// Check exit code
|
// Check exit code
|
||||||
|
@ -117,8 +118,6 @@ public class JstatGcCapacityResults extends JstatResults {
|
||||||
float MC = getFloatValue("MC");
|
float MC = getFloatValue("MC");
|
||||||
assertThat(MC >= MCMN, "MC < MCMN (generation capacity < min generation capacity)");
|
assertThat(MC >= MCMN, "MC < MCMN (generation capacity < min generation capacity)");
|
||||||
assertThat(MC <= MCMX, "MGC > MCMX (generation capacity > max generation capacity)");
|
assertThat(MC <= MCMX, "MGC > MCMX (generation capacity > max generation capacity)");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,21 +138,4 @@ public class JstatGcCapacityResults extends JstatResults {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
|
|
||||||
|
|
||||||
private static boolean checkFloatIsSum(float sum, float... floats) {
|
|
||||||
for (float f : floats) {
|
|
||||||
sum -= f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertThat(boolean b, String message) {
|
|
||||||
if (!b) {
|
|
||||||
throw new RuntimeException(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -56,6 +56,7 @@ public class JstatGcCauseResults extends JstatResults {
|
||||||
/**
|
/**
|
||||||
* Checks the overall consistency of the results reported by the tool
|
* Checks the overall consistency of the results reported by the tool
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void assertConsistency() {
|
public void assertConsistency() {
|
||||||
|
|
||||||
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
|
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
|
||||||
|
@ -83,21 +84,4 @@ public class JstatGcCauseResults extends JstatResults {
|
||||||
assertThat(checkFloatIsSum(GCT, YGCT, FGCT), "GCT != (YGCT + FGCT) " + "(GCT = " + GCT + ", YGCT = " + YGCT
|
assertThat(checkFloatIsSum(GCT, YGCT, FGCT), "GCT != (YGCT + FGCT) " + "(GCT = " + GCT + ", YGCT = " + YGCT
|
||||||
+ ", FGCT = " + FGCT + ", (YCGT + FGCT) = " + (YGCT + FGCT) + ")");
|
+ ", FGCT = " + FGCT + ", (YCGT + FGCT) = " + (YGCT + FGCT) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
|
|
||||||
|
|
||||||
private static boolean checkFloatIsSum(float sum, float... floats) {
|
|
||||||
for (float f : floats) {
|
|
||||||
sum -= f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertThat(boolean b, String message) {
|
|
||||||
if (!b) {
|
|
||||||
throw new RuntimeException(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -54,6 +54,7 @@ public class JstatGcNewResults extends JstatResults {
|
||||||
/**
|
/**
|
||||||
* Checks the overall consistency of the results reported by the tool
|
* Checks the overall consistency of the results reported by the tool
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void assertConsistency() {
|
public void assertConsistency() {
|
||||||
|
|
||||||
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
|
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
|
||||||
|
@ -84,10 +85,4 @@ public class JstatGcNewResults extends JstatResults {
|
||||||
int MTT = getIntValue("MTT");
|
int MTT = getIntValue("MTT");
|
||||||
assertThat(TT <= MTT, "TT > MTT (tenuring threshold > maximum tenuring threshold)");
|
assertThat(TT <= MTT, "TT > MTT (tenuring threshold > maximum tenuring threshold)");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertThat(boolean b, String message) {
|
|
||||||
if (!b) {
|
|
||||||
throw new RuntimeException(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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
|
||||||
|
@ -61,6 +61,7 @@ public class JstatGcResults extends JstatResults {
|
||||||
/**
|
/**
|
||||||
* Checks the overall consistency of the results reported by the tool
|
* Checks the overall consistency of the results reported by the tool
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void assertConsistency() {
|
public void assertConsistency() {
|
||||||
|
|
||||||
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
|
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
|
||||||
|
@ -112,21 +113,4 @@ public class JstatGcResults extends JstatResults {
|
||||||
assertThat(checkFloatIsSum(GCT, YGCT, FGCT), "GCT != (YGCT + FGCT) " + "(GCT = " + GCT + ", YGCT = " + YGCT
|
assertThat(checkFloatIsSum(GCT, YGCT, FGCT), "GCT != (YGCT + FGCT) " + "(GCT = " + GCT + ", YGCT = " + YGCT
|
||||||
+ ", FGCT = " + FGCT + ", (YCGT + FGCT) = " + (YGCT + FGCT) + ")");
|
+ ", FGCT = " + FGCT + ", (YCGT + FGCT) = " + (YGCT + FGCT) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
|
|
||||||
|
|
||||||
private static boolean checkFloatIsSum(float sum, float... floats) {
|
|
||||||
for (float f : floats) {
|
|
||||||
sum -= f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertThat(boolean b, String message) {
|
|
||||||
if (!b) {
|
|
||||||
throw new RuntimeException(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2017, 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,6 +30,8 @@ import common.ToolResults;
|
||||||
*/
|
*/
|
||||||
abstract public class JstatResults extends ToolResults {
|
abstract public class JstatResults extends ToolResults {
|
||||||
|
|
||||||
|
private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
|
||||||
|
|
||||||
public JstatResults(ToolResults rawResults) {
|
public JstatResults(ToolResults rawResults) {
|
||||||
super(rawResults);
|
super(rawResults);
|
||||||
}
|
}
|
||||||
|
@ -110,38 +112,61 @@ abstract public class JstatResults extends ToolResults {
|
||||||
* space has been utilized
|
* space has been utilized
|
||||||
*/
|
*/
|
||||||
public static void assertSpaceUtilization(JstatResults measurement, float targetMemoryUsagePercent) {
|
public static void assertSpaceUtilization(JstatResults measurement, float targetMemoryUsagePercent) {
|
||||||
|
assertSpaceUtilization(measurement, targetMemoryUsagePercent, targetMemoryUsagePercent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to assert the utilization of the space
|
||||||
|
*
|
||||||
|
* @param measurement - measurement results to analyze
|
||||||
|
* @param targetMetaspaceUsagePercent -assert that not less than this amount
|
||||||
|
* of metaspace has been utilized
|
||||||
|
* @param targetOldSpaceUsagePercent -assert that not less than this amount
|
||||||
|
* of old space has been utilized
|
||||||
|
*/
|
||||||
|
public static void assertSpaceUtilization(JstatResults measurement, float targetMetaspaceUsagePercent,
|
||||||
|
float targetOldSpaceUsagePercent) {
|
||||||
|
|
||||||
if (measurement.valueExists("OU")) {
|
if (measurement.valueExists("OU")) {
|
||||||
float OC = measurement.getFloatValue("OC");
|
float OC = measurement.getFloatValue("OC");
|
||||||
float OU = measurement.getFloatValue("OU");
|
float OU = measurement.getFloatValue("OU");
|
||||||
assertThat((OU / OC) > targetMemoryUsagePercent, "Old space utilization should be > "
|
assertThat((OU / OC) > targetOldSpaceUsagePercent, "Old space utilization should be > "
|
||||||
+ (targetMemoryUsagePercent * 100) + "%, actually OU / OC = " + (OU / OC));
|
+ (targetOldSpaceUsagePercent * 100) + "%, actually OU / OC = " + (OU / OC));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (measurement.valueExists("MU")) {
|
if (measurement.valueExists("MU")) {
|
||||||
float MC = measurement.getFloatValue("MC");
|
float MC = measurement.getFloatValue("MC");
|
||||||
float MU = measurement.getFloatValue("MU");
|
float MU = measurement.getFloatValue("MU");
|
||||||
assertThat((MU / MC) > targetMemoryUsagePercent, "Metaspace utilization should be > "
|
assertThat((MU / MC) > targetMetaspaceUsagePercent, "Metaspace utilization should be > "
|
||||||
+ (targetMemoryUsagePercent * 100) + "%, actually MU / MC = " + (MU / MC));
|
+ (targetMetaspaceUsagePercent * 100) + "%, actually MU / MC = " + (MU / MC));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (measurement.valueExists("O")) {
|
if (measurement.valueExists("O")) {
|
||||||
float O = measurement.getFloatValue("O");
|
float O = measurement.getFloatValue("O");
|
||||||
assertThat(O > targetMemoryUsagePercent * 100, "Old space utilization should be > "
|
assertThat(O > targetOldSpaceUsagePercent * 100, "Old space utilization should be > "
|
||||||
+ (targetMemoryUsagePercent * 100) + "%, actually O = " + O);
|
+ (targetOldSpaceUsagePercent * 100) + "%, actually O = " + O);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (measurement.valueExists("M")) {
|
if (measurement.valueExists("M")) {
|
||||||
float M = measurement.getFloatValue("M");
|
float M = measurement.getFloatValue("M");
|
||||||
assertThat(M > targetMemoryUsagePercent * 100, "Metaspace utilization should be > "
|
assertThat(M > targetMetaspaceUsagePercent * 100, "Metaspace utilization should be > "
|
||||||
+ (targetMemoryUsagePercent * 100) + "%, actually M = " + M);
|
+ (targetMetaspaceUsagePercent * 100) + "%, actually M = " + M);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assertThat(boolean result, String message) {
|
public static void assertThat(boolean result, String message) {
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new RuntimeException(message);
|
throw new RuntimeException(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean checkFloatIsSum(float sum, float... floats) {
|
||||||
|
for (float f : floats) {
|
||||||
|
sum -= f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.abs(sum) <= FLOAT_COMPARISON_TOLERANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract public void assertConsistency();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue