From b9e2a5384153e355f1bdab6fc84a390ebb81475b Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 3 Feb 2017 08:17:35 +0100 Subject: [PATCH 01/10] 8173699: Crash during deoptimization with "assert(result == __null || result->is_oop()) failed: must be oop" Ignore return_oop() when dispatching an exception and only try to retrieve the oop when performing re-allocation during a normal deoptimization (if exec_mode == Unpack_deopt). Reviewed-by: kvn, vlivanov --- hotspot/src/share/vm/runtime/deoptimization.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index e3b88640768..5ce9f345809 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -221,8 +221,9 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread // 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 From a44e07e4b3f43f92a99c4d48f428da0d4ec96b92 Mon Sep 17 00:00:00 2001 From: Rahul Raghavan Date: Fri, 3 Feb 2017 00:46:58 -0800 Subject: [PATCH 02/10] 8144484: assert(no_dead_loop) failed: dead loop detected Bailout early without splitting Phi through memory merges if TOP inputs present for Phi Nodes Reviewed-by: thartmann, kvn --- hotspot/src/share/vm/opto/cfgnode.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index de85b1cb155..69e7659a877 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -1889,6 +1889,12 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { bool saw_self = false; for( uint i=1; iis_MergeMem()) { MergeMemNode* n = ii->as_MergeMem(); merge_width = MAX2(merge_width, n->req()); From 00f485cdfa7619ae86551c133eaa318f0d54121a Mon Sep 17 00:00:00 2001 From: Michail Chernov Date: Fri, 3 Feb 2017 15:45:57 +0300 Subject: [PATCH 03/10] 8170737: Not enough old space utilisation Reviewed-by: dfazunen, tschatzl --- .../tmtools/jstat/GarbageProducerTest.java | 89 +++++++++++++ .../tmtools/jstat/GcCauseTest02.java | 30 +---- .../tmtools/jstat/GcTest02.java | 32 +---- .../tmtools/jstat/utils/GarbageProducer.java | 121 ++++++++++++++++++ .../tmtools/jstat/utils/GcProvoker.java | 84 +----------- .../tmtools/jstat/utils/GcProvokerImpl.java | 113 ---------------- .../jstat/utils/JstatGcCapacityResults.java | 22 +--- .../jstat/utils/JstatGcCauseResults.java | 20 +-- .../jstat/utils/JstatGcNewResults.java | 9 +- .../tmtools/jstat/utils/JstatGcResults.java | 20 +-- .../tmtools/jstat/utils/JstatResults.java | 45 +++++-- 11 files changed, 266 insertions(+), 319 deletions(-) create mode 100644 hotspot/test/serviceability/tmtools/jstat/GarbageProducerTest.java create mode 100644 hotspot/test/serviceability/tmtools/jstat/utils/GarbageProducer.java delete mode 100644 hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java diff --git a/hotspot/test/serviceability/tmtools/jstat/GarbageProducerTest.java b/hotspot/test/serviceability/tmtools/jstat/GarbageProducerTest.java new file mode 100644 index 00000000000..dfe1a8f12dc --- /dev/null +++ b/hotspot/test/serviceability/tmtools/jstat/GarbageProducerTest.java @@ -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 jstatTool; + + public GarbageProducerTest(TmTool 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(); + } +} diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java index 2bdf04d39c2..f2fec51d6b2 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCauseTest02.java @@ -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(); } } diff --git a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java index 91406fa3838..ad46e7919df 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcTest02.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcTest02.java @@ -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(); } } diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/GarbageProducer.java b/hotspot/test/serviceability/tmtools/jstat/utils/GarbageProducer.java new file mode 100644 index 00000000000..0dd7c858482 --- /dev/null +++ b/hotspot/test/serviceability/tmtools/jstat/utils/GarbageProducer.java @@ -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 allocatedMetaspace; + public static List 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 eatMetaspace(float targetUsage) { + List 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 allocateGarbage(long targetMemoryUsage) { + List 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(); + } +} diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java index f2111fa5724..8457091800c 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvoker.java @@ -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 @@ import java.util.List; 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 allocatedMetaspace; - public static List allocatedMemory; + private static final int MEMORY_CHUNK = 2048; private final Runtime runtime; @@ -61,21 +54,6 @@ public class GcProvoker{ return list; } - private List allocateAvailableHeap(float targetUsage) { - // Calculates size of free memory after allocation with small tolerance. - long minFreeMemory = (long) ((1.0 - (targetUsage + ALLOCATION_TOLERANCE)) * runtime.maxMemory()); - List 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 @@ public class GcProvoker{ } } - /** - * Allocates heap and metaspace upon exit not less than targetMemoryUsagePercent percents - * of heap and metaspace have been consumed. - * - * @param targetMemoryUsagePercent how many percent of heap and metaspace to - * allocate - */ - - public void allocateMetaspaceAndHeap(float targetMemoryUsagePercent) { - // Metaspace should be filled before Java Heap to prevent unexpected OOME - // in the Java Heap while filling Metaspace - allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent); - allocatedMemory = allocateHeap(targetMemoryUsagePercent); - } - - /** - * Allocates heap and metaspace upon exit targetMemoryUsagePercent percents - * of heap and metaspace have been consumed. - * - * @param targetMemoryUsagePercent how many percent of heap and metaspace to - * allocate - */ - public void allocateAvailableMetaspaceAndHeap(float targetMemoryUsagePercent) { - // Metaspace should be filled before Java Heap to prevent unexpected OOME - // in the Java Heap while filling Metaspace - allocatedMetaspace = eatMetaspace(targetMemoryUsagePercent); - allocatedMemory = allocateAvailableHeap(targetMemoryUsagePercent); - } - - private List eatMetaspace(float targetUsage) { - List 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(); } - } diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java b/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java deleted file mode 100644 index 565d86cf377..00000000000 --- a/hotspot/test/serviceability/tmtools/jstat/utils/GcProvokerImpl.java +++ /dev/null @@ -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 eatenMetaspace; - private static List eatenMemory; - - static List eatHeapMemory(float targetUsage) { - long maxMemory = Runtime.getRuntime().maxMemory(); - // uses fixed small objects to avoid Humongous objects allocation in G1 - int memoryChunk = 2048; - List 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 eatMetaspace(float targetUsage) { - List 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() { - } - -} diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java index 6ac62fa48ef..350a2a6470d 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCapacityResults.java @@ -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 @@ public class JstatGcCapacityResults extends JstatResults { /** * Checks the overall consistency of the results reported by the tool */ + @Override public void assertConsistency() { // Check exit code @@ -117,8 +118,6 @@ public class JstatGcCapacityResults extends JstatResults { 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 @@ public class JstatGcCapacityResults extends JstatResults { } 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); - } - } - } diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java index 3bb708dd7ba..cf435f8dba7 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java @@ -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 @@ public class JstatGcCauseResults extends JstatResults { /** * 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 @@ public class JstatGcCauseResults extends JstatResults { 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); - } - } - } diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java index 24ff4490b80..ca3c04af67c 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcNewResults.java @@ -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 @@ public class JstatGcNewResults extends JstatResults { /** * 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 @@ public class JstatGcNewResults extends JstatResults { 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); - } - } } diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java index 95905418a37..7b736d9f071 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatGcResults.java @@ -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 @@ public class JstatGcResults extends JstatResults { /** * 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 @@ public class JstatGcResults extends JstatResults { 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); - } - } - } diff --git a/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java b/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java index d4f961051f8..f628a27d1de 100644 --- a/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java +++ b/hotspot/test/serviceability/tmtools/jstat/utils/JstatResults.java @@ -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 @@ import common.ToolResults; */ 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 @@ abstract public class JstatResults extends ToolResults { * 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(); } From 104239fe8f5279de379360d4dbe135c6c60cbc0d Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 3 Feb 2017 12:26:10 +0100 Subject: [PATCH 04/10] 8173825: Adjust the comment for flags UseAES, UseFMA, UseSHA in globals.hpp Reviewed-by: kvn, clanger --- hotspot/src/share/vm/runtime/globals.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 90b274e58a2..5282a6b9e17 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -657,14 +657,13 @@ public: 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") \ From 6f2cad0c0c244db76614d9db5cb7007ca30e9ee6 Mon Sep 17 00:00:00 2001 From: Jamsheed Mohammed C M Date: Fri, 3 Feb 2017 19:26:35 -0800 Subject: [PATCH 05/10] 8173679: Disable ProfileTrap code and UseRTMLocking in emulated client Win32 Disabled mdo trap count update on deopt, and made +UseRTMLocking to exit. Reviewed-by: kvn --- hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 6 ++++++ hotspot/src/share/vm/runtime/deoptimization.cpp | 2 +- .../compiler/testlibrary/rtm/predicate/SupportedVM.java | 2 +- hotspot/test/compiler/types/correctness/OffTest.java | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 7bed10749f7..bba96562031 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -850,6 +850,12 @@ void VM_Version::get_processor_features() { #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) || diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 5ce9f345809..a656e89643a 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1813,7 +1813,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra // 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; diff --git a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java index f4958a607c2..fee36b9e5c1 100644 --- a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java +++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java @@ -30,6 +30,6 @@ import java.util.function.BooleanSupplier; public class SupportedVM implements BooleanSupplier { @Override public boolean getAsBoolean() { - return Platform.isServer(); + return Platform.isServer() && !Platform.isEmulatedClient(); } } diff --git a/hotspot/test/compiler/types/correctness/OffTest.java b/hotspot/test/compiler/types/correctness/OffTest.java index 7593fc68a0d..5a8fe5953ac 100644 --- a/hotspot/test/compiler/types/correctness/OffTest.java +++ b/hotspot/test/compiler/types/correctness/OffTest.java @@ -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 From a7f34a32959b5fd827c059bbac73c38c384f70c7 Mon Sep 17 00:00:00 2001 From: Oleg Pliss Date: Mon, 6 Feb 2017 08:32:08 +0100 Subject: [PATCH 06/10] 8173119: compiler/jvmci/events/JvmciNotifyBootstrapFinishedEventTest.java fails with custom Tiered Level set externally Check for invalid JVMCI flag combination at startup. Reviewed-by: kvn, thartmann --- hotspot/src/share/vm/runtime/arguments.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 168d5ce6ea4..15d010dcb53 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1894,6 +1894,11 @@ void Arguments::set_jvmci_specific_flags() { 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 @@ bool Arguments::check_vm_args_consistency() { } #endif } -#if INCLUDE_JVMCI +#if INCLUDE_JVMCI status = status && check_jvmci_args_consistency(); if (EnableJVMCI) { From 47960ed2aa463c52e4f087b5b8dc5e74c374b2a4 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Mon, 6 Feb 2017 10:45:11 +0100 Subject: [PATCH 07/10] 8173912: [JVMCI] fix memory overhead of JVMCI Reviewed-by: kvn --- hotspot/.mx.jvmci/mx_jvmci.py | 64 +--- .../src/jdk/vm/ci/hotspot/CompilerToVM.java | 19 +- .../vm/ci/hotspot/HotSpotConstantPool.java | 17 +- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 4 - .../src/jdk/vm/ci/hotspot/HotSpotMethod.java | 11 - .../ci/hotspot/HotSpotMethodUnresolved.java | 8 +- .../hotspot/HotSpotResolvedJavaFieldImpl.java | 22 +- .../HotSpotResolvedJavaMethodImpl.java | 45 ++- .../HotSpotResolvedObjectTypeImpl.java | 222 ++++++------- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 13 +- .../vm/ci/hotspot/HotSpotVMConfigAccess.java | 38 +-- .../vm/ci/hotspot/HotSpotVMConfigStore.java | 31 +- .../hotspot/GraalHotSpotVMConfig.java | 10 +- .../src/share/vm/jvmci/jvmciCompilerToVM.cpp | 310 +++++++++++++----- .../src/share/vm/jvmci/jvmciCompilerToVM.hpp | 28 +- .../src/share/vm/jvmci/vmStructs_jvmci.cpp | 13 +- .../jdk/vm/ci/hotspot/CompilerToVMHelper.java | 6 +- .../compilerToVM/ConstantPoolTestCase.java | 6 +- .../compilerToVM/ConstantPoolTestsHelper.java | 4 +- .../jvmci/compilerToVM/GetFlagValueTest.java | 93 ++++++ .../compilerToVM/ResolveFieldInPoolTest.java | 8 +- 21 files changed, 589 insertions(+), 383 deletions(-) create mode 100644 hotspot/test/compiler/jvmci/compilerToVM/GetFlagValueTest.java diff --git a/hotspot/.mx.jvmci/mx_jvmci.py b/hotspot/.mx.jvmci/mx_jvmci.py index daa27f5d607..b87bab712a2 100644 --- a/hotspot/.mx.jvmci/mx_jvmci.py +++ b/hotspot/.mx.jvmci/mx_jvmci.py @@ -158,8 +158,8 @@ To build hotspot and import it into the JDK: "mx make hotspot import-hotspot" # JDK9 must be bootstrapped with a JDK8 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 @@ To build hotspot and import it into the JDK: "mx make hotspot import-hotspot" 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""" diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index e0b5acb426f..a5c0c7c3b62 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -278,8 +278,10 @@ final class CompilerToVM { * {@code info} are: * *
-     *     [(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()
+     *     ]
      * 
* * The behavior of this method is undefined if {@code cpi} does not denote a @@ -288,7 +290,7 @@ final class CompilerToVM { * @param info an array in which the details of the field are returned * @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 @@ final class CompilerToVM { * {@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); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java index 957f66516b9..d88a8468e73 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantPool.java @@ -298,7 +298,7 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * @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 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject 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 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject 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 @@ final class HotSpotConstantPool implements ConstantPool, MetaspaceWrapperObject * 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); } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index f6c97ecb07f..b687ab5a367 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -513,10 +513,6 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider { for (Map.Entry e : constants.entrySet()) { printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue()); } - TreeMap typeSizes = new TreeMap<>(store.getTypeSizes()); - for (Map.Entry 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); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java index da04107bc1a..aca3b3ddb4d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethod.java @@ -59,23 +59,12 @@ abstract class HotSpotMethod implements JavaMethod, Formattable { 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'; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java index e68c7fef8c1..7eb437929c3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodUnresolved.java @@ -31,15 +31,21 @@ import jdk.vm.ci.meta.Signature; */ 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; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 24287261984..737135a8e52 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -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 @@ import jdk.vm.ci.meta.ResolvedJavaType; 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 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { 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 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { @Override public int hashCode() { - return name.hashCode(); + return offset ^ modifiers; } @Override @@ -109,7 +109,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { @Override public String getName() { - return name; + return holder.createFieldInfo(index).getName(); } @Override @@ -178,18 +178,12 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { 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; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 393b740a71e..f831db4c5f9 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -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 @@ -75,6 +75,12 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp private byte[] code; 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. * @@ -106,8 +112,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp } 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 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp 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); } @@ -146,6 +147,15 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp return UNSAFE.getAddress(metaspaceMethod + config().methodConstMethodOffset); } + @Override + public String getName() { + if (nameCache == null) { + final int nameIndex = UNSAFE.getChar(getConstMethod() + config().constMethodNameIndexOffset); + nameCache = constantPool.lookupUtf8(nameIndex); + } + return nameCache; + } + @Override public boolean equals(Object obj) { if (this == obj) { @@ -326,12 +336,24 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp @Override public boolean isClassInitializer() { - return "".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 "".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 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp @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 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp } 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 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp } 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; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index a0a3bc7a7a5..88974c3b415 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -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.Constructor; 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 @@ import jdk.vm.ci.meta.ResolvedJavaType; */ 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 fieldCache; - private HashMap methodCache; + private HotSpotResolvedJavaMethodImpl[] methodCacheArray; + private HashMap methodCacheHashMap; private HotSpotResolvedJavaField[] instanceFields; private HotSpotResolvedObjectTypeImpl[] interfaces; private HotSpotConstantPool constantPool; @@ -255,7 +256,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem * @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 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem } synchronized HotSpotResolvedJavaMethod createMethod(long metaspaceMethod) { - HotSpotResolvedJavaMethodImpl method = null; - if (methodCache == null) { - methodCache = new HashMap<>(8); + // Maintain cache as array. + if (methodCacheArray == null) { + methodCacheArray = new HotSpotResolvedJavaMethodImpl[METHOD_CACHE_ARRAY_CAPACITY]; + } + + int i = 0; + for (; i < methodCacheArray.length; ++i) { + HotSpotResolvedJavaMethodImpl curMethod = methodCacheArray[i]; + if (curMethod == null) { + HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod); + methodCacheArray[i] = newMethod; + context.add(newMethod); + return newMethod; + } else if (curMethod.getMetaspacePointer() == metaspaceMethod) { + return curMethod; + } + } + + // Fall-back to hash table. + if (methodCacheHashMap == null) { + methodCacheHashMap = new HashMap<>(); + } + + HotSpotResolvedJavaMethodImpl lookupResult = methodCacheHashMap.get(metaspaceMethod); + if (lookupResult == null) { + HotSpotResolvedJavaMethodImpl newMethod = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod); + methodCacheHashMap.put(metaspaceMethod, newMethod); + context.add(lookupResult); + return newMethod; } else { - method = methodCache.get(metaspaceMethod); + return lookupResult; } - if (method == null) { - method = new HotSpotResolvedJavaMethodImpl(this, metaspaceMethod); - methodCache.put(metaspaceMethod, method); - context.add(method); - } - return method; } public int getVtableLength() { @@ -509,37 +530,8 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem 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 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem 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 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem } } - @SuppressFBWarnings(value = "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE", justification = "comparator is only used transiently") - private static class OffsetComparator implements java.util.Comparator { - @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 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 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem if (isArray()) { return new HotSpotResolvedJavaField[0]; } else { - final int fieldCount = getFieldCount(); - ArrayList 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. * - *

- * 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++; + } } - return fieldCount; + + if (resultCount == 0) { + return prepend; + } + + int prependLength = prepend.length; + resultCount += prependLength; + + HotSpotResolvedJavaField[] result = new HotSpotResolvedJavaField[resultCount]; + if (prependLength != 0) { + System.arraycopy(prepend, 0, result, 0, prependLength); + } + + int resultIndex = prependLength; + for (int i = 0; i < index; ++i) { + FieldInfo field = new FieldInfo(i); + if (field.isStatic() == retrieveStaticFields) { + int offset = field.getOffset(); + HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i); + + // Make sure the result is sorted by offset. + int j; + for (j = resultIndex - 1; j >= prependLength && result[j].offset() > offset; j--) { + result[j + 1] = result[j]; + } + result[j + 1] = resolvedJavaField; + resultIndex++; + } + } + + return result; } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index c598f8a6f3f..25f6153f54e 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -85,7 +85,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess { 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 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess { 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*"); final int constantPoolHolderOffset = getFieldOffset("ConstantPool::_pool_holder", Integer.class, "InstanceKlass*"); final int constantPoolLengthOffset = getFieldOffset("ConstantPool::_length", Integer.class, "int"); @@ -237,12 +237,15 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess { final int heapWordSize = getConstant("HeapWordSize", Integer.class); - final int 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}. diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java index 9bb538d587b..33a07bcb9a9 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigAccess.java @@ -66,21 +66,6 @@ public class HotSpotVMConfigAccess { return getAddress(name, null); } - /** - * Gets the size of a C++ type. - * - * @param name name of the type - * @return the size in bytes of the requested field - * @throws JVMCIError if the field is not present and {@code notPresent} is null - */ - public int getTypeSize(String name) { - Long entry = store.vmTypeSizes.get(name); - if (entry == null) { - throw new JVMCIError("expected VM type not found: " + name); - } - return (int) (long) entry; - } - /** * Gets the value of a C++ constant. * @@ -291,13 +276,24 @@ public class HotSpotVMConfigAccess { */ public T getFlag(String name, Class 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 Object convertValue(String name, Class toType, Object value, String cppType) throws JVMCIError { @@ -319,6 +315,10 @@ public class HotSpotVMConfigAccess { } 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; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java index e6f074d948f..c388bbfa7c4 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfigStore.java @@ -46,15 +46,6 @@ public final class HotSpotVMConfigStore { return Collections.unmodifiableMap(vmAddresses); } - /** - * Gets the C++ type sizes exposed by this object. - * - * @return an unmodifiable map from C++ type names to their sizes in bytes - */ - public Map getTypeSizes() { - return Collections.unmodifiableMap(vmTypeSizes); - } - /** * Gets the C++ constants exposed by this object. * @@ -90,11 +81,11 @@ public final class HotSpotVMConfigStore { } final HashMap vmFields; - final HashMap vmTypeSizes; final HashMap vmConstants; final HashMap vmAddresses; final HashMap vmFlags; final List 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 @@ public final class HotSpotVMConfigStore { *

      *     info = [
      *         VMField[] vmFields,
-     *         [String name, Long size, ...] vmTypeSizes,
      *         [String name, Long value, ...] vmConstants,
      *         [String name, Long value, ...] vmAddresses,
      *         VMFlag[] vmFlags
@@ -113,25 +103,24 @@ public final class HotSpotVMConfigStore {
      */
     @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 fill maps")) {
@@ -139,12 +128,6 @@ public final class HotSpotVMConfigStore {
                 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];
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java
index 898d688747d..40cd58ce8c2 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java
@@ -244,7 +244,7 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
         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 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
         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 class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
     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 class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
     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 class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
     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");
diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
index 2fe6b45b79e..3734ae14c83 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp
@@ -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::cardtable_shift;
 
 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::dlog;
 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 @@ void CompilerToVM::Data::initialize() {
   assert(OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index)), "should be valid");
   assert(!OopMapValue::legal_vm_reg_name(VMRegImpl::stack2reg(max_oop_map_stack_index + 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 @@ void CompilerToVM::Data::initialize() {
     // No post barriers
     break;
   default:
-    ShouldNotReachHere();
+    JVMCI_ERROR("Unsupported BarrierSet kind %d", bs->kind());
     break;
   }
 
@@ -237,13 +253,114 @@ objArrayHandle CompilerToVM::initialize_intrinsics(TRAPS) {
   return vmIntrinsics;
 }
 
-C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
-#define BOXED_LONG(name, value) oop name; do { jvalue p; p.j = (jlong) (value); name = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL);} while(0)
+/**
+ * The set of VM flags known to be used.
+ */
+#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_intx_flag, do_uintx_flag) \
+  do_intx_flag(AllocateInstancePrefetchLines)                              \
+  do_intx_flag(AllocatePrefetchDistance)                                   \
+  do_intx_flag(AllocatePrefetchInstr)                                      \
+  do_intx_flag(AllocatePrefetchLines)                                      \
+  do_intx_flag(AllocatePrefetchStepSize)                                   \
+  do_intx_flag(AllocatePrefetchStyle)                                      \
+  do_intx_flag(BciProfileWidth)                                            \
+  do_bool_flag(BootstrapJVMCI)                                             \
+  do_bool_flag(CITime)                                                     \
+  do_bool_flag(CITimeEach)                                                 \
+  do_uintx_flag(CodeCacheSegmentSize)                                      \
+  do_intx_flag(CodeEntryAlignment)                                         \
+  do_bool_flag(CompactFields)                                              \
+  NOT_PRODUCT(do_intx_flag(CompileTheWorldStartAt))                        \
+  NOT_PRODUCT(do_intx_flag(CompileTheWorldStopAt))                         \
+  do_intx_flag(ContendedPaddingWidth)                                      \
+  do_bool_flag(DontCompileHugeMethods)                                     \
+  do_bool_flag(EnableContended)                                            \
+  do_intx_flag(FieldsAllocationStyle)                                      \
+  do_bool_flag(FoldStableValues)                                           \
+  do_bool_flag(ForceUnreachable)                                           \
+  do_intx_flag(HugeMethodLimit)                                            \
+  do_bool_flag(Inline)                                                     \
+  do_intx_flag(JVMCICounterSize)                                           \
+  do_bool_flag(JVMCIPrintProperties)                                       \
+  do_bool_flag(JVMCIUseFastLocking)                                        \
+  do_intx_flag(MethodProfileWidth)                                         \
+  do_intx_flag(ObjectAlignmentInBytes)                                     \
+  do_bool_flag(PrintInlining)                                              \
+  do_bool_flag(ReduceInitialCardMarks)                                     \
+  do_bool_flag(RestrictContended)                                          \
+  do_intx_flag(StackReservedPages)                                         \
+  do_intx_flag(StackShadowPages)                                           \
+  do_bool_flag(TLABStats)                                                  \
+  do_uintx_flag(TLABWasteIncrement)                                        \
+  do_intx_flag(TypeProfileWidth)                                           \
+  do_bool_flag(UseAESIntrinsics)                                           \
+  X86_ONLY(do_intx_flag(UseAVX))                                           \
+  do_bool_flag(UseBiasedLocking)                                           \
+  do_bool_flag(UseCRC32Intrinsics)                                         \
+  do_bool_flag(UseCompressedClassPointers)                                 \
+  do_bool_flag(UseCompressedOops)                                          \
+  do_bool_flag(UseConcMarkSweepGC)                                         \
+  X86_ONLY(do_bool_flag(UseCountLeadingZerosInstruction))                  \
+  X86_ONLY(do_bool_flag(UseCountTrailingZerosInstruction))                 \
+  do_bool_flag(UseG1GC)                                                    \
+  COMPILER2_PRESENT(do_bool_flag(UseMontgomeryMultiplyIntrinsic))          \
+  COMPILER2_PRESENT(do_bool_flag(UseMontgomerySquareIntrinsic))            \
+  COMPILER2_PRESENT(do_bool_flag(UseMulAddIntrinsic))                      \
+  COMPILER2_PRESENT(do_bool_flag(UseMultiplyToLenIntrinsic))               \
+  do_bool_flag(UsePopCountInstruction)                                     \
+  do_bool_flag(UseSHA1Intrinsics)                                          \
+  do_bool_flag(UseSHA256Intrinsics)                                        \
+  do_bool_flag(UseSHA512Intrinsics)                                        \
+  do_intx_flag(UseSSE)                                                     \
+  COMPILER2_PRESENT(do_bool_flag(UseSquareToLenIntrinsic))                 \
+  do_bool_flag(UseStackBanging)                                            \
+  do_bool_flag(UseTLAB)                                                    \
+  do_bool_flag(VerifyOops)                                                 \
+
+#define BOXED_BOOLEAN(name, value) oop name = ((jboolean)(value) ? boxedTrue() : boxedFalse())
 #define BOXED_DOUBLE(name, value) oop name; do { jvalue p; p.d = (jdouble) (value); name = java_lang_boxing_object::create(T_DOUBLE, &p, CHECK_NULL);} while(0)
+#define BOXED_LONG(name, value) \
+  oop name; \
+  do { \
+    jvalue p; p.j = (jlong) (value); \
+    Handle* e = longs.get(p.j); \
+    if (e == NULL) { \
+      Handle h = java_lang_boxing_object::create(T_LONG, &p, CHECK_NULL); \
+      longs.put(p.j, h); \
+      name = h(); \
+    } else { \
+      name = (*e)(); \
+    } \
+  } while (0)
+
+#define CSTRING_TO_JSTRING(name, value) \
+  Handle name; \
+  do { \
+    if (value != NULL) { \
+      Handle* e = strings.get(value); \
+      if (e == NULL) { \
+        Handle h = java_lang_String::create_from_str(value, CHECK_NULL); \
+        strings.put(value, h); \
+        name = h(); \
+      } else { \
+        name = (*e)(); \
+      } \
+    } \
+  } while (0)
+
+C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
   ResourceMark rm;
   HandleMark hm;
 
-  CompilerToVM::Data::initialize();
+  // Used to canonicalize Long and String values.
+  ResourceHashtable longs;
+  ResourceHashtable 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 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
     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 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
     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 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
   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 @@ C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv *env))
   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 @@ C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv*, jobjec
   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 @@ C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv*, jobject, jobject jvmci_consta
   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 @@ JNINativeMethod CompilerToVM::methods[] = {
   {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 @@ JNINativeMethod CompilerToVM::methods[] = {
   {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() {
diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp
index c0f21e2b8c2..500cdfec829 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp
@@ -66,6 +66,15 @@ class CompilerToVM {
 
     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 @@ class CompilerToVM {
     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 @@ class CompilerToVM {
     }
   };
 
+  static bool cstring_equals(const char* const& s0, const char* const& s1) {
+    return strcmp(s0, s1) == 0;
+  }
+
+  static unsigned cstring_hash(const char* const& s) {
+    int h = 0;
+    const char* p = s;
+    while (*p != '\0') {
+      h = 31 * h + *p;
+      p++;
+    }
+    return h;
+  }
+
   static JNINativeMethod methods[];
 
   static objArrayHandle initialize_intrinsics(TRAPS);
diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
index a01651f55aa..1cfc1021b39 100644
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
@@ -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,                  _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)                               \
diff --git a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
index fc03353f76a..1cdee2d2974 100644
--- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
+++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java
@@ -48,6 +48,10 @@ public class CompilerToVMHelper {
         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 class CompilerToVMHelper {
     }
 
     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);
     }
 
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java
index 6f2ccb0f3c0..f799f0c2734 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestCase.java
@@ -202,13 +202,13 @@ public class ConstantPoolTestCase {
         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;
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java
index e0bb9d41c8e..0ac7f3d6a6f 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ConstantPoolTestsHelper.java
@@ -206,7 +206,7 @@ public class ConstantPoolTestsHelper {
                                       "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 @@ public class ConstantPoolTestsHelper {
                                       "stringFieldEmpty",
                                       "Ljava/lang/String;",
                                       new byte[] {(byte) Opcodes.PUTFIELD | (byte) Opcodes.GETFIELD},
-                                      0L),
+                                      0),
                 }
         );
         CP_MAP_FOR_ABS_CLASS.put(CONSTANT_METHODREF,
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetFlagValueTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetFlagValueTest.java
new file mode 100644
index 00000000000..e1c46a18dee
--- /dev/null
+++ b/hotspot/test/compiler/jvmci/compilerToVM/GetFlagValueTest.java
@@ -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);
+            }
+        }
+    }
+}
diff --git a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java
index 2ee506ba4f9..640387a18c1 100644
--- a/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java
+++ b/hotspot/test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java
@@ -103,7 +103,7 @@ public class ResolveFieldInPoolTest {
             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 @@ public class ResolveFieldInPoolTest {
             } 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"

From e05df4e05ff6497e401fa4d87d543703d3c5796e Mon Sep 17 00:00:00 2001
From: Jamsheed Mohammed C M 
Date: Mon, 6 Feb 2017 09:56:48 -0800
Subject: [PATCH 08/10] 8170455: C2: Access to [].clone from interfaces fails

Passed holder klass to LR for proper resolution.

Reviewed-by: vlivanov
---
 hotspot/src/share/vm/ci/ciEnv.cpp             |  27 ++--
 hotspot/src/share/vm/ci/ciEnv.hpp             |  17 +--
 hotspot/src/share/vm/jvmci/jvmciEnv.cpp       |  10 +-
 hotspot/src/share/vm/jvmci/jvmciEnv.hpp       |   2 +-
 .../TestDefaultMethodArrayCloneDeoptC2.java   | 117 ++++++++++++++++++
 5 files changed, 145 insertions(+), 28 deletions(-)
 create mode 100644 hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java

diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp
index e8587cf9646..c7801a12dc4 100644
--- a/hotspot/src/share/vm/ci/ciEnv.cpp
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp
@@ -704,16 +704,17 @@ ciField* ciEnv::get_field_by_index(ciInstanceKlass* accessor,
 //
 // 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 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
     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 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
     }
 
     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 @@ ciMethod* ciEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
     // 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);
   }
 }
 
diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp
index 36934010ef8..a7fbe0bd843 100644
--- a/hotspot/src/share/vm/ci/ciEnv.hpp
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp
@@ -153,12 +153,12 @@ private:
   // 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 @@ private:
   // 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.
diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp
index 9c5d98361e0..8fb1e8cbdbf 100644
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.cpp
@@ -283,13 +283,14 @@ void JVMCIEnv::get_field_by_index(instanceKlassHandle accessor, fieldDescriptor&
 // 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 @@ methodHandle JVMCIEnv::get_method_by_index_impl(const constantPoolHandle& cpool,
   }
 
   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()
diff --git a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp
index 2c884494db8..1154a95d567 100644
--- a/hotspot/src/share/vm/jvmci/jvmciEnv.hpp
+++ b/hotspot/src/share/vm/jvmci/jvmciEnv.hpp
@@ -127,7 +127,7 @@ private:
   // 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,
diff --git a/hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java b/hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java
new file mode 100644
index 00000000000..c4100ad2f80
--- /dev/null
+++ b/hotspot/test/compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2.java
@@ -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 {
+}
+

From 2b8e240088fe533cad587360aa10948602ce5dcb Mon Sep 17 00:00:00 2001
From: Igor Veresov 
Date: Mon, 6 Feb 2017 14:20:33 -0800
Subject: [PATCH 09/10] 8173673: Fix comparison input types in
 GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported()

