# HG changeset patch # User Roland Schatz # Date 1372253758 -7200 # Node ID 554f67e4ff3f9814717a23b2bc3666cc43b2245e # Parent 9599e1a018128d81c962836b2f116e9d68121851 Use slow-path stub call instead of deopt in lowering of DynamicNewArrayNode. diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- 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; diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- 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); diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DynamicNewArrayStubCall.java --- /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); +} diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- 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); } /** diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/DynamicNewArrayNode.java --- 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); } diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DynamicNewArrayTest.java --- 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. 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); diff -r 9599e1a01812 -r 554f67e4ff3f graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ArraySubstitutions.java --- 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); } diff -r 9599e1a01812 -r 554f67e4ff3f src/share/vm/graal/graalCompilerToVM.cpp --- 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()); diff -r 9599e1a01812 -r 554f67e4ff3f src/share/vm/graal/graalRuntime.cpp --- 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 diff -r 9599e1a01812 -r 554f67e4ff3f src/share/vm/graal/graalRuntime.hpp --- 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);