# HG changeset patch # User Lukas Stadler # Date 1399307923 -7200 # Node ID a900caddcd6002ff4a281162ff796c35cf51327c # Parent 6f23b90c4129068d07cde650658f462fa4fe9e76# Parent 2e56c2096ac5254c80256744126b9becf0a95661 Merge (Merge) diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodHandleAccessProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodHandleAccessProvider.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014, 2014, 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.api.replacements; + +import java.lang.invoke.*; + +import com.oracle.graal.api.meta.*; + +/** + * Interface to access the internals of the {@link MethodHandle} implementation of the VM. An + * implementation of this interface is usually required to access non-public classes, methods, and + * fields of {@link MethodHandle}, i.e., data that is not standardized by the Java specification. + */ +public interface MethodHandleAccessProvider { + + /** + * Identification for methods defined on the class {@link MethodHandle} that are processed by + * the {@link MethodHandleAccessProvider}. + */ + public enum IntrinsicMethod { + /** The method {@code MethodHandle.invokeBasic}. */ + INVOKE_BASIC, + /** The method {@code MethodHandle.linkToStatic}. */ + LINK_TO_STATIC, + /** The method {@code MethodHandle.linkToSpecial}. */ + LINK_TO_SPECIAL, + /** The method {@code MethodHandle.linkToVirtual}. */ + LINK_TO_VIRTUAL, + /** The method {@code MethodHandle.linkToInterface}. */ + LINK_TO_INTERFACE + } + + /** + * Returns the method handle method intrinsic identifier for the provided method, or + * {@code null} if the method is not an intrinsic processed by this interface. + */ + IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method); + + /** + * Resolves the invocation target for an invocation of {@link IntrinsicMethod#INVOKE_BASIC + * MethodHandle.invokeBasic} with the given constant receiver {@link MethodHandle}. Returns + * {@code null} if the invocation target is not available at this time. + *

