changeset 10542:554f67e4ff3f

Use slow-path stub call instead of deopt in lowering of DynamicNewArrayNode.
author Roland Schatz <roland.schatz@oracle.com>
date Wed, 26 Jun 2013 15:35:58 +0200
parents 9599e1a01812
children 97caf20971ed 7b4afef906ca 9d3265486aad
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DynamicNewArrayStubCall.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DynamicNewArrayTest.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java src/share/vm/graal/graalCompilerToVM.cpp src/share/vm/graal/graalRuntime.cpp src/share/vm/graal/graalRuntime.hpp
diffstat 10 files changed, 80 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jun 26 15:22:21 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java	Wed Jun 26 15:35:58 2013 +0200
@@ -408,6 +408,7 @@
     public long newInstanceAddress;
     public long newArrayAddress;
     public long newMultiArrayAddress;
+    public long dynamicNewArrayAddress;
     public long registerFinalizerAddress;
     public long threadIsInterruptedAddress;
     public long vmMessageAddress;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Jun 26 15:22:21 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java	Wed Jun 26 15:35:58 2013 +0200
@@ -32,7 +32,7 @@
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*;
 import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*;
 import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
-import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*;
+import static com.oracle.graal.hotspot.nodes.DynamicNewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*;
 import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*;
@@ -42,6 +42,7 @@
 import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*;
 import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*;
 import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*;
+import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*;
 import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*;
 import static com.oracle.graal.hotspot.stubs.NewArrayStub.*;
 import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*;
@@ -289,6 +290,7 @@
         linkForeignCall(r, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
+        linkForeignCall(r, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_REEXECUTABLE, ANY_LOCATION);
         linkForeignCall(r, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
         linkForeignCall(r, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, REEXECUTABLE, NO_LOCATIONS);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DynamicNewArrayStubCall.java	Wed Jun 26 15:35:58 2013 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, 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 com.oracle.graal.hotspot.nodes;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Node implementing a call to {@code GraalRuntime::dynamic_new_array}.
+ */
+public class DynamicNewArrayStubCall extends ForeignCallNode {
+
+    private static final Stamp defaultStamp = StampFactory.objectNonNull();
+
+    @Input private ValueNode elementType;
+    @Input private ValueNode length;
+
+    public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class);
+
+    public DynamicNewArrayStubCall(MetaAccessProvider runtime, ValueNode elementType, ValueNode length) {
+        super(runtime, DYNAMIC_NEW_ARRAY, defaultStamp);
+        this.elementType = elementType;
+        this.length = length;
+    }
+
+    @Override
+    protected Value[] operands(LIRGeneratorTool gen) {
+        return new Value[]{gen.operand(elementType), gen.operand(length)};
+    }
+
+    @NodeIntrinsic
+    public static native Object call(Class<?> elementType, int length);
+}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Jun 26 15:22:21 2013 +0200
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java	Wed Jun 26 15:35:58 2013 +0200
@@ -101,7 +101,10 @@
             // This handles both negative array sizes and very large array sizes
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint);
         }
+        return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents);
+    }
 
+    private static Object allocateArrayImpl(Word hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents) {
         Object result;
         int alignment = wordSize();
         int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize);
