Merge
authorjwilhelm
Fri, 10 Feb 2017 15:14:27 +0100
changeset 43946 b683a1f9f2e5
parent 43684 771c619e190d (current diff)
parent 43945 e7f2e49d2274 (diff)
child 43947 a52ee13998f3
Merge
hotspot/src/share/vm/runtime/arguments.cpp
hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java
--- a/hotspot/.mx.jvmci/mx_jvmci.py	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/.mx.jvmci/mx_jvmci.py	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp	Fri Feb 10 15:14:27 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/aotCodeHeap.hpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.hpp	Fri Feb 10 15:14:27 2017 +0100
@@ -240,6 +240,11 @@
     assert(result == CodeHeap::contains(p), "");
     return result;
   }
+
+  bool contains_blob(const CodeBlob* blob) const {
+    return CodeHeap::contains(blob->code_begin());
+  }
+
   AOTCompiledMethod* find_aot(address p) const;
 
   virtual void* find_start(void* p)     const;
--- a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Fri Feb 10 15:14:27 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/code/codeCache.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/code/codeCache.cpp	Fri Feb 10 15:14:27 2017 +0100
@@ -417,7 +417,7 @@
 CodeHeap* CodeCache::get_code_heap(const CodeBlob* cb) {
   assert(cb != NULL, "CodeBlob is null");
   FOR_ALL_HEAPS(heap) {
-    if ((*heap)->contains(cb->code_begin())) {
+    if ((*heap)->contains_blob(cb)) {
       return *heap;
     }
   }
--- a/hotspot/src/share/vm/code/codeCache.hpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/code/codeCache.hpp	Fri Feb 10 15:14:27 2017 +0100
@@ -304,11 +304,10 @@
     // If set to NULL, initialized by first call to next()
     _code_blob = (CodeBlob*)nm;
     if (nm != NULL) {
-      address start = nm->code_begin();
-      while(!(*_heap)->contains(start)) {
+      while(!(*_heap)->contains_blob(_code_blob)) {
         ++_heap;
       }
-      assert((*_heap)->contains(start), "match not found");
+      assert((*_heap)->contains_blob(_code_blob), "match not found");
     }
   }
 
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp	Fri Feb 10 15:14:27 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/memory/heap.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/memory/heap.cpp	Fri Feb 10 15:14:27 2017 +0100
@@ -190,6 +190,10 @@
   if (block != NULL) {
     assert(block->length() >= number_of_segments && block->length() < number_of_segments + CodeCacheMinBlockLength, "sanity check");
     assert(!block->free(), "must be marked free");
+    guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(),
+              "The newly allocated block " INTPTR_FORMAT " is not within the heap "
+              "starting with "  INTPTR_FORMAT " and ending with "  INTPTR_FORMAT,
+              p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high()));
     DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, instance_size));
     _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
     _blob_count++;
@@ -204,6 +208,10 @@
     HeapBlock* b =  block_at(_next_segment);
     b->initialize(number_of_segments);
     _next_segment += number_of_segments;
+    guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(),
+              "The newly allocated block " INTPTR_FORMAT " is not within the heap "
+              "starting with "  INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
+              p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
     DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapNewVal, instance_size));
     _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
     _blob_count++;
@@ -219,6 +227,10 @@
   // Find start of HeapBlock
   HeapBlock* b = (((HeapBlock *)p) - 1);
   assert(b->allocated_space() == p, "sanity check");
+  guarantee((char*) b >= _memory.low_boundary() && (char*) b < _memory.high(),
+            "The block to be deallocated " INTPTR_FORMAT " is not within the heap "
+            "starting with "  INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
+            p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
   DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapFreeVal,
              segments_to_size(b->length()) - sizeof(HeapBlock)));
   add_to_freelist(b);
--- a/hotspot/src/share/vm/memory/heap.hpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/memory/heap.hpp	Fri Feb 10 15:14:27 2017 +0100
@@ -153,7 +153,9 @@
   char* high() const                             { return _memory.high(); }
   char* high_boundary() const                    { return _memory.high_boundary(); }
 
-  virtual bool  contains(const void* p) const    { return low_boundary() <= p && p < high(); }
+  virtual bool contains(const void* p) const     { return low_boundary() <= p && p < high(); }
+  virtual bool contains_blob(const CodeBlob* blob) const { return low_boundary() <= (char*) blob && (char*) blob < high(); }
+
   virtual void* find_start(void* p)     const;   // returns the block containing p or NULL
   virtual CodeBlob* find_blob_unsafe(void* start) const;
   size_t alignment_unit()       const;           // alignment of any block
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Fri Feb 10 15:14:27 2017 +0100
@@ -46,7 +46,7 @@
   return TypeFunc::make(method());
 }
 