+ * The first invocations of a method handle can use an interpreter to lookup the actual invoked + * method; frequently executed method handles can use Java bytecode generation to avoid the + * interpreter overhead. If the parameter forceBytecodeGeneration is set to true, the VM should + * try to generate bytecodes before this method returns. + */ + ResolvedJavaMethod resolveInvokeBasicTarget(Constant methodHandle, boolean forceBytecodeGeneration); + + /** + * Resolves the invocation target for an invocation of a {@code MethodHandle.linkTo*} method + * with the given constant member name. The member name is the last parameter of the + * {@code linkTo*} method. Returns {@code null} if the invocation target is not available at + * this time. + */ + ResolvedJavaMethod resolveLinkToTarget(Constant memberName); +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java --- a/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.asm.hsail/src/com/oracle/graal/asm/hsail/HSAILAssembler.java Mon May 05 18:38:43 2014 +0200 @@ -190,16 +190,9 @@ emitString("st_spill_" + getArgTypeFromKind(kind) + " " + HSAIL.mapRegister(src) + ", " + mapStackSlot(dest, getArgSizeFromKind(kind)) + ";"); } - /** - * The mapping to stack slots is always relative to the beginning of the spillseg. - * HSAIL.getStackOffset returns the positive version of the originally negative offset. Then we - * back up from that by the argSize in bytes. This ensures that slots of different size do not - * overlap, even though we have converted from negative to positive offsets. - */ public static String mapStackSlot(Value reg, int argSize) { - long offset = HSAIL.getStackOffset(reg); - int argSizeBytes = argSize / 8; - return "[%spillseg]" + "[" + (offset - argSizeBytes) + "]"; + long startOffset = HSAIL.getStackOffsetStart(reg, argSize); + return "[%spillseg]" + "[" + startOffset + "]"; } public void cbr(String target1) { diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/ForceDeoptSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/ForceDeoptSubstitutions.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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.compiler.hsail.test.infra; + +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.api.meta.*; + +@ClassSubstitution(GraalKernelTester.class) +class ForceDeoptSubstitutions { + + /** + * Allows us to force a non-exception throwing deopt from java code. + */ + @MethodSubstitution + public static int forceDeopt(int x) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + // will never get here but keep the compiler happy + return x * x; + } + + @MethodSubstitution + public static double forceDeopt(double x) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + // will never get here but keep the compiler happy + return x * x; + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java --- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/GraalKernelTester.java Mon May 05 18:38:43 2014 +0200 @@ -50,8 +50,18 @@ public abstract class GraalKernelTester extends KernelTester { + private static boolean substitutionsInstalled; + + private static synchronized void installSubstitutions() { + if (!substitutionsInstalled) { + getHSAILBackend().getProviders().getReplacements().registerSubstitutions(ForceDeoptSubstitutions.class); + substitutionsInstalled = true; + } + } + public GraalKernelTester() { super(getHSAILBackend().isDeviceInitialized()); + installSubstitutions(); } protected static HSAILHotSpotBackend getHSAILBackend() { @@ -193,4 +203,14 @@ super.testGeneratedHsailUsingLambdaMethod(); } } + + // used for forcing a deoptimization + public static int forceDeopt(int x) { + return x * x; + } + + public static double forceDeopt(double x) { + return x * x; + } + } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DVec3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DVec3.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +/** + * A simple 3 element Vector object used in some junit tests. + */ +public class DVec3 { + + public DVec3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public double x; + public double y; + public double z; + + public static DVec3 add(DVec3 a, DVec3 b) { + return new DVec3(a.x + b.x, a.y + b.y, a.z + b.z); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof DVec3)) { + return false; + } + DVec3 oth = (DVec3) other; + return (oth.x == x && oth.y == y && oth.z == z); + } + + @Override + public String toString() { + return ("DVec3[" + x + ", " + y + ", " + z + "]"); + } + + @Override + public int hashCode() { + return (int) (x + y + z); + } + +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptBase.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import java.util.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Base class for testing deopt when objects are in stack slots. + */ +public abstract class ObjSpillDeoptBase extends GraalKernelTester { + + abstract int getSize(); + + int loopcount = 5; + int objcount = 20; + @Result double[] out = new double[getSize()]; + @Result double[] aux = new double[getSize()]; + DVec3[] in = new DVec3[objcount]; + + public void doCompute(int gid, boolean causeDeopt) { + int idx = gid * 2 + 7; + DVec3 v0 = in[(idx++) % objcount]; + DVec3 v1 = in[(idx++) % objcount]; + DVec3 v2 = in[(idx++) % objcount]; + DVec3 v3 = in[(idx++) % objcount]; + DVec3 v4 = in[(idx++) % objcount]; + DVec3 v5 = in[(idx++) % objcount]; + DVec3 v6 = in[(idx++) % objcount]; + DVec3 v7 = in[(idx++) % objcount]; + DVec3 v8 = in[(idx++) % objcount]; + DVec3 v9 = in[(idx++) % objcount]; + idx += gid; + DVec3 v10 = in[(idx++) % objcount]; + DVec3 v11 = in[(idx++) % objcount]; + DVec3 v12 = in[(idx++) % objcount]; + DVec3 v13 = in[(idx++) % objcount]; + DVec3 v14 = in[(idx++) % objcount]; + DVec3 v15 = in[(idx++) % objcount]; + DVec3 v16 = in[(idx++) % objcount]; + DVec3 v17 = in[(idx++) % objcount]; + DVec3 v18 = in[(idx++) % objcount]; + DVec3 v19 = in[(idx++) % objcount]; + double sum = 0.0; + double sum1 = 0.0; + double sum2 = 0.0; + for (int i = 0; i < loopcount; i++) { + sum1 += v0.x + v1.y + v2.z + v3.x + v4.y + v5.z + v6.x + v7.y + v8.z + v9.x + i; + sum2 += v10.y + v11.z + v12.x + v13.y + v14.z + v15.x + v16.y + v17.z + v18.x + v19.y - i; + sum += sum1 - sum2 + i; + aux[gid] += sum1 + 1.2345; + } + if (causeDeopt) { + aux[gid] += forceDeopt(sum1); + } + out[gid] += sum; + } + + @Override + public void runTest() { + Arrays.fill(out, -1.0); + for (int i = 0; i < objcount; i++) { + in[i] = new DVec3(i / 10f, (i + 1) / 10f, (i + 2) / 10f); + } + dispatchMethodKernel(getSize()); + } + +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany20000Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany20000Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, with many items deopting. + */ +public class ObjSpillDeoptMany20000Test extends ObjSpillDeoptManyBase { + + @Override + int getSize() { + return 20000; + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany5000Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany5000Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, with many items deopting. + */ +public class ObjSpillDeoptMany5000Test extends ObjSpillDeoptManyBase { + + @Override + int getSize() { + return 5000; + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany99999Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMany99999Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, with many items deopting. + */ +public class ObjSpillDeoptMany99999Test extends ObjSpillDeoptManyBase { + + @Override + int getSize() { + return 99999; + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptManyBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptManyBase.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +/** + * Base class for testing deopt with objects in stack slots, with many items deopting. + */ +public abstract class ObjSpillDeoptManyBase extends ObjSpillDeoptBase { + + public void run(int gid) { + boolean causeDeopt = (gid < 4096 && gid % 512 == 1); + doCompute(gid, causeDeopt); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost20000Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost20000Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, with most items deopting. + */ +public class ObjSpillDeoptMost20000Test extends ObjSpillDeoptMostBase { + + @Override + int getSize() { + return 20000; + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost5000Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost5000Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, with most items deopting. + */ +public class ObjSpillDeoptMost5000Test extends ObjSpillDeoptMostBase { + + @Override + int getSize() { + return 5000; + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost99999Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMost99999Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, with most items deopting. + */ +public class ObjSpillDeoptMost99999Test extends ObjSpillDeoptMostBase { + + @Override + int getSize() { + return 99999; + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMostBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptMostBase.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +/** + * Base class for testing deopt with objects in stack slots. + */ +public abstract class ObjSpillDeoptMostBase extends ObjSpillDeoptBase { + + public void run(int gid) { + boolean causeDeopt = (gid % 500 != 1); + doCompute(gid, causeDeopt); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle100Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle100Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, one item deopting. + */ +public class ObjSpillDeoptSingle100Test extends ObjSpillDeoptBase { + + final int size = 100; + + @Override + int getSize() { + return size; + } + + public void run(int gid) { + boolean causeDeopt = (gid == size / 2); + doCompute(gid, causeDeopt); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle20000Test.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/ObjSpillDeoptSingle20000Test.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import org.junit.*; + +/** + * Tests deopt with objects in stack slots, one item deopting. + */ +public class ObjSpillDeoptSingle20000Test extends ObjSpillDeoptBase { + + final int size = 20000; + + @Override + int getSize() { + return size; + } + + public void run(int gid) { + boolean causeDeopt = (gid == size / 2); + doCompute(gid, causeDeopt); + } + + @Test + public void test() { + testGeneratedHsail(); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchOneTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchOneTest.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests the spilling of double variables into memory with deopt + */ +public class StaticDoubleSpillBoundsCatchOneTest extends GraalKernelTester { + + static final int size = 100; + private double[] in = new double[size * 400]; + @Result public double[] out = new double[size * 400]; + @Result public double[] aux = new double[2]; + + public static void run(double[] out, double[] in, double[] aux, int gid) { + int id = gid; + int step = 20; + double sum0; + double sum1; + double sum2; + double sum3; + double sum4; + double sum5; + double sum6; + double sum7; + double sum8; + double sum9; + double sum10; + double sum11; + double sum12; + double sum13; + double sum14; + double sum15; + double sum16; + double sum17; + double sum18; + double sum19; + sum0 = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = sum8 = sum9 = 0; + sum10 = sum11 = sum12 = sum13 = sum14 = sum15 = sum16 = sum17 = sum18 = sum19 = 0; + try { + for (int i = 0; i < size; i += step) { + sum0 += in[i + 0]; + sum1 += in[i + 1]; + sum2 += in[i + 2]; + sum3 += in[i + 3]; + sum4 += in[i + 4]; + sum5 += in[i + 5]; + sum6 += in[i + 6]; + sum7 += in[i + 7]; + sum8 += in[i + 8]; + sum9 += in[i + 9]; + sum10 += in[i + 0]; + sum11 += in[i + 1]; + sum12 += in[i + 2]; + sum13 += in[i + 3]; + sum14 += in[i + 4]; + sum15 += in[i + 5]; + sum16 += in[i + 6]; + sum17 += in[i + 7]; + sum18 += in[i + 8]; + sum19 += in[i + 9]; + + if (id == size / 2) { + aux[id] = sum1 + sum2 + sum3 + sum4 + sum5 + sum6 + sum7 + sum8 + sum9 + sum10 + sum11 + sum12 + sum13 + sum14 + sum15 + sum16; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + aux[0] += sum1 + sum2; + } + + out[id * step + 0] = sum0; + out[id * step + 1] = sum1; + out[id * step + 2] = sum2; + out[id * step + 3] = sum3; + out[id * step + 4] = sum4; + out[id * step + 5] = sum5; + out[id * step + 6] = sum6; + out[id * step + 7] = sum7; + out[id * step + 8] = sum8; + out[id * step + 9] = sum9; + out[id * step + 10] = sum10; + out[id * step + 11] = sum11; + out[id * step + 12] = sum12; + out[id * step + 13] = sum13; + out[id * step + 14] = sum14; + out[id * step + 15] = sum15; + out[id * step + 16] = sum16; + out[id * step + 17] = sum17; + out[id * step + 18] = sum18; + out[id * step + 19] = sum19; + } + + @Override + public void runTest() { + /** + * Call it for a range, specifying testmethod args (but not the fields it uses or the gid + * argument). + * + */ + Arrays.fill(out, -1f); + for (int i = 0; i < size; i++) { + in[i] = i + 1; + } + dispatchMethodKernel(size, out, in, aux); + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillBoundsCatchTest.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2009, 2012, 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.compiler.hsail.test; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.compiler.hsail.test.infra.*; + +/** + * Tests the spilling of double variables into memory with deopt + */ +public class StaticDoubleSpillBoundsCatchTest extends GraalKernelTester { + + static final int size = 100; + private double[] in = new double[size * 400]; + @Result public double[] out = new double[size * 400]; + @Result public double[] aux = new double[size]; + + public static void run(double[] out, double[] in, double[] aux, int gid) { + int id = gid; + int step = 20; + double sum0; + double sum1; + double sum2; + double sum3; + double sum4; + double sum5; + double sum6; + double sum7; + double sum8; + double sum9; + double sum10; + double sum11; + double sum12; + double sum13; + double sum14; + double sum15; + double sum16; + double sum17; + double sum18; + double sum19; + sum0 = sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = sum7 = sum8 = sum9 = 0; + sum10 = sum11 = sum12 = sum13 = sum14 = sum15 = sum16 = sum17 = sum18 = sum19 = 0; + try { + for (int i = 0; i < size; i += step) { + sum0 += in[i + 0]; + sum1 += in[i + 1]; + sum2 += in[i + 2]; + sum3 += in[i + 3]; + sum4 += in[i + 4]; + sum5 += in[i + 5]; + sum6 += in[i + 6]; + sum7 += in[i + 7]; + sum8 += in[i + 8]; + sum9 += in[i + 9]; + sum10 += in[i + 0]; + sum11 += in[i + 1]; + sum12 += in[i + 2]; + sum13 += in[i + 3]; + sum14 += in[i + 4]; + sum15 += in[i + 5]; + sum16 += in[i + 6]; + sum17 += in[i + 7]; + sum18 += in[i + 8]; + sum19 += in[i + 9]; + + if (id > size / 2) { + aux[id + 10] += sum1 + sum2; + // + sum3 + sum4 + sum5 + sum6 + sum7 + sum8 + sum9 + sum10 + sum11 + sum12 + + // sum13 + sum14 + sum15 + sum16; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + aux[id] += sum1 + sum2; + } + + out[id * step + 0] = sum0; + out[id * step + 1] = sum1; + out[id * step + 2] = sum2; + out[id * step + 3] = sum3; + out[id * step + 4] = sum4; + out[id * step + 5] = sum5; + out[id * step + 6] = sum6; + out[id * step + 7] = sum7; + out[id * step + 8] = sum8; + out[id * step + 9] = sum9; + out[id * step + 10] = sum10; + out[id * step + 11] = sum11; + out[id * step + 12] = sum12; + out[id * step + 13] = sum13; + out[id * step + 14] = sum14; + out[id * step + 15] = sum15; + out[id * step + 16] = sum16; + out[id * step + 17] = sum17; + out[id * step + 18] = sum18; + out[id * step + 19] = sum19; + } + + @Override + public void runTest() { + /** + * Call it for a range, specifying testmethod args (but not the fields it uses or the gid + * argument). + * + */ + Arrays.fill(out, -1f); + Arrays.fill(aux, 0f); + for (int i = 0; i < size; i++) { + in[i] = i + 1; + } + dispatchMethodKernel(size, out, in, aux); + } + + @Test + public void test() { + testGeneratedHsail(); + } + +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java Mon May 05 18:38:43 2014 +0200 @@ -113,13 +113,14 @@ * argument). * */ - Arrays.fill(out, 0f); - Arrays.fill(in, 0f); + Arrays.fill(out, -1f); + for (int i = 0; i < size; i++) { + in[i] = i + 1; + } dispatchMethodKernel(size, out, in); } @Test - @Ignore("until stack slots are supported in deopt") public void test() { testGeneratedHsail(); } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java Mon May 05 18:38:43 2014 +0200 @@ -88,7 +88,6 @@ } @Test - @Ignore("until stack slots are supported in deopt") public void test() { testGeneratedHsail(); } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon May 05 18:38:43 2014 +0200 @@ -37,20 +37,10 @@ import com.oracle.graal.lir.StandardOp.JumpOp; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; -import com.oracle.graal.lir.hsail.HSAILArithmetic.ConvertOp; -import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Stack; +import com.oracle.graal.lir.hsail.HSAILArithmetic.Op1Reg; import com.oracle.graal.lir.hsail.HSAILArithmetic.Op2Reg; -import com.oracle.graal.lir.hsail.HSAILArithmetic.Op2Stack; -import com.oracle.graal.lir.hsail.HSAILArithmetic.ShiftOp; -import com.oracle.graal.lir.hsail.HSAILControlFlow.CompareBranchOp; -import com.oracle.graal.lir.hsail.HSAILControlFlow.CondMoveOp; -import com.oracle.graal.lir.hsail.HSAILControlFlow.FloatCondMoveOp; -import com.oracle.graal.lir.hsail.HSAILControlFlow.ReturnOp; -import com.oracle.graal.lir.hsail.HSAILControlFlow.StrategySwitchOp; -import com.oracle.graal.lir.hsail.HSAILMove.LeaOp; -import com.oracle.graal.lir.hsail.HSAILMove.MembarOp; -import com.oracle.graal.lir.hsail.HSAILMove.MoveFromRegOp; -import com.oracle.graal.lir.hsail.HSAILMove.MoveToRegOp; +import com.oracle.graal.lir.hsail.HSAILControlFlow.*; +import com.oracle.graal.lir.hsail.HSAILMove.*; import com.oracle.graal.phases.util.*; /** @@ -262,16 +252,16 @@ case Int: // Note: The Int case also handles the negation of shorts, bytes, and chars because // Java treats these types as ints at the bytecode level. - append(new Op1Stack(INEG, result, input)); + append(new Op1Reg(INEG, result, input)); break; case Long: - append(new Op1Stack(LNEG, result, input)); + append(new Op1Reg(LNEG, result, input)); break; case Double: - append(new Op1Stack(DNEG, result, input)); + append(new Op1Reg(DNEG, result, input)); break; case Float: - append(new Op1Stack(FNEG, result, input)); + append(new Op1Reg(FNEG, result, input)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -293,10 +283,10 @@ case Int: // Note: The Int case also covers other primitive integral types smaller than an int // (char, byte, short) because Java treats these types as ints. - append(new Op1Stack(INOT, result, input)); + append(new Op1Reg(INOT, result, input)); break; case Long: - append(new Op1Stack(LNOT, result, input)); + append(new Op1Reg(LNOT, result, input)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -309,16 +299,16 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IADD, result, a, loadNonConst(b))); + append(new Op2Reg(IADD, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LADD, result, a, loadNonConst(b))); + append(new Op2Reg(LADD, result, a, loadNonConst(b))); break; case Float: - append(new Op2Stack(FADD, result, a, loadNonConst(b))); + append(new Op2Reg(FADD, result, a, loadNonConst(b))); break; case Double: - append(new Op2Stack(DADD, result, a, loadNonConst(b))); + append(new Op2Reg(DADD, result, a, loadNonConst(b))); break; case Object: throw GraalInternalError.shouldNotReachHere(); @@ -334,19 +324,19 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IADD, result, a, loadNonConst(b))); + append(new Op2Reg(IADD, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LADD, result, a, loadNonConst(b))); + append(new Op2Reg(LADD, result, a, loadNonConst(b))); break; case Float: - append(new Op2Stack(FADD, result, a, loadNonConst(b))); + append(new Op2Reg(FADD, result, a, loadNonConst(b))); break; case Double: - append(new Op2Stack(DADD, result, a, loadNonConst(b))); + append(new Op2Reg(DADD, result, a, loadNonConst(b))); break; case Object: - append(new Op2Stack(OADD, result, a, loadNonConst(b))); + append(new Op2Reg(OADD, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -359,16 +349,16 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(ISUB, result, a, loadNonConst(b))); + append(new Op2Reg(ISUB, result, a, loadNonConst(b))); break; case Float: - append(new Op2Stack(FSUB, result, a, loadNonConst(b))); + append(new Op2Reg(FSUB, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LSUB, result, a, loadNonConst(b))); + append(new Op2Reg(LSUB, result, a, loadNonConst(b))); break; case Double: - append(new Op2Stack(DSUB, result, a, loadNonConst(b))); + append(new Op2Reg(DSUB, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -418,16 +408,16 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IDIV, result, a, loadNonConst(b))); + append(new Op2Reg(IDIV, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LDIV, result, a, loadNonConst(b))); + append(new Op2Reg(LDIV, result, a, loadNonConst(b))); break; case Float: - append(new Op2Stack(FDIV, result, a, loadNonConst(b))); + append(new Op2Reg(FDIV, result, a, loadNonConst(b))); break; case Double: - append(new Op2Stack(DDIV, result, a, loadNonConst(b))); + append(new Op2Reg(DDIV, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -441,16 +431,16 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IREM, result, a, loadNonConst(b))); + append(new Op2Reg(IREM, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LREM, result, a, loadNonConst(b))); + append(new Op2Reg(LREM, result, a, loadNonConst(b))); break; case Float: - append(new Op2Stack(FREM, result, a, loadNonConst(b))); + append(new Op2Reg(FREM, result, a, loadNonConst(b))); break; case Double: - append(new Op2Stack(DREM, result, a, loadNonConst(b))); + append(new Op2Reg(DREM, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -473,10 +463,10 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IAND, result, a, loadNonConst(b))); + append(new Op2Reg(IAND, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LAND, result, a, loadNonConst(b))); + append(new Op2Reg(LAND, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -489,10 +479,10 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IOR, result, a, loadNonConst(b))); + append(new Op2Reg(IOR, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LOR, result, a, loadNonConst(b))); + append(new Op2Reg(LOR, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -505,10 +495,10 @@ Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IXOR, result, a, loadNonConst(b))); + append(new Op2Reg(IXOR, result, a, loadNonConst(b))); break; case Long: - append(new Op2Stack(LXOR, result, a, loadNonConst(b))); + append(new Op2Reg(LXOR, result, a, loadNonConst(b))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -720,7 +710,7 @@ @Override public Value emitMathAbs(Value input) { Variable result = newVariable(input.getPlatformKind()); - append(new Op1Stack(ABS, result, input)); + append(new Op1Reg(ABS, result, input)); return result; } @@ -732,7 +722,7 @@ */ public Value emitMathCeil(Value input) { Variable result = newVariable(input.getPlatformKind()); - append(new Op1Stack(CEIL, result, input)); + append(new Op1Reg(CEIL, result, input)); return result; } @@ -744,7 +734,7 @@ */ public Value emitMathFloor(Value input) { Variable result = newVariable(input.getPlatformKind()); - append(new Op1Stack(FLOOR, result, input)); + append(new Op1Reg(FLOOR, result, input)); return result; } @@ -756,7 +746,7 @@ */ public Value emitMathRint(Value input) { Variable result = newVariable(input.getPlatformKind()); - append(new Op1Stack(RINT, result, input)); + append(new Op1Reg(RINT, result, input)); return result; } @@ -769,7 +759,7 @@ @Override public Value emitMathSqrt(Value input) { Variable result = newVariable(input.getPlatformKind()); - append(new Op1Stack(SQRT, result, input)); + append(new Op1Reg(SQRT, result, input)); return result; } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java --- a/graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.gpu/src/com/oracle/graal/gpu/ExternalCompilationResult.java Mon May 05 18:38:43 2014 +0200 @@ -43,6 +43,8 @@ private long entryPoint; private StructuredGraph hostGraph; + private int[] oopMapArray; + /** * Set the address for the point of entry to the external compilation result. * @@ -75,4 +77,13 @@ public StructuredGraph getHostGraph() { return hostGraph; } + + public void setOopMapArray(int[] arr) { + oopMapArray = arr; + } + + public int[] getOopMapArray() { + return oopMapArray; + } + } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon May 05 18:38:43 2014 +0200 @@ -113,7 +113,9 @@ Replacements replacements = createReplacements(runtime, assumptions, p, snippetReflection); HotSpotDisassemblerProvider disassembler = createDisassembler(runtime); HotSpotSuitesProvider suites = createSuites(runtime); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); + HotSpotMethodHandleAccessProvider methodHandleAccess = new HotSpotMethodHandleAccessProvider(); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection, + methodHandleAccess); return createBackend(runtime, providers); } @@ -189,15 +191,15 @@ } else { /* * System V Application Binary Interface, AMD64 Architecture Processor Supplement - * + * * Draft Version 0.96 - * + * * http://www.uclibc.org/docs/psABI-x86_64.pdf - * + * * 3.2.1 - * + * * ... - * + * * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 * through %r15 "belong" to the calling function and the called function is required to * preserve their values. In other words, a called function must preserve these diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon May 05 18:38:43 2014 +0200 @@ -66,7 +66,6 @@ import com.oracle.graal.lir.hsail.HSAILMove.AtomicReadAndAddOp; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; @@ -145,7 +144,21 @@ */ public HotSpotNmethod compileAndInstallKernel(Method method) { ResolvedJavaMethod javaMethod = getProviders().getMetaAccess().lookupJavaMethod(method); - return installKernel(javaMethod, compileKernel(javaMethod, true)); + HotSpotNmethod nm = installKernel(javaMethod, compileKernel(javaMethod, true)); + try (Scope s = Debug.scope("HostCodeGen")) { + if (Debug.isLogEnabled()) { + DisassemblerProvider dis = getRuntime().getHostBackend().getDisassembler(); + if (dis != null) { + String disasm = dis.disassemble(nm); + Debug.log("host code generated for %s%n%s", javaMethod, disasm); + } else { + Debug.log("host code disassembler is null"); + } + } + } catch (Throwable e) { + throw Debug.handle(e); + } + return nm; } /** @@ -274,7 +287,8 @@ } } - HotSpotNmethod code = new HotSpotNmethod(javaMethod, hsailCode.getName(), false, true); + HSAILHotSpotNmethod code = new HSAILHotSpotNmethod(javaMethod, hsailCode.getName(), false, true); + code.setOopMapArray(hsailCode.getOopMapArray()); HotSpotCompiledNmethod compiled = new HotSpotCompiledNmethod(getTarget(), javaMethod, compilationResult); CodeInstallResult result = getRuntime().getCompilerToVM().installCode(compiled, code, null); if (result != CodeInstallResult.OK) { @@ -359,11 +373,16 @@ if (!deviceInitialized) { throw new GraalInternalError("Cannot execute GPU kernel if device is not initialized"); } - Object[] oopsSaveArea = new Object[maxDeoptIndex * 16]; - return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue()); + int[] oopMapArray = ((HSAILHotSpotNmethod) kernel).getOopMapArray(); + int saveAreaCounts = OopMapArrayBuilder.getSaveAreaCounts(oopMapArray); + int numDRegs = (saveAreaCounts >> 8) & 0xff; + int numStackSlots = (saveAreaCounts >> 16); + // pessimistically assume that any of the DRegs or stackslots could be oops + Object[] oopsSaveArea = new Object[maxDeoptIndex * (numDRegs + numStackSlots)]; + return executeKernel0(kernel, jobSize, args, oopsSaveArea, donorThreadPool.get().getThreads(), HsailAllocBytesPerWorkitem.getValue(), oopMapArray); } - private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem) + private static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args, Object[] oopsSave, Thread[] donorThreads, int allocBytesPerWorkitem, int[] oopMapArray) throws InvalidInstalledCodeException; /** @@ -419,6 +438,22 @@ } } + static class HSAILHotSpotNmethod extends HotSpotNmethod { + private int[] oopMapArray; + + HSAILHotSpotNmethod(HotSpotResolvedJavaMethod method, String name, boolean isDefault, boolean isExternal) { + super(method, name, isDefault, isExternal); + } + + void setOopMapArray(int[] array) { + oopMapArray = array; + } + + int[] getOopMapArray() { + return oopMapArray; + } + } + @Override protected Assembler createAssembler(FrameMap frameMap) { return new HSAILHotSpotAssembler(getTarget()); @@ -686,10 +721,54 @@ asm.emitString(spillsegStringFinal, spillsegDeclarationPosition); // Emit the epilogue. - // TODO: keep track of whether we need it + int numSRegs = 0; + int numDRegs = 0; + int numStackSlotBytes = 0; if (useHSAILDeoptimization) { + // get the union of registers and stack slots needed to be saved at the infopoints + // while doing this compute the highest register in each category + HSAILHotSpotRegisterConfig hsailRegConfig = (HSAILHotSpotRegisterConfig) regConfig; + Set infoUsedRegs = new TreeSet<>(); + Set infoUsedStackSlots = new HashSet<>(); + List infoList = crb.compilationResult.getInfopoints(); + for (Infopoint info : infoList) { + BytecodeFrame frame = info.debugInfo.frame(); + while (frame != null) { + for (int i = 0; i < frame.numLocals + frame.numStack; i++) { + Value val = frame.values[i]; + if (isLegal(val)) { + if (isRegister(val)) { + Register reg = asRegister(val); + infoUsedRegs.add(reg); + if (hsailRegConfig.isAllocatableSReg(reg)) { + numSRegs = Math.max(numSRegs, reg.encoding + 1); + } else if (hsailRegConfig.isAllocatableDReg(reg)) { + numDRegs = Math.max(numDRegs, reg.encoding + 1); + } + } else if (isStackSlot(val)) { + StackSlot slot = asStackSlot(val); + Kind slotKind = slot.getKind(); + int slotSizeBytes = (slotKind.isObject() ? 8 : slotKind.getByteCount()); + int slotOffsetMax = HSAIL.getStackOffsetStart(slot, slotSizeBytes * 8) + slotSizeBytes; + numStackSlotBytes = Math.max(numStackSlotBytes, slotOffsetMax); + infoUsedStackSlots.add(slot); + } + } + } + frame = frame.caller(); + } + } + + // round up numSRegs to even number so dregs start on aligned boundary + numSRegs += (numSRegs & 1); + + // numStackSlots is the number of 8-byte locations used for stack variables + int numStackSlots = (numStackSlotBytes + 7) / 8; + final int offsetToDeoptSaveStates = config.hsailSaveStatesOffset0; - final int sizeofKernelDeopt = config.hsailSaveStatesOffset1 - config.hsailSaveStatesOffset0; + final int sizeofKernelDeoptHeader = config.hsailKernelDeoptimizationHeaderSize; + final int bytesPerSaveArea = 4 * numSRegs + 8 * numDRegs + 8 * numStackSlots; + final int sizeofKernelDeopt = sizeofKernelDeoptHeader + bytesPerSaveArea; final int offsetToNeverRanArray = config.hsailNeverRanArrayOffset; final int offsetToDeoptNextIndex = config.hsailDeoptNextIndexOffset; final int offsetToDeoptimizationWorkItem = config.hsailDeoptimizationWorkItem; @@ -708,7 +787,6 @@ AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); AllocatableValue scratch32 = HSAIL.s34.asValue(Kind.Int); AllocatableValue workidreg = HSAIL.s35.asValue(Kind.Int); - AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int); HSAILAddress deoptNextIndexAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToDeoptNextIndex).toAddress(); HSAILAddress neverRanArrayAddr = new HSAILAddressValue(Kind.Int, scratch64, offsetToNeverRanArray).toAddress(); @@ -769,8 +847,6 @@ // Now scratch64 is the _deopt_info._first_frame HSAILAddress pcStoreAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToFramePc).toAddress(); HSAILAddress regCountsAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToNumSaves).toAddress(); - HSAILAddress dregOopMapAddr = new HSAILAddressValue(Kind.Int, waveMathScratch1, offsetToNumSaves + 2).toAddress(); - asm.emitComment("// store deopting workitem"); asm.emitWorkItemAbsId(scratch32); asm.emitStore(Kind.Int, scratch32, workItemAddr); @@ -778,58 +854,61 @@ asm.emitStore(Kind.Int, actionAndReasonReg, actionReasonStoreAddr); asm.emitComment("// store PC"); asm.emitStore(Kind.Int, codeBufferOffsetReg, pcStoreAddr); - asm.emitComment("// store regCounts"); - asm.emitStore(Kind.Short, Constant.forInt(32 + (16 << 8) + (0 << 16)), regCountsAddr); - asm.emitComment("// store dreg ref map bits"); - asm.emitStore(Kind.Short, dregOopMapReg, dregOopMapAddr); + + asm.emitComment("// store regCounts (" + numSRegs + " $s registers and " + numDRegs + " $d registers" + numStackSlots + " stack slots)"); + asm.emitStore(Kind.Int, Constant.forInt(numSRegs + (numDRegs << 8) + (numStackSlots << 16)), regCountsAddr); - // get the union of registers needed to be saved at the infopoints - boolean[] infoUsedRegs = new boolean[HSAIL.threadRegister.number + 1]; - List infoList = crb.compilationResult.getInfopoints(); - for (Infopoint info : infoList) { - BytecodeFrame frame = info.debugInfo.frame(); - for (int i = 0; i < frame.numLocals + frame.numStack; i++) { - Value val = frame.values[i]; - if (isLegal(val) && isRegister(val)) { - Register reg = asRegister(val); - infoUsedRegs[reg.number] = true; - } + // loop thru the usedValues storing each of the registers that are used. + // we always store in a fixed location, even if some registers are skipped + asm.emitComment("// store used regs"); + for (Register reg : infoUsedRegs) { + if (hsailRegConfig.isAllocatableSReg(reg)) { + // 32 bit registers + Kind kind = Kind.Int; + int ofst = offsetToSaveArea + reg.encoding * 4; + HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); + AllocatableValue regValue = reg.asValue(kind); + asm.emitStore(kind, regValue, addr); + } else if (hsailRegConfig.isAllocatableDReg(reg)) { + // 64 bit registers + Kind kind = Kind.Long; + // d reg ofst starts past the 32 sregs + int ofst = offsetToSaveArea + (numSRegs * 4) + reg.encoding * 8; + HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); + AllocatableValue regValue = reg.asValue(kind); + asm.emitStore(kind, regValue, addr); + } else { + throw GraalInternalError.unimplemented(); } } - // loop storing each of the 32 s registers that are used by infopoints - // we always store in a fixed location, even if some registers are not stored - asm.emitComment("// store used s regs"); - int ofst = offsetToSaveArea; - for (Register sreg : HSAIL.sRegisters) { - if (infoUsedRegs[sreg.number]) { - Kind kind = Kind.Int; + // loop thru the usedStackSlots creating instructions to save in the save area + if (numStackSlotBytes > 0) { + asm.emitComment("// store stack slots (uses " + numStackSlotBytes + " bytes)"); + for (StackSlot slot : infoUsedStackSlots) { + asm.emitComment("// store " + slot); + Kind kind = slot.getKind(); + int sizeInBits = (kind.isObject() || kind.getByteCount() == 8 ? 64 : 32); + int ofst = offsetToSaveArea + (numSRegs * 4) + (numDRegs * 8) + HSAIL.getStackOffsetStart(slot, sizeInBits); HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); - AllocatableValue sregValue = sreg.asValue(kind); - asm.emitStore(kind, sregValue, addr); + if (sizeInBits == 64) { + asm.emitSpillLoad(kind, scratch64, slot); + asm.emitStore(kind, scratch64, addr); + } else { + asm.emitSpillLoad(kind, scratch32, slot); + asm.emitStore(kind, scratch32, addr); + } } - ofst += 4; } - // loop storing each of the 16 d registers that are used by infopoints - asm.emitComment("// store used d regs"); - for (Register dreg : HSAIL.dRegisters) { - if (infoUsedRegs[dreg.number]) { - Kind kind = Kind.Long; - HSAILAddress addr = new HSAILAddressValue(kind, waveMathScratch1, ofst).toAddress(); - AllocatableValue dregValue = dreg.asValue(kind); - asm.emitStore(kind, dregValue, addr); - } - ofst += 8; - } - - // for now, ignore saving the spill variables but that would come here - asm.emitString0(labelExit + ":\n"); // and emit the return crb.frameContext.leave(crb); asm.exit(); + // build the oopMap Array + int[] oopMapArray = new OopMapArrayBuilder().build(infoList, numSRegs, numDRegs, numStackSlots, hsailRegConfig); + ((ExternalCompilationResult) crb.compilationResult).setOopMapArray(oopMapArray); } else { // Deoptimization is explicitly off, so emit simple return asm.emitString0(asm.getDeoptLabelName() + ":\n"); @@ -841,10 +920,115 @@ ExternalCompilationResult compilationResult = (ExternalCompilationResult) crb.compilationResult; HSAILHotSpotLIRGenerationResult lirGenRes = ((HSAILCompilationResultBuilder) crb).lirGenRes; - compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config)); + compilationResult.setHostGraph(prepareHostGraph(method, lirGenRes.getDeopts(), getProviders(), config, numSRegs, numDRegs)); } - private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List deopts, HotSpotProviders providers, HotSpotVMConfig config) { + private static class OopMapArrayBuilder { + // oopMapArray struct + // int bytesPerSaveArea; (not strictly part of oopsmap but convenient to put here) + // int intsPerInfopoint; + static final int SAVEAREACOUNTS_OFST = 0; + static final int INTSPERINFOPOINT_OFST = 1; + static final int HEADERSIZE = 2; + // for each infopoint: + // int deoptId + // one or more ints of bits for the oopmap + + private int[] array; + private int intsPerInfopoint; + + int[] build(List infoList, int numSRegs, int numDRegs, int numStackSlots, HSAILHotSpotRegisterConfig hsailRegConfig) { + // we are told that infoList is always sorted + // each infoPoint can have a different oopMap + + // since numStackSlots is the number of 8-byte stack slots used, it is an upper limit on + // the number of oop stack slots + int bitsPerInfopoint = numDRegs + numStackSlots; + int intsForBits = (bitsPerInfopoint + 31) / 32; + int numInfopoints = infoList.size(); + intsPerInfopoint = intsForBits + 1; // +1 for the pcoffset + int arraySize = HEADERSIZE + (numInfopoints * intsPerInfopoint); + array = new int[arraySize]; + array[INTSPERINFOPOINT_OFST] = intsPerInfopoint; + // compute saveAreaCounts + int saveAreaCounts = (numSRegs & 0xff) + (numDRegs << 8) + (numStackSlots << 16); + array[SAVEAREACOUNTS_OFST] = saveAreaCounts; + + // loop thru the infoList + int infoIndex = 0; + for (Infopoint info : infoList) { + setOopMapPcOffset(infoIndex, info.pcOffset); + BytecodeFrame frame = info.debugInfo.frame(); + while (frame != null) { + for (int i = 0; i < frame.numLocals + frame.numStack; i++) { + Value val = frame.values[i]; + if (isLegal(val)) { + if (isRegister(val)) { + Register reg = asRegister(val); + if (val.getKind().isObject()) { + assert (hsailRegConfig.isAllocatableDReg(reg)); + int bitIndex = reg.encoding(); + setOopMapBit(infoIndex, bitIndex); + } + } else if (isStackSlot(val)) { + StackSlot slot = asStackSlot(val); + if (val.getKind().isObject()) { + assert (HSAIL.getStackOffsetStart(slot, 64) % 8 == 0); + int bitIndex = numDRegs + HSAIL.getStackOffsetStart(slot, 64) / 8; + setOopMapBit(infoIndex, bitIndex); + } + } + } + } + frame = frame.caller(); + } + infoIndex++; + } + try (Scope s = Debug.scope("CodeGen")) { + if (Debug.isLogEnabled()) { + Debug.log("numSRegs=%d, numDRegs=%d, numStackSlots=%d", numSRegs, numDRegs, numStackSlots); + // show infopoint oopmap details + for (infoIndex = 0; infoIndex < infoList.size(); infoIndex++) { + String infoString = "Infopoint " + infoIndex + ", pcOffset=" + getOopMapPcOffset(infoIndex) + ", oopmap="; + for (int i = 0; i < intsForBits; i++) { + infoString += (i != 0 ? ", " : "") + Integer.toHexString(getOopMapBitsAsInt(infoIndex, i)); + } + Debug.log(infoString); + } + } + } catch (Throwable e) { + throw Debug.handle(e); + } + + return array; + } + + private void setOopMapPcOffset(int infoIndex, int pcOffset) { + int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint; + array[arrIndex] = pcOffset; + } + + private int getOopMapPcOffset(int infoIndex) { + int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint; + return array[arrIndex]; + } + + private void setOopMapBit(int infoIndex, int bitIndex) { + int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint + 1 + bitIndex / 32; + array[arrIndex] |= (1 << (bitIndex % 32)); + } + + private int getOopMapBitsAsInt(int infoIndex, int intIndex) { + int arrIndex = HEADERSIZE + infoIndex * intsPerInfopoint + 1 + intIndex; + return array[arrIndex]; + } + + public static int getSaveAreaCounts(int[] array) { + return array[SAVEAREACOUNTS_OFST]; + } + } + + private static StructuredGraph prepareHostGraph(ResolvedJavaMethod method, List deopts, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, int numDRegs) { if (deopts.isEmpty()) { return null; } @@ -868,7 +1052,7 @@ keyProbabilities[i] = 1.0 / deopts.size(); keys[i] = deopt.getCodeBufferPos(); assert keys[i] >= 0; - branches[i] = createHostDeoptBranch(deopt, hsailFrame, reasonAndAction, speculation, providers, config); + branches[i] = createHostDeoptBranch(deopt, hsailFrame, reasonAndAction, speculation, providers, config, numSRegs, numDRegs); i++; } @@ -892,34 +1076,35 @@ return BeginNode.begin(vmError); } - private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, HotSpotVMConfig config) { + private static BeginNode createHostDeoptBranch(DeoptimizingOp deopt, ParameterNode hsailFrame, ValueNode reasonAndAction, ValueNode speculation, HotSpotProviders providers, + HotSpotVMConfig config, int numSRegs, int numDRegs) { BeginNode branch = hsailFrame.graph().add(new BeginNode()); DynamicDeoptimizeNode deoptimization = hsailFrame.graph().add(new DynamicDeoptimizeNode(reasonAndAction, speculation)); - deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config)); + deoptimization.setStateBefore(createFrameState(deopt.getFrameState().topFrame, hsailFrame, providers, config, numSRegs, numDRegs)); branch.setNext(deoptimization); return branch; } - private static FrameState createFrameState(BytecodeFrame lowLevelFrame, ParameterNode hsailFrame, HotSpotProviders providers, HotSpotVMConfig config) { + private static FrameState createFrameState(BytecodeFrame lowLevelFrame, ParameterNode hsailFrame, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, int numDRegs) { StructuredGraph hostGraph = hsailFrame.graph(); ValueNode[] locals = new ValueNode[lowLevelFrame.numLocals]; for (int i = 0; i < lowLevelFrame.numLocals; i++) { - locals[i] = getNodeForValueFromFrame(lowLevelFrame.getLocalValue(i), hsailFrame, hostGraph, providers, config); + locals[i] = getNodeForValueFromFrame(lowLevelFrame.getLocalValue(i), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs); } List stack = new ArrayList<>(lowLevelFrame.numStack); for (int i = 0; i < lowLevelFrame.numStack; i++) { - stack.add(getNodeForValueFromFrame(lowLevelFrame.getStackValue(i), hsailFrame, hostGraph, providers, config)); + stack.add(getNodeForValueFromFrame(lowLevelFrame.getStackValue(i), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs)); } ValueNode[] locks = new ValueNode[lowLevelFrame.numLocks]; MonitorIdNode[] monitorIds = new MonitorIdNode[lowLevelFrame.numLocks]; for (int i = 0; i < lowLevelFrame.numLocks; i++) { HotSpotMonitorValue lockValue = (HotSpotMonitorValue) lowLevelFrame.getLockValue(i); - locks[i] = getNodeForValueFromFrame(lockValue, hsailFrame, hostGraph, providers, config); + locks[i] = getNodeForValueFromFrame(lockValue, hsailFrame, hostGraph, providers, config, numSRegs, numDRegs); monitorIds[i] = getMonitorIdForHotSpotMonitorValueFromFrame(lockValue, hsailFrame, hostGraph); } FrameState frameState = hostGraph.add(new FrameState(lowLevelFrame.getMethod(), lowLevelFrame.getBCI(), locals, stack, locks, monitorIds, lowLevelFrame.rethrowException, false)); if (lowLevelFrame.caller() != null) { - frameState.setOuterFrameState(createFrameState(lowLevelFrame.caller(), hsailFrame, providers, config)); + frameState.setOuterFrameState(createFrameState(lowLevelFrame.caller(), hsailFrame, providers, config, numSRegs, numDRegs)); } return frameState; } @@ -932,21 +1117,23 @@ throw GraalInternalError.unimplemented(); } - private static ValueNode getNodeForValueFromFrame(Value localValue, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config) { + private static ValueNode getNodeForValueFromFrame(Value localValue, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config, int numSRegs, + int numDRegs) { ValueNode valueNode; if (localValue instanceof Constant) { valueNode = ConstantNode.forConstant((Constant) localValue, providers.getMetaAccess(), hostGraph); } else if (localValue instanceof VirtualObject) { throw GraalInternalError.unimplemented(); } else if (localValue instanceof StackSlot) { - throw GraalInternalError.unimplemented(); + StackSlot slot = (StackSlot) localValue; + valueNode = getNodeForStackSlotFromFrame(slot, localValue.getKind(), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs); } else if (localValue instanceof HotSpotMonitorValue) { HotSpotMonitorValue hotSpotMonitorValue = (HotSpotMonitorValue) localValue; - return getNodeForValueFromFrame(hotSpotMonitorValue.getOwner(), hsailFrame, hostGraph, providers, config); + return getNodeForValueFromFrame(hotSpotMonitorValue.getOwner(), hsailFrame, hostGraph, providers, config, numSRegs, numDRegs); } else if (localValue instanceof RegisterValue) { RegisterValue registerValue = (RegisterValue) localValue; int regNumber = registerValue.getRegister().number; - valueNode = getNodeForRegisterFromFrame(regNumber, localValue.getKind(), hsailFrame, hostGraph, providers, config); + valueNode = getNodeForRegisterFromFrame(regNumber, localValue.getKind(), hsailFrame, hostGraph, providers, config, numSRegs); } else if (Value.ILLEGAL.equals(localValue)) { valueNode = null; } else { @@ -955,20 +1142,18 @@ return valueNode; } - private static ValueNode getNodeForRegisterFromFrame(int regNumber, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config) { + private static ValueNode getNodeForRegisterFromFrame(int regNumber, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config, + int numSRegs) { ValueNode valueNode; LocationNode location; + int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long); + int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int); if (regNumber >= HSAIL.s0.number && regNumber <= HSAIL.s31.number) { - int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int); long offset = config.hsailFrameSaveAreaOffset + intSize * (regNumber - HSAIL.s0.number); location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph); } else if (regNumber >= HSAIL.d0.number && regNumber <= HSAIL.d15.number) { - int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long); - long offset = config.hsailFrameSaveAreaOffset + longSize * (regNumber - HSAIL.d0.number); - LocationNode numSRegsLocation = ConstantLocationNode.create(FINAL_LOCATION, Kind.Byte, config.hsailFrameNumSRegOffset, hostGraph); - ValueNode numSRegs = hostGraph.unique(new FloatingReadNode(hsailFrame, numSRegsLocation, null, StampFactory.forInteger(8))); - numSRegs = SignExtendNode.convert(numSRegs, StampFactory.forKind(Kind.Byte)); - location = IndexedLocationNode.create(FINAL_LOCATION, valueKind, offset, numSRegs, hostGraph, 4); + long offset = config.hsailFrameSaveAreaOffset + intSize * numSRegs + longSize * (regNumber - HSAIL.d0.number); + location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph); } else { throw GraalInternalError.shouldNotReachHere("unknown hsail register: " + regNumber); } @@ -976,4 +1161,18 @@ return valueNode; } + private static ValueNode getNodeForStackSlotFromFrame(StackSlot slot, Kind valueKind, ParameterNode hsailFrame, StructuredGraph hostGraph, HotSpotProviders providers, HotSpotVMConfig config, + int numSRegs, int numDRegs) { + int slotSizeInBits = (valueKind == Kind.Object ? 64 : valueKind.getByteCount() * 8); + if ((slotSizeInBits == 32) || (slotSizeInBits == 64)) { + int longSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Long); + int intSize = providers.getCodeCache().getTarget().arch.getSizeInBytes(Kind.Int); + long offset = config.hsailFrameSaveAreaOffset + (intSize * numSRegs) + (longSize * numDRegs) + HSAIL.getStackOffsetStart(slot, slotSizeInBits); + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, valueKind, offset, hostGraph); + ValueNode valueNode = hostGraph.unique(new FloatingReadNode(hsailFrame, location, null, StampFactory.forKind(valueKind))); + return valueNode; + } else { + throw GraalInternalError.shouldNotReachHere("unsupported stack slot kind: " + valueKind); + } + } } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon May 05 18:38:43 2014 +0200 @@ -57,7 +57,8 @@ Replacements replacements = new HSAILHotSpotReplacementsImpl(p, host.getSnippetReflection(), assumptions, codeCache.getTarget(), host.getReplacements()); HotSpotDisassemblerProvider disassembler = host.getDisassembler(); SuitesProvider suites = new HotSpotSuitesProvider(runtime); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection()); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection(), + host.getMethodHandleAccess()); // pass registers info down to ReplacementsUtil (maybe a better way to do this?) HSAILHotSpotReplacementsUtil.initialize(providers.getRegisters()); diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotRegisterConfig.java Mon May 05 18:38:43 2014 +0200 @@ -194,6 +194,14 @@ throw new UnsupportedOperationException(); } + public boolean isAllocatableSReg(Register reg) { + return (reg.number >= HSAIL.s0.number && reg.number <= HSAIL.s31.number); + } + + public boolean isAllocatableDReg(Register reg) { + return (reg.number >= HSAIL.d0.number && reg.number <= HSAIL.d15.number); + } + public HSAILHotSpotRegisterConfig() { } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotSafepointOp.java Mon May 05 18:38:43 2014 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot.hsail; -import static com.oracle.graal.api.code.ValueUtil.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.hsail.*; @@ -42,7 +40,6 @@ private Constant actionAndReason; @State protected LIRFrameState frameState; protected int codeBufferPos = -1; - protected int dregOopMap = 0; final int offsetToNoticeSafepoints; public HSAILHotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, NodeLIRBuilderTool tool) { @@ -77,23 +74,10 @@ masm.emitCompare(Kind.Int, scratch32, Constant.forInt(0), "eq", false, false); masm.cbr(afterSafepointLabel); - BytecodeFrame frame = frameState.debugInfo().frame(); - for (int i = 0; i < frame.numLocals + frame.numStack; i++) { - Value val = frame.values[i]; - if (isLegal(val) && isRegister(val)) { - Register reg = asRegister(val); - if (val.getKind() == Kind.Object) { - dregOopMap |= 1 << (reg.encoding()); - } - } - } - AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); - AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int); masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); - masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap)); masm.emitJumpToLabelName(masm.getDeoptLabelName()); masm.emitString0(afterSafepointLabel + ":\n"); diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Mon May 05 18:38:43 2014 +0200 @@ -47,7 +47,8 @@ HotSpotDisassemblerProvider disassembler = host.getDisassembler(); SuitesProvider suites = new DefaultSuitesProvider(); HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection()); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, host.getSnippetReflection(), + host.getMethodHandleAccess()); return new PTXHotSpotBackend(runtime, providers); } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon May 05 18:38:43 2014 +0200 @@ -64,7 +64,9 @@ HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, runtime.getConfig(), assumptions, target); HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime); HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection); + HotSpotMethodHandleAccessProvider methodHandleAccess = new HotSpotMethodHandleAccessProvider(); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers, snippetReflection, + methodHandleAccess); return new SPARCHotSpotBackend(runtime, providers); } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon May 05 18:38:43 2014 +0200 @@ -368,6 +368,8 @@ return (T) this; } else if (clazz == SnippetReflectionProvider.class) { return (T) getHostProviders().getSnippetReflection(); + } else if (clazz == MethodHandleAccessProvider.class) { + return (T) getHostProviders().getMethodHandleAccess(); } return null; } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java Mon May 05 18:38:43 2014 +0200 @@ -86,16 +86,14 @@ HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; int intrinsicId = hsMethod.intrinsicId(); if (intrinsicId != 0) { - if (intrinsicId == config.vmIntrinsicInvokeBasic) { - return MethodHandleInvokeBasicNode.class; - } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { - return MethodHandleLinkToInterfaceNode.class; - } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { - return MethodHandleLinkToSpecialNode.class; - } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { - return MethodHandleLinkToStaticNode.class; - } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { - return MethodHandleLinkToVirtualNode.class; + /* + * The methods of MethodHandle that need substitution are signature-polymorphic, i.e., + * the VM replicates them for every signature that they are actually used for. + * Therefore, we cannot use the usual annotation-driven mechanism to define the + * substitution. + */ + if (MethodHandleNode.lookupMethodHandleIntrinsic(method) != null) { + return MethodHandleNode.class; } } return super.getMacroSubstitution(method); diff -r 6f23b90c4129 -r a900caddcd60 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 Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Mon May 05 18:38:43 2014 +0200 @@ -1022,8 +1022,6 @@ * exceptions from Hsail back to C++ runtime. */ @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_notice_safepoints", type = "jint*", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNoticeSafepointsOffset; - @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[0]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset0; - @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[1]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset1; @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_occurred", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptOccurredOffset; @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_never_ran_array", type = "jboolean *", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailNeverRanArrayOffset; @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_next_index", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailDeoptNextIndexOffset; @@ -1035,7 +1033,10 @@ @HotSpotVMField(name = "HSAILFrame::_pc_offset", type = "jint", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFramePcOffset; @HotSpotVMField(name = "HSAILFrame::_num_s_regs", type = "jbyte", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFrameNumSRegOffset; - @HotSpotVMField(name = "HSAILFrame::_save_area[0]", type = "jlong", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFrameSaveAreaOffset; + @HotSpotVMField(name = "HSAILFrame::_num_d_regs", type = "jbyte", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailFrameNumDRegOffset; + @HotSpotVMConstant(name = "sizeof(HSAILFrame)") @Stable public int hsailFrameSaveAreaOffset; + @HotSpotVMConstant(name = "sizeof(Hsail::HSAILKernelDeoptimization)") @Stable public int hsailKernelDeoptimizationHeaderSize; + @HotSpotVMField(name = "Hsail::HSAILDeoptimizationInfo::_deopt_save_states[0]", type = "Hsail::HSAILKernelDeoptimization", get = HotSpotVMField.Type.OFFSET) @Stable public int hsailSaveStatesOffset0; /** * Mark word right shift to get identity hash code. diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodHandleAccessProvider.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014, 2014, 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.meta; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.hotspot.*; + +public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider { + + /** + * Lazy initialization to break class initialization cycle. Field and method lookup is only + * possible after the {@link HotSpotGraalRuntime} is fully initialized. + */ + static class LazyInitialization { + static final ResolvedJavaField methodHandleFormField; + static final ResolvedJavaField lambdaFormVmentryField; + static final ResolvedJavaMethod lambdaFormCompileToBytecodeMethod; + static final ResolvedJavaField memberNameVmtargetField; + + /** + * Search for an instance field with the given name in a class. + * + * @param className name of the class to search in + * @param fieldName name of the field to be searched + * @return resolved java field + * @throws ClassNotFoundException + */ + private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException { + Class clazz = Class.forName(className); + ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(clazz); + ResolvedJavaField[] fields = type.getInstanceFields(false); + for (ResolvedJavaField field : fields) { + if (field.getName().equals(fieldName)) { + return field; + } + } + return null; + } + + private static ResolvedJavaMethod findMethodInClass(String className, String methodName) throws ClassNotFoundException { + Class clazz = Class.forName(className); + ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(clazz); + ResolvedJavaMethod result = null; + for (ResolvedJavaMethod method : type.getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + assert result == null : "more than one method found: " + className + "." + methodName; + result = method; + } + } + assert result != null : "method not found: " + className + "." + methodName; + return result; + } + + static { + try { + methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form"); + lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry"); + lambdaFormCompileToBytecodeMethod = findMethodInClass("java.lang.invoke.LambdaForm", "compileToBytecode"); + memberNameVmtargetField = findFieldInClass("java.lang.invoke.MemberName", "vmtarget"); + } catch (Throwable ex) { + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + @Override + public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) { + int intrinsicId = ((HotSpotResolvedJavaMethod) method).intrinsicId(); + if (intrinsicId != 0) { + HotSpotVMConfig config = runtime().getConfig(); + if (intrinsicId == config.vmIntrinsicInvokeBasic) { + return IntrinsicMethod.INVOKE_BASIC; + } else if (intrinsicId == config.vmIntrinsicLinkToInterface) { + return IntrinsicMethod.LINK_TO_INTERFACE; + } else if (intrinsicId == config.vmIntrinsicLinkToSpecial) { + return IntrinsicMethod.LINK_TO_SPECIAL; + } else if (intrinsicId == config.vmIntrinsicLinkToStatic) { + return IntrinsicMethod.LINK_TO_STATIC; + } else if (intrinsicId == config.vmIntrinsicLinkToVirtual) { + return IntrinsicMethod.LINK_TO_VIRTUAL; + } + } + return null; + } + + @Override + public ResolvedJavaMethod resolveInvokeBasicTarget(Constant methodHandle, boolean forceBytecodeGeneration) { + if (methodHandle.isNull()) { + return null; + } + + /* Load non-public field: LambdaForm MethodHandle.form */ + Constant lambdaForm = LazyInitialization.methodHandleFormField.readValue(methodHandle); + if (lambdaForm.isNull()) { + return null; + } + + Constant memberName; + if (forceBytecodeGeneration) { + /* Invoke non-public method: MemberName LambdaForm.compileToBytecode() */ + memberName = LazyInitialization.lambdaFormCompileToBytecodeMethod.invoke(lambdaForm, new Constant[0]); + } else { + /* Load non-public field: MemberName LambdaForm.vmentry */ + memberName = LazyInitialization.lambdaFormVmentryField.readValue(lambdaForm); + } + return getTargetMethod(memberName); + } + + @Override + public ResolvedJavaMethod resolveLinkToTarget(Constant memberName) { + return getTargetMethod(memberName); + } + + /** + * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName. + */ + private static ResolvedJavaMethod getTargetMethod(Constant memberName) { + if (memberName.isNull()) { + return null; + } + + /* Load injected field: JVM_Method* MemberName.vmtarget */ + Constant vmtarget = LazyInitialization.memberNameVmtargetField.readValue(memberName); + /* Create a method from the vmtarget method pointer. */ + return HotSpotResolvedJavaMethod.fromMetaspace(vmtarget.asLong()); + } +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNmethod.java Mon May 05 18:38:43 2014 +0200 @@ -36,7 +36,7 @@ * instance to be anything but weak. This is due to the fact that HotSpot does not treat nmethods as * strong GC roots. */ -public final class HotSpotNmethod extends HotSpotInstalledCode { +public class HotSpotNmethod extends HotSpotInstalledCode { /** * This (indirect) Method* reference is safe since class redefinition preserves all methods diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Mon May 05 18:38:43 2014 +0200 @@ -38,15 +38,17 @@ private final SuitesProvider suites; private final HotSpotRegistersProvider registers; private final SnippetReflectionProvider snippetReflection; + private final HotSpotMethodHandleAccessProvider methodHandleAccess; public HotSpotProviders(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, SuitesProvider suites, HotSpotRegistersProvider registers, - SnippetReflectionProvider snippetReflection) { + SnippetReflectionProvider snippetReflection, HotSpotMethodHandleAccessProvider methodHandleAccess) { super(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements); this.disassembler = disassembler; this.suites = suites; this.registers = registers; this.snippetReflection = snippetReflection; + this.methodHandleAccess = methodHandleAccess; } @Override @@ -79,4 +81,8 @@ public SnippetReflectionProvider getSnippetReflection() { return snippetReflection; } + + public HotSpotMethodHandleAccessProvider getMethodHandleAccess() { + return methodHandleAccess; + } } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/AbstractMethodHandleNode.java Mon May 05 18:38:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,283 +0,0 @@ -/* - * 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.replacements; - -import java.util.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.replacements.nodes.*; - -/** - * Common base class for method handle invoke nodes. - */ -public abstract class AbstractMethodHandleNode extends MacroNode implements Canonicalizable { - - private static final ResolvedJavaField methodHandleFormField; - private static final ResolvedJavaField lambdaFormVmentryField; - private static final ResolvedJavaField memberNameClazzField; - private static final ResolvedJavaField memberNameVmtargetField; - - // Replacement method data - private ResolvedJavaMethod replacementTargetMethod; - private JavaType replacementReturnType; - @Input private final NodeInputList replacementArguments; - - /** - * Search for an instance field with the given name in a class. - * - * @param className name of the class to search in - * @param fieldName name of the field to be searched - * @return resolved java field - * @throws ClassNotFoundException - */ - private static ResolvedJavaField findFieldInClass(String className, String fieldName) throws ClassNotFoundException { - Class clazz = Class.forName(className); - ResolvedJavaType type = HotSpotResolvedObjectType.fromClass(clazz); - ResolvedJavaField[] fields = type.getInstanceFields(false); - for (ResolvedJavaField field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - return null; - } - - static { - try { - methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form"); - lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry"); - memberNameClazzField = findFieldInClass("java.lang.invoke.MemberName", "clazz"); - memberNameVmtargetField = findFieldInClass("java.lang.invoke.MemberName", "vmtarget"); - } catch (ClassNotFoundException | SecurityException ex) { - throw GraalInternalError.shouldNotReachHere(); - } - } - - public AbstractMethodHandleNode(Invoke invoke) { - super(invoke); - - // See if we need to save some replacement method data. - CallTargetNode callTarget = invoke.callTarget(); - if (callTarget instanceof SelfReplacingMethodCallTargetNode) { - SelfReplacingMethodCallTargetNode selfReplacingMethodCallTargetNode = (SelfReplacingMethodCallTargetNode) callTarget; - replacementTargetMethod = selfReplacingMethodCallTargetNode.replacementTargetMethod(); - replacementReturnType = selfReplacingMethodCallTargetNode.replacementReturnType(); - replacementArguments = selfReplacingMethodCallTargetNode.replacementArguments(); - } else { - // NodeInputList can't be null. - replacementArguments = new NodeInputList<>(this); - } - } - - /** - * Get the receiver of a MethodHandle.invokeBasic call. - * - * @return the receiver argument node - */ - private ValueNode getReceiver() { - return arguments.first(); - } - - /** - * Get the MemberName argument of a MethodHandle.linkTo* call. - * - * @return the MemberName argument node (which is the last argument) - */ - private ValueNode getMemberName() { - return arguments.last(); - } - - /** - * Used from {@link MethodHandleInvokeBasicNode} to get the target {@link InvokeNode} if the - * method handle receiver is constant. - * - * @return invoke node for the {@link java.lang.invoke.MethodHandle} target - */ - protected InvokeNode getInvokeBasicTarget() { - ValueNode methodHandleNode = getReceiver(); - if (methodHandleNode.isConstant() && !methodHandleNode.isNullConstant()) { - // Get the data we need from MethodHandle.LambdaForm.MemberName - Constant methodHandle = methodHandleNode.asConstant(); - Constant lambdaForm = methodHandleFormField.readValue(methodHandle); - Constant memberName = lambdaFormVmentryField.readValue(lambdaForm); - return getTargetInvokeNode(memberName); - } - return null; - } - - /** - * Used from {@link MethodHandleLinkToStaticNode}, {@link MethodHandleLinkToSpecialNode}, - * {@link MethodHandleLinkToVirtualNode}, and {@link MethodHandleLinkToInterfaceNode} to get the - * target {@link InvokeNode} if the member name argument is constant. - * - * @return invoke node for the member name target - */ - protected InvokeNode getLinkToTarget() { - ValueNode memberNameNode = getMemberName(); - if (memberNameNode.isConstant() && !memberNameNode.isNullConstant()) { - Constant memberName = memberNameNode.asConstant(); - return getTargetInvokeNode(memberName); - } - return null; - } - - /** - * Helper function to get the {@link InvokeNode} for the vmtarget of a - * java.lang.invoke.MemberName. - * - * @param memberName constant member name node - * @return invoke node for the member name target - */ - private InvokeNode getTargetInvokeNode(Constant memberName) { - // Get the data we need from MemberName - Constant clazz = memberNameClazzField.readValue(memberName); - Constant vmtarget = memberNameVmtargetField.readValue(memberName); - - // Create a method from the vmtarget pointer - Class c = (Class) HotSpotObjectConstant.asObject(clazz); - HotSpotResolvedObjectType holderClass = (HotSpotResolvedObjectType) HotSpotResolvedObjectType.fromClass(c); - HotSpotResolvedJavaMethod targetMethod = HotSpotResolvedJavaMethod.fromMetaspace(vmtarget.asLong()); - - // In lambda forms we erase signature types to avoid resolving issues - // involving class loaders. When we optimize a method handle invoke - // to a direct call we must cast the receiver and arguments to its - // actual types. - HotSpotSignature signature = targetMethod.getSignature(); - final boolean isStatic = targetMethod.isStatic(); - final int receiverSkip = isStatic ? 0 : 1; - - // Cast receiver to its type. - if (!isStatic) { - JavaType receiverType = holderClass; - maybeCastArgument(0, receiverType); - } - - // Cast reference arguments to its type. - for (int index = 0; index < signature.getParameterCount(false); index++) { - JavaType parameterType = signature.getParameterType(index, holderClass); - maybeCastArgument(receiverSkip + index, parameterType); - } - - // Try to get the most accurate receiver type - if (this instanceof MethodHandleLinkToVirtualNode || this instanceof MethodHandleLinkToInterfaceNode) { - ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp()); - if (receiverType != null) { - ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod); - if (concreteMethod != null) { - return createTargetInvokeNode(concreteMethod); - } - } - } - - if (targetMethod.canBeStaticallyBound()) { - return createTargetInvokeNode(targetMethod); - } - - ResolvedJavaMethod concreteMethod = targetMethod.uniqueConcreteMethod(); - if (concreteMethod != null) { - return createTargetInvokeNode(concreteMethod); - } - - return null; - } - - /** - * Inserts a node to cast the argument at index to the given type if the given type is more - * concrete than the argument type. - * - * @param index of the argument to be cast - * @param type the type the argument should be cast to - */ - private void maybeCastArgument(int index, JavaType type) { - if (type instanceof ResolvedJavaType) { - ResolvedJavaType targetType = (ResolvedJavaType) type; - if (!targetType.isPrimitive()) { - ValueNode argument = arguments.get(index); - ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); - if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { - PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); - arguments.set(index, piNode); - } - } - } - } - - /** - * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed - * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. - * - * @param targetMethod the method the be called - * @return invoke node for the member name target - */ - private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) { - InvokeKind invokeKind = targetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; - JavaType returnType = targetMethod.getSignature().getReturnType(null); - - // MethodHandleLinkTo* nodes have a trailing MemberName argument which - // needs to be popped. - ValueNode[] originalArguments = arguments.toArray(new ValueNode[arguments.size()]); - ValueNode[] targetArguments; - if (this instanceof MethodHandleInvokeBasicNode) { - targetArguments = originalArguments; - } else { - assert this instanceof MethodHandleLinkToStaticNode || this instanceof MethodHandleLinkToSpecialNode || this instanceof MethodHandleLinkToVirtualNode || - this instanceof MethodHandleLinkToInterfaceNode : this; - targetArguments = Arrays.copyOfRange(originalArguments, 0, arguments.size() - 1); - } - - // If there is already replacement information, use that instead. - MethodCallTargetNode callTarget; - if (replacementTargetMethod == null) { - callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType()); - } else { - ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); - callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType); - } - graph().add(callTarget); - - // The call target can have a different return type than the invoker, - // e.g. the target returns an Object but the invoker void. In this case - // we need to use the stamp of the invoker. Note: always using the - // invoker's stamp would be wrong because it's a less concrete type - // (usually java.lang.Object). - InvokeNode invoke; - if (stamp() == StampFactory.forVoid()) { - invoke = new InvokeNode(callTarget, getBci(), stamp()); - } else { - invoke = new InvokeNode(callTarget, getBci()); - } - graph().add(invoke); - invoke.setStateAfter(stateAfter()); - return invoke; - } - -} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleInvokeBasicNode.java Mon May 05 18:38:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * 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.replacements; - -import java.lang.invoke.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodes.*; - -/** - * Macro node for {@link MethodHandle}{@code .invokeBasic(Object...)}. - */ -public class MethodHandleInvokeBasicNode extends AbstractMethodHandleNode { - - public MethodHandleInvokeBasicNode(Invoke invoke) { - super(invoke); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - InvokeNode invoke = getInvokeBasicTarget(); - if (invoke != null) { - return invoke; - } - return this; - } - -} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToInterfaceNode.java Mon May 05 18:38:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * 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.replacements; - -import java.lang.invoke.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodes.*; - -/** - * Macro node for {@link MethodHandle}{@code .linkToInterface(Object...)}. - */ -public class MethodHandleLinkToInterfaceNode extends AbstractMethodHandleNode { - - public MethodHandleLinkToInterfaceNode(Invoke invoke) { - super(invoke); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - InvokeNode invoke = getLinkToTarget(); - if (invoke != null) { - return invoke; - } - return this; - } - -} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToSpecialNode.java Mon May 05 18:38:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * 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.replacements; - -import java.lang.invoke.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodes.*; - -/** - * Macro node for {@link MethodHandle}{@code .linkToSpecial(Object...)}. - */ -public class MethodHandleLinkToSpecialNode extends AbstractMethodHandleNode { - - public MethodHandleLinkToSpecialNode(Invoke invoke) { - super(invoke); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - InvokeNode invoke = getLinkToTarget(); - if (invoke != null) { - return invoke; - } - return this; - } - -} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToStaticNode.java Mon May 05 18:38:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * 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.replacements; - -import java.lang.invoke.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodes.*; - -/** - * Macro node for {@link MethodHandle}{@code .linkToStatic(Object...)}. - */ -public class MethodHandleLinkToStaticNode extends AbstractMethodHandleNode { - - public MethodHandleLinkToStaticNode(Invoke invoke) { - super(invoke); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - InvokeNode invoke = getLinkToTarget(); - if (invoke != null) { - return invoke; - } - return this; - } - -} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleLinkToVirtualNode.java Mon May 05 18:38:13 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * 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.replacements; - -import java.lang.invoke.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodes.*; - -/** - * Macro node for {@link MethodHandle}{@code .linkToVirtual(Object...)}. - */ -public class MethodHandleLinkToVirtualNode extends AbstractMethodHandleNode { - - public MethodHandleLinkToVirtualNode(Invoke invoke) { - super(invoke); - } - - @Override - public Node canonical(CanonicalizerTool tool) { - InvokeNode invoke = getLinkToTarget(); - if (invoke != null) { - return invoke; - } - return this; - } - -} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MethodHandleNode.java Mon May 05 18:38:43 2014 +0200 @@ -0,0 +1,292 @@ +/* + * 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.replacements; + +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import java.lang.invoke.*; +import java.util.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.replacements.*; +import com.oracle.graal.api.replacements.MethodHandleAccessProvider.IntrinsicMethod; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.replacements.nodes.*; + +/** + * Node for invocation methods defined on the class {@link MethodHandle}. + */ +public class MethodHandleNode extends MacroNode implements Canonicalizable { + + /** The method that this node is representing. */ + private final IntrinsicMethod intrinsicMethod; + + // Replacement method data + private ResolvedJavaMethod replacementTargetMethod; + private JavaType replacementReturnType; + @Input private final NodeInputList replacementArguments; + + public MethodHandleNode(Invoke invoke) { + super(invoke); + + MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); + intrinsicMethod = lookupMethodHandleIntrinsic(callTarget.targetMethod()); + assert intrinsicMethod != null; + + // See if we need to save some replacement method data. + if (callTarget instanceof SelfReplacingMethodCallTargetNode) { + SelfReplacingMethodCallTargetNode selfReplacingMethodCallTargetNode = (SelfReplacingMethodCallTargetNode) callTarget; + replacementTargetMethod = selfReplacingMethodCallTargetNode.replacementTargetMethod(); + replacementReturnType = selfReplacingMethodCallTargetNode.replacementReturnType(); + replacementArguments = selfReplacingMethodCallTargetNode.replacementArguments(); + } else { + // NodeInputList can't be null. + replacementArguments = new NodeInputList<>(this); + } + } + + /** + * Returns the method handle method intrinsic identifier for the provided method, or + * {@code null} if the method is not a method that can be handled by this class. + */ + public static IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) { + return methodHandleAccess().lookupMethodHandleIntrinsic(method); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + InvokeNode invoke; + switch (intrinsicMethod) { + case INVOKE_BASIC: + invoke = getInvokeBasicTarget(); + break; + case LINK_TO_STATIC: + case LINK_TO_SPECIAL: + case LINK_TO_VIRTUAL: + case LINK_TO_INTERFACE: + invoke = getLinkToTarget(); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + if (invoke != null) { + return invoke; + } + return this; + } + + /** + * Get the receiver of a MethodHandle.invokeBasic call. + * + * @return the receiver argument node + */ + private ValueNode getReceiver() { + return arguments.first(); + } + + /** + * Get the MemberName argument of a MethodHandle.linkTo* call. + * + * @return the MemberName argument node (which is the last argument) + */ + private ValueNode getMemberName() { + return arguments.last(); + } + + /** + * Returns the {@link MethodHandleAccessProvider} that provides introspection of internal + * {@link MethodHandle} data. + */ + private static MethodHandleAccessProvider methodHandleAccess() { + return runtime().getHostProviders().getMethodHandleAccess(); + } + + /** + * Used for the MethodHandle.invokeBasic method (the {@link IntrinsicMethod#INVOKE_BASIC } + * method) to get the target {@link InvokeNode} if the method handle receiver is constant. + * + * @return invoke node for the {@link java.lang.invoke.MethodHandle} target + */ + protected InvokeNode getInvokeBasicTarget() { + ValueNode methodHandleNode = getReceiver(); + if (methodHandleNode.isConstant()) { + return getTargetInvokeNode(methodHandleAccess().resolveInvokeBasicTarget(methodHandleNode.asConstant(), false)); + } + return null; + } + + /** + * Used for the MethodHandle.linkTo* methods (the {@link IntrinsicMethod#LINK_TO_STATIC}, + * {@link IntrinsicMethod#LINK_TO_SPECIAL}, {@link IntrinsicMethod#LINK_TO_VIRTUAL}, and + * {@link IntrinsicMethod#LINK_TO_INTERFACE} methods) to get the target {@link InvokeNode} if + * the member name argument is constant. + * + * @return invoke node for the member name target + */ + protected InvokeNode getLinkToTarget() { + ValueNode memberNameNode = getMemberName(); + if (memberNameNode.isConstant()) { + return getTargetInvokeNode(methodHandleAccess().resolveLinkToTarget(memberNameNode.asConstant())); + } + return null; + } + + /** + * Helper function to get the {@link InvokeNode} for the targetMethod of a + * java.lang.invoke.MemberName. + * + * @param targetMethod the target, already loaded from the member name node + * @return invoke node for the member name target + */ + private InvokeNode getTargetInvokeNode(ResolvedJavaMethod targetMethod) { + if (targetMethod == null) { + return null; + } + + // In lambda forms we erase signature types to avoid resolving issues + // involving class loaders. When we optimize a method handle invoke + // to a direct call we must cast the receiver and arguments to its + // actual types. + Signature signature = targetMethod.getSignature(); + final boolean isStatic = targetMethod.isStatic(); + final int receiverSkip = isStatic ? 0 : 1; + + // Cast receiver to its type. + if (!isStatic) { + JavaType receiverType = targetMethod.getDeclaringClass(); + maybeCastArgument(0, receiverType); + } + + // Cast reference arguments to its type. + for (int index = 0; index < signature.getParameterCount(false); index++) { + JavaType parameterType = signature.getParameterType(index, targetMethod.getDeclaringClass()); + maybeCastArgument(receiverSkip + index, parameterType); + } + + // Try to get the most accurate receiver type + if (intrinsicMethod == IntrinsicMethod.LINK_TO_VIRTUAL || intrinsicMethod == IntrinsicMethod.LINK_TO_INTERFACE) { + ResolvedJavaType receiverType = StampTool.typeOrNull(getReceiver().stamp()); + if (receiverType != null) { + ResolvedJavaMethod concreteMethod = receiverType.findUniqueConcreteMethod(targetMethod); + if (concreteMethod != null) { + return createTargetInvokeNode(concreteMethod); + } + } + } + + if (targetMethod.canBeStaticallyBound()) { + return createTargetInvokeNode(targetMethod); + } + + ResolvedJavaMethod concreteMethod = targetMethod.getDeclaringClass().findUniqueConcreteMethod(targetMethod); + if (concreteMethod != null) { + return createTargetInvokeNode(concreteMethod); + } + + return null; + } + + /** + * Inserts a node to cast the argument at index to the given type if the given type is more + * concrete than the argument type. + * + * @param index of the argument to be cast + * @param type the type the argument should be cast to + */ + private void maybeCastArgument(int index, JavaType type) { + if (type instanceof ResolvedJavaType) { + ResolvedJavaType targetType = (ResolvedJavaType) type; + if (!targetType.isPrimitive()) { + ValueNode argument = arguments.get(index); + ResolvedJavaType argumentType = StampTool.typeOrNull(argument.stamp()); + if (argumentType == null || (argumentType.isAssignableFrom(targetType) && !argumentType.equals(targetType))) { + PiNode piNode = graph().unique(new PiNode(argument, StampFactory.declared(targetType))); + arguments.set(index, piNode); + } + } + } + } + + /** + * Creates an {@link InvokeNode} for the given target method. The {@link CallTargetNode} passed + * to the InvokeNode is in fact a {@link SelfReplacingMethodCallTargetNode}. + * + * @param targetMethod the method the be called + * @return invoke node for the member name target + */ + private InvokeNode createTargetInvokeNode(ResolvedJavaMethod targetMethod) { + InvokeKind invokeKind = targetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; + JavaType returnType = targetMethod.getSignature().getReturnType(null); + + // MethodHandleLinkTo* nodes have a trailing MemberName argument which + // needs to be popped. + ValueNode[] originalArguments = arguments.toArray(new ValueNode[arguments.size()]); + ValueNode[] targetArguments; + switch (intrinsicMethod) { + case INVOKE_BASIC: + targetArguments = originalArguments; + break; + case LINK_TO_STATIC: + case LINK_TO_SPECIAL: + case LINK_TO_VIRTUAL: + case LINK_TO_INTERFACE: + targetArguments = Arrays.copyOfRange(originalArguments, 0, arguments.size() - 1); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + + // If there is already replacement information, use that instead. + MethodCallTargetNode callTarget; + if (replacementTargetMethod == null) { + callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, getTargetMethod(), originalArguments, getReturnType()); + } else { + ValueNode[] args = replacementArguments.toArray(new ValueNode[replacementArguments.size()]); + callTarget = new SelfReplacingMethodCallTargetNode(invokeKind, targetMethod, targetArguments, returnType, replacementTargetMethod, args, replacementReturnType); + } + graph().add(callTarget); + + // The call target can have a different return type than the invoker, + // e.g. the target returns an Object but the invoker void. In this case + // we need to use the stamp of the invoker. Note: always using the + // invoker's stamp would be wrong because it's a less concrete type + // (usually java.lang.Object). + InvokeNode invoke; + if (stamp() == StampFactory.forVoid()) { + invoke = new InvokeNode(callTarget, getBci(), stamp()); + } else { + invoke = new InvokeNode(callTarget, getBci()); + } + graph().add(invoke); + invoke.setStateAfter(stateAfter()); + return invoke; + } + +} diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java --- a/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAIL.java Mon May 05 18:38:43 2014 +0200 @@ -136,7 +136,6 @@ public static final Register threadRegister = d20; public static final Register actionAndReasonReg = s32; public static final Register codeBufferOffsetReg = s33; - public static final Register dregOopMapReg = s39; // @formatter:off public static final Register[] cRegisters = { @@ -178,10 +177,16 @@ return -(((StackSlot) reg).getRawOffset()); } - public static String mapStackSlot(Value reg) { - StackSlot s = (StackSlot) reg; - long offset = -s.getRawOffset(); - return "[%spillseg]" + "[" + offset + "]"; + /** + * The mapping to stack slots is always relative to the beginning of the spillseg. + * {@link #getStackOffset(Value)} returns the positive version of the originally negative + * offset. Then we back up from that by {@code argSize} in bytes. This ensures that slots of + * different size do not overlap, even though we have converted from negative to positive + * offsets. + */ + public static int getStackOffsetStart(Value reg, int argSize) { + int argSizeInBytes = argSize / 8; + return getStackOffset(reg) - argSizeInBytes; } public static String mapRegister(Value arg) { diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java Mon May 05 18:38:43 2014 +0200 @@ -108,7 +108,7 @@ private final String from; private final String to; @Def({REG}) protected AllocatableValue result; - @Use({REG, STACK}) protected AllocatableValue x; + @Use({REG}) protected AllocatableValue x; public ConvertOp(AllocatableValue result, AllocatableValue x, String to, String from) { this.from = from; @@ -123,52 +123,10 @@ } } - public static class Op1Stack extends HSAILLIRInstruction { - @Opcode private final HSAILArithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; - - public Op1Stack(HSAILArithmetic opcode, Value result, Value x) { - this.opcode = opcode; - this.result = result; - this.x = x; - } - - @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - emit(crb, masm, opcode, result, x, null); - } - } - - public static class Op2Stack extends HSAILLIRInstruction { + public static class Op1Reg extends HSAILLIRInstruction { @Opcode private final HSAILArithmetic opcode; @Def({REG, HINT}) protected Value result; @Use({REG, CONST}) protected Value x; - @Alive({REG, CONST}) protected Value y; - - public Op2Stack(HSAILArithmetic opcode, Value result, Value x, Value y) { - this.opcode = opcode; - this.result = result; - this.x = x; - this.y = y; - } - - @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - emit(crb, masm, opcode, result, x, y, null); - } - - @Override - public void verify() { - super.verify(); - verifyKind(opcode, result, x, y); - } - } - - public static class Op1Reg extends HSAILLIRInstruction { - @Opcode private final HSAILArithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG}) protected Value x; public Op1Reg(HSAILArithmetic opcode, Value result, Value x) { this.opcode = opcode; @@ -185,7 +143,7 @@ public static class Op2Reg extends HSAILLIRInstruction { @Opcode private final HSAILArithmetic opcode; @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; + @Use({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; public Op2Reg(HSAILArithmetic opcode, Value result, Value x, Value y) { @@ -207,35 +165,10 @@ } } - public static class Op2RegCommutative extends HSAILLIRInstruction { - @Opcode private final HSAILArithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; - @Use({REG, CONST}) protected Value y; - - public Op2RegCommutative(HSAILArithmetic opcode, Value result, Value x, Value y) { - this.opcode = opcode; - this.result = result; - this.x = x; - this.y = y; - } - - @Override - public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) { - throw GraalInternalError.shouldNotReachHere(); - } - - @Override - protected void verify() { - super.verify(); - verifyKind(opcode, result, x, y); - } - } - public static class ShiftOp extends HSAILLIRInstruction { @Opcode private final HSAILArithmetic opcode; @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; + @Use({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; public ShiftOp(HSAILArithmetic opcode, Value result, Value x, Value y) { @@ -295,7 +228,7 @@ /** * Emits the HSAIL code for an arithmetic operation taking one input parameter. - * + * * @param crb the CompilationResultBuilder * @param masm the HSAIL assembler * @param opcode the opcode of the arithmetic operation diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILCompare.java Mon May 05 18:38:43 2014 +0200 @@ -50,8 +50,8 @@ public static class CompareOp extends HSAILLIRInstruction { @Opcode private final HSAILCompare opcode; - @Use({REG, STACK, CONST}) protected Value x; - @Use({REG, STACK, CONST}) protected Value y; + @Use({REG, CONST}) protected Value x; + @Use({REG, CONST}) protected Value y; @Def({REG}) protected Value z; private final Condition condition; public boolean unordered = false; diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java Mon May 05 18:38:43 2014 +0200 @@ -146,7 +146,6 @@ protected MetaAccessProvider metaAccessProvider; protected String emitName; protected int codeBufferPos = -1; - protected int dregOopMap = 0; public DeoptimizeOp(Value actionAndReason, LIRFrameState frameState, String emitName, MetaAccessProvider metaAccessProvider) { super(Value.ILLEGAL); // return with no ret value @@ -181,20 +180,10 @@ masm.emitComment("/* HSAIL Deoptimization pos=" + codeBufferPos + ", bci=" + frameState.debugInfo().getBytecodePosition().getBCI() + ", frameState=" + frameState + " */"); - // get the bitmap of $d regs that contain references - ReferenceMap referenceMap = frameState.debugInfo().getReferenceMap(); - for (int dreg = HSAIL.d0.number; dreg <= HSAIL.d15.number; dreg++) { - if (referenceMap.getRegister(dreg) == Kind.Object) { - dregOopMap |= 1 << (dreg - HSAIL.d0.number); - } - } - AllocatableValue actionAndReasonReg = HSAIL.actionAndReasonReg.asValue(Kind.Int); AllocatableValue codeBufferOffsetReg = HSAIL.codeBufferOffsetReg.asValue(Kind.Int); - AllocatableValue dregOopMapReg = HSAIL.dregOopMapReg.asValue(Kind.Int); masm.emitMov(Kind.Int, actionAndReasonReg, actionAndReason); masm.emitMov(Kind.Int, codeBufferOffsetReg, Constant.forInt(codeBufferPos)); - masm.emitMov(Kind.Int, dregOopMapReg, Constant.forInt(dregOopMap)); masm.emitJumpToLabelName(masm.getDeoptLabelName()); // now record the debuginfo @@ -305,10 +294,10 @@ @Opcode protected final HSAILCompare opcode; @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value trueValue; - @Use({REG, STACK, CONST}) protected Value falseValue; - @Use({REG, STACK, CONST}) protected Value left; - @Use({REG, STACK, CONST}) protected Value right; + @Use({REG, CONST}) protected Value trueValue; + @Use({REG, CONST}) protected Value falseValue; + @Use({REG, CONST}) protected Value left; + @Use({REG, CONST}) protected Value right; protected final Condition condition; public CondMoveOp(HSAILCompare opcode, Variable left, Variable right, Variable result, Condition condition, Value trueValue, Value falseValue) { diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java --- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILMove.java Mon May 05 18:38:43 2014 +0200 @@ -63,29 +63,6 @@ } @Opcode("MOVE") - public static class SpillMoveOp extends AbstractMoveOp { - - @Def({REG, STACK}) protected AllocatableValue result; - @Use({REG, STACK, CONST}) protected Value input; - - public SpillMoveOp(Kind moveKind, AllocatableValue result, Value input) { - super(moveKind); - this.result = result; - this.input = input; - } - - @Override - public Value getInput() { - return input; - } - - @Override - public AllocatableValue getResult() { - return result; - } - } - - @Opcode("MOVE") public static class MoveToRegOp extends AbstractMoveOp { @Def({REG, HINT}) protected AllocatableValue result; diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/BaseReduction.java Mon May 05 18:38:43 2014 +0200 @@ -44,11 +44,16 @@ * disadvantages. *

* - * *

* This class makes available little more than a few fields and a few utility methods used * throughout the remaining components making up control-flow sensitive reductions. *

+ * + *

+ * The laundry-list of all flow-sensitive reductions is summarized in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} + *

+ * */ public abstract class BaseReduction extends PostOrderNodeIterator { @@ -83,6 +88,12 @@ this.deoptReason = deoptReason; } + /* + * TODO Actually, we want to emit instructions to signal "should-not-reach-here". An + * imperfect substitute (as done here) is emitting FixedGuard(false). + * "should-not-reach-here" would be better for the runtime error it raises, thus pointing to + * a bug in FlowSensitiveReduction (the code was reachable, after all). + */ public void doRewrite(LogicNode falseConstant) { StructuredGraph graph = fixed.graph(); // have to insert a FixedNode other than a ControlSinkNode diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java Mon May 05 18:38:43 2014 +0200 @@ -41,6 +41,11 @@ * {@link com.oracle.graal.nodes.java.CheckCastNode}. *

* + *

+ * The laundry-list of all flow-sensitive reductions is summarized in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} + *

+ * * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) */ public abstract class CheckCastReduction extends GuardingPiReduction { @@ -51,17 +56,37 @@ /** *

- * This phase is able to refine the types of reference-values at use sites provided a - * {@link com.oracle.graal.nodes.extended.GuardingNode GuardingNode} is available witnessing - * that fact. + * Upon visiting a {@link com.oracle.graal.nodes.java.CheckCastNode}, based on flow-sensitive + * conditions, we need to determine whether: + *

*

* *

- * This method turns non-redundant {@link com.oracle.graal.nodes.java.CheckCastNode}s into - * {@link com.oracle.graal.nodes.GuardingPiNode}s. Once such lowering has been performed (during - * run N of this phase) follow-up runs attempt to further simplify the resulting node, see - * {@link EquationalReasoner#downcastGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode, Witness)} - * and {@link #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode)} + * This method realizes the above by testing first for situations that require less work: + *

    + *
  1. the stamp of the subject deems the check-cast redundant or unsatisfiable (ie, + * always-succeeds or always-fails). A previous round of canonicalization takes care of this + * situation, however it can also arise due to consecutive runs of + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} without intervening + * {@link com.oracle.graal.phases.common.CanonicalizerPhase canonicalization}.
  2. + *
  3. + * flow-sensitive information reveals the subject to be null, trivially fulfilling the + * check-cast.
  4. + *
  5. + * flow-sensitive information reveals the subject to be narrower than it stamp says. If the + * narrower ("downcasted") value fulfills the check-cast, the check-cast is removed.
  6. + *
  7. + * otherwise the check-cast provides additional flow-sensitive information. For that, a + * {@link com.oracle.graal.nodes.FixedGuardNode} is needed, as described in + * {@link #lowerCheckCastAnchorFriendlyWay(com.oracle.graal.nodes.java.CheckCastNode, com.oracle.graal.nodes.ValueNode)} + * . Please notice this lowering is currently performed unconditionally: it might occur no + * flow-sensitive reduction is enabled down the road.
  8. + *
*

* *

@@ -155,19 +180,24 @@ * *

* Rather than tracking the CheckCastNode via {@link com.oracle.graal.phases.common.cfs.State - * State} (doing so woud add a special case because a + * State} (doing so would add a special case because a * {@link com.oracle.graal.nodes.java.CheckCastNode} isn't a - * {@link com.oracle.graal.nodes.extended.GuardingNode}) this method creates an anchor by - * lowering the CheckCastNode into a FixedGuardNode. Not the same way as done by - * {@link com.oracle.graal.nodes.java.CheckCastNode#lower(com.oracle.graal.nodes.spi.LoweringTool)} - * which lowers into a {@link com.oracle.graal.nodes.GuardingPiNode} (which is not a - * {@link com.oracle.graal.nodes.extended.GuardingNode}). + * {@link com.oracle.graal.nodes.extended.GuardingNode guarding node}) this method creates an + * anchor by lowering the CheckCastNode into a FixedGuardNode. Not the same as the + * {@link com.oracle.graal.nodes.java.CheckCastNode#lower(com.oracle.graal.nodes.spi.LoweringTool) + * lowering of a CheckCastNode} which results in a {@link com.oracle.graal.nodes.GuardingPiNode} + * (which is not a {@link com.oracle.graal.nodes.extended.GuardingNode guarding node}). *

* *

* With that, state tracking can proceed as usual. *

* + *

+ * TODO This lowering is currently performed unconditionally: it might occur no flow-sensitive + * reduction is enabled down the road + *

+ * * @see #visitCheckCastNode(com.oracle.graal.nodes.java.CheckCastNode) * */ diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java Mon May 05 18:38:43 2014 +0200 @@ -219,7 +219,7 @@ if (n == null) { return null; } - assert !(n instanceof GuardNode) : "This phase not yet ready to run during MidTier"; + assert !(n instanceof GuardNode) : "This phase not intended to run during MidTier"; if (!(n instanceof ValueNode)) { return n; } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FixedGuardReduction.java Mon May 05 18:38:43 2014 +0200 @@ -33,6 +33,11 @@ * This class implements control-flow sensitive reductions for * {@link com.oracle.graal.nodes.FixedGuardNode}. *

+ * + *

+ * The laundry-list of all flow-sensitive reductions is summarized in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} + *