@@ -124,9 +127,8 @@
     @Snippet
     public static Object allocateArrayDynamic(Class<?> elementType, int length, @ConstantParameter boolean fillContents) {
         Word hub = loadWordFromObject(elementType, arrayKlassOffset());
-        if (hub.equal(Word.zero())) {
-            // the array class is not yet loaded
-            DeoptimizeNode.deopt(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved);
+        if (hub.equal(Word.zero()) || !belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) {
+            return DynamicNewArrayStubCall.call(elementType, length);
         }
 
         int layoutHelper = readLayoutHelper(hub);
@@ -147,7 +149,7 @@
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask();
         Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(), PROTOTYPE_MARK_WORD_LOCATION);
 
-        return allocateArray(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents);
+        return allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents);
     }
 
     /**
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Wed Jun 26 15:22:21 2013 +0200
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java	Wed Jun 26 15:35:58 2013 +0200
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.nodes.java;
 
-import java.lang.reflect.*;
-
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
@@ -81,7 +79,5 @@
     }
 
     @NodeIntrinsic
-    public static Object newArray(Class<?> componentType, int length) {
-        return Array.newInstance(componentType, length);
-    }
+    public static native Object newArray(Class<?> componentType, int length);
 }
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DynamicNewArrayTest.java	Wed Jun 26 15:22:21 2013 +0200
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DynamicNewArrayTest.java	Wed Jun 26 15:35:58 2013 +0200
@@ -23,11 +23,9 @@
 package com.oracle.graal.replacements.test;
 
 import java.lang.reflect.*;
-import java.util.*;
 
 import org.junit.*;
 
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.compiler.test.*;
 
 /**
@@ -74,10 +72,12 @@
     }
 
     @Test
-    public void testDeopt() {
+    public void testStub() {
         Method method = getMethod("dynamic");
+        // this will use the stub call because Element[] is not loaded
         Result actual1 = executeActual(method, null, Element.class, 7);
-        Result actual2 = executeActualCheckDeopt(method, Collections.<DeoptimizationReason> singleton(DeoptimizationReason.Unresolved), null, Element.class, 7);
+        // this call will use the fast path
+        Result actual2 = executeActual(method, null, Element.class, 7);
         Result expected = executeExpected(method, null, Element.class, 7);
         assertEquals(actual1, expected);
         assertEquals(actual2, expected);
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java	Wed Jun 26 15:22:21 2013 +0200
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java	Wed Jun 26 15:35:58 2013 +0200
@@ -35,7 +35,7 @@
 public class ArraySubstitutions {
 
     @MethodSubstitution
-    public static Object newArray(Class<?> componentType, int length) throws NegativeArraySizeException {
+    public static Object newInstance(Class<?> componentType, int length) throws NegativeArraySizeException {
         if (componentType == null) {
             DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.NullCheckException);
         }
--- a/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jun 26 15:22:21 2013 +0200
+++ b/src/share/vm/graal/graalCompilerToVM.cpp	Wed Jun 26 15:35:58 2013 +0200
@@ -809,6 +809,7 @@
   set_address("newInstanceAddress", GraalRuntime::new_instance);
   set_address("newArrayAddress", GraalRuntime::new_array);
   set_address("newMultiArrayAddress", GraalRuntime::new_multi_array);
+  set_address("dynamicNewArrayAddress", GraalRuntime::dynamic_new_array);
   set_address("registerFinalizerAddress", SharedRuntime::register_finalizer);
   set_address("threadIsInterruptedAddress", GraalRuntime::thread_is_interrupted);
   set_address("uncommonTrapStub", SharedRuntime::deopt_blob()->uncommon_trap());
--- a/src/share/vm/graal/graalRuntime.cpp	Wed Jun 26 15:22:21 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.cpp	Wed Jun 26 15:35:58 2013 +0200
@@ -29,6 +29,7 @@
 #include "prims/jvm.h"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/reflection.hpp"
 #include "utilities/debug.hpp"
 
 // Simple helper to see if the caller of a runtime stub which
@@ -101,6 +102,11 @@
   thread->set_vm_result(obj);
 JRT_END
 
+JRT_ENTRY(void, GraalRuntime::dynamic_new_array(JavaThread* thread, oop element_mirror, jint length))
+  oop obj = Reflection::reflect_new_array(element_mirror, length, CHECK);
+  thread->set_vm_result(obj);
+JRT_END
+
 extern void vm_exit(int code);
 
 // Enter this method from compiled code handler below. This is where we transition
--- a/src/share/vm/graal/graalRuntime.hpp	Wed Jun 26 15:22:21 2013 +0200
+++ b/src/share/vm/graal/graalRuntime.hpp	Wed Jun 26 15:35:58 2013 +0200
@@ -33,6 +33,7 @@
   static void new_instance(JavaThread* thread, Klass* klass);
   static void new_array(JavaThread* thread, Klass* klass, jint length);
   static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims);
+  static void dynamic_new_array(JavaThread* thread, oop element_mirror, jint length);
   static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte);
   static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3);
   static jint identity_hash_code(JavaThread* thread, oopDesc* objd);