-bool CallGenerator::is_inlined_mh_linker(JVMState* jvms, ciMethod* callee) {
+bool CallGenerator::is_inlined_method_handle_intrinsic(JVMState* jvms, ciMethod* callee) {
   ciMethod* symbolic_info = jvms->method()->get_method_at_bci(jvms->bci());
   return symbolic_info->is_method_handle_intrinsic() && !callee->is_method_handle_intrinsic();
 }
@@ -142,7 +142,7 @@
   }
 
   CallStaticJavaNode *call = new CallStaticJavaNode(kit.C, tf(), target, method(), kit.bci());
-  if (is_inlined_mh_linker(jvms, method())) {
+  if (is_inlined_method_handle_intrinsic(jvms, method())) {
     // To be able to issue a direct call and skip a call to MH.linkTo*/invokeBasic adapter,
     // additional information about the method being invoked should be attached
     // to the call site to make resolution logic work
@@ -241,7 +241,7 @@
   address target = SharedRuntime::get_resolve_virtual_call_stub();
   // Normal inline cache used for call
   CallDynamicJavaNode *call = new CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci());
-  if (is_inlined_mh_linker(jvms, method())) {
+  if (is_inlined_method_handle_intrinsic(jvms, method())) {
     // To be able to issue a direct call (optimized virtual or virtual)
     // and skip a call to MH.linkTo*/invokeBasic adapter, additional information
     // about the method being invoked should be attached to the call site to
@@ -785,8 +785,7 @@
 
 
 CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden) {
-  assert(callee->is_method_handle_intrinsic() ||
-         callee->is_compiled_lambda_form(), "for_method_handle_call mismatch");
+  assert(callee->is_method_handle_intrinsic(), "for_method_handle_call mismatch");
   bool input_not_const;
   CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee, input_not_const);
   Compile* C = Compile::current();
@@ -810,6 +809,81 @@
   }
 }
 
+static BasicType erase_to_word_type(BasicType bt) {
+  if (is_subword_type(bt)) return T_INT;
+  if (bt == T_ARRAY)       return T_OBJECT;
+  return bt;
+}
+
+static bool basic_types_match(ciType* t1, ciType* t2) {
+  if (t1 == t2)  return true;
+  return erase_to_word_type(t1->basic_type()) == erase_to_word_type(t2->basic_type());
+}
+
+bool CallGenerator::ensure_mh_intrinsic_matches_target_method(ciMethod* linker, ciMethod* target) {
+  assert(linker->is_method_handle_intrinsic(), "sanity");
+  assert(!target->is_method_handle_intrinsic(), "sanity");
+
+  // Linkers have appendix argument which is not passed to callee.
+  int has_appendix = MethodHandles::has_member_arg(linker->intrinsic_id()) ? 1 : 0;
+  if (linker->arg_size() != (target->arg_size() + has_appendix)) {
+    return false; // argument slot count mismatch
+  }
+
+  ciSignature* linker_sig = linker->signature();
+  ciSignature* target_sig = target->signature();
+
+  if (linker_sig->count() + (linker->is_static() ? 0 : 1) !=
+      target_sig->count() + (target->is_static() ? 0 : 1) + has_appendix) {
+    return false; // argument count mismatch
+  }
+
+  int sbase = 0, rbase = 0;
+  switch (linker->intrinsic_id()) {
+    case vmIntrinsics::_linkToVirtual:
+    case vmIntrinsics::_linkToInterface:
+    case vmIntrinsics::_linkToSpecial: {
+      if (target->is_static()) {
+        return false;
+      }
+      if (linker_sig->type_at(0)->is_primitive_type()) {
+        return false;  // receiver should be an oop
+      }
+      sbase = 1; // skip receiver
+      break;
+    }
+    case vmIntrinsics::_linkToStatic: {
+      if (!target->is_static()) {
+        return false;
+      }
+      break;
+    }
+    case vmIntrinsics::_invokeBasic: {
+      if (target->is_static()) {
+        if (target_sig->type_at(0)->is_primitive_type()) {
+          return false; // receiver should be an oop
+        }
+        rbase = 1; // skip receiver
+      }
+      break;
+    }
+  }
+  assert(target_sig->count() - rbase == linker_sig->count() - sbase - has_appendix, "argument count mismatch");
+  int arg_count = target_sig->count() - rbase;
+  for (int i = 0; i < arg_count; i++) {
+    if (!basic_types_match(linker_sig->type_at(sbase + i), target_sig->type_at(rbase + i))) {
+      return false;
+    }
+  }
+  // Only check the return type if the symbolic info has non-void return type.
+  // I.e. the return value of the resolved method can be dropped.
+  if (!linker->return_type()->is_void() &&
+      !basic_types_match(linker->return_type(), target->return_type())) {
+    return false;
+  }
+  return true; // no mismatch found
+}
+
 CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const) {
   GraphKit kit(jvms);
   PhaseGVN& gvn = kit.gvn();
@@ -826,6 +900,13 @@
         const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr();
         ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
         const int vtable_index = Method::invalid_vtable_index;
+
+        if (!ensure_mh_intrinsic_matches_target_method(callee, target)) {
+          print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(),
+                                 "signatures mismatch");
+          return NULL;
+        }
+
         CallGenerator* cg = C->call_generator(target, vtable_index,
                                               false /* call_does_dispatch */,
                                               jvms,
@@ -833,9 +914,8 @@
                                               PROB_ALWAYS);
         return cg;
       } else {
-        const char* msg = "receiver not constant";
-        if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);
-        C->log_inline_failure(msg);
+        print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(),
+                               "receiver not constant");
       }
     }
     break;