* * @see #visitFixedGuardNode(com.oracle.graal.nodes.FixedGuardNode) */ @@ -43,15 +48,33 @@ } /** - * In case the condition is constant, - * {@link com.oracle.graal.nodes.FixedGuardNode#simplify(com.oracle.graal.graph.spi.SimplifierTool) - * FixedGuardNode#simplify(SimplifierTool)} will eventually remove the - * {@link com.oracle.graal.nodes.FixedGuardNode} ("always succeeds") or kill the code that - * should be killed ("always fails"). + *

+ * Upon visiting a {@link com.oracle.graal.nodes.FixedGuardNode}, based on flow-sensitive + * conditions, we need to determine whether: + *

+ *

* *

- * The only thing we do here is tracking as true fact (from this program point onwards) the - * condition of the {@link com.oracle.graal.nodes.FixedGuardNode FixedGuardNode}. + * This method realizes the above by inspecting the + * {@link com.oracle.graal.nodes.FixedGuardNode}'s condition: + *

    + *
  1. a constant condition signals the node won't be reduced here
  2. + *
  3. the outcome of the condition can be predicted:
  4. + *
      + *
    • + * "always succeeds", after finding an equivalent (or stronger) + * {@link com.oracle.graal.nodes.extended.GuardingNode} in scope. The + * {@link com.oracle.graal.nodes.FixedGuardNode} is removed after replacing its usages with the + * existing guarding node
    • + *
    • + * "always fails", which warrants making that explicit by making the condition constant, see + * {@link #markFixedGuardNodeAlwaysFails(com.oracle.graal.nodes.FixedGuardNode)}
    • + *
    + *
  5. otherwise the condition is tracked flow-sensitively
  6. + *
*

* *

@@ -62,6 +85,8 @@ /* * A FixedGuardNode with LogicConstantNode condition is left untouched. + * `FixedGuardNode.simplify()` will eventually remove the FixedGuardNode (in case it + * "always succeeds") or kill code ("always fails"). */ if (f.condition() instanceof LogicConstantNode) { @@ -92,10 +117,10 @@ final boolean isTrue = !f.isNegated(); /* - * FixedGuardNode requires handling similar to that of GuardingPiNode, (ie the condition - * can't simply be deverbosified in place). A replacement anchor is needed, ie an anchor - * that amounts to the same combination of (negated, condition) for the FixedGuardNode at - * hand. + * A FixedGuardNode can only be removed provided a replacement anchor is found (so called + * "evidence"), ie an anchor that amounts to the same combination of (negated, condition) as + * for the FixedGuardNode at hand. Just deverbosifying the condition in place isn't + * semantics-preserving. */ // TODO what about isDependencyTainted @@ -202,7 +227,8 @@ * Porcelain method. * *

- * The `replacement` guard must be such that it implies the `old` guard. + * The `replacement` guard must be such that it implies the `old` guard. Moreover, rhe + * `replacement` guard must be in scope. *

*/ private void removeFixedGuardNode(FixedGuardNode old, GuardingNode replacement) { diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java Mon May 05 18:38:43 2014 +0200 @@ -43,20 +43,37 @@ /** *

- * All control-flow-sensitive reductions follow the common pattern of + * In a nutshell, {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReductionPhase} makes a + * single pass in dominator-based order over the graph: + *

    + *
  1. collecting properties of interest at control-splits; as well as for check-casts, + * guarding-pis, null-checks, and fixed-guards. Such flow-sensitive information is tracked via a + * dedicated {@link com.oracle.graal.phases.common.cfs.State state instance} for each control-flow + * path.
  2. + *
  3. performing rewritings that are safe at specific program-points. This comprises: *
      - *
    • Recognizing properties of interest (ie, LogicNode-s) at control-flow splits, as well as upon - * check-casts and fixed-guards.
    • - *
    • Using the information thus tracked to simplify - *
        - *
      • side-effects free expressions, via + *
      • simplification of side-effects free expressions, via * {@link com.oracle.graal.phases.common.cfs.EquationalReasoner#deverbosify(com.oracle.graal.graph.Node)} *
      • - *
      • control-flow, eg. by eliminating redundant fixed-guards and check-casts, ie which are known - * always to hold.
      • + *
      • simplification of control-flow: + *
          + *
        • + * by simplifying the input-condition to an {@link com.oracle.graal.nodes.IfNode}
        • + *
        • + * by eliminating redundant check-casts, guarding-pis, null-checks, and fixed-guards; where + * "redundancy" is determined using flow-sensitive information. In these cases, redundancy can be + * due to: + *
            + *
          • an equivalent, existing, guarding node is already in scope (thus, use it as replacement and + * remove the redundant one)
          • + *
          • "always fails" (thus, replace the node in question with FixedGuardNode(false))
          • *
          *
        • *
        + *
      • + *
      + *
    • + *
*

* * @see com.oracle.graal.phases.common.cfs.CheckCastReduction @@ -145,6 +162,9 @@ if (begin instanceof LoopExitNode) { state.clear(); + /* + * TODO return or not? (by not returning we agree it's ok to update the state as below) + */ } if (pred instanceof IfNode) { @@ -253,7 +273,7 @@ public boolean deverbosifyInputsInPlace(ValueNode parent) { boolean changed = false; for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) { - assert !(i instanceof GuardNode) : "ConditionalElim shouldn't run in MidTier"; + assert !(i instanceof GuardNode) : "This phase not intended to run during MidTier"; ValueNode j = (ValueNode) reasoner.deverbosify(i); if (i != j) { changed = true; @@ -390,7 +410,7 @@ * Step 5: After special-case handling, we do our best for those FixedNode-s * where the effort to reduce their inputs might pay off. * - * Why is this useful? For example, by the time the AbstractBeginNode for an If-branch + * Why is this useful? For example, by the time the BeginNode for an If-branch * is visited (in general a ControlSplitNode), the If-condition will have gone already * through simplification (and thus potentially have been reduced to a * LogicConstantNode). @@ -407,8 +427,7 @@ paysOffToReduce = true; } - // TODO comb the remaining FixedWithNextNode subclasses, pick those with good changes of - // paying-off + // TODO comb remaining FixedWithNextNode subclasses, pick those with chances of paying-off // TODO UnsafeLoadNode takes a condition @@ -423,8 +442,7 @@ */ // TODO some nodes are GuardingNodes (eg, FixedAccessNode) we could use them to track state - // TODO others are additionally guarded (eg JavaReadNode), thus *their* guards could be - // simplified. + // TODO other nodes are guarded (eg JavaReadNode), thus *their* guards could be replaced. } @@ -498,11 +516,29 @@ } /** - * One or more arguments at `invoke` may have control-flow sensitive simplifications. In such - * case, a new {@link com.oracle.graal.nodes.java.MethodCallTargetNode MethodCallTargetNode} is - * prepared just for this callsite, consuming reduced arguments. This proves useful in - * connection with inlining, in order to specialize callees on the types of arguments other than - * the receiver (examples: multi-methods, the inlining problem, lambdas as arguments). + *

+ * For one or more `invoke` arguments, flow-sensitive information may suggest their narrowing or + * simplification. In those cases, a new + * {@link com.oracle.graal.nodes.java.MethodCallTargetNode MethodCallTargetNode} is prepared + * just for this callsite, consuming reduced arguments. + *

+ * + *

+ * Specializing the {@link com.oracle.graal.nodes.java.MethodCallTargetNode + * MethodCallTargetNode} as described above may enable two optimizations: + *

+ *

* *

* Precondition: inputs haven't been deverbosified yet. diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReductionPhase.java Mon May 05 18:38:43 2014 +0200 @@ -43,6 +43,10 @@ @Override protected final void run(StructuredGraph graph, PhaseContext context) { try (Debug.Scope s = Debug.scope("FlowSensitiveReduction")) { + if (graph.isOSR()) { + Debug.log("Skipping OSR method %s", graph.method() == null ? "" : MetaUtil.format("%H.%n", graph.method())); + return; + } Debug.dump(graph, "FlowSensitiveReduction initial"); new FlowSensitiveReduction(graph.start(), new State(), context).apply(); Debug.dump(graph, "FlowSensitiveReduction done"); diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowUtil.java Mon May 05 18:38:43 2014 +0200 @@ -23,10 +23,6 @@ package com.oracle.graal.phases.common.cfs; import com.oracle.graal.api.meta.ResolvedJavaType; -import com.oracle.graal.debug.Debug; -import com.oracle.graal.debug.DebugConfig; -import com.oracle.graal.debug.DebugConfigScope; -import com.oracle.graal.debug.internal.DebugScope; import com.oracle.graal.graph.InputType; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeClass; @@ -290,28 +286,4 @@ // `oldInput` if unused wil be removed in finished() } - public static StructuredGraph visualize(StructuredGraph graph, String title) { - DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = Debug.fixedConfig(false, true, false, false, debugConfig.dumpHandlers(), debugConfig.output()); - try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { - Debug.dump(graph, title); - - return graph; - } - } - - public static final String ANSI_RESET = "\u001B[0m"; - public static final String ANSI_BLACK = "\u001B[30m"; - public static final String ANSI_RED = "\u001B[31m"; - public static final String ANSI_GREEN = "\u001B[32m"; - public static final String ANSI_YELLOW = "\u001B[33m"; - public static final String ANSI_BLUE = "\u001B[34m"; - public static final String ANSI_PURPLE = "\u001B[35m"; - public static final String ANSI_CYAN = "\u001B[36m"; - public static final String ANSI_WHITE = "\u001B[37m"; - - public static void highlightInRed(String msg) { - System.out.println(ANSI_RED + msg + ANSI_RESET); - } - } diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/GuardingPiReduction.java Mon May 05 18:38:43 2014 +0200 @@ -37,7 +37,12 @@ * This class implements control-flow sensitive reductions for * {@link com.oracle.graal.nodes.GuardingPiNode}. *

- * + * + *

+ * The laundry-list of all flow-sensitive reductions is summarized in + * {@link com.oracle.graal.phases.common.cfs.FlowSensitiveReduction} + *

+ * * @see #visitGuardingPiNode(com.oracle.graal.nodes.GuardingPiNode) */ public abstract class GuardingPiReduction extends BaseReduction { @@ -139,6 +144,12 @@ FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(envelope.condition(), envelope.getReason(), envelope.getAction(), envelope.isNegated())); graph.addBeforeFixed(envelope, fixedGuard); + /* + * + * TODO This lowering is currently performed unconditionally: it might occur no + * flow-sensitive reduction is enabled down the road + */ + if (!FlowUtil.lacksUsages(envelope)) { // not calling wrapInPiNode() because we don't want to rememberSubstitution() PiNode replacement = graph.unique(new PiNode(envelope.object(), envelope.stamp(), fixedGuard)); diff -r 6f23b90c4129 -r a900caddcd60 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java Mon May 05 18:38:13 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/Histogram.java Mon May 05 18:38:43 2014 +0200 @@ -54,7 +54,7 @@ int percentOut = (int) (numCases / casesTotal * 100); String msg = prefix + String.format("%d iters in %4d cases (%2d %%)", entry.getKey(), numCases, percentOut); if (entry.getKey() > 3) { - FlowUtil.highlightInRed(msg); + highlightInRed(msg); } else { System.out.println(msg); } @@ -67,4 +67,11 @@ return (Histogram) super.clone(); } + public static final String ANSI_RESET = "\u001B[0m"; + public static final String ANSI_RED = "\u001B[31m"; + + public static void highlightInRed(String msg) { + System.out.println(ANSI_RED + msg + ANSI_RESET); + } + } diff -r 6f23b90c4129 -r a900caddcd60 src/gpu/hsail/vm/gpu_hsail.cpp --- a/src/gpu/hsail/vm/gpu_hsail.cpp Mon May 05 18:38:13 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.cpp Mon May 05 18:38:43 2014 +0200 @@ -67,7 +67,7 @@ JNINativeMethod Hsail::HSAIL_methods[] = { {CC"initialize", CC"()Z", FN_PTR(Hsail::initialize)}, {CC"generateKernel", CC"([B" STRING ")J", FN_PTR(Hsail::generate_kernel)}, - {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, + {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT"["OBJECT"["JLTHREAD"I[I)Z", FN_PTR(Hsail::execute_kernel_void_1d)}, }; void * Hsail::_device_context = NULL; @@ -147,7 +147,7 @@ } GPU_VMENTRY(jboolean, Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args, jobject oops_save, - jobject donor_threads, jint allocBytesPerWorkitem)) + jobject donor_threads, jint allocBytesPerWorkitem, jobject oop_map_array)) ResourceMark rm; jlong nmethodValue = InstalledCode::address(kernel_handle); @@ -163,7 +163,7 @@ SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL); } - return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, CHECK_0); +return execute_kernel_void_1d_internal((address) kernel, dimX, args, mh, nm, oops_save, donor_threads, allocBytesPerWorkitem, oop_map_array, CHECK_0); GPU_END static void showRanges(jboolean *a, int len) { @@ -215,9 +215,139 @@ tty->print_cr("(%p, %p, %p), siz=%ld, free=%ld (%f%%)", start, top, end, tlabSize, tlabFree, freePct); } +class OopSaver : public StackObj { +private: + objArrayOop _oopsSaveArray; + typeArrayOop _oopMapArray; + jobject _oops_save; + jobject _oop_map_array; + int _last_pcoffset; + int _last_idx; + int _saveAreaCounts; -jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save, - jobject donor_threads, int allocBytesPerWorkitem, TRAPS) { + enum { + SAVEAREACOUNTS_OFST=0, + SPAN_OFST=1, + HEADERSIZE=2 + }; + int mapPcOffsetToIndex(int pcOffset) { + if (pcOffset == _last_pcoffset) { + return _last_idx; + } + int span = _oopMapArray->int_at(SPAN_OFST); + for (int idx = HEADERSIZE; idx < _oopMapArray->length(); idx += span) { + int ofst = _oopMapArray->int_at(idx); + if (ofst == pcOffset) { + _last_pcoffset = pcOffset; + _last_idx = idx + 1; + return _last_idx; + } + } + } + +public: + OopSaver(jobject oops_save, jobject oop_map_array) { + _oops_save = oops_save; + _oop_map_array = oop_map_array; + _last_pcoffset = -1; + _saveAreaCounts = getSaveAreaCounts(oop_map_array); + resolveArrays(); + } + + void resolveArrays() { + _oopsSaveArray = (objArrayOop) JNIHandles::resolve(_oops_save); + _oopMapArray = (typeArrayOop) JNIHandles::resolve(_oop_map_array); + } + + void * getOopForBit(HSAILFrame * hsailFrame, int bit) { + assert(isOop(hsailFrame, bit), ""); + void *oop; + if (bit < hsailFrame->num_d_regs()) { + // d register + oop = (void*) hsailFrame->get_d_reg(bit); + } else { + // stack slot + int stackOffset = (bit - hsailFrame->num_d_regs()) * 8; // 8 bytes per stack slot + oop = (void *) hsailFrame->get_stackslot64(stackOffset); + } + return oop; + } + + void putOopForBit(HSAILFrame * hsailFrame, int bit, void *oop) { + assert(isOop(hsailFrame, bit), ""); + if (bit < hsailFrame->num_d_regs()) { + // d register + hsailFrame->put_d_reg(bit, (jlong) oop); + } else { + // stack slot + int stackOffset = (bit - hsailFrame->num_d_regs()) * 8; // 8 bytes per stack slot + hsailFrame->put_stackslot64(stackOffset, (jlong) oop); + } + } + + void saveOopsFromFrame(HSAILFrame * hsailFrame, int deoptSlot){ + // as used, no need to resolve arrays on each call + int oopsPerDeopt = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots(); + + // handle the dregister and stackSlot based oops + for (int bit = 0; bit < oopsPerDeopt; bit++) { + if (isOop(hsailFrame, bit)) { + void* saved_oop = getOopForBit(hsailFrame, bit); + int saveArrayIndex = deoptSlot * oopsPerDeopt + bit; + _oopsSaveArray->obj_at_put(saveArrayIndex, (oop) saved_oop); + } + } + } + + void restoreOopsToFrame(HSAILFrame * hsailFrame, int deoptSlot, int workitem){ + // need to re-resolve on each restore + resolveArrays(); + int oopsPerDeopt = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots(); + + // handle the dregister and stackSlot based oops + for (int bit = 0; bit < oopsPerDeopt; bit++) { + if (isOop(hsailFrame, bit)) { + // the dregister or stack slot at this bit is an oop, retrieve it from array and put back in frame + int saveArrayIndex = deoptSlot * oopsPerDeopt + bit; + void * newValue = (void *) _oopsSaveArray->obj_at(saveArrayIndex); + void * oldValue = getOopForBit(hsailFrame, bit); + assert((oldValue != 0 ? newValue != 0 : newValue == 0), "bad dregValue retrieved"); + if (newValue != oldValue) { + if (TraceGPUInteraction) { + int numDRegs = hsailFrame->num_d_regs(); + const char *name = (bit < numDRegs ? "$d" : "stk"); + int num = (bit < numDRegs ? bit : bit - numDRegs); + tty->print_cr("oop moved for %s%d, workitem %d, slot %d, old=%p, new=%p", + name, num, workitem, deoptSlot, oldValue, newValue); + } + putOopForBit(hsailFrame, bit, newValue); + } + } + } + } + + bool isOop(HSAILFrame * hsailFrame, int bit){ + // re-resolve on each access + resolveArrays(); + if (bit > hsailFrame->num_d_regs() + hsailFrame->num_stack_slots()) { + return false; + } + int pcOffset = hsailFrame->pc_offset(); + int bits_int_idx = mapPcOffsetToIndex(pcOffset) + (bit / 32); + int bitpos = bit % 32; + int bits = _oopMapArray->int_at(bits_int_idx); + return ((bits & (1 << bitpos)) != 0); + } + + static int getSaveAreaCounts(jobject oopMapArrayObject) { + typeArrayOop oopMapArray = (typeArrayOop) JNIHandles::resolve(oopMapArrayObject); + return oopMapArray->int_at(SAVEAREACOUNTS_OFST); + } + +}; + +jboolean Hsail::execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oops_save, + jobject donor_threads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS) { ResourceMark rm(THREAD); objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args); @@ -260,9 +390,16 @@ // Reset the kernel arguments _okra_clearargs(kernel); + // get how many bytes per deopt save area are required + int saveAreaCounts = OopSaver::getSaveAreaCounts(oop_map_array); + int numSRegs = saveAreaCounts & 0xff; + int numDRegs = (saveAreaCounts >> 8) & 0xff; + int numStackSlots = (saveAreaCounts >> 16); + int bytesPerSaveArea = numSRegs * 4 + (numDRegs + numStackSlots) * 8; + HSAILDeoptimizationInfo* e; if (UseHSAILDeoptimization) { - e = new (ResourceObj::C_HEAP, mtInternal) HSAILDeoptimizationInfo(); + e = new (MAX_DEOPT_SLOTS, bytesPerSaveArea) HSAILDeoptimizationInfo(MAX_DEOPT_SLOTS, bytesPerSaveArea); e->set_never_ran_array(NEW_C_HEAP_ARRAY(jboolean, dimX, mtInternal)); memset(e->never_ran_array(), 0, dimX * sizeof(jboolean)); e->set_donor_threads(donorThreads); @@ -318,7 +455,6 @@ if (UseHSAILDeoptimization) { kernelStats.incDeopts(); // check if any workitem requested a deopt - // currently we only support at most one such workitem int deoptcode = e->deopt_occurred(); if (deoptcode != 1) { if (deoptcode == 0) { @@ -337,40 +473,30 @@ TraceTime t3("handle deoptimizing workitems", TraceGPUInteraction); if (TraceGPUInteraction) { tty->print_cr("deopt happened."); - HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[0]; + HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(0); tty->print_cr("first deopter was workitem %d", pdeopt->workitem()); } // Before handling any deopting workitems, save the pointers from // the hsail frames in oops_save so they get adjusted by any // GC. Need to do this before leaving thread_in_vm mode. + OopSaver oopSaver(oops_save, oop_map_array); // resolve handle only needed once here (not exiting vm mode) - objArrayOop oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save); + oopSaver.resolveArrays(); // since slots are allocated from the beginning, we know how far to look - assert(e->num_deopts() < MAX_DEOPT_SAVE_STATES_SIZE, "deopt save state overflow"); + assert(e->num_deopts() < e->num_slots(), "deopt save state overflow"); for (int k = 0; k < e->num_deopts(); k++) { - HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[k]; - jint workitem = pdeopt->workitem(); - if (workitem != -1) { - // this is a workitem that deopted - HSAILFrame *hsailFrame = pdeopt->first_frame(); - int dregOopMap = hsailFrame->dreg_oops_map(); - for (int bit = 0; bit < 16; bit++) { - if ((dregOopMap & (1 << bit)) != 0) { - // the dregister at this bit is an oop, save it in the array - int index = k * 16 + bit; - void* saved_oop = (void*) hsailFrame->get_d_reg(bit); - oopsSaveArray->obj_at_put(index, (oop) saved_oop); - } - } - } + HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(k); + assert (pdeopt->workitem() >= 0, "bad workitem in deopt"); + // this is a workitem that deopted + oopSaver.saveOopsFromFrame(pdeopt->first_frame(), k); } // Handle any deopting workitems. int count_deoptimized = 0; for (int k = 0; k < e->num_deopts(); k++) { - HSAILKernelDeoptimization * pdeopt = &e->_deopt_save_states[k]; + HSAILKernelDeoptimization * pdeopt = e->get_deopt_save_state(k); jint workitem = pdeopt->workitem(); if (workitem != -1) { @@ -378,25 +504,8 @@ HSAILFrame *hsailFrame = pdeopt->first_frame(); // update the hsailFrame from the oopsSaveArray - // re-resolve the handle - oopsSaveArray = (objArrayOop) JNIHandles::resolve(oops_save); - - int dregOopMap = hsailFrame->dreg_oops_map(); - for (int bit = 0; bit < 16; bit++) { - if ((dregOopMap & (1 << bit)) != 0) { - // the dregister at this bit is an oop, retrieve it from array and put back in frame - int index = k * 16 + bit; - void * dregValue = (void *) oopsSaveArray->obj_at(index); - void * oldDregValue = (void *) hsailFrame->get_d_reg(bit); - assert((oldDregValue != 0 ? dregValue != 0 : dregValue == 0), "bad dregValue retrieved"); - if (TraceGPUInteraction) { - if (dregValue != oldDregValue) { - tty->print_cr("oop moved for $d%d, workitem %d, slot %d, old=%p, new=%p", bit, workitem, k, oldDregValue, dregValue); - } - } - hsailFrame->put_d_reg(bit, (jlong) dregValue); - } - } + // will re-resolve the handles each time + oopSaver.restoreOopsToFrame(hsailFrame, k, workitem); JavaValue result(T_VOID); JavaCallArguments javaArgs; @@ -410,12 +519,19 @@ javaArgs.push_int(myActionReason); javaArgs.push_oop((oop) NULL); if (TraceGPUInteraction) { - int dregOopMap = hsailFrame->dreg_oops_map(); - tty->print_cr("[HSAIL] Deoptimizing to host for workitem=%d (slot=%d) with deoptId=%d, frame=" INTPTR_FORMAT ", actionAndReason=%d, dregOopMap=%04x", workitem, k, deoptId, hsailFrame, myActionReason, dregOopMap); - // show the registers containing references - for (int bit = 0; bit < 16; bit++) { - if ((dregOopMap & (1 << bit)) != 0) { - tty->print_cr(" oop $d%d = %p", bit, hsailFrame->get_d_reg(bit)); + tty->print_cr("[HSAIL] Deoptimizing to host for workitem=%d (slot=%d) with deoptId=%d, frame=" INTPTR_FORMAT ", actionAndReason=%d", workitem, k, deoptId, hsailFrame, myActionReason); + // show the $d registers or stack slots containing references + int maxOopBits = hsailFrame->num_d_regs() + hsailFrame->num_stack_slots(); + for (int bit = 0; bit < maxOopBits; bit++) { + if (oopSaver.isOop(hsailFrame, bit)) { + if (bit < hsailFrame->num_d_regs()) { + // show $d reg oop + tty->print_cr(" oop $d%d = %p", bit, oopSaver.getOopForBit(hsailFrame, bit)); + } else { + // show stack slot oop + int stackOffset = (bit - hsailFrame->num_d_regs()) * 8; // 8 bytes per stack slot + tty->print_cr(" oop stk:%d = %p", stackOffset, oopSaver.getOopForBit(hsailFrame, bit)); + } } } } @@ -461,7 +577,7 @@ } } TraceGPUInteraction = savedTraceGPUInteraction; - if (TraceGPUInteraction) { + if (TraceGPUInteraction && (count_never_ran > 0)) { tty->print_cr("%d workitems never ran, have been run via JavaCall", count_never_ran); showRanges(never_ran_array, dimX); } diff -r 6f23b90c4129 -r a900caddcd60 src/gpu/hsail/vm/gpu_hsail.hpp --- a/src/gpu/hsail/vm/gpu_hsail.hpp Mon May 05 18:38:13 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail.hpp Mon May 05 18:38:43 2014 +0200 @@ -51,7 +51,8 @@ }; // 8 compute units * 40 waves per cu * wavesize 64 -#define MAX_DEOPT_SAVE_STATES_SIZE (8 * 40 * 64) +// TODO: query the device to get this number +#define MAX_DEOPT_SLOTS (8 * 40 * 64) class HSAILDeoptimizationInfo : public ResourceObj { friend class VMStructs; @@ -61,14 +62,23 @@ jint _deopt_next_index; JavaThread** _donor_threads; jboolean * _never_ran_array; + jint _num_slots; + jint _bytesPerSaveArea; + jint _deopt_span; public: - HSAILKernelDeoptimization _deopt_save_states[MAX_DEOPT_SAVE_STATES_SIZE]; + HSAILKernelDeoptimization _deopt_save_states[1]; // number and size of these can vary per kernel - inline HSAILDeoptimizationInfo() { + inline HSAILDeoptimizationInfo(int numSlots, int bytesPerSaveArea) { _notice_safepoints = &Hsail::_notice_safepoints; _deopt_occurred = 0; _deopt_next_index = 0; + _num_slots = numSlots; + _bytesPerSaveArea = bytesPerSaveArea; + _deopt_span = sizeof(HSAILKernelDeoptimization) + bytesPerSaveArea; + if (TraceGPUInteraction) { + tty->print_cr("HSAILDeoptimizationInfo allocated, %d slots of size %d, total size = 0x%lx bytes", _num_slots, _deopt_span, (_num_slots * _deopt_span + sizeof(HSAILDeoptimizationInfo))); + } } inline jint deopt_occurred() { @@ -78,6 +88,23 @@ inline jboolean *never_ran_array() { return _never_ran_array; } inline void set_never_ran_array(jboolean *p) { _never_ran_array = p; } inline void set_donor_threads(JavaThread **threads) { _donor_threads = threads; } + inline jint num_slots() {return _num_slots;} + + inline HSAILKernelDeoptimization * get_deopt_save_state(int slot) { + // use _deopt_span to index into _deopt_states + char *p = (char *) _deopt_save_states; + p += _deopt_span * slot; + return (HSAILKernelDeoptimization *) p; + } + + void * operator new (size_t hdrSize, int numSlots, int bytesPerSaveArea) { + size_t totalSizeBytes = hdrSize + numSlots * (sizeof(HSAILKernelDeoptimization) + bytesPerSaveArea); + return NEW_C_HEAP_ARRAY(char, totalSizeBytes, mtInternal); + } + + void operator delete (void *ptr) { + FREE_C_HEAP_ARRAY(char, ptr, mtInternal); + } }; @@ -93,7 +120,7 @@ // static native boolean executeKernel0(HotSpotInstalledCode kernel, int jobSize, Object[] args); JNIEXPORT static jboolean execute_kernel_void_1d(JNIEnv *env, jclass, jobject hotspotInstalledCode, jint dimX, jobject args, jobject oopsSave, - jobject donorThreads, int allocBytesPerWorkitem); + jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array); // static native void getThreadPointers(Object[] donorThreads, long[] threadPointersOut); JNIEXPORT static void get_thread_pointers(JNIEnv *env, jclass, jobject donor_threads_handle, jobject thread_ptrs_handle); @@ -101,8 +128,8 @@ static void getNewTlabForDonorThread(ThreadLocalAllocBuffer* tlab, size_t tlabMinHsail); static jboolean execute_kernel_void_1d_internal(address kernel, int dimX, jobject args, methodHandle& mh, nmethod *nm, jobject oopsSave, - jobject donor_threads, int allocBytesPerWorkitem, TRAPS); - + jobject donorThreads, int allocBytesPerWorkitem, jobject oop_map_array, TRAPS); + static void register_heap(); static GraalEnv::CodeInstallResult install_code(Handle& compiled_code, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations); diff -r 6f23b90c4129 -r a900caddcd60 src/gpu/hsail/vm/gpu_hsail_Frame.hpp --- a/src/gpu/hsail/vm/gpu_hsail_Frame.hpp Mon May 05 18:38:13 2014 +0200 +++ b/src/gpu/hsail/vm/gpu_hsail_Frame.hpp Mon May 05 18:38:43 2014 +0200 @@ -5,39 +5,44 @@ #include "code/debugInfo.hpp" #include "code/location.hpp" -// maximum registers that could be saved for now -#define MAX_SREGS 32 -#define MAX_DREGS 16 - class HSAILFrame { friend class VMStructs; private: jint _pc_offset; // The HSAIL "pc_offset" where the exception happens jbyte _num_s_regs; jbyte _num_d_regs; - jshort _dreg_oops_map; // bits = 1 if that dreg is an oop - jlong _save_area[MAX_SREGS/2 + MAX_DREGS]; + jshort _num_stack_slots; + jbyte _save_area[0]; // save area size can vary per kernel compilation public: // Accessors jint pc_offset() { return _pc_offset; } jint num_s_regs() {return _num_s_regs; } jint num_d_regs() {return _num_d_regs; } - jint dreg_oops_map() {return _dreg_oops_map; } + jint num_stack_slots() {return _num_stack_slots; } jlong get_d_reg(int idx) { - char *p = (char *) _save_area; int ofst = num_s_regs() * 4 + idx * 8; - return(*(jlong *) (p + ofst)); + return(*(jlong *) (_save_area + ofst)); } jint get_s_reg(int idx) { - char *p = (char *) _save_area; int ofst = idx * 4; - return(*(jint *) (p + ofst)); + return(*(jint *) (_save_area + ofst)); } void put_d_reg(int idx, jlong val) { - char *p = (char *) _save_area; int ofst = num_s_regs() * 4 + idx * 8; - (*(jlong *) (p + ofst)) = val; + (*(jlong *) (_save_area + ofst)) = val; + } + jint get_stackslot32(int stackOffset) { + int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset; + return(*(jint *) (_save_area + ofst)); + } + jlong get_stackslot64(int stackOffset) { + int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset; + return(*(jlong *) (_save_area + ofst)); + } + void put_stackslot64(int stackOffset, jlong val) { + int ofst = num_s_regs() * 4 + num_d_regs() * 8 + stackOffset; + (*(jlong *) (_save_area + ofst)) = val; } }; diff -r 6f23b90c4129 -r a900caddcd60 src/gpu/hsail/vm/vmStructs_hsail.hpp --- a/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon May 05 18:38:13 2014 +0200 +++ b/src/gpu/hsail/vm/vmStructs_hsail.hpp Mon May 05 18:38:43 2014 +0200 @@ -32,10 +32,11 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_GPU_HSAIL(nonstatic_field) \ +#define VM_STRUCTS_GPU_HSAIL(nonstatic_field) \ nonstatic_field(HSAILFrame, _pc_offset, jint) \ nonstatic_field(HSAILFrame, _num_s_regs, jbyte) \ - nonstatic_field(HSAILFrame, _save_area[0], jlong) \ + nonstatic_field(HSAILFrame, _num_d_regs, jbyte) \ + nonstatic_field(HSAILFrame, _num_stack_slots, jshort) \ \ nonstatic_field(Hsail::HSAILKernelDeoptimization, _workitemid, jint) \ nonstatic_field(Hsail::HSAILKernelDeoptimization, _actionAndReason, jint) \ @@ -47,7 +48,6 @@ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _donor_threads, JavaThread**) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _never_ran_array, jboolean *) \ nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[0], Hsail::HSAILKernelDeoptimization) \ - nonstatic_field(Hsail::HSAILDeoptimizationInfo, _deopt_save_states[1], Hsail::HSAILKernelDeoptimization) #define VM_TYPES_GPU_HSAIL(declare_type, declare_toplevel_type) \ declare_toplevel_type(HSAILFrame) \ @@ -55,4 +55,8 @@ declare_toplevel_type(Hsail::HSAILKernelDeoptimization) \ declare_toplevel_type(Hsail::HSAILDeoptimizationInfo) +#define VM_INT_CONSTANTS_GPU_HSAIL(declare_constant) \ + declare_constant(sizeof(HSAILFrame)) \ + declare_constant(sizeof(Hsail::HSAILKernelDeoptimization)) \ + #endif // GPU_HSAIL_VM_VMSTRUCTS_HSAIL_HPP diff -r 6f23b90c4129 -r a900caddcd60 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Mon May 05 18:38:13 2014 +0200 +++ b/src/share/vm/runtime/vmStructs.cpp Mon May 05 18:38:43 2014 +0200 @@ -106,6 +106,7 @@ #include "utilities/macros.hpp" #ifdef GRAAL # include "graal/vmStructs_graal.hpp" +# include "hsail/vm/vmStructs_hsail.hpp" #endif #ifdef TARGET_ARCH_x86 # include "vmStructs_x86.hpp" @@ -153,8 +154,6 @@ # include "vmStructs_bsd_zero.hpp" #endif -#include "hsail/vm/vmStructs_hsail.hpp" - #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" @@ -3042,7 +3041,9 @@ GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) +#ifdef GRAAL VM_STRUCTS_GPU_HSAIL(GENERATE_NONSTATIC_VM_STRUCT_ENTRY) +#endif VM_STRUCTS_OS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, @@ -3094,8 +3095,10 @@ GENERATE_C2_VM_TYPE_ENTRY, GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) +#ifdef GRAAL VM_TYPES_GPU_HSAIL(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) +#endif VM_TYPES_OS_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, @@ -3120,6 +3123,8 @@ #ifdef GRAAL VM_INT_CONSTANTS_GRAAL(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + + VM_INT_CONSTANTS_GPU_HSAIL(GENERATE_VM_INT_CONSTANT_ENTRY) #endif #if INCLUDE_ALL_GCS @@ -3201,7 +3206,9 @@ CHECK_NO_OP, CHECK_NO_OP); - VM_STRUCTS_GPU_HSAIL(CHECK_NONSTATIC_VM_STRUCT_ENTRY); +#ifdef GRAAL + VM_STRUCTS_GPU_HSAIL(CHECK_NONSTATIC_VM_STRUCT_ENTRY) +#endif VM_STRUCTS_OS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, @@ -3243,8 +3250,10 @@ CHECK_C2_VM_TYPE_ENTRY, CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); +#ifdef GRAAL VM_TYPES_GPU_HSAIL(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); +#endif VM_TYPES_OS_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP,