--- a/hotspot/.mx.jvmci/mx_jvmci.py Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/.mx.jvmci/mx_jvmci.py Sun Feb 12 04:49:38 2017 +0100
@@ -158,8 +158,8 @@
# JDK9 must be bootstrapped with a JDK8
compliance = mx.JavaCompliance('8')
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',
- '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk8.home]
+ 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-features=graal']
mx.run(cmd, cwd=_jdkSourceRoot)
cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel]
if mx.get_opts().verbose:
@@ -176,66 +176,6 @@
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):
"""run the JDK make process for one or more configurations"""
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -850,6 +850,12 @@
#if INCLUDE_RTM_OPT
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 ((_model == CPU_MODEL_HASWELL_E3) ||
(_model == CPU_MODEL_HASWELL_E7 && _stepping < 3) ||
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java Sun Feb 12 04:49:38 2017 +0100
@@ -59,12 +59,6 @@
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
* {@link BinaryContainer#getExtLinkageGOTContainer()}.
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java Sun Feb 12 04:49:38 2017 +0100
@@ -37,6 +37,7 @@
final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
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};
public JavaCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation, BinaryContainer binaryContainer) {
@@ -79,30 +80,39 @@
}
// 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);
Symbol gotSymbol = binaryContainer.getGotSymbol(gotSymbolName);
addExternalPltToGotRelocation(binaryContainer, gotSymbol, stub.getResolveJumpOffset());
// 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);
addCodeContainerRelocation(binaryContainer, pltJmpSymbolName, stub.getResolveJumpStart(), gotStartOffset);
// 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);
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;
- 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).
String gotMoveSymbolName = relocationSymbolName("got.move", mi, call, callSiteRelocation);
- addMetaspaceGotRelocation(binaryContainer, gotMoveSymbolName, gotMetaOffset, stub.getMovOffset());
+ addExtLinkageGotContainerRelocation(binaryContainer, gotMoveSymbolName, gotMetaOffset, stub.getMovOffset());
if (isVirtualCall) {
// Nothing.
} else {
// 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);
addExtLinkageGotContainerRelocation(binaryContainer, gotC2ISymbolName, gotStartOffset + 8, stub.getC2IJumpOffset());
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java Sun Feb 12 04:49:38 2017 +0100
@@ -278,8 +278,10 @@
* {@code info} are:
*
* <pre>
- * [(int) flags, // only valid if field is resolved
- * (int) offset] // only valid if field is resolved
+ * [ flags, // fieldDescriptor::access_flags()
+ * offset, // fieldDescriptor::offset()
+ * index // fieldDescriptor::index()
+ * ]
* </pre>
*
* The behavior of this method is undefined if {@code cpi} does not denote a
@@ -288,7 +290,7 @@
* @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
*/
- 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
@@ -631,4 +633,15 @@
* {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance).
*/
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);
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java Sun Feb 12 04:49:38 2017 +0100
@@ -298,7 +298,7 @@
* @param index constant pool index
* @return constant pool entry
*/
- private long getEntryAt(int index) {
+ long getEntryAt(int index) {
assert checkBounds(index);
int offset = index * runtime().getHostJVMCIBackend().getTarget().wordSize;
return UNSAFE.getAddress(getMetaspaceConstantPool() + config().constantPoolSize + offset);
@@ -605,8 +605,6 @@
public JavaField lookupField(int cpi, ResolvedJavaMethod method, int opcode) {
final int index = rawIndexToConstantPoolIndex(cpi, opcode);
final int nameAndTypeIndex = getNameAndTypeRefIndexAt(index);
- final int nameIndex = getNameRefIndexAt(nameAndTypeIndex);
- String name = lookupUtf8(nameIndex);
final int typeIndex = getSignatureRefIndexAt(nameAndTypeIndex);
String typeName = lookupUtf8(typeIndex);
JavaType type = runtime().lookupType(typeName, getHolder(), false);
@@ -615,7 +613,7 @@
JavaType holder = lookupType(holderIndex, opcode);
if (holder instanceof HotSpotResolvedObjectTypeImpl) {
- long[] info = new long[2];
+ int[] info = new int[3];
HotSpotResolvedObjectTypeImpl resolvedHolder;
try {
resolvedHolder = compilerToVM().resolveFieldInPool(this, index, (HotSpotResolvedJavaMethodImpl) method, (byte) opcode, info);
@@ -624,14 +622,15 @@
* If there was an exception resolving the field we give up and return an unresolved
* field.
*/
- return new HotSpotUnresolvedField(holder, name, type);
+ return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
}
- final int flags = (int) info[0];
- final long offset = info[1];
- HotSpotResolvedJavaField result = resolvedHolder.createField(name, type, offset, flags);
+ final int flags = info[0];
+ final int offset = info[1];
+ final int fieldIndex = info[2];
+ HotSpotResolvedJavaField result = resolvedHolder.createField(type, offset, flags, fieldIndex);
return result;
} else {
- return new HotSpotUnresolvedField(holder, name, type);
+ return new HotSpotUnresolvedField(holder, lookupUtf8(getNameRefIndexAt(nameAndTypeIndex)), type);
}
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java Sun Feb 12 04:49:38 2017 +0100
@@ -513,10 +513,6 @@
for (Map.Entry<String, Long> e : constants.entrySet()) {
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()) {
printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java Sun Feb 12 04:49:38 2017 +0100
@@ -59,23 +59,12 @@
return res;
}
- protected String name;
-
/**
* Controls whether {@link #toString()} includes the qualified or simple name of the class in
* which the method is declared.
*/
public static final boolean FULLY_QUALIFIED_METHOD_NAME = false;
- protected HotSpotMethod(String name) {
- this.name = name;
- }
-
- @Override
- public final String getName() {
- return name;
- }
-
@Override
public final String toString() {
char h = FULLY_QUALIFIED_METHOD_NAME ? 'H' : 'h';
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java Sun Feb 12 04:49:38 2017 +0100
@@ -31,16 +31,22 @@
*/
final class HotSpotMethodUnresolved extends HotSpotMethod {
+ private final String name;
private final Signature signature;
protected JavaType holder;
HotSpotMethodUnresolved(String name, Signature signature, JavaType holder) {
- super(name);
+ this.name = name;
this.holder = holder;
this.signature = signature;
}
@Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
public Signature getSignature() {
return signature;
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,19 +38,20 @@
class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField {
private final HotSpotResolvedObjectTypeImpl holder;
- private final String name;
private JavaType type;
private final int offset;
+ private final short index;
/**
* This value contains all flags as stored in the VM including internal ones.
*/
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.name = name;
this.type = type;
+ this.index = (short) index;
+ assert this.index == index;
assert offset != -1;
assert offset == (int) offset : "offset larger than int";
this.offset = (int) offset;
@@ -67,7 +68,6 @@
if (that.offset != this.offset || that.isStatic() != this.isStatic()) {
return false;
} else if (this.holder.equals(that.holder)) {
- assert this.name.equals(that.name) && this.type.equals(that.type);
return true;
}
}
@@ -76,7 +76,7 @@
@Override
public int hashCode() {
- return name.hashCode();
+ return offset ^ modifiers;
}
@Override
@@ -109,7 +109,7 @@
@Override
public String getName() {
- return name;
+ return holder.createFieldInfo(index).getName();
}
@Override
@@ -178,18 +178,12 @@
return null;
}
- private Field toJavaCache;
-
private Field toJava() {
- if (toJavaCache != null) {
- return toJavaCache;
- }
-
if (isInternal()) {
return null;
}
try {
- return toJavaCache = holder.mirror().getDeclaredField(name);
+ return holder.mirror().getDeclaredField(getName());
} catch (NoSuchFieldException | NoClassDefFoundError e) {
return null;
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,6 +76,12 @@
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.
*
* @param metaspaceMethod a metaspace Method object
@@ -106,8 +112,6 @@
}
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.holder = holder;
@@ -126,9 +130,6 @@
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);
this.signature = (HotSpotSignature) constantPool.lookupSignature(signatureIndex);
}
@@ -147,6 +148,15 @@
}
@Override
+ public String getName() {
+ if (nameCache == null) {
+ final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset);
+ nameCache = constantPool.lookupUtf8(nameIndex);
+ }
+ return nameCache;
+ }
+
+ @Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
@@ -326,12 +336,24 @@
@Override
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
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
@@ -472,7 +494,7 @@
@Override
public Annotation[][] getParameterAnnotations() {
Executable javaMethod = toJava();
- return javaMethod == null ? null : javaMethod.getParameterAnnotations();
+ return javaMethod == null ? new Annotation[signature.getParameterCount(false)][0] : javaMethod.getParameterAnnotations();
}
@Override
@@ -513,9 +535,6 @@
}
public boolean isDefault() {
- if (isConstructor()) {
- return false;
- }
// Copied from java.lang.Method.isDefault()
int mask = Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC;
return ((getModifiers() & mask) == Modifier.PUBLIC) && getDeclaringClass().isInterface();
@@ -562,7 +581,7 @@
} else {
// Do not use Method.getDeclaredMethod() as it can return a bridge method
// 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;
return result;
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,8 +36,6 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.HashMap;
import jdk.vm.ci.common.JVMCIError;
@@ -59,12 +57,15 @@
*/
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.
*/
private final Class<?> javaClass;
- private HashMap<Long, HotSpotResolvedJavaField> fieldCache;
- private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCache;
+ private HotSpotResolvedJavaMethodImpl[] methodCacheArray;
+ private HashMap<Long, HotSpotResolvedJavaMethodImpl> methodCacheHashMap;
private HotSpotResolvedJavaField[] instanceFields;
private HotSpotResolvedObjectTypeImpl[] interfaces;
private HotSpotConstantPool constantPool;
@@ -255,7 +256,7 @@
* @return true if the type is a leaf class
*/
private boolean isLeafClass() {
- return getSubklass() == null;
+ return UNSAFE.getLong(this.getMetaspaceKlass() + config().subklassOffset) == 0;
}
/**
@@ -484,18 +485,38 @@
}
synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) {
- HotSpotResolvedJavaMethodImpl method = null;
- if (methodCache == null) {
- methodCache = new HashMap<>(8);
- } else {
- method = methodCache.get(metaspaceMethod);
+ // Maintain cache as array.
+ if (methodCacheArray == null) {
+ methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY];
}
- if (method == null) {
- method = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod);
- methodCache.put(metaspaceMethod, method);
- context.add(method);
+
+ 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;
+ }
}
- return method;
+
+ // 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 {
+ return lookupResult;
+ }
}
public int getVtableLength() {
@@ -509,37 +530,8 @@
return result;
}
- synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) {
- HotSpotResolvedJavaField result = null;
-
- 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;
+ synchronized HotSpotResolvedJavaField createField(JavaType type, long offset, int rawFlags, int index) {
+ return new HotSpotResolvedJavaFieldImpl(this, type, offset, rawFlags, index);
}
@Override
@@ -577,11 +569,15 @@
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
* {@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.
*/
@@ -666,61 +662,31 @@
}
}
- @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
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
if (instanceFields == null) {
if (isArray() || isInterface()) {
- instanceFields = new HotSpotResolvedJavaField[0];
+ instanceFields = NO_FIELDS;
} else {
- final int fieldCount = getFieldCount();
- ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount);
-
- 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);
- }
+ HotSpotResolvedJavaField[] prepend = NO_FIELDS;
+ if (getSuperclass() != null) {
+ prepend = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true);
}
-
- 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;
- }
-
+ instanceFields = getFields(false, prepend);
}
}
- if (!includeSuperclasses) {
- int myFieldsStart = 0;
- while (myFieldsStart < instanceFields.length && !instanceFields[myFieldsStart].getDeclaringClass().equals(this)) {
- myFieldsStart++;
+ if (!includeSuperclasses && getSuperclass() != null) {
+ int superClassFieldCount = getSuperclass().getInstanceFields(true).length;
+ if (superClassFieldCount == instanceFields.length) {
+ // 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;
}
@@ -730,45 +696,63 @@
if (isArray()) {
return new HotSpotResolvedJavaField[0];
} else {
- final int fieldCount = getFieldCount();
- 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()]);
+ return getFields(true, NO_FIELDS);
}
}
/**
- * Returns the actual field count of this class's internal {@code InstanceKlass::_fields} array
- * by walking the array and discounting the generic signature slots at the end of the array.
+ * Gets the instance or static fields of this class.
*
- * <p>
- * See {@code FieldStreamBase::init_generic_signature_start_slot}
+ * @param retrieveStaticFields specifies whether to return instance or static fields
+ * @param prepend an array to be prepended to the returned result
*/
- private int getFieldCount() {
+ private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSpotResolvedJavaField[] prepend) {
HotSpotVMConfig config = config();
final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset);
int metaspaceFieldsLength = UNSAFE.getInt(metaspaceFields + config.arrayU1LengthOffset);
- int fieldCount = 0;
-
- for (int i = 0, index = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
+ int resultCount = 0;
+ int index = 0;
+ for (int i = 0; i < metaspaceFieldsLength; i += config.fieldInfoFieldSlots, index++) {
FieldInfo field = new FieldInfo(index);
if (field.hasGenericSignature()) {
metaspaceFieldsLength--;
}
- fieldCount++;
+
+ if (field.isStatic() == retrieveStaticFields) {
+ resultCount++;
+ }
+ }
+
+ 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);
}
- return fieldCount;
+
+ 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
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java Sun Feb 12 04:49:38 2017 +0100
@@ -85,7 +85,7 @@
final int klassLayoutHelperNeutralValue = getConstant("Klass::_lh_neutral_value", 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 instanceKlassSourceFileNameIndexOffset = getFieldOffset("InstanceKlass::_source_file_name_index", Integer.class, "u2");
@@ -192,20 +192,20 @@
final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_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 exceptionTableElementEndPcOffset = getFieldOffset("ExceptionTableElement::end_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 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 localVariableTableElementLengthOffset = getFieldOffset("LocalVariableTableElement::length", 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 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 constantPoolHolderOffset = getFieldOffset("ConstantPool::_pool_holder", Integer.class, "InstanceKlass*");
final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length", Integer.class, "int");
@@ -237,12 +237,15 @@
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 int vmSymbolsFirstSID = getConstant("vmSymbols::FIRST_SID", 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
* {@link String}.
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java Sun Feb 12 04:49:38 2017 +0100
@@ -67,21 +67,6 @@
}
/**
- * 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.
*
* @param name name of the constant (e.g., {@code "frame::arg_reg_save_area_bytes"})
@@ -291,13 +276,24 @@
*/
public <T> T getFlag(String name, Class<T> type, T notPresent) {
VMFlag entry = store.vmFlags.get(name);
+ Object value;
+ String cppType;
if (entry == null) {
- if (notPresent != null) {
- return notPresent;
+ // Fall back to VM call
+ 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 {
@@ -319,6 +315,10 @@
} else if (value instanceof Long) {
return (int) (long) value;
}
+ } else if (toType == String.class) {
+ if (value == null || value instanceof String) {
+ return value;
+ }
} else if (toType == Long.class) {
return value;
}
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java Sun Feb 12 04:49:38 2017 +0100
@@ -47,15 +47,6 @@
}
/**
- * 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.
*
* @return an unmodifiable map from the names of C++ constants to their values
@@ -90,11 +81,11 @@
}
final HashMap<String, VMField> vmFields;
- final HashMap<String, Long> vmTypeSizes;
final HashMap<String, Long> vmConstants;
final HashMap<String, Long> vmAddresses;
final HashMap<String, VMFlag> vmFlags;
final List<VMIntrinsicMethod> vmIntrinsics;
+ final CompilerToVM compilerToVm;
/**
* Reads the database of VM info. The return value encodes the info in a nested object array
@@ -103,7 +94,6 @@
* <pre>
* info = [
* VMField[] vmFields,
- * [String name, Long size, ...] vmTypeSizes,
* [String name, Long value, ...] vmConstants,
* [String name, Long value, ...] vmAddresses,
* VMFlag[] vmFlags
@@ -113,25 +103,24 @@
*/
@SuppressWarnings("try")
HotSpotVMConfigStore(CompilerToVM compilerToVm) {
+ this.compilerToVm = compilerToVm;
Object[] data;
try (InitTimer t = timer("CompilerToVm readConfiguration")) {
data = compilerToVm.readConfiguration();
}
- assert data.length == 6 : data.length;
+ assert data.length == 5 : data.length;
// @formatter:off
VMField[] vmFieldsInfo = (VMField[]) data[0];
- Object[] vmTypesSizesInfo = (Object[]) data[1];
- Object[] vmConstantsInfo = (Object[]) data[2];
- Object[] vmAddressesInfo = (Object[]) data[3];
- VMFlag[] vmFlagsInfo = (VMFlag[]) data[4];
+ Object[] vmConstantsInfo = (Object[]) data[1];
+ Object[] vmAddressesInfo = (Object[]) data[2];
+ VMFlag[] vmFlagsInfo = (VMFlag[]) data[3];
vmFields = new HashMap<>(vmFieldsInfo.length);
- vmTypeSizes = new HashMap<>(vmTypesSizesInfo.length);
vmConstants = new HashMap<>(vmConstantsInfo.length);
vmAddresses = new HashMap<>(vmAddressesInfo.length);
vmFlags = new HashMap<>(vmFlagsInfo.length);
- vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[5]);
+ vmIntrinsics = Arrays.asList((VMIntrinsicMethod[]) data[4]);
// @formatter:on
try (InitTimer t = timer("HotSpotVMConfigStore<init> fill maps")) {
@@ -139,12 +128,6 @@
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++) {
String name = (String) vmConstantsInfo[i * 2];
Long value = (Long) vmConstantsInfo[i * 2 + 1];
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -497,9 +497,8 @@
}
@Override
- public Value emitLoadConfigValue(int markId) {
- // Globals are always full-pointer width.
- Variable result = newVariable(LIRKind.value(target().arch.getWordKind()));
+ public Value emitLoadConfigValue(int markId, LIRKind kind) {
+ Variable result = newVariable(kind);
append(new AMD64HotSpotLoadConfigValueOp(markId, result));
return result;
}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,12 @@
import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
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 org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.lir.LIRInstructionClass;
@@ -48,7 +52,25 @@
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
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 {
throw GraalError.unimplemented();
}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java Sun Feb 12 04:49:38 2017 +0100
@@ -244,7 +244,7 @@
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 int narrowKlassShift = getFieldValue("CompilerToVM::Data::Universe_narrow_klass_shift", Integer.class, "int");
public final int logKlassAlignment = getConstant("LogKlassAlignmentInBytes", Integer.class);
@@ -290,7 +290,7 @@
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 instanceKlassInitStateOffset = getFieldOffset("InstanceKlass::_init_state", Integer.class, "u1");
@@ -302,7 +302,7 @@
public final int instanceKlassStateLinked = getConstant("InstanceKlass::linked", 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.
@@ -496,7 +496,7 @@
public final int compilationLevelFullOptimization = getConstant("CompLevel_full_optimization",
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",
Integer.class, "int");
@@ -553,7 +553,7 @@
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 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 threadAllocatedBytesOffset = getFieldOffset("Thread::_allocated_bytes", Integer.class, "jlong");
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java Sun Feb 12 04:49:38 2017 +0100
@@ -22,6 +22,7 @@
*/
package org.graalvm.compiler.hotspot;
+import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -141,10 +142,10 @@
/**
* 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
*/
- @SuppressWarnings("unused")
default Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) {
throw GraalError.unimplemented();
}
@@ -152,21 +153,23 @@
/**
* 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
*/
- default Value emitLoadConfigValue(int markId) {
+ default Value emitLoadConfigValue(int markId, LIRKind kind) {
throw GraalError.unimplemented();
}
/**
* 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
* 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.
*/
- @SuppressWarnings("unused")
default Value emitObjectConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
throw GraalError.unimplemented();
}
@@ -174,11 +177,12 @@
/**
* Emits code for a {@link ResolveConstantNode} to resolve a {@link HotSpotMetaspaceConstant}.
*
+ * @param constant original constant
* @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant}
* generated by {@link EncodedSymbolConstant}
+ * @param frameState frame state for the runtime call
* @return Returns the address of the requested constant.
*/
- @SuppressWarnings("unused")
default Value emitMetaspaceConstantRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
throw GraalError.unimplemented();
}
@@ -188,12 +192,13 @@
* {@link HotSpotMetaspaceConstant} that represents a {@link ResolvedJavaMethod} and return the
* corresponding MethodCounters object.
*
+ * @param method original constant
* @param klassHint a klass in which the method is declared
* @param methodDescription is symbolic description of the constant generated by
* {@link EncodedSymbolConstant}
+ * @param frameState frame state for the runtime call
* @return Returns the address of the requested constant.
*/
- @SuppressWarnings("unused")
default Value emitResolveMethodAndLoadCounters(Constant method, Value klassHint, Value methodDescription, LIRFrameState frameState) {
throw GraalError.unimplemented();
}
@@ -202,11 +207,13 @@
* Emits code for a {@link ResolveConstantNode} to resolve a klass
* {@link HotSpotMetaspaceConstant} and run static initializer.
*
+ *
+ * @param constant original constant
* @param constantDescription a symbolic description of the {@link HotSpotMetaspaceConstant}
* generated by {@link EncodedSymbolConstant}
+ * @param frameState frame state for the runtime call
* @return Returns the address of the requested constant.
*/
- @SuppressWarnings("unused")
default Value emitKlassInitializationAndRetrieval(Constant constant, Value constantDescription, LIRFrameState frameState) {
throw GraalError.unimplemented();
}
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -55,62 +55,86 @@
private final GraalHotSpotVMConfig config;
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) {
super(TYPE, StampFactory.forKind(kind));
this.config = config;
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
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);
}
@NodeIntrinsic
- private static native boolean isConfigValueConstant(@ConstantNodeParameter int markId);
+ private static native boolean areConfigValuesConstant();
+
+ @NodeIntrinsic(setStampFromReturnType = true)
+ private static native long loadLongConfigValue(@ConstantNodeParameter int markId);
- @NodeIntrinsic
- private static native long loadConfigValue(@ConstantNodeParameter int markId, @ConstantNodeParameter JavaKind kind);
+ @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() {
- return loadConfigValue(cardTableAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
+ return loadLongConfigValue(cardTableAddressMark(INJECTED_VMCONFIG));
}
public static boolean isCardTableAddressConstant() {
- return isConfigValueConstant(cardTableAddressMark(INJECTED_VMCONFIG));
+ return areConfigValuesConstant();
}
public static long heapTopAddress() {
- return loadConfigValue(heapTopAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
+ return loadLongConfigValue(heapTopAddressMark(INJECTED_VMCONFIG));
}
public static long heapEndAddress() {
- return loadConfigValue(heapEndAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
+ return loadLongConfigValue(heapEndAddressMark(INJECTED_VMCONFIG));
}
public static long crcTableAddress() {
- return loadConfigValue(crcTableAddressMark(INJECTED_VMCONFIG), JavaKind.Long);
+ return loadLongConfigValue(crcTableAddressMark(INJECTED_VMCONFIG));
}
public static int logOfHeapRegionGrainBytes() {
- return (int) loadConfigValue(logOfHeapRegionGrainBytesMark(INJECTED_VMCONFIG), JavaKind.Byte);
+ return loadIntConfigValue(logOfHeapRegionGrainBytesMark(INJECTED_VMCONFIG));
}
public static boolean inlineContiguousAllocationSupported() {
- return loadConfigValue(inlineContiguousAllocationSupportedMark(INJECTED_VMCONFIG), JavaKind.Byte) > 0;
+ return loadByteConfigValue(inlineContiguousAllocationSupportedMark(INJECTED_VMCONFIG)) != 0;
}
@Fold
--- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -830,38 +830,19 @@
}
}
-// Yes, this is faster than going through the relocations,
-// but there are two problems:
-// 1) GOT slots are sometimes patched with non-Metadata values
-// 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.
+// Scan only metaspace_got cells which should have only Klass*,
+// metadata_got cells are scanned only for alive AOT methods
+// by AOTCompiledMethod::metadata_do().
void AOTCodeHeap::got_metadata_do(void f(Metadata*)) {
for (int i = 1; i < _metaspace_got_size; i++) {
Metadata** p = &_metaspace_got[i];
Metadata* md = *p;
if (md == NULL) continue; // skip non-oops
- intptr_t meta = (intptr_t)md;
- if (meta == -1) continue; // skip non-oops
if (Metaspace::contains(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 {
- continue;
- }
- if (md == NULL) continue; // skip non-oops
- if (Metaspace::contains(md)) {
- f(md);
+ intptr_t meta = (intptr_t)md;
+ fatal("Invalid value in _metaspace_got[%d] = " INTPTR_FORMAT, i, meta);
}
}
}
@@ -910,8 +891,6 @@
aot->metadata_do(f);
}
}
-#if 0
- // With the marking above, this call doesn't seem to be needed
+ // Scan metaspace_got cells.
got_metadata_do(f);
-#endif
}
--- a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -71,15 +71,6 @@
}
#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) {
return false;
}
@@ -161,9 +152,6 @@
*entry = (Metadata*)meta; // Should be atomic on x64
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;
}
@@ -288,11 +276,19 @@
f(cichk->holder_method());
f(cichk->holder_klass());
} else {
+ // Get Klass* or NULL (if value is -1) from GOT cell of virtual call PLT stub.
Metadata* ic_oop = ic->cached_metadata();
if (ic_oop != NULL) {
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 @@
st->print("%4d ", _aot_id); // print compilation number
st->print(" aot[%2d]", _heap->dso_id());
// 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) {
st->print(" entry at " INTPTR_FORMAT, p2i(_code));
}
--- a/hotspot/src/share/vm/aot/aotCompiledMethod.hpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp Sun Feb 12 04:49:38 2017 +0100
@@ -257,8 +257,6 @@
return (int) (*_state_adr);
}
- virtual void oops_do(OopClosure* f);
-
// inlined and non-virtual for AOTCodeHeap::oops_do
void do_oops(OopClosure* f) {
assert(_is_alive(), "");
--- a/hotspot/src/share/vm/ci/ciEnv.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -704,16 +704,17 @@
//
// Perform an appropriate method lookup based on accessor, holder,
// name, signature, and bytecode.
-Method* ciEnv::lookup_method(InstanceKlass* accessor,
- InstanceKlass* holder,
- Symbol* name,
- Symbol* sig,
- Bytecodes::Code bc,
- constantTag tag) {
- EXCEPTION_CONTEXT;
- KlassHandle h_accessor(THREAD, accessor);
- KlassHandle h_holder(THREAD, holder);
- LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
+Method* ciEnv::lookup_method(ciInstanceKlass* accessor,
+ ciKlass* holder,
+ Symbol* name,
+ Symbol* sig,
+ Bytecodes::Code bc,
+ constantTag tag) {
+ // Accessibility checks are performed in ciEnv::get_method_by_index_impl.
+ assert(check_klass_accessibility(accessor, holder->get_Klass()), "holder not accessible");
+
+ KlassHandle h_accessor(accessor->get_instanceKlass());
+ KlassHandle h_holder(holder->get_Klass());
methodHandle dest_method;
LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
switch (bc) {
@@ -772,7 +773,6 @@
const int holder_index = cpool->klass_ref_index_at(index);
bool holder_is_accessible;
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.
Symbol* name_sym = cpool->name_ref_at(index);
@@ -800,10 +800,9 @@
}
if (holder_is_accessible) { // Our declared holder is loaded.
- InstanceKlass* lookup = declared_holder->get_instanceKlass();
constantTag tag = cpool->tag_ref_at(index);
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 &&
(bc == Bytecodes::_invokestatic
? m->method_holder()->is_not_initialized()
@@ -826,7 +825,7 @@
// lookup.
ciSymbol* name = get_symbol(name_sym);
ciSymbol* signature = get_symbol(sig_sym);
- return get_unloaded_method(declared_holder, name, signature, accessor);
+ return get_unloaded_method(holder, name, signature, accessor);
}
}
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp Sun Feb 12 04:49:38 2017 +0100
@@ -153,12 +153,12 @@
// Helper methods
bool check_klass_accessibility(ciKlass* accessing_klass,
Klass* resolved_klass);
- Method* lookup_method(InstanceKlass* accessor,
- InstanceKlass* holder,
- Symbol* name,
- Symbol* sig,
- Bytecodes::Code bc,
- constantTag tag);
+ Method* lookup_method(ciInstanceKlass* accessor,
+ ciKlass* holder,
+ Symbol* name,
+ Symbol* sig,
+ Bytecodes::Code bc,
+ constantTag tag);
// Get a ciObject from the object factory. Ensures uniqueness
// of ciObjects.
@@ -227,11 +227,12 @@
// Get a ciMethod representing either an unfound method or
// a method with an unloaded holder. Ensures uniqueness of
// the result.
- ciMethod* get_unloaded_method(ciInstanceKlass* holder,
+ ciMethod* get_unloaded_method(ciKlass* holder,
ciSymbol* name,
ciSymbol* signature,
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.
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -53,6 +53,7 @@
#include "runtime/vframe.hpp"
#include "runtime/vframe_hp.hpp"
#include "runtime/vmStructs.hpp"
+#include "utilities/resourceHash.hpp"
// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
@@ -120,6 +121,15 @@
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::dcos;
address CompilerToVM::Data::dtan;
@@ -128,7 +138,10 @@
address CompilerToVM::Data::dlog10;
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_length_offset = in_bytes(Klass::vtable_length_offset());
@@ -160,6 +173,9 @@
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");
+ symbol_init = (address) vmSymbols::object_initializer_name();
+ symbol_clinit = (address) vmSymbols::class_initializer_name();
+
BarrierSet* bs = Universe::heap()->barrier_set();
switch (bs->kind()) {
case BarrierSet::CardTableModRef:
@@ -179,7 +195,7 @@
// No post barriers
break;
default:
- ShouldNotReachHere();
+ JVMCI_ERROR("Unsupported BarrierSet kind %d", bs->kind());
break;
}
@@ -237,13 +253,114 @@
return vmIntrinsics;
}
+/**
+ * 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_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))
-#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)
-#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)
ResourceMark rm;
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);
VMFlag::klass()->initialize(CHECK_NULL);
@@ -257,31 +374,31 @@
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);
sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName);
- Handle name = java_lang_String::create_from_str(name_buf, CHECK_NULL);
- Handle type = java_lang_String::create_from_str(vmField.typeString, CHECK_NULL);
+ CSTRING_TO_JSTRING(name, name_buf);
+ CSTRING_TO_JSTRING(type, vmField.typeString);
VMField::set_name(vmFieldObj, name());
VMField::set_type(vmFieldObj, type());
VMField::set_offset(vmFieldObj, vmField.offset);
VMField::set_address(vmFieldObj, (jlong) vmField.address);
- if (vmField.isStatic) {
+ if (vmField.isStatic && vmField.typeString != NULL) {
if (strcmp(vmField.typeString, "bool") == 0) {
- BOXED_LONG(value, *(jbyte*) vmField.address);
- VMField::set_value(vmFieldObj, value);
+ BOXED_BOOLEAN(box, *(jbyte*) vmField.address);
+ VMField::set_value(vmFieldObj, box);
} else if (strcmp(vmField.typeString, "int") == 0 ||
strcmp(vmField.typeString, "jint") == 0) {
- BOXED_LONG(value, *(jint*) vmField.address);
- VMField::set_value(vmFieldObj, value);
+ BOXED_LONG(box, *(jint*) vmField.address);
+ VMField::set_value(vmFieldObj, box);
} else if (strcmp(vmField.typeString, "uint64_t") == 0) {
- BOXED_LONG(value, *(uint64_t*) vmField.address);
- VMField::set_value(vmFieldObj, value);
+ BOXED_LONG(box, *(uint64_t*) vmField.address);
+ VMField::set_value(vmFieldObj, box);
} else if (strcmp(vmField.typeString, "address") == 0 ||
strcmp(vmField.typeString, "intptr_t") == 0 ||
strcmp(vmField.typeString, "uintptr_t") == 0 ||
strcmp(vmField.typeString, "size_t") == 0 ||
// All foo* types are addresses.
vmField.typeString[strlen(vmField.typeString) - 1] == '*') {
- BOXED_LONG(value, *((address*) vmField.address));
- VMField::set_value(vmFieldObj, value);
+ BOXED_LONG(box, *((address*) vmField.address));
+ VMField::set_value(vmFieldObj, box);
} else {
JVMCI_ERROR_NULL("VM field %s has unsupported type %s", name_buf, vmField.typeString);
}
@@ -289,16 +406,6 @@
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 longs_len = JVMCIVMStructs::localHotSpotVMLongConstants_count();
len = ints_len + longs_len;
@@ -306,14 +413,14 @@
int insert = 0;
for (int i = 0; i < ints_len ; 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);
vmConstants->obj_at_put(insert++, name());
vmConstants->obj_at_put(insert++, value);
}
for (int i = 0; i < longs_len ; 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);
vmConstants->obj_at_put(insert++, name());
vmConstants->obj_at_put(insert++, value);
@@ -324,69 +431,104 @@
objArrayHandle vmAddresses = oopFactory::new_objArray(SystemDictionary::Object_klass(), len * 2, CHECK_NULL);
for (int i = 0; i < len ; 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);
vmAddresses->obj_at_put(i * 2, name());
vmAddresses->obj_at_put(i * 2 + 1, value);
}
- // The last entry is the null entry.
- len = (int) Flag::numFlags - 1;
+#define COUNT_FLAG(ignore) +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);
- for (int i = 0; i < len; i++) {
- Flag* flag = &Flag::flags[i];
- 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());
- }
+ int i = 0;
+ PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG)
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(1, vmTypes());
- data->obj_at_put(2, vmConstants());
- data->obj_at_put(3, vmAddresses());
- data->obj_at_put(4, vmFlags());
- data->obj_at_put(5, vmIntrinsics());
+ data->obj_at_put(1, vmConstants());
+ data->obj_at_put(2, vmAddresses());
+ data->obj_at_put(3, vmFlags());
+ data->obj_at_put(4, vmIntrinsics());
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_DOUBLE
-C2V_END
+#undef CSTRING_TO_JSTRING
C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv *, jobject, jobject jvmci_method))
methodHandle method = CompilerToVM::asMethod(jvmci_method);
@@ -743,7 +885,7 @@
return cp->remap_instruction_operand_from_cache(index);
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;
constantPoolHandle cp = CompilerToVM::asConstantPool(jvmci_constant_pool);
Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
@@ -751,9 +893,12 @@
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);
typeArrayOop info = (typeArrayOop) JNIHandles::resolve(info_handle);
- assert(info != NULL && info->length() == 2, "must be");
- info->long_at_put(0, (jlong) fd.access_flags().as_int());
- info->long_at_put(1, (jlong) fd.offset());
+ if (info == NULL || info->length() != 3) {
+ JVMCI_ERROR_NULL("info must not be null and have a length of 3");
+ }
+ 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);
return JNIHandles::make_local(THREAD, field_holder);
C2V_END
@@ -1610,7 +1755,7 @@
{CC "resolveConstantInPool", CC "(" HS_CONSTANT_POOL "I)" OBJECT, FN_PTR(resolveConstantInPool)},
{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 "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 "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)},
@@ -1648,6 +1793,7 @@
{CC "getFingerprint", CC "(J)J", FN_PTR(getFingerprint)},
{CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)},
{CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)},
+ {CC "getFlagValue", CC "(" STRING ")" OBJECT, FN_PTR(getFlagValue)},
};
int CompilerToVM::methods_count() {
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp Sun Feb 12 04:49:38 2017 +0100
@@ -66,6 +66,15 @@
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 dcos;
static address dtan;
@@ -74,8 +83,11 @@
static address dlog10;
static address dpow;
+ static address symbol_init;
+ static address symbol_clinit;
+
public:
- static void initialize();
+ static void initialize(TRAPS);
static int max_oop_map_stack_offset() {
assert(_max_oop_map_stack_offset > 0, "must be initialized");
@@ -83,6 +95,20 @@
}
};
+ 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 objArrayHandle initialize_intrinsics(TRAPS);
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -283,13 +283,14 @@
// Perform an appropriate method lookup based on accessor, holder,
// name, signature, and bytecode.
methodHandle JVMCIEnv::lookup_method(instanceKlassHandle h_accessor,
- instanceKlassHandle h_holder,
+ KlassHandle h_holder,
Symbol* name,
Symbol* sig,
Bytecodes::Code bc,
constantTag tag) {
- JVMCI_EXCEPTION_CONTEXT;
- LinkResolver::check_klass_accessability(h_accessor, h_holder, KILL_COMPILE_ON_FATAL_(NULL));
+ // Accessibility checks are performed in JVMCIEnv::get_method_by_index_impl().
+ assert(check_klass_accessibility(h_accessor, h_holder), "holder not accessible");
+
methodHandle dest_method;
LinkInfo link_info(h_holder, name, sig, h_accessor, LinkInfo::needs_access_check, tag);
switch (bc) {
@@ -363,9 +364,8 @@
}
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);
- 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() &&
(bc == Bytecodes::_invokestatic
? InstanceKlass::cast(m->method_holder())->is_not_initialized()
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp Sun Feb 12 04:49:38 2017 +0100
@@ -127,7 +127,7 @@
// Helper methods
static bool check_klass_accessibility(KlassHandle accessing_klass, KlassHandle resolved_klass);
static methodHandle lookup_method(instanceKlassHandle accessor,
- instanceKlassHandle holder,
+ KlassHandle holder,
Symbol* name,
Symbol* sig,
Bytecodes::Code bc,
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -78,6 +78,15 @@
\
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, dcos, address) \
static_field(CompilerToVM::Data, dtan, address) \
@@ -86,6 +95,9 @@
static_field(CompilerToVM::Data, dlog10, 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) \
\
nonstatic_field(Array<int>, _length, int) \
@@ -293,7 +305,6 @@
static_field(StubRoutines, _crc32c_table_addr, address) \
static_field(StubRoutines, _updateBytesCRC32C, address) \
static_field(StubRoutines, _updateBytesAdler32, address) \
- static_field(StubRoutines, _multiplyToLen, address) \
static_field(StubRoutines, _squareToLen, address) \
static_field(StubRoutines, _mulAdd, address) \
static_field(StubRoutines, _montgomeryMultiply, address) \
--- a/hotspot/src/share/vm/opto/cfgnode.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -1889,6 +1889,12 @@
bool saw_self = false;
for( uint i=1; i<req(); ++i ) {// For all paths in
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()) {
MergeMemNode* n = ii->as_MergeMem();
merge_width = MAX2(merge_width, n->req());
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -1894,6 +1894,11 @@
if (FLAG_IS_DEFAULT(NewSizeThreadIncrease)) {
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)) {
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
}
@@ -2506,8 +2511,8 @@
}
#endif
}
+
#if INCLUDE_JVMCI
-
status = status && check_jvmci_args_consistency();
if (EnableJVMCI) {
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Sun Feb 12 04:49:38 2017 +0100
@@ -221,8 +221,9 @@
// It is not guaranteed that we can get such information here only
// by analyzing bytecode in deoptimized frames. This is why this flag
// is set during method compilation (see Compile::Process_OopMap_Node()).
- // If the previous frame was popped, we don't have a result.
- bool save_oop_result = chunk->at(0)->scope()->return_oop() && !thread->popframe_forcing_deopt_reexecution();
+ // If the previous frame was popped or if we are dispatching an exception,
+ // 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;
if (save_oop_result) {
// Reallocation may trigger GC. If deoptimization happened on return from
@@ -1596,9 +1597,9 @@
get_method_data(thread, profiled_method, create_if_missing);
// 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_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.
if (TraceDeoptimization || LogCompilation) {
@@ -1812,7 +1813,7 @@
// aggressive optimization.
bool inc_recompile_count = false;
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");
uint this_trap_count = 0;
bool maybe_prior_trap = false;
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/src/share/vm/runtime/globals.hpp Sun Feb 12 04:49:38 2017 +0100
@@ -657,14 +657,13 @@
range(0, 99) \
\
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, \
- "Control whether FMA instructions can be used") \
+ "Control whether FMA instructions are used when available") \
\
product(bool, UseSHA, false, \
- "Control whether SHA instructions can be used " \
- "on SPARC, on ARM and on x86") \
+ "Control whether SHA instructions are used when available") \
\
diagnostic(bool, UseGHASHIntrinsics, false, \
"Use intrinsics for GHASH versions of crypto") \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java Sun Feb 12 04:49:38 2017 +0100
@@ -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 {
+}
+
--- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java Sun Feb 12 04:49:38 2017 +0100
@@ -48,6 +48,10 @@
return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method);
}
+ public static Object getFlagValue(String name) {
+ return CTVM.getFlagValue(name);
+ }
+
public static boolean isCompilable(HotSpotResolvedJavaMethod method) {
return CTVM.isCompilable((HotSpotResolvedJavaMethodImpl)method);
}
@@ -128,7 +132,7 @@
}
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);
}
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java Sun Feb 12 04:49:38 2017 +0100
@@ -202,13 +202,13 @@
public final String type;
public final ResolvedJavaMethod[] methods;
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);
}
- 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.name = name;
this.type = type;
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java Sun Feb 12 04:49:38 2017 +0100
@@ -206,7 +206,7 @@
"stringFieldEmpty",
"Ljava/lang/String;",
new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
- 0L),
+ 0),
}
);
CP_MAP_FOR_CLASS.put(CONSTANT_METHODREF,
@@ -362,7 +362,7 @@
"stringFieldEmpty",
"Ljava/lang/String;",
new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
- 0L),
+ 0),
}
);
CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODREF,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetFlagValueTest.java Sun Feb 12 04:49:38 2017 +0100
@@ -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);
+ }
+ }
+ }
+}
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java Sun Feb 12 04:49:38 2017 +0100
@@ -103,7 +103,7 @@
cached = "cached ";
}
for (int j = 0; j < entry.opcodes.length; j++) {
- long[] info = new long[2];
+ int[] info = new int[3];
HotSpotResolvedObjectType fieldToVerify
= CompilerToVMHelper.resolveFieldInPool(constantPoolCTVM,
index,
@@ -147,11 +147,11 @@
} catch (Exception ex) {
throw new Error("Unexpected exception", ex);
}
- long offsetToRefer;
+ int offsetToRefer;
if ((entry.accFlags & Opcodes.ACC_STATIC) != 0) {
- offsetToRefer = UNSAFE.staticFieldOffset(fieldToRefer);
+ offsetToRefer = (int) UNSAFE.staticFieldOffset(fieldToRefer);
} else {
- offsetToRefer = UNSAFE.objectFieldOffset(fieldToRefer);
+ offsetToRefer = (int) UNSAFE.objectFieldOffset(fieldToRefer);
}
msg = String.format("Field offset returned by resolveFieldInPool"
+ " method is wrong for the field %s.%s"
--- a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java Sun Feb 12 04:49:38 2017 +0100
@@ -30,6 +30,6 @@
public class SupportedVM implements BooleanSupplier {
@Override
public boolean getAsBoolean() {
- return Platform.isServer();
+ return Platform.isServer() && !Platform.isEmulatedClient();
}
}
--- a/hotspot/test/compiler/types/correctness/OffTest.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/compiler/types/correctness/OffTest.java Sun Feb 12 04:49:38 2017 +0100
@@ -24,6 +24,7 @@
/*
* @test CorrectnessTest
* @bug 8038418
+ * @requires vm.flavor == "server" & !vm.emulatedClient
* @library /test/lib /
* @modules java.base/jdk.internal.misc
* java.management
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/tmtools/jstat/GarbageProducerTest.java Sun Feb 12 04:49:38 2017 +0100
@@ -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();
+ }
+}
--- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,39 +25,19 @@
* @test
* @summary Test checks output displayed with jstat -gccause.
* Test scenario:
- * tests forces debuggee application eat ~70% of heap and runs jstat.
- * jstat should show that ~70% of heap (OC/OU ~= 70%).
+ * test forces debuggee application eat ~70% of heap and runs jstat.
+ * jstat should show actual usage of old gen (OC/OU ~= old gen usage).
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
* @modules java.base/jdk.internal.misc
* @library /test/lib
* @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.*;
public class GcCauseTest02 {
- private final static float targetMemoryUsagePercent = 0.7f;
-
public static void main(String[] args) throws Exception {
-
- // 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);
+ new GarbageProducerTest(new JstatGcCauseTool(ProcessHandle.current().getPid())).run();
}
}
--- a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,43 +21,23 @@
* questions.
*/
-import utils.*;
/*
* @test
* @summary Test checks output displayed with jstat -gc.
* Test scenario:
- * tests forces debuggee application eat ~70% of heap and runs jstat.
- * jstat should show that ~70% of heap is utilized (OC/OU ~= 70%).
+ * test forces debuggee application eat ~70% of heap and runs jstat.
+ * jstat should show actual usage of old gen (OC/OU ~= old gen usage).
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
* @modules java.base/jdk.internal.misc
* @library /test/lib
* @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 {
- private final static float targetMemoryUsagePercent = 0.7f;
-
public static void main(String[] args) throws Exception {
-
- // 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);
+ new GarbageProducerTest(new JstatGcTool(ProcessHandle.current().getPid())).run();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/GarbageProducer.java Sun Feb 12 04:49:38 2017 +0100
@@ -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();
+ }
+}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,9 +22,6 @@
*/
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;
@@ -36,11 +33,7 @@
public class GcProvoker{
// Uses fixed small objects to avoid Humongous objects allocation in G1
- public 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 static final int MEMORY_CHUNK = 2048;
private final Runtime runtime;
@@ -61,21 +54,6 @@
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
*/
@@ -93,65 +71,7 @@
}
}
- /**
- * 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() {
runtime = Runtime.getRuntime();
}
-
}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java Thu Feb 09 23:35:22 2017 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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() {
- }
-
-}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,6 +62,7 @@
/**
* Checks the overall consistency of the results reported by the tool
*/
+ @Override
public void assertConsistency() {
// Check exit code
@@ -117,8 +118,6 @@
float MC = getFloatValue("MC");
assertThat(MC >= MCMN, "MC < MCMN (generation capacity < min generation capacity)");
assertThat(MC <= MCMX, "MGC > MCMX (generation capacity > max generation capacity)");
-
-
}
/**
@@ -139,21 +138,4 @@
}
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);
- }
- }
-
}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -56,6 +56,7 @@
/**
* Checks the overall consistency of the results reported by the tool
*/
+ @Override
public void assertConsistency() {
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
@@ -83,21 +84,4 @@
assertThat(checkFloatIsSum(GCT, YGCT, FGCT), "GCT != (YGCT + FGCT) " + "(GCT = " + GCT + ", YGCT = " + YGCT
+ ", 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);
- }
- }
-
}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,6 +54,7 @@
/**
* Checks the overall consistency of the results reported by the tool
*/
+ @Override
public void assertConsistency() {
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
@@ -84,10 +85,4 @@
int MTT = getIntValue("MTT");
assertThat(TT <= MTT, "TT > MTT (tenuring threshold > maximum tenuring threshold)");
}
-
- private void assertThat(boolean b, String message) {
- if (!b) {
- throw new RuntimeException(message);
- }
- }
}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,6 +61,7 @@
/**
* Checks the overall consistency of the results reported by the tool
*/
+ @Override
public void assertConsistency() {
assertThat(getExitCode() == 0, "Unexpected exit code: " + getExitCode());
@@ -112,21 +113,4 @@
assertThat(checkFloatIsSum(GCT, YGCT, FGCT), "GCT != (YGCT + FGCT) " + "(GCT = " + GCT + ", YGCT = " + YGCT
+ ", 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);
- }
- }
-
}
--- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java Thu Feb 09 23:35:22 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java Sun Feb 12 04:49:38 2017 +0100
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,8 @@
*/
abstract public class JstatResults extends ToolResults {
+ private static final float FLOAT_COMPARISON_TOLERANCE = 0.0011f;
+
public JstatResults(ToolResults rawResults) {
super(rawResults);
}
@@ -110,38 +112,61 @@
* space has been utilized
*/
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")) {
float OC = measurement.getFloatValue("OC");
float OU = measurement.getFloatValue("OU");
- assertThat((OU / OC) > targetMemoryUsagePercent, "Old space utilization should be > "
- + (targetMemoryUsagePercent * 100) + "%, actually OU / OC = " + (OU / OC));
+ assertThat((OU / OC) > targetOldSpaceUsagePercent, "Old space utilization should be > "
+ + (targetOldSpaceUsagePercent * 100) + "%, actually OU / OC = " + (OU / OC));
}
if (measurement.valueExists("MU")) {
float MC = measurement.getFloatValue("MC");
float MU = measurement.getFloatValue("MU");
- assertThat((MU / MC) > targetMemoryUsagePercent, "Metaspace utilization should be > "
- + (targetMemoryUsagePercent * 100) + "%, actually MU / MC = " + (MU / MC));
+ assertThat((MU / MC) > targetMetaspaceUsagePercent, "Metaspace utilization should be > "
+ + (targetMetaspaceUsagePercent * 100) + "%, actually MU / MC = " + (MU / MC));
}
if (measurement.valueExists("O")) {
float O = measurement.getFloatValue("O");
- assertThat(O > targetMemoryUsagePercent * 100, "Old space utilization should be > "
- + (targetMemoryUsagePercent * 100) + "%, actually O = " + O);
+ assertThat(O > targetOldSpaceUsagePercent * 100, "Old space utilization should be > "
+ + (targetOldSpaceUsagePercent * 100) + "%, actually O = " + O);
}
if (measurement.valueExists("M")) {
float M = measurement.getFloatValue("M");
- assertThat(M > targetMemoryUsagePercent * 100, "Metaspace utilization should be > "
- + (targetMemoryUsagePercent * 100) + "%, actually M = " + M);
+ assertThat(M > targetMetaspaceUsagePercent * 100, "Metaspace utilization should be > "
+ + (targetMetaspaceUsagePercent * 100) + "%, actually M = " + M);
}
}
- private static void assertThat(boolean result, String message) {
+ public static void assertThat(boolean result, String message) {
if (!result) {
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();
}