This commit is contained in:
Jesper Wilhelmsson 2017-02-12 04:49:38 +01:00
commit faf9972570
53 changed files with 1152 additions and 830 deletions

View file

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

View file

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

View file

@ -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()}.

View file

@ -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());
} }

View file

@ -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);
} }

View file

@ -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);
} }
} }

View file

@ -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);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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();
} }

View file

@ -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");

View file

@ -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();
} }

View file

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

View file

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

View file

@ -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));
} }

View file

@ -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(), "");

View file

@ -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);
} }
} }

View file

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

View file

@ -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() {

View file

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

View file

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

View file

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

View file

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

View file

@ -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());

View file

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

View file

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

View file

@ -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") \

View file

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

View file

@ -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);
} }

View file

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

View file

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

View file

@ -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);
}
}
}
}

View file

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

View file

@ -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();
} }
} }

View file

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

View file

@ -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();
}
}

View file

@ -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);
} }
} }

View file

@ -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);
} }
} }

View file

@ -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();
}
}

View file

@ -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();
} }
} }

View file

@ -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() {
}
}

View file

@ -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);
}
}
} }

View file

@ -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);
}
}
} }

View file

@ -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);
}
}
} }

View file

@ -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);
}
}
} }

View file

@ -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();
} }