@@ -852,6 +932,12 @@
         const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr();
         ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget();
 
+        if (!ensure_mh_intrinsic_matches_target_method(callee, target)) {
+          print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(),
+                                 "signatures mismatch");
+          return NULL;
+        }
+
         // In lambda forms we erase signature types to avoid resolving issues
         // involving class loaders.  When we optimize a method handle invoke
         // to a direct call we must cast the receiver and arguments to its
@@ -912,9 +998,8 @@
                                               speculative_receiver_type);
         return cg;
       } else {
-        const char* msg = "member_name not constant";
-        if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);
-        C->log_inline_failure(msg);
+        print_inlining_failure(C, callee, jvms->depth() - 1, jvms->bci(),
+                               "member_name not constant");
       }
     }
     break;
--- a/hotspot/src/share/vm/opto/callGenerator.hpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp	Fri Feb 10 15:14:27 2017 +0100
@@ -170,7 +170,14 @@
     }
   }
 
-  static bool is_inlined_mh_linker(JVMState* jvms, ciMethod* m);
+  static void print_inlining_failure(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) {
+    print_inlining(C, callee, inline_level, bci, msg);
+    C->log_inline_failure(msg);
+  }
+
+  static bool is_inlined_method_handle_intrinsic(JVMState* jvms, ciMethod* m);
+
+  static bool ensure_mh_intrinsic_matches_target_method(ciMethod* linker, ciMethod* target);
 };
 
 
--- a/hotspot/src/share/vm/opto/cfgnode.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/opto/cfgnode.cpp	Fri Feb 10 15:14:27 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/opto/doCall.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Fri Feb 10 15:14:27 2017 +0100
@@ -400,83 +400,12 @@
 }
 
 #ifdef ASSERT
-static bool check_type(ciType* t1, ciType* t2) {
-  // Either oop-oop or prim-prim pair.
-  if (t1->is_primitive_type() && t2->is_primitive_type()) {
-    return t1->size() == t2->size(); // argument sizes should match
-  } else {
-    return !t1->is_primitive_type() && !t2->is_primitive_type(); // oop-oop
-  }
-}
-
-static bool check_inlined_mh_linker_info(ciMethod* symbolic_info, ciMethod* resolved_method) {
-  assert(symbolic_info->is_method_handle_intrinsic(), "sanity");
-  assert(!resolved_method->is_method_handle_intrinsic(), "sanity");
-
-  if (!symbolic_info->is_loaded() || !resolved_method->is_loaded()) {
-    return true; // Don't compare unloaded methods.
-  }
-  // Linkers have appendix argument which is not passed to callee.
-  int has_appendix = MethodHandles::has_member_arg(symbolic_info->intrinsic_id()) ? 1 : 0;
-  if (symbolic_info->arg_size() != (resolved_method->arg_size() + has_appendix)) {
-    return false; // Total size of arguments on stack mismatch.
-  }
-  if (!symbolic_info->return_type()->is_void()) {
-    // Only check the return type if the symbolic method is not void
-    // i.e. the return value of the resolved method can be dropped
-    if (!check_type(symbolic_info->return_type(), resolved_method->return_type())) {
-      return false; // Return value size or type mismatch encountered.
-    }
-  }
-
-  switch (symbolic_info->intrinsic_id()) {
-    case vmIntrinsics::_linkToVirtual:
-    case vmIntrinsics::_linkToInterface:
-    case vmIntrinsics::_linkToSpecial: {
-      if (resolved_method->is_static())  return false;
-      break;
-    }
-    case vmIntrinsics::_linkToStatic: {
-      if (!resolved_method->is_static())  return false;
-      break;
-    }
-  }
-
-  ciSignature* symbolic_sig = symbolic_info->signature();
-  ciSignature* resolved_sig = resolved_method->signature();
-
-  if (symbolic_sig->count() + (symbolic_info->is_static() ? 0 : 1) !=
-      resolved_sig->count() + (resolved_method->is_static() ? 0 : 1) + has_appendix) {
-    return false; // Argument count mismatch
-  }
-
-  int sbase = 0, rbase = 0;
-  int arg_count = MIN2(symbolic_sig->count() - has_appendix, resolved_sig->count());
-  ciType* recv_type = NULL;
-  if (symbolic_info->is_static() && !resolved_method->is_static()) {
-    recv_type = symbolic_sig->type_at(0);
-    sbase = 1;
-  } else if (!symbolic_info->is_static() && resolved_method->is_static()) {
-    recv_type = resolved_sig->type_at(0);
-    rbase = 1;
-  }
-  if (recv_type != NULL && recv_type->is_primitive_type()) {
-    return false; // Receiver should be an oop.
-  }
-  for (int i = 0; i < arg_count; i++) {
-    if (!check_type(symbolic_sig->type_at(sbase + i), resolved_sig->type_at(rbase + i))) {
-      return false; // Argument size or type mismatch encountered.
-    }
-  }
-  return true;
-}
-
 static bool is_call_consistent_with_jvms(JVMState* jvms, CallGenerator* cg) {
   ciMethod* symbolic_info = jvms->method()->get_method_at_bci(jvms->bci());
   ciMethod* resolved_method = cg->method();
 
-  if (CallGenerator::is_inlined_mh_linker(jvms, resolved_method)) {
-    return check_inlined_mh_linker_info(symbolic_info, resolved_method);
+  if (CallGenerator::is_inlined_method_handle_intrinsic(jvms, resolved_method)) {
+    return CallGenerator::ensure_mh_intrinsic_matches_target_method(symbolic_info, resolved_method);
   } else {
     // Method name & descriptor should stay the same.
     return (symbolic_info->get_Method()->name() == resolved_method->get_Method()->name()) &&
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp	Fri Feb 10 15:14:27 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -51,6 +51,7 @@
 #include "services/serviceUtil.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
 #endif // INCLUDE_ALL_GCS
 
@@ -1534,6 +1535,14 @@
       if (_tags[i] == entry->tag()) {
         oop o = entry->object();
         assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check");
+#if INCLUDE_ALL_GCS
+        if (UseG1GC) {
+          // The reference in this tag map could be the only (implicitly weak)
+          // reference to that object. If we hand it out, we need to keep it live wrt
+          // SATB marking similar to other j.l.ref.Reference referents.
+          G1SATBCardTableModRefBS::enqueue(o);
+        }
+#endif
         jobject ref = JNIHandles::make_local(JavaThread::current(), o);
         _object_results->append(ref);
         _tag_results->append((uint64_t)entry->tag());
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Feb 10 15:14:27 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")                    \
@@ -3375,7 +3374,7 @@
           "Code cache expansion size (in bytes)")                           \
           range(0, max_uintx)                                               \
                                                                             \
-  develop_pd(uintx, CodeCacheMinBlockLength,                                \
+  diagnostic_pd(uintx, CodeCacheMinBlockLength,                             \
           "Minimum number of segments in a code cache block")               \
           range(1, 100)                                                     \
                                                                             \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java	Fri Feb 10 15:14:27 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 {
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java	Fri Feb 10 15:14:27 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.
+ */
+
+/*
+ * @test ReturnBlobToWrongHeapTest
+ * @key stress
+ * @summary Test if VM attempts to return code blobs to an incorrect code heap or to outside of the code cache.
+ * @library /test/lib /
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                                sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
+ *                   -XX:+WhiteBoxAPI
+ *                   -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method
+ *                   -XX:+SegmentedCodeCache
+ *                   -XX:ReservedCodeCacheSize=16M
+ *                   -XX:CodeCacheMinBlockLength=1
+ *                   compiler.codecache.stress.ReturnBlobToWrongHeapTest
+ */
+
+package compiler.codecache.stress;
+
+import sun.hotspot.code.BlobType;
+
+import java.util.ArrayList;
+
+public class ReturnBlobToWrongHeapTest {
+    private static final long largeBlobSize = Helper.WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize") >> 6;
+    private static final long codeCacheMinBlockLength = Helper.WHITE_BOX.getUintxVMFlag("CodeCacheMinBlockLength");
+    private static final BlobType[] BLOB_TYPES = BlobType.getAvailable().toArray(new BlobType[0]);
+
+    // Allocate blob in first code heap (the code heap with index 0).
+    private static long allocate(int size) {
+        return Helper.WHITE_BOX.allocateCodeBlob(size, BLOB_TYPES[0].id);
+    }
+
+    // Free blob.
+    private static void free(long address) {
+        Helper.WHITE_BOX.freeCodeBlob(address);
+    }
+
+    public static void main(String[] args) {
+        if (codeCacheMinBlockLength == 1) {
+            // Fill first code heap with large blobs until allocation fails.
+            long address;
+            while ((address = allocate((int)largeBlobSize)) != 0) {
+            }
+
+            // Allocate segment-sized blocks in first code heap.
+            long lastSegmentSizedAddress = 0; // Address of the last segment-sized blob allocated
+            while ((address = allocate(0)) != 0) {
+                lastSegmentSizedAddress = address;
+            }
+
+            if (lastSegmentSizedAddress == 0) {
+                throw new RuntimeException("Test failed: Not possible to allocate segment-sized blob");
+            }
+
+            // Remove last segment-sized block from the first code heap.
+            free(lastSegmentSizedAddress);
+        } else {
+            throw new RuntimeException("Test requires CodeCacheMinBlockLength==1; CodeCacheMinBlockLength is " +
+                                       codeCacheMinBlockLength);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/jsr292/InvokerSignatureMismatch.java	Fri Feb 10 15:14:27 2017 +0100
@@ -0,0 +1,58 @@
+package compiler.jsr292;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MethodHandleHelper;
+import jdk.internal.vm.annotation.ForceInline;
+
+/*
+ * @test
+ * @bug 8166110
+ * @library /test/lib / patches
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.vm.annotation
+ *
+ * @build java.base/java.lang.invoke.MethodHandleHelper
+ * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch -XX:-TieredCompilation
+ *                                 compiler.jsr292.InvokerSignatureMismatch
+ */
+public class InvokerSignatureMismatch {
+
+    static final MethodHandle INT_MH;
+
+    static {
+        MethodHandle mhI = null;
+        try {
+           mhI = MethodHandles.lookup().findStatic(InvokerSignatureMismatch.class, "bodyI", MethodType.methodType(void.class, int.class));
+        } catch (Throwable e) {
+        }
+        INT_MH = mhI;
+    }
+
+    public static void main(String[] args) throws Throwable {
+        mainLink();
+        mainInvoke();
+    }
+
+    static void mainLink() throws Throwable {
+        for (int i = 0; i < 50_000; i++) { // OSR
+            Object name = MethodHandleHelper.internalMemberName(INT_MH);
+            MethodHandleHelper.linkToStatic(INT_MH, (float) i, name);
+        }
+    }
+
+    static void mainInvoke() throws Throwable {
+        for (int i = 0; i < 50_000; i++) { // OSR
+            MethodHandleHelper.invokeBasicV(INT_MH, (float) i);
+        }
+    }
+
+    static int cnt = 0;
+    static void bodyI(int x) {
+        if ((x & 1023) == 0) { // already optimized x % 1024 == 0
+            ++cnt;
+        }
+    }
+
+}
--- a/hotspot/test/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/test/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java	Fri Feb 10 15:14:27 2017 +0100
@@ -44,6 +44,21 @@
     }
 
     @ForceInline
+    public static Object internalMemberName(MethodHandle mh) throws Throwable {
+        return mh.internalMemberName();
+    }
+
+    @ForceInline
+    public static void linkToStatic(MethodHandle mh, float arg, Object name) throws Throwable {
+        MethodHandle.linkToStatic(mh, arg, name);
+    }
+
+    @ForceInline
+    public static void invokeBasicV(MethodHandle mh, float arg) throws Throwable {
+        mh.invokeBasic(arg);
+    }
+
+    @ForceInline
     public static Object invokeBasicL(MethodHandle mh) throws Throwable {
         return mh.invokeBasic();
     }
--- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Thu Feb 09 23:15:52 2017 +0100
+++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java	Fri Feb 10 15:14:27 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	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/compiler/types/correctness/OffTest.java	Fri Feb 10 15:14:27 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	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java	Fri Feb 10 15:14:27 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	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java	Fri Feb 10 15:14:27 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:15:52 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java	Fri Feb 10 15:14:27 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:15:52 2017 +0100
+++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java	Fri Feb 10 15:14:27 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();
 }