Make sure GraalHotSpotVMConfigNode has correct stamp

Reviewed-by: kvn, never, gdub
---
 .../amd64/AMD64HotSpotLIRGenerator.java       |  7 +-
 .../amd64/AMD64HotSpotLoadConfigValueOp.java  | 26 ++++++-
 .../compiler/hotspot/HotSpotLIRGenerator.java | 23 +++---
 .../nodes/GraalHotSpotVMConfigNode.java       | 72 ++++++++++++-------
 4 files changed, 90 insertions(+), 38 deletions(-)

diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java
index 850faa1c525..bd87349a2d4 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java
@@ -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 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp
     }
 
     @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;
     }
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java
index 28e2c0d6ba6..24b11237bda 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java
@@ -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 @@ package org.graalvm.compiler.hotspot.amd64;
 
 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 @@ public final class AMD64HotSpotLoadConfigValueOp extends AMD64LIRInstruction {
     @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();
         }
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java
index d2c61d89a9d..f2f45e24fec 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java
@@ -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 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
     /**
      * 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 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
     /**
      * 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 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
     /**
      * 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 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
      * {@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 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool {
      * 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();
     }
diff --git a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java
index cdb8160632e..8d0575fe6b5 100644
--- a/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java
+++ b/hotspot/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java
@@ -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 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab
     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
-    private static native long loadConfigValue(@ConstantNodeParameter int markId, @ConstantNodeParameter JavaKind kind);
+    @NodeIntrinsic(setStampFromReturnType = true)
+    private static native long loadLongConfigValue(@ConstantNodeParameter int markId);
+
+    @NodeIntrinsic(setStampFromReturnType = true)
+    private static native int loadIntConfigValue(@ConstantNodeParameter int markId);
+
+    @NodeIntrinsic(setStampFromReturnType = true)
+    private static native byte loadByteConfigValue(@ConstantNodeParameter int markId);
 
     public static long cardTableAddress() {
-        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

From 4dd3138c5d047a477e5ce2d71373e553b6047172 Mon Sep 17 00:00:00 2001
From: Vladimir Kozlov 
Date: Wed, 18 Jan 2017 14:36:54 -0800
Subject: [PATCH 10/10] 8173794: [REDO] [AOT] Missing GC scan of _metaspace_got
 array containing Klass*

Added back _metaspace_got array scan.

Reviewed-by: dlong
---
 .../tools/jaotc/CallSiteRelocationSymbol.java |  6 ----
 .../jaotc/JavaCallSiteRelocationSymbol.java   | 16 +++++++--
 hotspot/src/share/vm/aot/aotCodeHeap.cpp      | 33 ++++---------------
 .../src/share/vm/aot/aotCompiledMethod.cpp    | 27 +++++++--------
 .../src/share/vm/aot/aotCompiledMethod.hpp    |  2 --
 .../src/share/vm/runtime/deoptimization.cpp   |  4 +--
 6 files changed, 35 insertions(+), 53 deletions(-)

diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
index 68f86ef65e3..5fce078a470 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/CallSiteRelocationSymbol.java
@@ -59,12 +59,6 @@ abstract class CallSiteRelocationSymbol {
         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()}.
diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
index a14049dd87f..f589610ded8 100644
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/JavaCallSiteRelocationSymbol.java
@@ -37,6 +37,7 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 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 @@ final class JavaCallSiteRelocationSymbol extends CallSiteRelocationSymbol {
         }
 
         // 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());
         }
diff --git a/hotspot/src/share/vm/aot/aotCodeHeap.cpp b/hotspot/src/share/vm/aot/aotCodeHeap.cpp
index 52e2c8d55b1..87d41f80777 100644
--- a/hotspot/src/share/vm/aot/aotCodeHeap.cpp
+++ b/hotspot/src/share/vm/aot/aotCodeHeap.cpp
@@ -830,38 +830,19 @@ void AOTCodeHeap::oops_do(OopClosure* f) {
   }
 }
 
-// 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 @@ void AOTCodeHeap::metadata_do(void f(Metadata*)) {
       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
 }
diff --git a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp
index 1f40284da7e..c501ce12e69 100644
--- a/hotspot/src/share/vm/aot/aotCompiledMethod.cpp
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.cpp
@@ -71,15 +71,6 @@ static void metadata_oops_do(Metadata** metadata_begin, Metadata **metadata_end,
 }
 #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 @@ Metadata* AOTCompiledMethod::metadata_at(int index) const {
       *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 @@ void AOTCompiledMethod::metadata_do(void f(Metadata*)) {
           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 @@ void AOTCompiledMethod::print_on(outputStream* st, const char* msg) const {
     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));
     }
diff --git a/hotspot/src/share/vm/aot/aotCompiledMethod.hpp b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp
index 7fef6fdb433..723bbdb8d30 100644
--- a/hotspot/src/share/vm/aot/aotCompiledMethod.hpp
+++ b/hotspot/src/share/vm/aot/aotCompiledMethod.hpp
@@ -257,8 +257,6 @@ private:
     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(), "");
diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp
index a656e89643a..7a8ee4253f1 100644
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp
@@ -1597,9 +1597,9 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
       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) {