Mercurial > hg > truffle
changeset 5768:99567466b008
Merge.
author | Lukas Stadler <lukas.stadler@jku.at> |
---|---|
date | Thu, 05 Jul 2012 16:54:45 +0200 |
parents | 5967805da8f5 (current diff) 8d0a6bceb112 (diff) |
children | 772118da9f68 |
files | graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformPhase.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/VMAdapter.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewTypeArrayNode.java |
diffstat | 122 files changed, 4053 insertions(+), 1779 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Thu Jul 05 16:54:45 2012 +0200 @@ -44,14 +44,6 @@ String disassemble(CodeInfo code, CompilationResult tm); /** - * Returns the disassembly of the given method in a {@code javap}-like format. - * - * @param method the method that should be disassembled - * @return the disassembly. This will be of length 0 if the runtime does not support disassembling. - */ - String disassemble(ResolvedJavaMethod method); - - /** * Gets the register configuration to use when compiling a given method. * * @param method the top level method of a compilation
--- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java Thu Jul 05 16:54:45 2012 +0200 @@ -25,5 +25,6 @@ import com.oracle.graal.api.meta.*; public interface Interpreter extends VirtualMachineComponent { - Object execute(ResolvedJavaMethod method, Object... arguments); + boolean initialize(String args); + Object execute(ResolvedJavaMethod method, Object... arguments) throws Throwable; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/RuntimeInterpreterInterface.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 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.api.interpreter; + +import com.oracle.graal.api.meta.*; + +/** + * Please note: The parameters of the interface are currently in reversed order + * since it was derived from the java ByteCodeInterpreter implementation. There + * it was simpler to use the parameters in reversed order since they are popped from + * the stack in reversed order. + */ +public interface RuntimeInterpreterInterface { + + Object invoke(ResolvedJavaMethod method, Object... args); + + void monitorEnter(Object value); + + void monitorExit(Object value); + + Object newObject(ResolvedJavaType type) throws InstantiationException; + + Object getFieldObject(Object base, ResolvedJavaField field); + + boolean getFieldBoolean(Object base, ResolvedJavaField field); + + byte getFieldByte(Object base, ResolvedJavaField field); + + char getFieldChar(Object base, ResolvedJavaField field); + + short getFieldShort(Object base, ResolvedJavaField field); + + int getFieldInt(Object base, ResolvedJavaField field); + + long getFieldLong(Object base, ResolvedJavaField field); + + double getFieldDouble(Object base, ResolvedJavaField field); + + float getFieldFloat(Object base, ResolvedJavaField field); + + void setFieldObject(Object value, Object base, ResolvedJavaField field); + + void setFieldInt(int value, Object base, ResolvedJavaField field); + + void setFieldFloat(float value, Object base, ResolvedJavaField field); + + void setFieldDouble(double value, Object base, ResolvedJavaField field); + + void setFieldLong(long value, Object base, ResolvedJavaField field); + + byte getArrayByte(long index, Object array); + + char getArrayChar(long index, Object array); + + short getArrayShort(long index, Object array); + + int getArrayInt(long index, Object array); + + long getArrayLong(long index, Object array); + + double getArrayDouble(long index, Object array); + + float getArrayFloat(long index, Object array); + + Object getArrayObject(long index, Object array); + + void setArrayByte(byte value, long index, Object array); + + void setArrayChar(char value, long index, Object array); + + void setArrayShort(short value, long index, Object array); + + void setArrayInt(int value, long index, Object array); + + void setArrayLong(long value, long index, Object array); + + void setArrayFloat(float value, long index, Object array); + + void setArrayDouble(double value, long index, Object array); + + void setArrayObject(Object value, long index, Object array); + +}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaType.java Thu Jul 05 16:54:45 2012 +0200 @@ -65,7 +65,9 @@ /** * For array types, gets the type of the components. - * @return the component type of this array type + * This will be null if this is not an array type. + * + * @return the component type of this type if it is an array type otherwise null */ JavaType componentType();
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Thu Jul 05 16:54:45 2012 +0200 @@ -25,6 +25,7 @@ import static java.lang.reflect.Modifier.*; import java.lang.annotation.*; +import java.lang.reflect.*; import java.util.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; @@ -308,6 +309,27 @@ /** + * Gets the annotations of a particular type for the formal parameters of a given method. + * + * @param annotationClass the Class object corresponding to the annotation type + * @param method the method for which a parameter annotations are being requested + * @return the annotation of type {@code annotationClass} (if any) for each formal parameter present + */ + public static <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass, ResolvedJavaMethod method) { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + @SuppressWarnings("unchecked") + T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length); + for (int i = 0; i < parameterAnnotations.length; i++) { + for (Annotation a : parameterAnnotations[i]) { + if (a.annotationType() == annotationClass) { + result[i] = annotationClass.cast(a); + } + } + } + return result; + } + + /** * Gets the annotation of a particular type for a formal parameter of a given method. * * @param annotationClass the Class object corresponding to the annotation type @@ -328,7 +350,6 @@ return null; } - /** * Convenient shortcut for calling {@link #appendLocation(StringBuilder, ResolvedJavaMethod, int)} without having to supply a * a {@link StringBuilder} instance and convert the result to a string.
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/BigBangTest.java Thu Jul 05 16:54:45 2012 +0200 @@ -30,14 +30,14 @@ public void helloWorldTest() { BootImageGenerator generator = new BootImageGenerator(); generator.addEntryMethod(TestPrograms.class, "helloWorldTest"); - Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{3, 118, 58, 21}); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{3, 148, 66, 24}); } @Test public void formattedOutputTest() { BootImageGenerator generator = new BootImageGenerator(); generator.addEntryMethod(TestPrograms.class, "formattedOutputTest"); - Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{15, 979, 346, 98}); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{19, 1668, 611, 179}); } @@ -60,6 +60,13 @@ public void arrayListTest() { BootImageGenerator generator = new BootImageGenerator(); generator.addEntryMethod(TestPrograms.class, "arrayListTest"); + Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 28, 5, 3}); + } + + @Test + public void arrayListTestWithCalls() { + BootImageGenerator generator = new BootImageGenerator(); + generator.addEntryMethod(TestPrograms.class, "arrayListTestWithCalls"); Assert.assertArrayEquals(generator.getBigBang().printState(), new int[]{2, 20, 3, 2}); } }
--- a/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.boot.test/src/com/oracle/graal/boot/TestPrograms.java Thu Jul 05 16:54:45 2012 +0200 @@ -53,8 +53,26 @@ newArr[0].testMethod(); } + @SuppressWarnings("unchecked") + public static void arrayListTestWithCalls() { + ArrayList list = createNewArrayList(); + list.add(new TestObject()); + TestObject[] newArr = (TestObject[]) list.toArray(new TestObject[0]); + TestObject t2 = newArr[0].testMethod(); + t2.testMethod2(); + } + + private static ArrayList createNewArrayList() { + return new ArrayList(); + } + public static class TestObject { - public void testMethod() { + public TestObject testMethod() { + return new TestObject(); + } + + public void testMethod2() { + } } }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/ArrayTypeElement.java Thu Jul 05 16:54:45 2012 +0200 @@ -52,6 +52,13 @@ if (type == null) { System.out.println("FATAL error: Array access without type!"); System.out.println(load.array()); + if (load.array() instanceof ValueProxyNode) { + ValueProxyNode valueProxyNode = (ValueProxyNode) load.array(); + System.out.println("value proxy node stamp " + valueProxyNode.stamp()); + System.out.println("value proxy node stamp type " + valueProxyNode.objectStamp().type()); + System.out.println("value proxy source: " + valueProxyNode.value()); + System.out.println("value proxy source stamp: " + valueProxyNode.value().stamp()); + } System.out.println(((StructuredGraph) load.graph()).method()); System.exit(-1); }
--- a/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.boot/src/com/oracle/graal/boot/meta/InvokeElement.java Thu Jul 05 16:54:45 2012 +0200 @@ -68,6 +68,7 @@ ResolvedJavaMethod method = methodCallTarget.targetMethod(); concreteTargets.add(method); MethodElement processedMethod = bb.getProcessedMethod(method); + processedMethod.addUsage(bb, this.methodCallTarget.invoke().node()); processedMethod.postParseGraph(bb); } } @@ -94,6 +95,7 @@ bb.getProcessedMethod(method).getParameter(i).postUnionTypes(bb, null, newSeenTypesTemp); } } + processedMethod.addUsage(bb, this.methodCallTarget.invoke().node()); } // Register new type for receiver.
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu Jul 05 16:54:45 2012 +0200 @@ -188,18 +188,17 @@ if (GraalOptions.CheckCastElimination) { new CheckCastEliminationPhase().apply(graph); } + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(target, runtime, assumptions).apply(graph); + } if (GraalOptions.OptLoopTransform) { new LoopTransformLowPhase().apply(graph); } new RemoveValueProxyPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(target, runtime, assumptions).apply(graph); - } - if (GraalOptions.CheckCastElimination) { - new CheckCastEliminationPhase().apply(graph); - } - plan.runPhases(PhasePosition.MID_LEVEL, graph);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Thu Jul 05 16:54:45 2012 +0200 @@ -97,12 +97,13 @@ //rematerialize settings public static float MinimumUsageProbability = 0.95f; - //loop transform settings - public static float MinimumPeelProbability = 0.35f; + //loop transform settings TODO (gd) tune + public static boolean LoopPeeling = true; public static boolean ReassociateInvariants = true; public static boolean FullUnroll = true; - public static int FullUnrollMaxNodes = 150; // TODO (gd) tune public static boolean LoopUnswitch = ____; + public static int FullUnrollMaxNodes = 150; + public static float MinimumPeelProbability = 0.35f; public static int LoopUnswitchMaxIncrease = 50; public static int LoopUnswitchUncertaintyBoost = 5; @@ -263,6 +264,7 @@ */ public static String HIRLowerCheckcast = ""; public static String HIRLowerNewInstance = ""; + public static String HIRLowerNewArray = ""; static { // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Thu Jul 05 16:54:45 2012 +0200 @@ -31,9 +31,9 @@ import java.util.Map.Entry; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; +import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; +import com.oracle.graal.api.meta.JavaType.Representation; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.util.*; import com.oracle.graal.debug.*; @@ -590,7 +590,7 @@ } @Override - public void visitNewTypeArray(NewTypeArrayNode x) { + public void visitNewPrimitiveArray(NewPrimitiveArrayNode x) { XirArgument length = toXirArgument(x.length()); XirSnippet snippet = xir.genNewArray(site(x), length, x.elementType().kind(), null, null); emitXir(snippet, x, state(), true);
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java Thu Jul 05 16:54:45 2012 +0200 @@ -89,7 +89,13 @@ public abstract NodeIterable<Node> nodes(); public StructuredGraph graph() { - return (StructuredGraph) loop.loopBegin().graph(); + LoopEx l; + if (isDuplicate()) { + l = original().loop(); + } else { + l = loop(); + } + return (StructuredGraph) l.loopBegin().graph(); } protected abstract DuplicationReplacement getDuplicationReplacement(); @@ -99,11 +105,13 @@ protected void patchNodes(final DuplicationReplacement dataFix) { if (isDuplicate() && !nodesReady) { assert !original.isDuplicate(); - final DuplicationReplacement cfgFix = getDuplicationReplacement(); + final DuplicationReplacement cfgFix = original().getDuplicationReplacement(); DuplicationReplacement dr; - if (cfgFix == null) { + if (cfgFix == null && dataFix != null) { dr = dataFix; - } else { + } else if (cfgFix != null && dataFix == null) { + dr = cfgFix; + } else if (cfgFix != null && dataFix != null) { dr = new DuplicationReplacement() { @Override public Node replacement(Node o) { @@ -119,8 +127,15 @@ return o; } }; + } else { + dr = new DuplicationReplacement() { + @Override + public Node replacement(Node o) { + return o; + } + }; } - duplicationMap = graph().addDuplicates(nodes(), dr); + duplicationMap = graph().addDuplicates(original().nodes(), dr); finishDuplication(); nodesReady = true; } else { @@ -221,11 +236,13 @@ StructuredGraph graph = graph(); for (BeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().lirLoop().exits)) { FixedNode next = earlyExit.next(); - if (earlyExit.isDeleted() || !this.contains(earlyExit)) { + if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) { continue; } BeginNode newEarlyExit = getDuplicatedNode(earlyExit); - assert newEarlyExit != null; + if (newEarlyExit == null) { + continue; + } MergeNode merge = graph.add(new MergeNode()); merge.setProbability(next.probability()); EndNode originalEnd = graph.add(new EndNode());
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentInside.java Thu Jul 05 16:54:45 2012 +0200 @@ -41,7 +41,7 @@ * In the unrolling case they will be used as the value that replace the loop-phis of the duplicated inside fragment */ private Map<PhiNode, ValueNode> mergedInitializers; - private final DuplicationReplacement dataFix = new DuplicationReplacement() { + private final DuplicationReplacement dataFixBefore = new DuplicationReplacement() { @Override public Node replacement(Node oriInput) { if (!(oriInput instanceof ValueNode)) { @@ -56,7 +56,7 @@ } public LoopFragmentInside(LoopFragmentInside original) { - super(original.loop(), original); + super(null, original); } @Override @@ -76,11 +76,16 @@ } @Override + public LoopEx loop() { + assert !this.isDuplicate(); + return super.loop(); + } + + @Override public void insertBefore(LoopEx loop) { - if (this.loop() != loop) { - throw new UnsupportedOperationException(); - } - patchNodes(dataFix); + assert this.isDuplicate() && this.original().loop() == loop; + + patchNodes(dataFixBefore); BeginNode end = mergeEnds(); @@ -88,7 +93,7 @@ mergeEarlyExits(); - BeginNode entry = getDuplicatedNode(this.loop().loopBegin()); + BeginNode entry = getDuplicatedNode(loop.loopBegin()); FrameState state = entry.stateAfter(); if (state != null) { entry.setStateAfter(null); @@ -137,7 +142,6 @@ @Override protected void finishDuplication() { // TODO (gd) ? - } private void patchPeeling(LoopFragmentInside peel) { @@ -187,7 +191,8 @@ * @return corresponding value in the peel */ private ValueNode prim(ValueNode b) { - LoopBeginNode loopBegin = loop().loopBegin(); + assert isDuplicate(); + LoopBeginNode loopBegin = original().loop().loopBegin(); if (loopBegin.isPhiAtMerge(b)) { PhiNode phi = (PhiNode) b; return phi.valueAt(loopBegin.forwardEnd()); @@ -203,9 +208,10 @@ } private BeginNode mergeEnds() { + assert isDuplicate(); List<EndNode> endsToMerge = new LinkedList<>(); Map<EndNode, LoopEndNode> reverseEnds = new HashMap<>(); // map peel's exit to the corresponding loop exits - LoopBeginNode loopBegin = loop().loopBegin(); + LoopBeginNode loopBegin = original().loop().loopBegin(); for (LoopEndNode le : loopBegin.loopEnds()) { EndNode duplicate = getDuplicatedNode(le); if (duplicate != null) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentWhole.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragmentWhole.java Thu Jul 05 16:54:45 2012 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.lir.cfg.*; +import com.oracle.graal.nodes.*; public class LoopFragmentWhole extends LoopFragment { @@ -34,10 +35,23 @@ super(loop); } + public LoopFragmentWhole(LoopFragmentWhole original) { + super(null, original); + } + @Override public LoopFragmentWhole duplicate() { - // TODO (gd) do not forget to make a FULL loop : do not forget the forward end which is not part of the original loop stricto sensus - return null; + LoopFragmentWhole loopFragmentWhole = new LoopFragmentWhole(this); + loopFragmentWhole.reify(); + return loopFragmentWhole; + } + + private void reify() { + assert this.isDuplicate(); + + patchNodes(null); + + mergeEarlyExits(); } @Override @@ -51,13 +65,30 @@ @Override protected DuplicationReplacement getDuplicationReplacement() { - return null; + final FixedNode entry = loop().entryPoint(); + final Graph graph = this.graph(); + return new DuplicationReplacement() { + @Override + public Node replacement(Node o) { + if (o == entry) { + return graph.add(new EndNode()); + } + return o; + } + }; + } + + public FixedNode entryPoint() { + if (isDuplicate()) { + LoopBeginNode newLoopBegin = getDuplicatedNode(original().loop().loopBegin()); + return newLoopBegin.forwardEnd(); + } + return loop().entryPoint(); } @Override protected void finishDuplication() { - // TODO Auto-generated method stub - + // TODO (gd) ? } @Override
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopTransformations.java Thu Jul 05 16:54:45 2012 +0200 @@ -23,13 +23,43 @@ package com.oracle.graal.compiler.loop; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; public abstract class LoopTransformations { private static final int UNROLL_LIMIT = GraalOptions.FullUnrollMaxNodes * 2; + private static final SimplifierTool simplifier = new SimplifierTool() { + @Override + public TargetDescription target() { + return null; + } + @Override + public CodeCacheProvider runtime() { + return null; + } + @Override + public boolean isImmutable(Constant objectConstant) { + return false; + } + @Override + public Assumptions assumptions() { + return null; + } + @Override + public void deleteBranch(FixedNode branch) { + branch.predecessor().replaceFirstSuccessor(branch, null); + GraphUtil.killCFG(branch); + } + @Override + public void addToWorkList(Node node) { + } + }; private LoopTransformations() { // does not need to be instantiated @@ -47,7 +77,7 @@ loop.inside().duplicate().insertBefore(loop); } - public static void fullUnroll(LoopEx loop, CodeCacheProvider runtime) { + public static void fullUnroll(LoopEx loop, MetaAccessProvider runtime) { //assert loop.isCounted(); //TODO (gd) strenghten : counted with known trip count int iterations = 0; LoopBeginNode loopBegin = loop.loopBegin(); @@ -64,16 +94,19 @@ public static void unswitch(LoopEx loop, IfNode ifNode) { // duplicate will be true case, original will be false case - LoopFragmentWhole duplicateLoop = loop.whole().duplicate(); + LoopFragmentWhole originalLoop = loop.whole(); + LoopFragmentWhole duplicateLoop = originalLoop.duplicate(); StructuredGraph graph = (StructuredGraph) ifNode.graph(); BeginNode tempBegin = graph.add(new BeginNode()); - loop.entryPoint().replaceAtPredecessor(tempBegin); + originalLoop.entryPoint().replaceAtPredecessor(tempBegin); double takenProbability = ifNode.probability(ifNode.blockSuccessorIndex(ifNode.trueSuccessor())); - IfNode newIf = graph.add(new IfNode(ifNode.compare(), duplicateLoop.loop().entryPoint(), loop.entryPoint(), takenProbability, ifNode.leafGraphId())); + IfNode newIf = graph.add(new IfNode(ifNode.compare(), duplicateLoop.entryPoint(), originalLoop.entryPoint(), takenProbability, ifNode.leafGraphId())); tempBegin.setNext(newIf); ifNode.setCompare(graph.unique(ConstantNode.forBoolean(false, graph))); IfNode duplicateIf = duplicateLoop.getDuplicatedNode(ifNode); duplicateIf.setCompare(graph.unique(ConstantNode.forBoolean(true, graph))); + ifNode.simplify(simplifier); + duplicateIf.simplify(simplifier); // TODO (gd) probabilities need some amount of fixup.. (probably also in other transforms) }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/CanonicalizerPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -45,14 +45,14 @@ private final int newNodesMark; private final TargetDescription target; private final Assumptions assumptions; - private final CodeCacheProvider runtime; + private final MetaAccessProvider runtime; private final IsImmutablePredicate immutabilityPredicate; private final Iterable<Node> initWorkingSet; private NodeWorkList workList; private Tool tool; - public CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions) { + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions) { this(target, runtime, assumptions, null, 0, null); } @@ -63,7 +63,7 @@ * @param workingSet the initial working set of nodes on which the canonicalizer works, should be an auto-grow node bitmap * @param immutabilityPredicate */ - public CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) { + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, IsImmutablePredicate immutabilityPredicate) { this(target, runtime, assumptions, workingSet, 0, immutabilityPredicate); } @@ -71,11 +71,11 @@ * @param newNodesMark only the {@linkplain Graph#getNewNodes(int) new nodes} specified by * this mark are processed otherwise all nodes in the graph are processed */ - public CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { + public CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { this(target, runtime, assumptions, null, newNodesMark, immutabilityPredicate); } - private CanonicalizerPhase(TargetDescription target, CodeCacheProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { + private CanonicalizerPhase(TargetDescription target, MetaAccessProvider runtime, Assumptions assumptions, Iterable<Node> workingSet, int newNodesMark, IsImmutablePredicate immutabilityPredicate) { this.newNodesMark = newNodesMark; this.target = target; this.assumptions = assumptions; @@ -255,12 +255,12 @@ private static final class Tool implements SimplifierTool { private final NodeWorkList nodeWorkSet; - private final CodeCacheProvider runtime; + private final MetaAccessProvider runtime; private final TargetDescription target; private final Assumptions assumptions; private final IsImmutablePredicate immutabilityPredicate; - public Tool(NodeWorkList nodeWorkSet, CodeCacheProvider runtime, TargetDescription target, Assumptions assumptions, IsImmutablePredicate immutabilityPredicate) { + public Tool(NodeWorkList nodeWorkSet, MetaAccessProvider runtime, TargetDescription target, Assumptions assumptions, IsImmutablePredicate immutabilityPredicate) { this.nodeWorkSet = nodeWorkSet; this.runtime = runtime; this.target = target; @@ -291,7 +291,7 @@ } @Override - public CodeCacheProvider runtime() { + public MetaAccessProvider runtime() { return runtime; }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformHighPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformHighPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.compiler.phases; +import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.loop.*; import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; @@ -31,12 +32,14 @@ @Override protected void run(StructuredGraph graph) { if (graph.hasLoops()) { - LoopsData data = new LoopsData(graph); - for (LoopEx loop : data.outterFirst()) { - if (LoopPolicies.shouldPeel(loop)) { - Debug.log("Peeling %s", loop); - LoopTransformations.peel(loop); - Debug.dump(graph, "After peeling %s", loop); + if (GraalOptions.LoopPeeling) { + LoopsData data = new LoopsData(graph); + for (LoopEx loop : data.outterFirst()) { + if (LoopPolicies.shouldPeel(loop)) { + Debug.log("Peeling %s", loop); + LoopTransformations.peel(loop); + Debug.dump(graph, "After peeling %s", loop); + } } } }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformLowPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -25,7 +25,6 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.loop.*; import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; public class LoopTransformLowPhase extends Phase { @@ -46,7 +45,6 @@ }); } if (GraalOptions.LoopUnswitch) { - NodeBitMap unswitchedDebug = graph.createNodeBitMap(); boolean unswitched; do { unswitched = false; @@ -54,12 +52,11 @@ for (LoopEx loop : dataUnswitch.loops()) { if (LoopPolicies.shouldTryUnswitch(loop)) { IfNode ifNode = LoopTransformations.findUnswitchableIf(loop); - if (ifNode != null && !unswitchedDebug.isMarked(ifNode) && LoopPolicies.shouldUnswitch(loop, ifNode)) { - unswitchedDebug.mark(ifNode); + if (ifNode != null && LoopPolicies.shouldUnswitch(loop, ifNode)) { Debug.log("Unswitching %s at %s [%f - %f]", loop, ifNode, ifNode.probability(0), ifNode.probability(1)); - //LoopTransformations.unswitch(loop, ifNode); + LoopTransformations.unswitch(loop, ifNode); UNSWITCHED.increment(); - //Debug.dump(graph, "After unswitch %s", loop); + Debug.dump(graph, "After unswitch %s", loop); unswitched = true; break; }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LoopTransformPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2012, 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.phases; - -import com.oracle.graal.compiler.*; -import com.oracle.graal.compiler.loop.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.nodes.*; - -public class LoopTransformPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - if (graph.hasLoops()) { - LoopsData data = new LoopsData(graph); - for (LoopEx loop : data.outterFirst()) { - double entryProbability = loop.loopBegin().forwardEnd().probability(); - if (entryProbability > GraalOptions.MinimumPeelProbability - && loop.size() + graph.getNodeCount() < GraalOptions.MaximumDesiredSize) { - Debug.log("Peeling %s", loop); - LoopTransformations.peel(loop); - Debug.dump(graph, "After peeling %s", loop); - } - } - } - } - - -}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu Jul 05 16:54:45 2012 +0200 @@ -25,6 +25,7 @@ import java.lang.reflect.*; import com.oracle.graal.api.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.interpreter.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; @@ -52,6 +53,7 @@ private HotSpotRuntime runtime; private GraalCompiler compiler; private TargetDescription target; + private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface; private volatile HotSpotGraphCache cache; private final HotSpotVMConfig config; @@ -176,6 +178,13 @@ return compilerToVm.Signature_lookupType(returnType, accessingClass, eagerResolve); } + public HotSpotRuntimeInterpreterInterface getRuntimeInterpreterInterface() { + if (runtimeInterpreterInterface == null) { + runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(getRuntime()); + } + return runtimeInterpreterInterface; + } + public HotSpotRuntime getRuntime() { if (runtime == null) { runtime = new HotSpotRuntime(config, this); @@ -210,6 +219,12 @@ if (clazz == GraalCompiler.class) { return (T) getCompiler(); } + if (clazz == MetaAccessProvider.class) { + return (T) getRuntime(); + } + if (clazz == RuntimeInterpreterInterface.class) { + return (T) getRuntimeInterpreterInterface(); + } return null; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,339 @@ +/* + * Copyright (c) 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.hotspot; + +import java.lang.reflect.*; + +import sun.misc.*; + +import com.oracle.graal.api.interpreter.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.meta.*; + +public class HotSpotRuntimeInterpreterInterface implements RuntimeInterpreterInterface { + + private static final Unsafe unsafe = loadUnsafe(); + + private final MetaAccessProvider metaProvider; + + public HotSpotRuntimeInterpreterInterface(MetaAccessProvider metaProvider) { + this.metaProvider = metaProvider; + } + + public native Object invoke(ResolvedJavaMethod method, Object... args); + + public void monitorEnter(Object value) { + nullCheck(value); + unsafe.monitorEnter(value); + } + + public void monitorExit(Object value) { + nullCheck(value); + unsafe.monitorExit(value); + } + + public Object newObject(ResolvedJavaType type) throws InstantiationException { + return unsafe.allocateInstance(type.toJava()); + } + + public Object getFieldObject(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getObjectVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getObject(resolveBase(base, field), offset); + } + } + + public boolean getFieldBoolean(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getBooleanVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getBoolean(resolveBase(base, field), offset); + } + } + + public byte getFieldByte(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getByteVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getByte(resolveBase(base, field), offset); + } + } + + public char getFieldChar(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getCharVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getChar(resolveBase(base, field), offset); + } + } + + public short getFieldShort(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getShortVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getShort(resolveBase(base, field), offset); + } + } + + public int getFieldInt(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getIntVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getInt(resolveBase(base, field), offset); + } + } + + public long getFieldLong(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getLongVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getLong(resolveBase(base, field), offset); + } + } + + public double getFieldDouble(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getDoubleVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getDouble(resolveBase(base, field), offset); + } + } + + public float getFieldFloat(Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + return unsafe.getFloatVolatile(resolveBase(base, field), offset); + } else { + return unsafe.getFloat(resolveBase(base, field), offset); + } + } + + public void setFieldObject(Object value, Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + unsafe.putObjectVolatile(resolveBase(base, field), offset, value); + } else { + unsafe.putObject(resolveBase(base, field), offset, value); + } + } + + public void setFieldInt(int value, Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + unsafe.putIntVolatile(resolveBase(base, field), offset, value); + } else { + unsafe.putInt(resolveBase(base, field), offset, value); + } + } + + + public void setFieldFloat(float value, Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + unsafe.putFloatVolatile(resolveBase(base, field), offset, value); + } else { + unsafe.putFloat(resolveBase(base, field), offset, value); + } + } + + public void setFieldDouble(double value, Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + unsafe.putDoubleVolatile(resolveBase(base, field), offset, value); + } else { + unsafe.putDouble(resolveBase(base, field), offset, value); + } + } + + public void setFieldLong(long value, Object base, ResolvedJavaField field) { + long offset = resolveOffset(field); + if (isVolatile(field)) { + unsafe.putDoubleVolatile(resolveBase(base, field), offset, value); + } else { + unsafe.putDouble(resolveBase(base, field), offset, value); + } + } + + public byte getArrayByte(long index, Object array) { + checkArray(array, index); + return unsafe.getByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index); + } + + public char getArrayChar(long index, Object array) { + checkArray(array, index); + return unsafe.getChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index); + } + + public short getArrayShort(long index, Object array) { + checkArray(array, index); + return unsafe.getShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index); + } + + public int getArrayInt(long index, Object array) { + checkArray(array, index); + return unsafe.getInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index); + } + + public long getArrayLong(long index, Object array) { + checkArray(array, index); + return unsafe.getLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index); + } + + public double getArrayDouble(long index, Object array) { + checkArray(array, index); + return unsafe.getDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index); + } + + public float getArrayFloat(long index, Object array) { + checkArray(array, index); + return unsafe.getFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index); + } + + public Object getArrayObject(long index, Object array) { + checkArray(array, index); + return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index); + } + + public void setArrayByte(byte value, long index, Object array) { + checkArray(array, index); + if (array instanceof boolean[]) { + checkArrayType(array, boolean.class); + } else { + checkArrayType(array, byte.class); + } + unsafe.putByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index, value); + } + + public void setArrayChar(char value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, char.class); + unsafe.putChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index, value); + } + + public void setArrayShort(short value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, short.class); + unsafe.putShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index, value); + } + + public void setArrayInt(int value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, int.class); + unsafe.putInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index, value); + } + + public void setArrayLong(long value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, long.class); + unsafe.putLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index, value); + } + + public void setArrayFloat(float value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, float.class); + unsafe.putFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index, value); + } + + public void setArrayDouble(double value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, double.class); + unsafe.putDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index, value); + } + + public void setArrayObject(Object value, long index, Object array) { + checkArray(array, index); + checkArrayType(array, value != null ? value.getClass() : null); + unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index, value); + } + + private static void nullCheck(Object value) { + if (value == null) { + throw new NullPointerException(); + } + } + + private void checkArrayType(Object array, Class<?> arrayType) { + if (arrayType == null) { + return; + } + ResolvedJavaType type = metaProvider.getResolvedJavaType(array.getClass()).componentType(); + if (!type.toJava().isAssignableFrom(arrayType)) { + throw new ArrayStoreException(arrayType.getName()); + } + } + + private void checkArray(Object array, long index) { + nullCheck(array); + ResolvedJavaType type = metaProvider.getResolvedJavaType(array.getClass()); + if (!type.isArrayClass()) { + throw new ArrayStoreException(array.getClass().getName()); + } + if (index < 0 || index >= arrayLength(array)) { + throw new ArrayIndexOutOfBoundsException((int) index); + } + } + + private static int arrayLength(Object array) { + assert array != null; + return Array.getLength(array); + } + + private static boolean isVolatile(ResolvedJavaField field) { + return Modifier.isVolatile(field.accessFlags()); + } + + private static long resolveOffset(ResolvedJavaField field) { + return ((HotSpotResolvedJavaField) field).offset(); + } + + private static Object resolveBase(Object base, ResolvedJavaField field) { + Object accessorBase = base; + if (accessorBase == null) { + accessorBase = field.holder().toJava(); + } + return accessorBase; + } + + private static Unsafe loadUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException e) { + } + try { + Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafeInstance.setAccessible(true); + return (Unsafe) theUnsafeInstance.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); + } + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.hotspot; -import com.oracle.graal.api.meta.*; - /** * Used to communicate configuration details, runtime offsets, etc. to graal upon compileMethod. */ @@ -46,22 +44,69 @@ // offsets, ... public int vmPageSize; public int stackShadowPages; + + /** + * The offset of the mark word in an object's header. + */ + public int markOffset; + + /** + * The offset of the hub/klassOop word in an object's header. + */ public int hubOffset; + + /** + * The offset of an the array length in an array's header. + */ + public int arrayLengthOffset; + + /** + * The offset of the _super_check_offset field in a Klass. + */ public int superCheckOffsetOffset; + + /** + * The offset of the _secondary_super_cache field in a Klass. + */ public int secondarySuperCacheOffset; + + /** + * The offset of the _secondary_supers field in a Klass. + */ public int secondarySupersOffset; - public int arrayLengthOffset; + + /** + * The offset of the _init_state field in an instanceKlass. + */ public int klassStateOffset; + + /** + * The value of instanceKlass::fully_initialized. + */ public int klassStateFullyInitialized; - public int[] arrayOffsets; + + /** + * The value of objArrayKlass::element_klass_offset(). + */ public int arrayClassElementOffset; + + /** + * The value of JavaThread::tlab_top_offset(). + */ public int threadTlabTopOffset; + + /** + * The value of JavaThread::tlab_end_offset(). + */ public int threadTlabEndOffset; + public int threadObjectOffset; + public int instanceHeaderPrototypeOffset; + public int threadExceptionOopOffset; public int threadExceptionPcOffset; - public int threadMultiNewArrayStorage; + public int threadMultiNewArrayStorageOffset; public long cardtableStartAddress; public int cardtableShift; public long safepointPollingAddress; @@ -110,8 +155,4 @@ assert codeEntryAlignment > 0; assert stackShadowPages > 0; } - - public int getArrayOffset(Kind kind) { - return arrayOffsets[kind.ordinal()]; - } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Thu Jul 05 16:54:45 2012 +0200 @@ -105,8 +105,6 @@ String disassembleNative(byte[] code, long address); - String disassembleJava(HotSpotResolvedJavaMethod method); - StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); Object executeCompiledMethod(HotSpotCompiledMethod method, Object arg1, Object arg2, Object arg3);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Thu Jul 05 16:54:45 2012 +0200 @@ -150,9 +150,6 @@ public native String disassembleNative(byte[] code, long address); @Override - public native String disassembleJava(HotSpotResolvedJavaMethod method); - - @Override public native StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Thu Jul 05 16:54:45 2012 +0200 @@ -48,7 +48,7 @@ */ public class VMToCompilerImpl implements VMToCompiler { - private final HotSpotGraalRuntime compiler; + private final HotSpotGraalRuntime graalRuntime; private IntrinsifyArrayCopyPhase intrinsifyArrayCopy; public final HotSpotTypePrimitive typeBoolean; @@ -68,7 +68,7 @@ private PrintStream log = System.out; public VMToCompilerImpl(HotSpotGraalRuntime compiler) { - this.compiler = compiler; + this.graalRuntime = compiler; typeBoolean = new HotSpotTypePrimitive(Kind.Boolean); typeChar = new HotSpotTypePrimitive(Kind.Char); @@ -105,9 +105,10 @@ Debug.setConfig(hotspotDebugConfig); } // Install intrinsics. - final HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime; + GraalCompiler compiler = graalRuntime.getCompiler(); + final HotSpotRuntime runtime = (HotSpotRuntime) compiler.runtime; if (GraalOptions.Intrinsify) { - Debug.scope("InstallSnippets", new DebugDumpScope("InstallSnippets"), new Runnable() { + Debug.scope("InstallSnippets", new Object[] {new DebugDumpScope("InstallSnippets"), compiler}, new Runnable() { @Override public void run() { @@ -214,16 +215,16 @@ CompilationStatistics.clear("bootstrap"); TTY.println(" in %d ms", System.currentTimeMillis() - startTime); - if (compiler.getCache() != null) { - compiler.getCache().clear(); + if (graalRuntime.getCache() != null) { + graalRuntime.getCache().clear(); } System.gc(); CompilationStatistics.clear("bootstrap2"); - MethodEntryCounters.printCounters(compiler); + MethodEntryCounters.printCounters(graalRuntime); } private void enqueue(Method m) throws Throwable { - JavaMethod javaMethod = compiler.getRuntime().getResolvedJavaMethod(m); + JavaMethod javaMethod = graalRuntime.getRuntime().getResolvedJavaMethod(m); assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).accessFlags()) : javaMethod; compileMethod((HotSpotResolvedJavaMethod) javaMethod, 0, false, 10); } @@ -285,7 +286,7 @@ } } CompilationStatistics.clear("final"); - MethodEntryCounters.printCounters(compiler); + MethodEntryCounters.printCounters(graalRuntime); HotSpotXirGenerator.printCounters(TTY.out().out()); CheckCastSnippets.printCounters(TTY.out().out()); } @@ -374,7 +375,7 @@ final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); int id = compileTaskIds.incrementAndGet(); - CompilationTask task = CompilationTask.create(compiler, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); + CompilationTask task = CompilationTask.create(graalRuntime, createPhasePlan(optimisticOpts), optimisticOpts, method, id, priority); if (blocking) { task.runCompilation(); } else { @@ -483,7 +484,7 @@ public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts) { PhasePlan phasePlan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(graalRuntime.getRuntime(), GraphBuilderConfiguration.getDefault(), optimisticOpts); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); if (GraalOptions.Intrinsify) { phasePlan.addPhase(PhasePosition.HIGH_LEVEL, intrinsifyArrayCopy);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Thu Jul 05 16:54:45 2012 +0200 @@ -54,7 +54,11 @@ private ConstantPool constantPool; private boolean isInitialized; private ResolvedJavaType arrayOfType; - private long prototypeHeader; + + /** + * Initial value for the mark word in a new object of this type. + */ + private long initialMarkWord; private HotSpotResolvedJavaType() { throw new GraalInternalError(HotSpotResolvedJavaType.class + " should only be created from C++ code"); @@ -285,7 +289,7 @@ return superCheckOffset; } - public long prototypeHeader() { - return prototypeHeader; + public long initialMarkWord() { + return initialMarkWord; } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Thu Jul 05 16:54:45 2012 +0200 @@ -28,10 +28,13 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.*; -import com.oracle.graal.api.code.CodeUtil.*; +import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.DataPatch; +import com.oracle.graal.api.code.CompilationResult.Mark; +import com.oracle.graal.api.code.CompilationResult.Safepoint; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; +import com.oracle.graal.api.meta.JavaType.Representation; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; @@ -57,7 +60,7 @@ private final HotSpotRegisterConfig globalStubRegConfig; private final HotSpotGraalRuntime compiler; private CheckCastSnippets.Templates checkcastSnippets; - private NewInstanceSnippets.Templates newInstanceSnippets; + private NewObjectSnippets.Templates newObjectSnippets; public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime compiler) { this.config = config; @@ -73,9 +76,9 @@ installer.install(UnsafeSnippets.class); installer.install(ArrayCopySnippets.class); installer.install(CheckCastSnippets.class); - installer.install(NewInstanceSnippets.class); + installer.install(NewObjectSnippets.class); checkcastSnippets = new CheckCastSnippets.Templates(this); - newInstanceSnippets = new NewInstanceSnippets.Templates(this, config.useTLAB); + newObjectSnippets = new NewObjectSnippets.Templates(this, compiler.getTarget(), config.useTLAB); } @@ -177,11 +180,6 @@ } @Override - public String disassemble(ResolvedJavaMethod method) { - return compiler.getCompilerToVM().disassembleJava((HotSpotResolvedJavaMethod) method); - } - - @Override public ResolvedJavaType getResolvedJavaType(Kind kind) { return (ResolvedJavaType) compiler.getCompilerToVM().getType(kind.toJavaClass()); } @@ -373,12 +371,18 @@ } } else if (n instanceof NewInstanceNode) { if (shouldLower(graph, GraalOptions.HIRLowerNewInstance)) { - newInstanceSnippets.lower((NewInstanceNode) n, tool); + newObjectSnippets.lower((NewInstanceNode) n, tool); + } + } else if (n instanceof NewArrayNode) { + if (shouldLower(graph, GraalOptions.HIRLowerNewArray)) { + newObjectSnippets.lower((NewArrayNode) n, tool); } } else if (n instanceof TLABAllocateNode) { - newInstanceSnippets.lower((TLABAllocateNode) n, tool); - } else if (n instanceof InitializeNode) { - newInstanceSnippets.lower((InitializeNode) n, tool); + newObjectSnippets.lower((TLABAllocateNode) n, tool); + } else if (n instanceof InitializeObjectNode) { + newObjectSnippets.lower((InitializeObjectNode) n, tool); + } else if (n instanceof InitializeArrayNode) { + newObjectSnippets.lower((InitializeArrayNode) n, tool); } else { assert false : "Node implementing Lowerable not handled: " + n; } @@ -395,8 +399,8 @@ return false; } - private IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { - return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph, true); + private static IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index) { + return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, elementKind.arrayBaseOffset(), index, graph, true); } private SafeReadNode safeReadArrayLength(ValueNode array, long leafGraphId) { @@ -528,6 +532,7 @@ @Override public int convertDeoptAction(DeoptimizationAction action) { + // This must be kept in sync with the DeoptAction enum defined in deoptimization.hpp switch(action) { case None: return 0; case RecompileIfTooManyDeopts: return 1; @@ -540,6 +545,7 @@ @Override public int convertDeoptReason(DeoptimizationReason reason) { + // This must be kept in sync with the DeoptReason enum defined in deoptimization.hpp switch(reason) { case None: return 0; case NullCheckException: return 1;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Thu Jul 05 16:54:45 2012 +0200 @@ -315,7 +315,7 @@ asm.bindInline(resume); asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); + asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false); asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); @@ -378,7 +378,7 @@ final int aligning = target.wordSize; final int arrayLengthOffset = target.wordSize * 2; - final int arrayElementOffset = config.getArrayOffset(kind); + final int arrayElementOffset = kind.arrayBaseOffset(); // Calculate aligned size asm.mov(size, length); @@ -401,7 +401,7 @@ // Now the new object is in result, store mark word and klass asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); + asm.pstore(target.wordKind, result, asm.i(config.markOffset), temp1, false); asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory asm.pstore(Kind.Object, result, asm.i(config.hubOffset), temp1o, false); @@ -447,7 +447,7 @@ XirOperand rank = asm.createRegisterTemp("rank", Kind.Int, AMD64.rbx); XirOperand sizes = asm.createRegisterTemp("sizes", Kind.Long, AMD64.rcx); XirOperand thread = asm.createRegisterTemp("thread", Kind.Long, AMD64.r15); - asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); + asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorageOffset)); for (int i = 0; i < dimensions; i++) { XirParameter length = asm.createInputParameter("length" + i, Kind.Int, true); asm.pstore(Kind.Int, sizes, asm.i(i * target.sizeInBytes(Kind.Int)), length, false);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CastFromHub.java Thu Jul 05 16:54:45 2012 +0200 @@ -32,7 +32,7 @@ import com.oracle.graal.nodes.type.*; /** - * This node is used by the {@link NewInstanceSnippets} to give a formatted new instance its exact type. + * This node is used by the {@link NewObjectSnippets} to give a formatted new instance or object its exact type. */ public final class CastFromHub extends FloatingNode implements Canonicalizable {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 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.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Initializes the header and body of an uninitialized array cell. + * This node calls out to a stub to do both the allocation and formatting + * if the memory address it is given is zero/null (e.g. due to + * {@linkplain TLABAllocateNode TLAB allocation} failing). + */ +public final class InitializeArrayNode extends FixedWithNextNode implements Lowerable { + + @Input private final ValueNode memory; + @Input private final ValueNode length; + @Input private final ValueNode size; + private final ResolvedJavaType type; + + public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode size, ResolvedJavaType type) { + super(StampFactory.exactNonNull(type)); + this.memory = memory; + this.type = type; + this.length = length; + this.size = size; + } + + public ValueNode memory() { + return memory; + } + + public ValueNode length() { + return length; + } + + public ValueNode size() { + return size; + } + + public ResolvedJavaType type() { + return type; + } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object initialize(Object memory, int length, int size, @ConstantNodeParameter ResolvedJavaType type) { + throw new UnsupportedOperationException(); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeNode.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Copyright (c) 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.hotspot.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * Initializes the header and body of an uninitialized object cell. - * This node calls out to a stub to do both the allocation and formatting - * if the memory address it is given is zero/null (e.g. due to - * {@linkplain TLABAllocateNode TLAB allocation} failing). - */ -public final class InitializeNode extends FixedWithNextNode implements Lowerable { - - @Input private final ValueNode memory; - private final ResolvedJavaType type; - - public InitializeNode(ValueNode memory, ResolvedJavaType type) { - super(StampFactory.exactNonNull(type)); - this.memory = memory; - this.type = type; - } - - public ValueNode memory() { - return memory; - } - - public ResolvedJavaType type() { - return type; - } - - @Override - public void lower(LoweringTool tool) { - tool.getRuntime().lower(this, tool); - } - - @SuppressWarnings("unused") - @NodeIntrinsic - public static Object initialize(Object memory, @ConstantNodeParameter ResolvedJavaType type) { - throw new UnsupportedOperationException(); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeObjectNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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.hotspot.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Initializes the header and body of an uninitialized object cell. + * This node calls out to a stub to do both the allocation and formatting + * if the memory address it is given is zero/null (e.g. due to + * {@linkplain TLABAllocateNode TLAB allocation} failing). + */ +public final class InitializeObjectNode extends FixedWithNextNode implements Lowerable { + + @Input private final ValueNode memory; + private final ResolvedJavaType type; + + public InitializeObjectNode(ValueNode memory, ResolvedJavaType type) { + super(StampFactory.exactNonNull(type)); + this.memory = memory; + this.type = type; + } + + public ValueNode memory() { + return memory; + } + + public ResolvedJavaType type() { + return type; + } + + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 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.hotspot.nodes; + +import static com.oracle.graal.hotspot.target.amd64.AMD64NewArrayStubCallOp.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.target.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Node implementing a call to HotSpot's {@code new_[object|type]_array} stub. + * + * @see AMD64NewArrayStubCallOp + */ +public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable { + + private static final Stamp defaultStamp = StampFactory.objectNonNull(); + + @Input private final ValueNode hub; + @Input private final ValueNode length; + private final boolean isObjectArray; + + public NewArrayStubCall(boolean isObjectArray, ValueNode hub, ValueNode length) { + super(defaultStamp); + this.isObjectArray = isObjectArray; + this.hub = hub; + this.length = length; + } + + @Override + public boolean inferStamp() { + if (stamp() == defaultStamp && hub.isConstant()) { + HotSpotKlassOop klassOop = (HotSpotKlassOop) this.hub.asConstant().asObject(); + updateStamp(StampFactory.exactNonNull(klassOop.type)); + return true; + } + return false; + } + + @Override + public void generate(LIRGenerator gen) { + RegisterValue hubFixed = HUB.asValue(Kind.Object); + RegisterValue lengthFixed = LENGTH.asValue(Kind.Int); + RegisterValue resultFixed = RESULT.asValue(Kind.Object); + gen.emitMove(gen.operand(length), lengthFixed); + gen.emitMove(gen.operand(hub), hubFixed); + LIRFrameState info = gen.state(); + gen.append(new AMD64NewArrayStubCallOp(isObjectArray, resultFixed, hubFixed, lengthFixed, info)); + Variable result = gen.emitMove(resultFixed); + gen.setResult(this, result); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object call(@ConstantNodeParameter boolean isObjectArray, Object hub, int length) { + throw new UnsupportedOperationException(); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,15 +22,17 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.target.amd64.AMD64NewInstanceStubCallOp.*; + +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.target.*; +import com.oracle.graal.hotspot.target.amd64.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; -import com.oracle.max.asm.target.amd64.*; /** * Node implementing a call to HotSpot's {@code new_instance} stub. @@ -60,11 +62,12 @@ @Override public void generate(LIRGenerator gen) { - Variable result = gen.newVariable(Kind.Object); - gen.emitMove(gen.operand(hub), AMD64.rdx.asValue(Kind.Object)); + RegisterValue hubFixed = HUB.asValue(Kind.Object); + RegisterValue resultFixed = RESULT.asValue(Kind.Object); + gen.emitMove(gen.operand(hub), hubFixed); LIRFrameState info = gen.state(); - AMD64NewInstanceStubCallOp op = new AMD64NewInstanceStubCallOp(result, AMD64.rdx.asValue(Kind.Object), info); - gen.append(op); + gen.append(new AMD64NewInstanceStubCallOp(resultFixed, hubFixed, info)); + Variable result = gen.emitMove(resultFixed); gen.setResult(this, result); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/TLABAllocateNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.nodes; +import java.util.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -35,27 +37,61 @@ public final class TLABAllocateNode extends FixedWithNextNode implements Lowerable { private final int size; + @Input private ValueNode sizeNode; public TLABAllocateNode(int size, Kind wordKind) { super(StampFactory.forWord(wordKind, true)); this.size = size; + this.sizeNode = null; + } + + public TLABAllocateNode(Kind wordKind, ValueNode size) { + super(StampFactory.forWord(wordKind, true)); + this.size = -1; + this.sizeNode = size; } - public int size() { + public boolean isSizeConstant() { + return sizeNode == null; + } + + public int constantSize() { + assert isSizeConstant(); return size; } + public ValueNode variableSize() { + assert !isSizeConstant(); + return sizeNode; + } + @Override public void lower(LoweringTool tool) { tool.getRuntime().lower(this, tool); } + @Override + public Map<Object, Object> getDebugProperties() { + Map<Object, Object> debugProperties = super.getDebugProperties(); + debugProperties.put("size", String.valueOf(size)); + return debugProperties; + } + /** * @return null if allocation fails */ @SuppressWarnings("unused") @NodeIntrinsic - public static Word allocate(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) { + public static Word allocateConstantSize(@ConstantNodeParameter int size, @ConstantNodeParameter Kind wordKind) { + throw new UnsupportedOperationException(); + } + + /** + * @return null if allocation fails + */ + @SuppressWarnings("unused") + @NodeIntrinsic + public static Word allocateVariableSize(@ConstantNodeParameter Kind wordKind, int size) { throw new UnsupportedOperationException(); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,9 +22,13 @@ */ package com.oracle.graal.hotspot.nodes; +import static com.oracle.graal.hotspot.target.amd64.AMD64VerifyOopStubCallOp.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; -import com.oracle.graal.hotspot.target.*; +import com.oracle.graal.hotspot.target.amd64.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -45,9 +49,10 @@ @Override public void generate(LIRGenerator gen) { + RegisterValue objectFixed = OBJECT.asValue(Kind.Object); + gen.emitMove(gen.operand(object), objectFixed); LIRFrameState info = gen.state(); - AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info); - gen.append(op); + gen.append(new AMD64VerifyOopStubCallOp(gen.operand(object), info)); } @SuppressWarnings("unused")
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ArrayCopySnippets.java Thu Jul 05 16:54:45 2012 +0200 @@ -81,7 +81,7 @@ long srcOffset = srcPos * arrayIndexScale(baseKind); long destOffset = destPos * arrayIndexScale(baseKind); if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) { + for (long i = byteLength - arrayIndexScale(Kind.Byte); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Byte)) { Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); } @@ -91,7 +91,7 @@ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND); } } else { - for (long i = 0; i < nonVectorBytes; i++) { + for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Byte)) { Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); } @@ -117,9 +117,9 @@ long srcOffset = srcPos * arrayIndexScale(baseKind); long destOffset = destPos * arrayIndexScale(baseKind); if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = byteLength - arrayIndexScale(Kind.Char); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Char)) { + Character a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Char); + UnsafeStoreNode.store(dest, header, i + destOffset, a.charValue(), Kind.Char); } long vectorLength = byteLength - nonVectorBytes; for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) { @@ -127,9 +127,9 @@ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND); } } else { - for (long i = 0; i < nonVectorBytes; i++) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Char)) { + Character a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Char); + UnsafeStoreNode.store(dest, header, i + destOffset, a.charValue(), Kind.Char); } for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) { Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND); @@ -153,9 +153,9 @@ long srcOffset = srcPos * arrayIndexScale(baseKind); long destOffset = destPos * arrayIndexScale(baseKind); if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = byteLength - arrayIndexScale(Kind.Short); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Short)) { + Short a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Short); + UnsafeStoreNode.store(dest, header, i + destOffset, a.shortValue(), Kind.Short); } long vectorLength = byteLength - nonVectorBytes; for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) { @@ -163,9 +163,9 @@ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND); } } else { - for (long i = 0; i < nonVectorBytes; i++) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Short)) { + Short a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Short); + UnsafeStoreNode.store(dest, header, i + destOffset, a.shortValue(), Kind.Short); } for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) { Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND); @@ -189,9 +189,9 @@ long srcOffset = srcPos * arrayIndexScale(baseKind); long destOffset = destPos * arrayIndexScale(baseKind); if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = byteLength - arrayIndexScale(Kind.Int); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Int)) { + Integer a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Int); + UnsafeStoreNode.store(dest, header, i + destOffset, a.intValue(), Kind.Int); } long vectorLength = byteLength - nonVectorBytes; for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) { @@ -199,9 +199,9 @@ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND); } } else { - for (long i = 0; i < nonVectorBytes; i++) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Int)) { + Integer a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Int); + UnsafeStoreNode.store(dest, header, i + destOffset, a.intValue(), Kind.Int); } for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) { Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND); @@ -225,9 +225,9 @@ long srcOffset = srcPos * arrayIndexScale(baseKind); long destOffset = destPos * arrayIndexScale(baseKind); if (src == dest && srcPos < destPos) { // bad aliased case - for (long i = byteLength - 1; i > byteLength - 1 - nonVectorBytes; i--) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = byteLength - arrayIndexScale(Kind.Float); i >= byteLength - nonVectorBytes; i -= arrayIndexScale(Kind.Float)) { + Float a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Float); + UnsafeStoreNode.store(dest, header, i + destOffset, a.floatValue(), Kind.Float); } long vectorLength = byteLength - nonVectorBytes; for (long i = vectorLength - VECTOR_SIZE; i >= 0; i -= VECTOR_SIZE) { @@ -235,9 +235,9 @@ UnsafeStoreNode.store(dest, header, i + destOffset, a.longValue(), VECTOR_KIND); } } else { - for (long i = 0; i < nonVectorBytes; i++) { - Byte a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Byte); - UnsafeStoreNode.store(dest, header, i + destOffset, a.byteValue(), Kind.Byte); + for (long i = 0; i < nonVectorBytes; i += arrayIndexScale(Kind.Float)) { + Float a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Float); + UnsafeStoreNode.store(dest, header, i + destOffset, a.floatValue(), Kind.Float); } for (long i = nonVectorBytes; i < byteLength; i += VECTOR_SIZE) { Long a = UnsafeLoadNode.load(src, header, i + srcOffset, VECTOR_KIND); @@ -308,13 +308,19 @@ throw new IndexOutOfBoundsException(); } final int scale = arrayIndexScale(Kind.Object); + int header = arrayBaseOffset(Kind.Object); if (src == dest && srcPos < destPos) { // bad aliased case - copyObjectsDown(src, srcPos * scale, dest, destPos * scale, length); + for (long i = (length - 1) * scale; i >= 0; i -= scale) { + Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object); + DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a); + } } else { - copyObjectsUp(src, srcPos * scale, dest, destPos * scale, length); + for (long i = 0; i < length * scale; i += scale) { + Object a = UnsafeLoadNode.load(src, header, i + (long) srcPos * scale, Kind.Object); + DirectObjectStoreNode.storeObject(dest, header, i + (long) destPos * scale, a); + } } if (length > 0) { - int header = arrayBaseOffset(Kind.Object); int cardShift = cardTableShift(); long cardStart = cardTableStart(); long dstAddr = GetObjectAddressNode.get(dest); @@ -327,28 +333,6 @@ } } - // Does NOT perform store checks - @Snippet - public static void copyObjectsDown(Object src, long srcOffset, Object dest, long destOffset, int length) { - int header = arrayBaseOffset(Kind.Object); - final int scale = arrayIndexScale(Kind.Object); - for (long i = (length - 1) * scale; i >= 0; i -= scale) { - Object a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Object); - DirectObjectStoreNode.store(dest, header, i + destOffset, a); - } - } - - // Does NOT perform store checks - @Snippet - public static void copyObjectsUp(Object src, long srcOffset, Object dest, long destOffset, int length) { - int header = arrayBaseOffset(Kind.Object); - final int scale = arrayIndexScale(Kind.Object); - for (long i = 0; i < length * scale; i += scale) { - Object a = UnsafeLoadNode.load(src, header, i + srcOffset, Kind.Object); - DirectObjectStoreNode.store(dest, header, i + destOffset, a); - } - } - @Fold static int arrayBaseOffset(Kind elementKind) { return elementKind.arrayBaseOffset();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Thu Jul 05 16:54:45 2012 +0200 @@ -174,7 +174,7 @@ for (int i = 0; i < secondarySupers.length; i++) { if (t == loadNonNullObjectElement(secondarySupers, i)) { - DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t); + DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t); secondariesHit.inc(); return true; } @@ -214,7 +214,7 @@ Object[] secondarySupers = UnsafeCastNode.cast(UnsafeLoadNode.loadObject(s, 0, secondarySupersOffset(), true), Object[].class); for (int i = 0; i < secondarySupers.length; i++) { if (t == loadNonNullObjectElement(secondarySupers, i)) { - DirectObjectStoreNode.store(s, secondarySuperCacheOffset(), 0, t); + DirectObjectStoreNode.storeObject(s, secondarySuperCacheOffset(), 0, t); secondariesHit.inc(); return true; } @@ -264,7 +264,7 @@ */ void inc() { if (ENABLED) { - DirectObjectStoreNode.store(this, countOffset(), 0, count + 1); + DirectObjectStoreNode.storeLong(this, countOffset(), 0, count + 1); } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/DirectObjectStoreNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.*; /** * A special purpose store node that differs from {@link UnsafeStoreNode} in that @@ -47,13 +48,25 @@ @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) { + public static void storeObject(Object obj, @ConstantNodeParameter int displacement, long offset, Object value) { throw new UnsupportedOperationException(); } @SuppressWarnings("unused") @NodeIntrinsic - public static void store(Object obj, @ConstantNodeParameter int displacement, long offset, long value) { + public static void storeLong(Object obj, @ConstantNodeParameter int displacement, long offset, long value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void storeWord(Object obj, @ConstantNodeParameter int displacement, long offset, Word value) { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static void storeInt(Object obj, @ConstantNodeParameter int displacement, long offset, int value) { throw new UnsupportedOperationException(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,229 +0,0 @@ -/* - * Copyright (c) 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.hotspot.snippets; - -import static com.oracle.graal.hotspot.nodes.CastFromHub.*; -import static com.oracle.graal.hotspot.nodes.RegisterNode.*; -import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*; -import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*; -import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; -import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; -import static com.oracle.max.asm.target.amd64.AMD64.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.snippets.*; -import com.oracle.graal.snippets.Snippet.ConstantParameter; -import com.oracle.graal.snippets.Snippet.Fold; -import com.oracle.graal.snippets.Snippet.Parameter; -import com.oracle.graal.snippets.SnippetTemplate.Arguments; -import com.oracle.graal.snippets.SnippetTemplate.Cache; -import com.oracle.graal.snippets.SnippetTemplate.Key; - -/** - * Snippets used for implementing NEW. - */ -public class NewInstanceSnippets implements SnippetsInterface { - - @Snippet - public static Word allocate(@ConstantParameter("size") int size) { - Word thread = asWord(register(r15, wordKind())); - Word top = loadWord(thread, threadTlabTopOffset()); - Word end = loadWord(thread, threadTlabEndOffset()); - Word newTop = top.plus(size); - if (newTop.belowOrEqual(end)) { - store(thread, 0, threadTlabTopOffset(), newTop); - return top; - } - return Word.zero(); - } - - @Snippet - public static Object initialize( - @Parameter("memory") Word memory, - @Parameter("hub") Object hub, - @Parameter("prototypeHeader") Word headerPrototype, - @ConstantParameter("size") int size) { - - if (memory == Word.zero()) { - return NewInstanceStubCall.call(hub); - } - formatObject(hub, size, memory, headerPrototype); - Object instance = memory.toObject(); - return castFromHub(verifyOop(instance), hub); - } - - private static Object verifyOop(Object object) { - if (verifyOops()) { - VerifyOopStubCall.call(object); - } - return object; - } - - private static Word asWord(Object object) { - return Word.fromObject(object); - } - - private static Word loadWord(Word address, int offset) { - Object value = loadObject(address, 0, offset, true); - return asWord(value); - } - - /** - * Maximum size of an object whose body is initialized by a sequence of - * zero-stores to its fields. Larger objects have their bodies initialized - * in a loop. - */ - private static final int MAX_UNROLLED_OBJECT_INITIALIZATION_SIZE = 10 * wordSize(); - - /** - * Formats some allocated memory with an object header zeroes out the rest. - */ - private static void formatObject(Object hub, int size, Word memory, Word headerPrototype) { - store(memory, 0, 0, headerPrototype); - store(memory, 0, hubOffset(), hub); - if (size <= MAX_UNROLLED_OBJECT_INITIALIZATION_SIZE) { - explodeLoop(); - for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - store(memory, 0, offset, 0); - } - } else { - for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { - store(memory, 0, offset, 0); - } - } - } - - @Fold - private static boolean verifyOops() { - return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; - } - - @Fold - private static int threadTlabTopOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset; - } - - @Fold - private static int threadTlabEndOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset; - } - - @Fold - private static Kind wordKind() { - return HotSpotGraalRuntime.getInstance().getTarget().wordKind; - } - - @Fold - private static int wordSize() { - return HotSpotGraalRuntime.getInstance().getTarget().wordSize; - } - - @Fold - private static int hubOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().hubOffset; - } - - public static class Templates { - - private final Cache cache; - private final ResolvedJavaMethod allocate; - private final ResolvedJavaMethod initialize; - private final CodeCacheProvider runtime; - private final boolean useTLAB; - - public Templates(CodeCacheProvider runtime, boolean useTLAB) { - this.runtime = runtime; - this.cache = new Cache(runtime); - this.useTLAB = useTLAB; - try { - allocate = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("allocate", int.class)); - initialize = runtime.getResolvedJavaMethod(NewInstanceSnippets.class.getDeclaredMethod("initialize", Word.class, Object.class, Word.class, int.class)); - } catch (NoSuchMethodException e) { - throw new GraalInternalError(e); - } - } - - /** - * Lowers a {@link NewInstanceNode}. - */ - @SuppressWarnings("unused") - public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) newInstanceNode.graph(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass(); - HotSpotKlassOop hub = type.klassOop(); - int size = type.instanceSize(); - assert (size % wordSize()) == 0; - assert size >= 0; - - ValueNode memory; - if (!useTLAB) { - memory = ConstantNode.forObject(null, runtime, graph); - } else { - TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind())); - graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); - memory = tlabAllocateNode; - } - InitializeNode initializeNode = graph.add(new InitializeNode(memory, type)); - graph.replaceFixedWithFixed(newInstanceNode, initializeNode); - } - - @SuppressWarnings("unused") - public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); - int size = tlabAllocateNode.size(); - assert (size % wordSize()) == 0; - assert size >= 0; - Key key = new Key(allocate).add("size", size); - Arguments arguments = new Arguments(); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); - template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments); - } - - @SuppressWarnings("unused") - public void lower(InitializeNode initializeNode, LoweringTool tool) { - StructuredGraph graph = (StructuredGraph) initializeNode.graph(); - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); - HotSpotKlassOop hub = type.klassOop(); - int size = type.instanceSize(); - assert (size % wordSize()) == 0; - assert size >= 0; - Key key = new Key(initialize).add("size", size); - ValueNode memory = initializeNode.memory(); - //assert memory instanceof AllocateNode || memory instanceof ConstantNode : memory; - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeHeader", type.prototypeHeader()); - SnippetTemplate template = cache.get(key); - Debug.log("Lowering initialize in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); - template.instantiate(runtime, initializeNode, initializeNode, arguments); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,383 @@ +/* + * Copyright (c) 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.hotspot.snippets; + +import static com.oracle.graal.hotspot.nodes.CastFromHub.*; +import static com.oracle.graal.hotspot.nodes.RegisterNode.*; +import static com.oracle.graal.hotspot.snippets.DirectObjectStoreNode.*; +import static com.oracle.graal.nodes.extended.UnsafeLoadNode.*; +import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.ExplodeLoopNode.*; +import static com.oracle.max.asm.target.amd64.AMD64.*; +import static com.oracle.max.criutils.UnsignedMath.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.ConstantParameter; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.snippets.Snippet.Parameter; +import com.oracle.graal.snippets.SnippetTemplate.Arguments; +import com.oracle.graal.snippets.SnippetTemplate.Cache; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * Snippets used for implementing NEW, ANEWARRAY and NEWARRAY. + */ +public class NewObjectSnippets implements SnippetsInterface { + + @Snippet + public static Word allocate(@Parameter("size") int size) { + Word thread = asWord(register(r15, wordKind())); + Word top = loadWord(thread, threadTlabTopOffset()); + Word end = loadWord(thread, threadTlabEndOffset()); + Word newTop = top.plus(size); + if (newTop.belowOrEqual(end)) { + storeObject(thread, 0, threadTlabTopOffset(), newTop); + return top; + } + return Word.zero(); + } + + @Snippet + public static Object initializeObject( + @Parameter("memory") Word memory, + @Parameter("hub") Object hub, + @Parameter("initialMarkWord") Word initialMarkWord, + @ConstantParameter("size") int size) { + + if (memory == Word.zero()) { + return NewInstanceStubCall.call(hub); + } + formatObject(hub, size, memory, initialMarkWord); + Object instance = memory.toObject(); + return castFromHub(verifyOop(instance), hub); + } + + @Snippet + public static Object initializeObjectArray( + @Parameter("memory") Word memory, + @Parameter("hub") Object hub, + @Parameter("length") int length, + @Parameter("size") int size, + @Parameter("initialMarkWord") Word initialMarkWord, + @ConstantParameter("headerSize") int headerSize) { + return initializeArray(memory, hub, length, size, initialMarkWord, headerSize, true); + } + + @Snippet + public static Object initializePrimitiveArray( + @Parameter("memory") Word memory, + @Parameter("hub") Object hub, + @Parameter("length") int length, + @Parameter("size") int size, + @Parameter("initialMarkWord") Word initialMarkWord, + @ConstantParameter("headerSize") int headerSize) { + return initializeArray(memory, hub, length, size, initialMarkWord, headerSize, false); + } + + private static Object initializeArray(Word memory, Object hub, int length, int size, Word initialMarkWord, int headerSize, boolean isObjectArray) { + if (memory == Word.zero()) { + return NewArrayStubCall.call(isObjectArray, hub, length); + } + formatArray(hub, size, length, headerSize, memory, initialMarkWord); + Object instance = memory.toObject(); + return castFromHub(verifyOop(instance), hub); + } + + /** + * Maximum array length for which fast path allocation is used. + */ + private static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; + + @Snippet + public static Object allocateArrayAndInitialize( + @Parameter("length") int length, + @ConstantParameter("alignment") int alignment, + @ConstantParameter("headerSize") int headerSize, + @ConstantParameter("log2ElementSize") int log2ElementSize, + @ConstantParameter("type") ResolvedJavaType type, + @ConstantParameter("wordKind") Kind wordKind) { + if (!belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { + // This handles both negative array sizes and very large array sizes + DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.RuntimeConstraint); + } + int size = getArraySize(length, alignment, headerSize, log2ElementSize); + Word memory = TLABAllocateNode.allocateVariableSize(wordKind, size); + return InitializeArrayNode.initialize(memory, length, size, type); + } + + public static int getArraySize(int length, int alignment, int headerSize, int log2ElementSize) { + int size = (length << log2ElementSize) + headerSize + (alignment - 1); + int mask = ~(alignment - 1); + return size & mask; + } + + private static Object verifyOop(Object object) { + if (verifyOops()) { + VerifyOopStubCall.call(object); + } + return object; + } + + private static Word asWord(Object object) { + return Word.fromObject(object); + } + + private static Word loadWord(Word address, int offset) { + Object value = loadObject(address, 0, offset, true); + return asWord(value); + } + + /** + * Maximum size of an object whose body is initialized by a sequence of + * zero-stores to its fields. Larger objects have their bodies initialized + * in a loop. + */ + private static final int MAX_UNROLLED_OBJECT_ZEROING_SIZE = 10 * wordSize(); + + /** + * Formats some allocated memory with an object header zeroes out the rest. + */ + private static void formatObject(Object hub, int size, Word memory, Word headerPrototype) { + storeObject(memory, 0, markOffset(), headerPrototype); + storeObject(memory, 0, hubOffset(), hub); + if (size <= MAX_UNROLLED_OBJECT_ZEROING_SIZE) { + explodeLoop(); + for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + } else { + for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + } + } + + /** + * Formats some allocated memory with an object header zeroes out the rest. + */ + private static void formatArray(Object hub, int size, int length, int headerSize, Word memory, Word headerPrototype) { + storeObject(memory, 0, markOffset(), headerPrototype); + storeObject(memory, 0, hubOffset(), hub); + storeInt(memory, 0, arrayLengthOffset(), length); + for (int offset = headerSize; offset < size; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + } + + public static class Templates { + + private final Cache cache; + private final ResolvedJavaMethod allocate; + private final ResolvedJavaMethod initializeObject; + private final ResolvedJavaMethod initializeObjectArray; + private final ResolvedJavaMethod initializePrimitiveArray; + private final ResolvedJavaMethod allocateArrayAndInitialize; + private final TargetDescription target; + private final CodeCacheProvider runtime; + private final boolean useTLAB; + + public Templates(CodeCacheProvider runtime, TargetDescription target, boolean useTLAB) { + this.runtime = runtime; + this.target = target; + this.cache = new Cache(runtime); + this.useTLAB = useTLAB; + try { + allocate = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("allocate", int.class)); + initializeObject = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializeObject", Word.class, Object.class, Word.class, int.class)); + initializeObjectArray = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializeObjectArray", Word.class, Object.class, int.class, int.class, Word.class, int.class)); + initializePrimitiveArray = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("initializePrimitiveArray", Word.class, Object.class, int.class, int.class, Word.class, int.class)); + allocateArrayAndInitialize = runtime.getResolvedJavaMethod(NewObjectSnippets.class.getDeclaredMethod("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, ResolvedJavaType.class, Kind.class)); + } catch (NoSuchMethodException e) { + throw new GraalInternalError(e); + } + } + + /** + * Lowers a {@link NewInstanceNode}. + */ + @SuppressWarnings("unused") + public void lower(NewInstanceNode newInstanceNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) newInstanceNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass(); + HotSpotKlassOop hub = type.klassOop(); + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + + ValueNode memory; + if (!useTLAB) { + memory = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph); + } else { + TLABAllocateNode tlabAllocateNode = graph.add(new TLABAllocateNode(size, wordKind())); + graph.addBeforeFixed(newInstanceNode, tlabAllocateNode); + memory = tlabAllocateNode; + } + InitializeObjectNode initializeNode = graph.add(new InitializeObjectNode(memory, type)); + graph.replaceFixedWithFixed(newInstanceNode, initializeNode); + } + + /** + * Lowers a {@link NewArrayNode}. + */ + @SuppressWarnings("unused") + public void lower(NewArrayNode newArrayNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) newArrayNode.graph(); + ValueNode lengthNode = newArrayNode.length(); + TLABAllocateNode tlabAllocateNode; + ResolvedJavaType elementType = newArrayNode.elementType(); + ResolvedJavaType arrayType = elementType.arrayOf(); + Kind elementKind = elementType.kind(); + final int alignment = target.wordSize; + final int headerSize = elementKind.arrayBaseOffset(); + final Integer length = lengthNode.isConstant() ? Integer.valueOf(lengthNode.asConstant().asInt()) : null; + int log2ElementSize = CodeUtil.log2(target.sizeInBytes(elementKind)); + if (!useTLAB) { + ConstantNode zero = ConstantNode.forConstant(new Constant(target.wordKind, 0L), runtime, graph); + // value for 'size' doesn't matter as it isn't used since a stub call will be made anyway + // for both allocation and initialization - it just needs to be non-null + ConstantNode size = ConstantNode.forInt(-1, graph); + InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(zero, lengthNode, size, arrayType)); + graph.replaceFixedWithFixed(newArrayNode, initializeNode); + } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { + // Calculate aligned size + int size = getArraySize(length, alignment, headerSize, log2ElementSize); + ConstantNode sizeNode = ConstantNode.forInt(size, graph); + tlabAllocateNode = graph.add(new TLABAllocateNode(size, target.wordKind)); + graph.addBeforeFixed(newArrayNode, tlabAllocateNode); + InitializeArrayNode initializeNode = graph.add(new InitializeArrayNode(tlabAllocateNode, lengthNode, sizeNode, arrayType)); + graph.replaceFixedWithFixed(newArrayNode, initializeNode); + } else { + Key key = new Key(allocateArrayAndInitialize). + add("alignment", alignment). + add("headerSize", headerSize). + add("log2ElementSize", log2ElementSize). + add("wordKind", target.wordKind). + add("type", arrayType); + Arguments arguments = new Arguments().add("length", lengthNode); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering allocateArrayAndInitialize in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, arguments); + template.instantiate(runtime, newArrayNode, newArrayNode, arguments); + } + } + + @SuppressWarnings("unused") + public void lower(TLABAllocateNode tlabAllocateNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) tlabAllocateNode.graph(); + ValueNode size; + if (tlabAllocateNode.isSizeConstant()) { + size = ConstantNode.forInt(tlabAllocateNode.constantSize(), graph); + } else { + size = tlabAllocateNode.variableSize(); + } + Key key = new Key(allocate); + Arguments arguments = arguments("size", size); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering fastAllocate in %s: node=%s, template=%s, arguments=%s", graph, tlabAllocateNode, template, arguments); + template.instantiate(runtime, tlabAllocateNode, tlabAllocateNode, arguments); + } + + @SuppressWarnings("unused") + public void lower(InitializeObjectNode initializeNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) initializeNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); + assert !type.isArrayClass(); + HotSpotKlassOop hub = type.klassOop(); + int size = type.instanceSize(); + assert (size % wordSize()) == 0; + assert size >= 0; + Key key = new Key(initializeObject).add("size", size); + ValueNode memory = initializeNode.memory(); + Arguments arguments = arguments("memory", memory).add("hub", hub).add("initialMarkWord", type.initialMarkWord()); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering initializeObject in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); + template.instantiate(runtime, initializeNode, initializeNode, arguments); + } + + @SuppressWarnings("unused") + public void lower(InitializeArrayNode initializeNode, LoweringTool tool) { + StructuredGraph graph = (StructuredGraph) initializeNode.graph(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) initializeNode.type(); + ResolvedJavaType elementType = type.componentType(); + assert elementType != null; + HotSpotKlassOop hub = type.klassOop(); + Kind elementKind = elementType.kind(); + final int headerSize = elementKind.arrayBaseOffset(); + Key key = new Key(elementKind.isObject() ? initializeObjectArray : initializePrimitiveArray).add("headerSize", headerSize); + ValueNode memory = initializeNode.memory(); + Arguments arguments = arguments("memory", memory).add("hub", hub).add("initialMarkWord", type.initialMarkWord()).add("size", initializeNode.size()).add("length", initializeNode.length()); + SnippetTemplate template = cache.get(key); + Debug.log("Lowering initializeObjectArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); + template.instantiate(runtime, initializeNode, initializeNode, arguments); + } + } + + @Fold + private static boolean verifyOops() { + return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; + } + + @Fold + private static int threadTlabTopOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset; + } + + @Fold + private static int threadTlabEndOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset; + } + + @Fold + private static Kind wordKind() { + return HotSpotGraalRuntime.getInstance().getTarget().wordKind; + } + + @Fold + private static int wordSize() { + return HotSpotGraalRuntime.getInstance().getTarget().wordSize; + } + + @Fold + private static int markOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().markOffset; + } + + @Fold + private static int hubOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().hubOffset; + } + + @Fold + private static int arrayLengthOffset() { + return HotSpotGraalRuntime.getInstance().getConfig().arrayLengthOffset; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/UnsignedMathSnippets.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011, 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.snippets; + +import static com.oracle.graal.nodes.MaterializeNode.*; +import static com.oracle.graal.nodes.calc.Condition.*; + +import com.oracle.graal.snippets.*; +import com.oracle.max.criutils.*; + +/** + * Snippets for {@link UnsignedMath}. + */ +@ClassSubstitution(UnsignedMath.class) +public class UnsignedMathSnippets implements SnippetsInterface { + + public static boolean aboveThan(int a, int b) { + return materialize(BT, b, a); + } + + public static boolean aboveOrEqual(int a, int b) { + return !materialize(BT, a, b); + } + + /** + * Unsigned comparison belowThan for two numbers. + */ + public static boolean belowThan(int a, int b) { + return materialize(BT, a, b); + } + + /** + * Unsigned comparison belowOrEqual for two numbers. + */ + public static boolean belowOrEqual(int a, int b) { + return !materialize(BT, b, a); + } + + /** + * Unsigned comparison aboveThan for two numbers. + */ + public static boolean aboveThan(long a, long b) { + return materialize(BT, b, a); + } + + /** + * Unsigned comparison aboveOrEqual for two numbers. + */ + public static boolean aboveOrEqual(long a, long b) { + return !materialize(BT, a, b); + } + + /** + * Unsigned comparison belowThan for two numbers. + */ + public static boolean belowThan(long a, long b) { + return materialize(BT, a, b); + } + + /** + * Unsigned comparison belowOrEqual for two numbers. + */ + public static boolean belowOrEqual(long a, long b) { + return !materialize(BT, b, a); + } +}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64NewInstanceStubCallOp.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 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.hotspot.target; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.target.amd64.*; -import com.oracle.graal.lir.LIRInstruction.Opcode; - -/** - * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp - * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. - */ -@Opcode("NEW_INSTANCE") -public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction { - @Def protected Value result; - @Use protected Value hub; - @Temp protected Value temp; - @State protected LIRFrameState state; - - public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) { - this.result = result; - this.hub = hub; - this.temp = AMD64.rax.asValue(Kind.Object); - this.state = state; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // rdx: (in) hub - // rax: (out) result - AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state); - if (asRegister(result) != AMD64.rax) { - masm.movq(asRegister(result), AMD64.rax); - } - } - - @Override - protected void verify() { - super.verify(); - assert asRegister(hub) == AMD64.rdx; - } -}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 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.hotspot.target; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.Opcode; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.asm.*; -import com.oracle.max.asm.target.amd64.*; - -/** - * A call to HotSpot's object pointer verification stub. - */ -@Opcode("VERIFY_OOP") -public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { - @Use protected Value object; - @State protected LIRFrameState state; - - public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) { - this.object = object; - this.state = state; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // r13: (in) object - if (asRegister(object) != AMD64.r13) { - masm.push(AMD64.r13); - masm.movq(AMD64.r13, asRegister(object)); - } - AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state); - if (asRegister(object) != AMD64.r13) { - masm.pop(AMD64.r13); - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64NewArrayStubCallOp.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 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.hotspot.target.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * LIR instruction for calling HotSpot's {@code new_[object|type]_array} stub. This stub is declared in c1_Runtime1.hpp + * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. + */ +@Opcode("NEW_ARRAY") +public class AMD64NewArrayStubCallOp extends AMD64LIRInstruction { + + /** + * The stub places the result in RAX. + */ + public static final Register RESULT = AMD64.rax; + + /** + * The stub expects the hub in RDX. + */ + public static final Register HUB = AMD64.rdx; + + /** + * The stub expects the length in RBX. + */ + public static final Register LENGTH = AMD64.rbx; + + /** + * The stub uses RCX, RSI, and RDI as temps. + */ + public static final Register[] TEMPS = {AMD64.rcx, AMD64.rdi, AMD64.rsi}; + + private final boolean isObjectArray; + + @Def protected Value result; + @Use protected Value hub; + @Use protected Value length; + @Temp protected Value[] temps; + + @State protected LIRFrameState state; + + public AMD64NewArrayStubCallOp(boolean isObjectArray, Value result, Value hub, Value length, LIRFrameState state) { + this.isObjectArray = isObjectArray; + this.result = result; + this.hub = hub; + this.length = length; + this.temps = new Value[TEMPS.length]; + for (int i = 0; i < temps.length; i++) { + temps[i] = TEMPS[i].asValue(Kind.Long); + } + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + long stub = isObjectArray ? config.newObjectArrayStub : config.newTypeArrayStub; + AMD64Call.directCall(tasm, masm, stub, state); + } + + @Override + protected void verify() { + super.verify(); + assert asRegister(hub) == HUB : "stub expects hub in " + HUB; + assert asRegister(length) == LENGTH : "stub expect length in " + LENGTH; + assert asRegister(result) == RESULT : "stub places result in " + RESULT; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64NewInstanceStubCallOp.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 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.hotspot.target.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * LIR instruction for calling HotSpot's {@code new_instance} stub. This stub is declared in c1_Runtime1.hpp + * and implemented in Runtime1::generate_code_for() which is located in c1_Runtime1_x86.cpp. + */ +@Opcode("NEW_INSTANCE") +public class AMD64NewInstanceStubCallOp extends AMD64LIRInstruction { + + /** + * The stub expects the hub in RDX. + */ + public static final Register HUB = AMD64.rdx; + + /** + * The stub places the result in RAX. + */ + public static final Register RESULT = AMD64.rax; + + @Def protected Value result; + @Use protected Value hub; + @State protected LIRFrameState state; + + public AMD64NewInstanceStubCallOp(Value result, Value hub, LIRFrameState state) { + this.hub = hub; + this.result = result; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().newInstanceStub, state); + } + + @Override + protected void verify() { + super.verify(); + assert asRegister(hub) == HUB : "expects hub in " + HUB; + assert asRegister(result) == RESULT : "expects result in " + RESULT; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/amd64/AMD64VerifyOopStubCallOp.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 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.hotspot.target.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * A call to HotSpot's object pointer verification stub. + */ +@Opcode("VERIFY_OOP") +public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { + + /** + * The stub expects the object pointer in R13. + */ + public static final Register OBJECT = AMD64.r13; + + @Use protected Value object; + @State protected LIRFrameState state; + + public AMD64VerifyOopStubCallOp(Value object, LIRFrameState state) { + this.object = object; + this.state = state; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, state); + } + + @Override + protected void verify() { + super.verify(); + assert asRegister(object) == OBJECT : "expects object in " + OBJECT; + } +}
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Thu Jul 05 16:54:45 2012 +0200 @@ -25,22 +25,14 @@ import java.lang.reflect.*; import java.util.*; +import com.oracle.graal.api.*; import com.oracle.graal.api.interpreter.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.bytecode.*; /** - * - * <h1>Implementation notes</h1> - * <li>Native methods are invoked using standard java reflection.</li> - * - * <h1>Features:</h1> - * - * - * <h1>Limitations:</h1> - * - * <li>The interpreter is not able to recognize a native method that calls a java method. - * In that case the java method will be interpreted directly on the vm interpreter.</li> + * High-level bytecode interpreter that executes on top of Java. Java native methods + * are executed using the {@link com.oracle.graal.api.interpreter.RuntimeInterpreterInterface}. */ @SuppressWarnings("static-method") public final class BytecodeInterpreter implements Interpreter { @@ -49,7 +41,7 @@ private static final boolean TRACE = false; private static final boolean TRACE_BYTE_CODE = false; - private static final int DEFAULT_MAX_STACK_SIZE = 200; + private static final int DEFAULT_MAX_STACK_SIZE = 1500; private static final int NEXT = -1; private static final int BRANCH = -2; @@ -58,28 +50,31 @@ private InterpreterFrame callFrame; - //TODO try to remove this reference - private ExceptionHandler catchAllExceptionHandler; + private Map<ResolvedJavaMethod, MethodRedirectionInfo> methodDelegates; + + private int maxStackFrames; - private final Map<ResolvedJavaMethod, InterpreterCallable> methodDelegates = new HashMap<>(); - - private int maxStackFrames = DEFAULT_MAX_STACK_SIZE; - private int stackFrameDepth; + private ResolvedJavaMethod rootMethod; + private RuntimeInterpreterInterface runtimeInterface; + private MetaAccessProvider metaAccessProvider; - private final ResolvedJavaMethod rootMethod; - private final VMAdapter vm; + public boolean initialize(String args) { + methodDelegates = new HashMap<>(); + maxStackFrames = DEFAULT_MAX_STACK_SIZE; - public BytecodeInterpreter() { - this(VMAdapter.getInstance()); - } + GraalRuntime runtime = Graal.getRuntime(); + this.runtimeInterface = runtime.getCapability(RuntimeInterpreterInterface.class); + if (this.runtimeInterface == null) { + throw new UnsupportedOperationException("The provided graal runtime does not support the required capability " + RuntimeInterpreterInterface.class.getName() + "."); + } + this.metaAccessProvider = runtime.getCapability(MetaAccessProvider.class); + if (this.metaAccessProvider == null) { + throw new UnsupportedOperationException("The provided graal runtime does not support the required capability " + MetaAccessProvider.class.getName() + "."); + } - public BytecodeInterpreter(VMAdapter accessor) { - if (accessor == null) { - throw new NullPointerException(); - } - this.vm = accessor; this.rootMethod = resolveRootMethod(); registerDelegates(); + return parseArguments(args); } @Override @@ -89,38 +84,46 @@ } } + private void registerDelegates() { + addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() { - private void registerDelegates() { - addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() { - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable { - setBackTrace(caller, (Throwable) base, createStackTraceElements(caller)); - return null; - } - }); - addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() { - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable { - StackTraceElement[] elements = getBackTrace(caller, (Throwable) base); - if (elements != null) { - return elements.length; - } - return 0; - } - }); - addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() { - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable { - StackTraceElement[] elements = getBackTrace(caller, (Throwable) base); - if (elements != null) { - Integer index = (Integer) arguments[0]; - if (index != null) { - return elements[index]; - } - } - return null; - } - }); + @Override + public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { + setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller)); + return null; + } + }); + addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() { + + @Override + public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { + StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); + if (elements != null) { + return elements.length; + } + return 0; + } + }); + addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() { + + @Override + public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { + StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); + if (elements != null) { + Integer index = (Integer) arguments[0]; + if (index != null) { + return elements[index]; + } + } + return null; + } + }); + } + + @SuppressWarnings("unused") + private boolean parseArguments(String stringArgs) { + // TODO: parse the arguments + return true; } public void setMaxStackFrames(int maxStackSize) { @@ -132,59 +135,64 @@ } public void addDelegate(Method method, InterpreterCallable callable) { - ResolvedJavaMethod resolvedMethod = vm.getRuntime().getResolvedJavaMethod(method); + ResolvedJavaMethod resolvedMethod = metaAccessProvider.getResolvedJavaMethod(method); if (methodDelegates.containsKey(resolvedMethod)) { throw new IllegalArgumentException("Delegate for method " + method + " already added."); } - methodDelegates.put(resolvedMethod, callable); + + methodDelegates.put(resolvedMethod, new MethodRedirectionInfo(callable)); } public void removeDelegate(Method method) { - methodDelegates.remove(vm.getRuntime().getResolvedJavaMethod(method)); + methodDelegates.remove(metaAccessProvider.getResolvedJavaMethod(method)); } @Override - public Object execute(ResolvedJavaMethod method, Object... boxedArguments) { - Signature signature = method.signature(); - assert boxedArguments != null; - assert signature.argumentCount(false) == boxedArguments.length; + public Object execute(ResolvedJavaMethod method, Object... boxedArguments) throws Throwable { + try { + boolean receiver = hasReceiver(method); + Signature signature = method.signature(); + assert boxedArguments != null; + assert signature.argumentCount(receiver) == boxedArguments.length; - if (!Modifier.isStatic(method.accessFlags())) { - throw new UnsupportedOperationException("The interpreter can currently only be started with static methods."); - } + if (TRACE) { + trace(0, "Executing root method " + method); + } - InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.argumentSlots(true)); - rootFrame.pushObject(this); - rootFrame.pushObject(method); - rootFrame.pushObject(boxedArguments); + InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.argumentSlots(true)); + rootFrame.pushObject(this); + rootFrame.pushObject(method); + rootFrame.pushObject(boxedArguments); - for (int i = 0; i < boxedArguments.length; i++) { - pushAsObject(rootFrame, signature.argumentKindAt(i), boxedArguments[i]); - } + int index = 0; + if (receiver) { + pushAsObject(rootFrame, Kind.Object, boxedArguments[index]); + index++; + } - InterpreterFrame frame = rootFrame.create(method, false); + for (int i = 0; index < boxedArguments.length; i++, index++) { + pushAsObject(rootFrame, signature.argumentKindAt(i), boxedArguments[index]); + } - try { + InterpreterFrame frame = rootFrame.create(method, receiver); executeRoot(rootFrame, frame); - } catch (Throwable e) { - // clear backtrace for compatibilty and store it in stacktrace - StackTraceElement[] backtrace = getBackTrace(rootFrame, e); - setBackTrace(rootFrame, e, null); - setStackTrace(rootFrame, e, backtrace); - throw new InterpreterException(e); + return popAsObject(rootFrame, signature.returnKind()); + } catch (Exception e) { + // TODO (chaeubl): remove this exception handler (only used for debugging) + throw e; } - - return popAsObject(rootFrame, signature.returnKind()); } - public Object execute(Method javaMethod, Object... boxedArguments) throws InterpreterException { - return execute(vm.getRuntime().getResolvedJavaMethod(javaMethod), boxedArguments); + public Object execute(Method javaMethod, Object... boxedArguments) throws Throwable { + return execute(metaAccessProvider.getResolvedJavaMethod(javaMethod), boxedArguments); + } + + private boolean hasReceiver(ResolvedJavaMethod method) { + return !Modifier.isStatic(method.accessFlags()); } private void executeRoot(InterpreterFrame root, InterpreterFrame frame) throws Throwable { - //TODO reflection redirection - stackFrameDepth = 0; - + // TODO reflection redirection InterpreterFrame prevFrame = frame; InterpreterFrame currentFrame = frame; BytecodeStream bs = new BytecodeStream(currentFrame.getMethod().code()); @@ -208,17 +216,17 @@ while (true) { int result = executeInstruction(frame, bs); switch (result) { - case NEXT : + case NEXT: bs.next(); break; - case RETURN : + case RETURN: return popFrame(frame); case CALL: return allocateFrame(frame, bs); - case BRANCH : + case BRANCH: bs.setBCI(bs.readBranchDest()); break; - default : + default: // the outcome depends on stack values assert result >= 0 : "negative branch target"; bs.setBCI(result); @@ -227,7 +235,7 @@ } } catch (Throwable t) { if (TRACE) { - traceOp("Exception " + t.toString()); + traceOp(frame, "Exception " + t.toString()); } updateStackTrace(frame, t); @@ -240,7 +248,7 @@ throw t; } else { if (TRACE) { - traceOp("Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI()); + traceOp(frame, "Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI()); } // update bci from frame bs.setBCI(handlerFrame.getBCI()); @@ -256,79 +264,80 @@ private int executeInstruction(InterpreterFrame frame, BytecodeStream bs) throws Throwable { if (TRACE_BYTE_CODE) { - traceOp(bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC())); + traceOp(frame, bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC())); } - switch(bs.currentBC()) { - case Bytecodes.NOP : break; - case Bytecodes.ACONST_NULL : + switch (bs.currentBC()) { + case Bytecodes.NOP: + break; + case Bytecodes.ACONST_NULL: frame.pushObject(null); break; - case Bytecodes.ICONST_M1 : + case Bytecodes.ICONST_M1: frame.pushInt(-1); break; - case Bytecodes.ICONST_0 : + case Bytecodes.ICONST_0: frame.pushInt(0); break; - case Bytecodes.ICONST_1 : + case Bytecodes.ICONST_1: frame.pushInt(1); break; - case Bytecodes.ICONST_2 : + case Bytecodes.ICONST_2: frame.pushInt(2); break; - case Bytecodes.ICONST_3 : + case Bytecodes.ICONST_3: frame.pushInt(3); break; - case Bytecodes.ICONST_4 : + case Bytecodes.ICONST_4: frame.pushInt(4); break; - case Bytecodes.ICONST_5 : + case Bytecodes.ICONST_5: frame.pushInt(5); break; - case Bytecodes.LCONST_0 : + case Bytecodes.LCONST_0: frame.pushLong(0L); break; - case Bytecodes.LCONST_1 : + case Bytecodes.LCONST_1: frame.pushLong(1L); break; - case Bytecodes.FCONST_0 : + case Bytecodes.FCONST_0: frame.pushFloat(0.0F); break; - case Bytecodes.FCONST_1 : + case Bytecodes.FCONST_1: frame.pushFloat(1.0F); break; - case Bytecodes.FCONST_2 : + case Bytecodes.FCONST_2: frame.pushFloat(2.0F); break; - case Bytecodes.DCONST_0 : + case Bytecodes.DCONST_0: frame.pushDouble(0.0D); break; - case Bytecodes.DCONST_1 : + case Bytecodes.DCONST_1: frame.pushDouble(1.0D); break; - case Bytecodes.BIPUSH : + case Bytecodes.BIPUSH: frame.pushInt(bs.readByte()); break; - case Bytecodes.SIPUSH : + case Bytecodes.SIPUSH: frame.pushInt(bs.readShort()); break; - case Bytecodes.LDC : - case Bytecodes.LDC_W : - case Bytecodes.LDC2_W : + case Bytecodes.LDC: + case Bytecodes.LDC_W: + case Bytecodes.LDC2_W: pushCPConstant(frame, bs.readCPI()); break; - case Bytecodes.ILOAD : + case Bytecodes.ILOAD: frame.pushInt(frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.LLOAD : + case Bytecodes.LLOAD: frame.pushLong(frame.getLong(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.FLOAD : + case Bytecodes.FLOAD: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.DLOAD : + case Bytecodes.DLOAD: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(bs.readLocalIndex()))); break; - case Bytecodes.ALOAD : + case Bytecodes.ALOAD: frame.pushObject(frame.getObject(frame.resolveLocalIndex(bs.readLocalIndex()))); break; case Bytecodes.ILOAD_0: @@ -343,441 +352,441 @@ case Bytecodes.ILOAD_3: frame.pushInt(frame.getInt(frame.resolveLocalIndex(3))); break; - case Bytecodes.LLOAD_0 : + case Bytecodes.LLOAD_0: frame.pushLong(frame.getLong(frame.resolveLocalIndex(0))); break; - case Bytecodes.LLOAD_1 : + case Bytecodes.LLOAD_1: frame.pushLong(frame.getLong(frame.resolveLocalIndex(1))); break; - case Bytecodes.LLOAD_2 : + case Bytecodes.LLOAD_2: frame.pushLong(frame.getLong(frame.resolveLocalIndex(2))); break; - case Bytecodes.LLOAD_3 : + case Bytecodes.LLOAD_3: frame.pushLong(frame.getLong(frame.resolveLocalIndex(3))); break; - case Bytecodes.FLOAD_0 : + case Bytecodes.FLOAD_0: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(0))); break; - case Bytecodes.FLOAD_1 : + case Bytecodes.FLOAD_1: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(1))); break; - case Bytecodes.FLOAD_2 : + case Bytecodes.FLOAD_2: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(2))); break; - case Bytecodes.FLOAD_3 : + case Bytecodes.FLOAD_3: frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(3))); break; - case Bytecodes.DLOAD_0 : + case Bytecodes.DLOAD_0: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(0))); break; - case Bytecodes.DLOAD_1 : + case Bytecodes.DLOAD_1: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(1))); break; - case Bytecodes.DLOAD_2 : + case Bytecodes.DLOAD_2: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(2))); break; - case Bytecodes.DLOAD_3 : + case Bytecodes.DLOAD_3: frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(3))); break; - case Bytecodes.ALOAD_0 : + case Bytecodes.ALOAD_0: frame.pushObject(frame.getObject(frame.resolveLocalIndex(0))); break; - case Bytecodes.ALOAD_1 : + case Bytecodes.ALOAD_1: frame.pushObject(frame.getObject(frame.resolveLocalIndex(1))); break; - case Bytecodes.ALOAD_2 : + case Bytecodes.ALOAD_2: frame.pushObject(frame.getObject(frame.resolveLocalIndex(2))); break; - case Bytecodes.ALOAD_3 : + case Bytecodes.ALOAD_3: frame.pushObject(frame.getObject(frame.resolveLocalIndex(3))); break; - case Bytecodes.IALOAD : - frame.pushInt(vm.getArrayInt(frame.popInt(), frame.popObject())); + case Bytecodes.IALOAD: + frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject())); break; - case Bytecodes.LALOAD : - frame.pushLong(vm.getArrayLong(frame.popInt(), frame.popObject())); + case Bytecodes.LALOAD: + frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject())); break; - case Bytecodes.FALOAD : - frame.pushFloat(vm.getArrayFloat(frame.popInt(), frame.popObject())); + case Bytecodes.FALOAD: + frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject())); break; - case Bytecodes.DALOAD : - frame.pushDouble(vm.getArrayDouble(frame.popInt(), frame.popObject())); + case Bytecodes.DALOAD: + frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject())); break; - case Bytecodes.AALOAD : - frame.pushObject(vm.getArrayObject(frame.popInt(), frame.popObject())); + case Bytecodes.AALOAD: + frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject())); break; - case Bytecodes.BALOAD : - frame.pushInt(vm.getArrayByte(frame.popInt(), frame.popObject())); + case Bytecodes.BALOAD: + frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject())); break; - case Bytecodes.CALOAD : - frame.pushInt(vm.getArrayChar(frame.popInt(), frame.popObject())); + case Bytecodes.CALOAD: + frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject())); break; - case Bytecodes.SALOAD: - frame.pushInt(vm.getArrayShort(frame.popInt(), frame.popObject())); + case Bytecodes.SALOAD: + frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject())); break; case Bytecodes.ISTORE: frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt()); break; - case Bytecodes.LSTORE : + case Bytecodes.LSTORE: frame.setLong(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popLong()); break; - case Bytecodes.FSTORE : + case Bytecodes.FSTORE: frame.setFloat(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popFloat()); break; - case Bytecodes.DSTORE : + case Bytecodes.DSTORE: frame.setDouble(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popDouble()); break; - case Bytecodes.ASTORE : + case Bytecodes.ASTORE: frame.setObject(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popObject()); break; - case Bytecodes.ISTORE_0 : + case Bytecodes.ISTORE_0: frame.setInt(frame.resolveLocalIndex(0), frame.popInt()); break; - case Bytecodes.ISTORE_1 : + case Bytecodes.ISTORE_1: frame.setInt(frame.resolveLocalIndex(1), frame.popInt()); break; - case Bytecodes.ISTORE_2 : + case Bytecodes.ISTORE_2: frame.setInt(frame.resolveLocalIndex(2), frame.popInt()); break; - case Bytecodes.ISTORE_3 : + case Bytecodes.ISTORE_3: frame.setInt(frame.resolveLocalIndex(3), frame.popInt()); break; - case Bytecodes.LSTORE_0 : + case Bytecodes.LSTORE_0: frame.setLong(frame.resolveLocalIndex(0), frame.popLong()); break; - case Bytecodes.LSTORE_1 : + case Bytecodes.LSTORE_1: frame.setLong(frame.resolveLocalIndex(1), frame.popLong()); break; - case Bytecodes.LSTORE_2 : + case Bytecodes.LSTORE_2: frame.setLong(frame.resolveLocalIndex(2), frame.popLong()); break; - case Bytecodes.LSTORE_3 : + case Bytecodes.LSTORE_3: frame.setLong(frame.resolveLocalIndex(3), frame.popLong()); break; - case Bytecodes.FSTORE_0 : + case Bytecodes.FSTORE_0: frame.setFloat(frame.resolveLocalIndex(0), frame.popFloat()); break; - case Bytecodes.FSTORE_1 : + case Bytecodes.FSTORE_1: frame.setFloat(frame.resolveLocalIndex(1), frame.popFloat()); break; - case Bytecodes.FSTORE_2 : + case Bytecodes.FSTORE_2: frame.setFloat(frame.resolveLocalIndex(2), frame.popFloat()); break; - case Bytecodes.FSTORE_3 : + case Bytecodes.FSTORE_3: frame.setFloat(frame.resolveLocalIndex(3), frame.popFloat()); break; - case Bytecodes.DSTORE_0 : + case Bytecodes.DSTORE_0: frame.setDouble(frame.resolveLocalIndex(0), frame.popDouble()); break; - case Bytecodes.DSTORE_1 : + case Bytecodes.DSTORE_1: frame.setDouble(frame.resolveLocalIndex(1), frame.popDouble()); break; - case Bytecodes.DSTORE_2 : + case Bytecodes.DSTORE_2: frame.setDouble(frame.resolveLocalIndex(2), frame.popDouble()); break; - case Bytecodes.DSTORE_3 : + case Bytecodes.DSTORE_3: frame.setDouble(frame.resolveLocalIndex(3), frame.popDouble()); break; - case Bytecodes.ASTORE_0 : + case Bytecodes.ASTORE_0: frame.setObject(frame.resolveLocalIndex(0), frame.popObject()); break; - case Bytecodes.ASTORE_1 : + case Bytecodes.ASTORE_1: frame.setObject(frame.resolveLocalIndex(1), frame.popObject()); break; - case Bytecodes.ASTORE_2 : + case Bytecodes.ASTORE_2: frame.setObject(frame.resolveLocalIndex(2), frame.popObject()); break; - case Bytecodes.ASTORE_3 : + case Bytecodes.ASTORE_3: frame.setObject(frame.resolveLocalIndex(3), frame.popObject()); break; - case Bytecodes.IASTORE : - vm.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject()); + case Bytecodes.IASTORE: + runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.LASTORE : - vm.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject()); + case Bytecodes.LASTORE: + runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject()); break; - case Bytecodes.FASTORE : - vm.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject()); + case Bytecodes.FASTORE: + runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject()); break; - case Bytecodes.DASTORE : - vm.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject()); + case Bytecodes.DASTORE: + runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject()); break; - case Bytecodes.AASTORE : - vm.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject()); + case Bytecodes.AASTORE: + runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject()); break; - case Bytecodes.BASTORE : - vm.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject()); + case Bytecodes.BASTORE: + runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.CASTORE : - vm.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject()); + case Bytecodes.CASTORE: + runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.SASTORE : - vm.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject()); + case Bytecodes.SASTORE: + runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject()); break; - case Bytecodes.POP : + case Bytecodes.POP: frame.popVoid(1); break; - case Bytecodes.POP2 : + case Bytecodes.POP2: frame.popVoid(2); break; - case Bytecodes.DUP : + case Bytecodes.DUP: frame.dup(1); break; - case Bytecodes.DUP_X1 : + case Bytecodes.DUP_X1: frame.dupx1(); break; - case Bytecodes.DUP_X2 : + case Bytecodes.DUP_X2: frame.dupx2(); break; - case Bytecodes.DUP2 : + case Bytecodes.DUP2: frame.dup(2); break; - case Bytecodes.DUP2_X1 : + case Bytecodes.DUP2_X1: frame.dup2x1(); break; - case Bytecodes.DUP2_X2 : + case Bytecodes.DUP2_X2: frame.dup2x2(); break; - case Bytecodes.SWAP : + case Bytecodes.SWAP: frame.swapSingle(); break; - case Bytecodes.IADD : + case Bytecodes.IADD: frame.pushInt(frame.popInt() + frame.popInt()); break; - case Bytecodes.LADD : + case Bytecodes.LADD: frame.pushLong(frame.popLong() + frame.popLong()); break; - case Bytecodes.FADD : + case Bytecodes.FADD: frame.pushFloat(frame.popFloat() + frame.popFloat()); break; - case Bytecodes.DADD : + case Bytecodes.DADD: frame.pushDouble(frame.popDouble() + frame.popDouble()); break; - case Bytecodes.ISUB : + case Bytecodes.ISUB: frame.pushInt(-frame.popInt() + frame.popInt()); break; - case Bytecodes.LSUB : + case Bytecodes.LSUB: frame.pushLong(-frame.popLong() + frame.popLong()); break; - case Bytecodes.FSUB : + case Bytecodes.FSUB: frame.pushFloat(-frame.popFloat() + frame.popFloat()); break; - case Bytecodes.DSUB : + case Bytecodes.DSUB: frame.pushDouble(-frame.popDouble() + frame.popDouble()); break; - case Bytecodes.IMUL : + case Bytecodes.IMUL: frame.pushInt(frame.popInt() * frame.popInt()); break; - case Bytecodes.LMUL : + case Bytecodes.LMUL: frame.pushLong(frame.popLong() * frame.popLong()); break; - case Bytecodes.FMUL : + case Bytecodes.FMUL: frame.pushFloat(frame.popFloat() * frame.popFloat()); break; - case Bytecodes.DMUL : + case Bytecodes.DMUL: frame.pushDouble(frame.popDouble() * frame.popDouble()); break; - case Bytecodes.IDIV : + case Bytecodes.IDIV: divInt(frame); break; - case Bytecodes.LDIV : + case Bytecodes.LDIV: divLong(frame); break; - case Bytecodes.FDIV : + case Bytecodes.FDIV: divFloat(frame); break; - case Bytecodes.DDIV : + case Bytecodes.DDIV: divDouble(frame); break; - case Bytecodes.IREM : + case Bytecodes.IREM: remInt(frame); break; - case Bytecodes.LREM : + case Bytecodes.LREM: remLong(frame); break; - case Bytecodes.FREM : + case Bytecodes.FREM: remFloat(frame); break; - case Bytecodes.DREM : + case Bytecodes.DREM: remDouble(frame); break; - case Bytecodes.INEG : + case Bytecodes.INEG: frame.pushInt(-frame.popInt()); break; - case Bytecodes.LNEG : + case Bytecodes.LNEG: frame.pushLong(-frame.popLong()); break; - case Bytecodes.FNEG : + case Bytecodes.FNEG: frame.pushFloat(-frame.popFloat()); break; - case Bytecodes.DNEG : + case Bytecodes.DNEG: frame.pushDouble(-frame.popDouble()); break; - case Bytecodes.ISHL : + case Bytecodes.ISHL: shiftLeftInt(frame); break; - case Bytecodes.LSHL : + case Bytecodes.LSHL: shiftLeftLong(frame); break; - case Bytecodes.ISHR : + case Bytecodes.ISHR: shiftRightSignedInt(frame); break; - case Bytecodes.LSHR : + case Bytecodes.LSHR: shiftRightSignedLong(frame); break; - case Bytecodes.IUSHR : + case Bytecodes.IUSHR: shiftRightUnsignedInt(frame); break; - case Bytecodes.LUSHR : + case Bytecodes.LUSHR: shiftRightUnsignedLong(frame); break; - case Bytecodes.IAND : + case Bytecodes.IAND: frame.pushInt(frame.popInt() & frame.popInt()); break; - case Bytecodes.LAND : + case Bytecodes.LAND: frame.pushLong(frame.popLong() & frame.popLong()); break; - case Bytecodes.IOR : + case Bytecodes.IOR: frame.pushInt(frame.popInt() | frame.popInt()); break; - case Bytecodes.LOR : + case Bytecodes.LOR: frame.pushLong(frame.popLong() | frame.popLong()); break; - case Bytecodes.IXOR : + case Bytecodes.IXOR: frame.pushInt(frame.popInt() ^ frame.popInt()); break; - case Bytecodes.LXOR : + case Bytecodes.LXOR: frame.pushLong(frame.popLong() ^ frame.popLong()); break; - case Bytecodes.IINC : + case Bytecodes.IINC: iinc(frame, bs); break; - case Bytecodes.I2L : + case Bytecodes.I2L: frame.pushLong(frame.popInt()); break; - case Bytecodes.I2F : + case Bytecodes.I2F: frame.pushFloat(frame.popInt()); break; - case Bytecodes.I2D : + case Bytecodes.I2D: frame.pushDouble(frame.popInt()); break; - case Bytecodes.L2I : + case Bytecodes.L2I: frame.pushInt((int) frame.popLong()); break; - case Bytecodes.L2F : + case Bytecodes.L2F: frame.pushFloat(frame.popLong()); break; - case Bytecodes.L2D : + case Bytecodes.L2D: frame.pushDouble(frame.popLong()); break; - case Bytecodes.F2I : + case Bytecodes.F2I: frame.pushInt((int) frame.popFloat()); break; - case Bytecodes.F2L : + case Bytecodes.F2L: frame.pushLong((long) frame.popFloat()); break; - case Bytecodes.F2D : + case Bytecodes.F2D: frame.pushDouble(frame.popFloat()); break; - case Bytecodes.D2I : + case Bytecodes.D2I: frame.pushInt((int) frame.popDouble()); break; - case Bytecodes.D2L : + case Bytecodes.D2L: frame.pushLong((long) frame.popDouble()); break; - case Bytecodes.D2F : + case Bytecodes.D2F: frame.pushFloat((float) frame.popDouble()); break; - case Bytecodes.I2B : + case Bytecodes.I2B: frame.pushInt((byte) frame.popInt()); break; - case Bytecodes.I2C : + case Bytecodes.I2C: frame.pushInt((char) frame.popInt()); break; - case Bytecodes.I2S : + case Bytecodes.I2S: frame.pushInt((short) frame.popInt()); break; - case Bytecodes.LCMP : + case Bytecodes.LCMP: compareLong(frame); break; - case Bytecodes.FCMPL : + case Bytecodes.FCMPL: compareFloatLess(frame); break; - case Bytecodes.FCMPG : + case Bytecodes.FCMPG: compareFloatGreater(frame); break; - case Bytecodes.DCMPL : + case Bytecodes.DCMPL: compareDoubleLess(frame); break; - case Bytecodes.DCMPG : + case Bytecodes.DCMPG: compareDoubleGreater(frame); break; - case Bytecodes.IFEQ : + case Bytecodes.IFEQ: if (frame.popInt() == 0) { return BRANCH; } break; - case Bytecodes.IFNE : + case Bytecodes.IFNE: if (frame.popInt() != 0) { return BRANCH; } break; - case Bytecodes.IFLT : + case Bytecodes.IFLT: if (frame.popInt() < 0) { return BRANCH; } break; - case Bytecodes.IFGE : + case Bytecodes.IFGE: if (frame.popInt() >= 0) { return BRANCH; } break; - case Bytecodes.IFGT : + case Bytecodes.IFGT: if (frame.popInt() > 0) { return BRANCH; } break; - case Bytecodes.IFLE : + case Bytecodes.IFLE: if (frame.popInt() <= 0) { return BRANCH; } break; - case Bytecodes.IF_ICMPEQ : + case Bytecodes.IF_ICMPEQ: if (frame.popInt() == frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPNE : + case Bytecodes.IF_ICMPNE: if (frame.popInt() != frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPLT : + case Bytecodes.IF_ICMPLT: if (frame.popInt() > frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPGE : + case Bytecodes.IF_ICMPGE: if (frame.popInt() <= frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPGT : + case Bytecodes.IF_ICMPGT: if (frame.popInt() < frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ICMPLE : + case Bytecodes.IF_ICMPLE: if (frame.popInt() >= frame.popInt()) { return BRANCH; } break; - case Bytecodes.IF_ACMPEQ : + case Bytecodes.IF_ACMPEQ: if (frame.popObject() == frame.popObject()) { return BRANCH; } break; - case Bytecodes.IF_ACMPNE : + case Bytecodes.IF_ACMPNE: if (frame.popObject() != frame.popObject()) { return BRANCH; } @@ -785,58 +794,58 @@ case Bytecodes.GOTO: case Bytecodes.GOTO_W: return BRANCH; - case Bytecodes.JSR : - case Bytecodes.JSR_W : + case Bytecodes.JSR: + case Bytecodes.JSR_W: frame.pushInt(bs.currentBCI()); return BRANCH; - case Bytecodes.RET : + case Bytecodes.RET: return frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex())); - case Bytecodes.TABLESWITCH : + case Bytecodes.TABLESWITCH: return tableSwitch(frame, bs); - case Bytecodes.LOOKUPSWITCH : + case Bytecodes.LOOKUPSWITCH: return lookupSwitch(frame, bs); - case Bytecodes.IRETURN : + case Bytecodes.IRETURN: frame.getParentFrame().pushInt(frame.popInt()); return RETURN; - case Bytecodes.LRETURN : + case Bytecodes.LRETURN: frame.getParentFrame().pushLong(frame.popLong()); return RETURN; - case Bytecodes.FRETURN : + case Bytecodes.FRETURN: frame.getParentFrame().pushFloat(frame.popFloat()); return RETURN; - case Bytecodes.DRETURN : + case Bytecodes.DRETURN: frame.getParentFrame().pushDouble(frame.popDouble()); return RETURN; - case Bytecodes.ARETURN : + case Bytecodes.ARETURN: frame.getParentFrame().pushObject(frame.popObject()); return RETURN; - case Bytecodes.RETURN : + case Bytecodes.RETURN: return RETURN; - case Bytecodes.GETSTATIC : + case Bytecodes.GETSTATIC: getField(frame, null, bs.currentBC(), bs.readCPI()); break; - case Bytecodes.PUTSTATIC : + case Bytecodes.PUTSTATIC: putStatic(frame, bs.readCPI()); break; case Bytecodes.GETFIELD: getField(frame, nullCheck(frame.popObject()), bs.currentBC(), bs.readCPI()); break; - case Bytecodes.PUTFIELD : + case Bytecodes.PUTFIELD: putField(frame, bs.readCPI()); break; - case Bytecodes.INVOKEVIRTUAL : + case Bytecodes.INVOKEVIRTUAL: callFrame = invokeVirtual(frame, bs.readCPI()); if (callFrame == null) { break; } return CALL; - case Bytecodes.INVOKESPECIAL : + case Bytecodes.INVOKESPECIAL: callFrame = invokeSpecial(frame, bs.readCPI()); if (callFrame == null) { break; } return CALL; - case Bytecodes.INVOKESTATIC : + case Bytecodes.INVOKESTATIC: callFrame = invokeStatic(frame, bs.readCPI()); if (callFrame == null) { break; @@ -848,53 +857,57 @@ break; } return CALL; - case Bytecodes.XXXUNUSEDXXX : - assert false : "unused bytecode used. behaviour unspecfied."; + case Bytecodes.XXXUNUSEDXXX: + assert false : "unused bytecode used. behaviour unspecified."; // nop break; - case Bytecodes.NEW : + case Bytecodes.NEW: frame.pushObject(allocateInstance(frame, bs.readCPI())); break; - case Bytecodes.NEWARRAY : + case Bytecodes.NEWARRAY: frame.pushObject(allocateNativeArray(frame, bs.readByte())); break; - case Bytecodes.ANEWARRAY : + case Bytecodes.ANEWARRAY: frame.pushObject(allocateArray(frame, bs.readCPI())); break; - case Bytecodes.ARRAYLENGTH : + case Bytecodes.ARRAYLENGTH: frame.pushInt(Array.getLength(nullCheck(frame.popObject()))); break; - case Bytecodes.ATHROW : - throw (Throwable) frame.popObject(); - case Bytecodes.CHECKCAST : + case Bytecodes.ATHROW: + Throwable t = (Throwable) frame.popObject(); + if ("break".equals(t.getMessage())) { + t.printStackTrace(); + } + throw t; + case Bytecodes.CHECKCAST: checkCast(frame, bs.readCPI()); break; - case Bytecodes.INSTANCEOF : + case Bytecodes.INSTANCEOF: instanceOf(frame, bs.readCPI()); break; - case Bytecodes.MONITORENTER : - vm.monitorEnter(frame.popObject()); + case Bytecodes.MONITORENTER: + runtimeInterface.monitorEnter(frame.popObject()); break; - case Bytecodes.MONITOREXIT : - vm.monitorExit(frame.popObject()); + case Bytecodes.MONITOREXIT: + runtimeInterface.monitorExit(frame.popObject()); break; - case Bytecodes.WIDE : + case Bytecodes.WIDE: assert false; break; - case Bytecodes.MULTIANEWARRAY : + case Bytecodes.MULTIANEWARRAY: frame.pushObject(allocateMultiArray(frame, bs.readCPI(), bs.readUByte(bs.currentBCI() + 3))); break; - case Bytecodes.IFNULL : + case Bytecodes.IFNULL: if (frame.popObject() == null) { return BRANCH; } break; - case Bytecodes.IFNONNULL : + case Bytecodes.IFNONNULL: if (frame.popObject() != null) { return BRANCH; } break; - case Bytecodes.BREAKPOINT : + case Bytecodes.BREAKPOINT: assert false : "no breakpoints supported at this time."; break; // nop } @@ -912,11 +925,6 @@ currentFrame = popFrame(currentFrame); } else { // found a handler -> execute it - if (handler.isCatchAll()) { - catchAllExceptionHandler = handler; - } else { - catchAllExceptionHandler = null; - } currentFrame.setBCI(handler.handlerBCI()); currentFrame.popStack(); currentFrame.pushObject(t); @@ -938,13 +946,12 @@ } } - private void setStackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] stackTrace) { - vm.setField(stackTrace, t, findThrowableField(frame, "stackTrace")); + runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace")); } private StackTraceElement[] getBackTrace(InterpreterFrame frame, Throwable t) { - Object value = vm.getField(t, findThrowableField(frame, "backtrace")); + Object value = runtimeInterface.getFieldObject(t, findThrowableField(frame, "backtrace")); if (value instanceof StackTraceElement[]) { return (StackTraceElement[]) value; } @@ -952,25 +959,23 @@ } private void setBackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] backtrace) { - vm.setField(backtrace, t, findThrowableField(frame, "backtrace")); + runtimeInterface.setFieldObject(backtrace, t, findThrowableField(frame, "backtrace")); } private ExceptionHandler resolveExceptionHandlers(InterpreterFrame frame, int bci, Throwable t) { ExceptionHandler[] handlers = frame.getMethod().exceptionHandlers(); for (int i = 0; i < handlers.length; i++) { ExceptionHandler handler = handlers[i]; - if (bci >= handler.startBCI() - && bci <= handler.endBCI() - && (catchAllExceptionHandler == null || !handler.isCatchAll())) { + if (bci >= handler.startBCI() && bci <= handler.endBCI()) { ResolvedJavaType catchType = null; if (!handler.isCatchAll()) { - catchType = resolveType(frame, bci, (char) handler.catchTypeCPI()); + // exception handlers are similar to instanceof bytecodes, so we pass instanceof + catchType = resolveType(frame, Bytecodes.INSTANCEOF, (char) handler.catchTypeCPI()); } - if (catchType == null - || catchType.toJava().isInstance(t)) { + if (catchType == null || catchType.toJava().isInstance(t)) { // the first found exception handler is our exception handler - return handler; + return handler; } } } @@ -979,8 +984,6 @@ private InterpreterFrame allocateFrame(InterpreterFrame frame, BytecodeStream bs) { try { - stackFrameDepth++; - InterpreterFrame nextFrame = this.callFrame; assert nextFrame != null; @@ -994,58 +997,53 @@ } if (Modifier.isSynchronized(nextFrame.getMethod().accessFlags())) { if (TRACE) { - traceOp("Method monitor enter"); + traceOp(frame, "Method monitor enter"); } if (Modifier.isStatic(nextFrame.getMethod().accessFlags())) { - vm.monitorEnter(nextFrame.getMethod().holder().toJava()); + runtimeInterface.monitorEnter(nextFrame.getMethod().holder().toJava()); } else { Object enterObject = nextFrame.getObject(frame.resolveLocalIndex(0)); assert enterObject != null; - vm.monitorEnter(enterObject); + runtimeInterface.monitorEnter(enterObject); } } return nextFrame; } finally { - // catch all exception handlers are not allowed to call any method anyway. - catchAllExceptionHandler = null; callFrame = null; bs.next(); } } private InterpreterFrame popFrame(InterpreterFrame frame) { - catchAllExceptionHandler = null; InterpreterFrame parent = frame.getParentFrame(); if (Modifier.isSynchronized(frame.getMethod().accessFlags())) { if (TRACE) { - traceOp("Method monitor exit"); + traceOp(frame, "Method monitor exit"); } if (Modifier.isStatic(frame.getMethod().accessFlags())) { - vm.monitorExit(frame.getMethod().holder().toJava()); + runtimeInterface.monitorExit(frame.getMethod().holder().toJava()); } else { Object exitObject = frame.getObject(frame.resolveLocalIndex(0)); if (exitObject != null) { - vm.monitorExit(exitObject); + runtimeInterface.monitorExit(exitObject); } } } if (TRACE) { traceCall(frame, "Ret"); } - stackFrameDepth--; frame.dispose(); return parent; } - private void traceOp(String opName) { - trace(stackFrameDepth + 1, opName); + private void traceOp(InterpreterFrame frame, String opName) { + trace(frame.depth(), opName); } private void traceCall(InterpreterFrame frame, String type) { - trace(stackFrameDepth, type + " " + - frame.getMethod() + " - " + frame.getMethod().signature().asString()); + trace(frame.depth(), type + " " + frame.getMethod() + " - " + frame.getMethod().signature().asString()); } private void trace(int level, String message) { @@ -1057,7 +1055,6 @@ System.out.println(builder); } - private void divInt(InterpreterFrame frame) { int dividend = frame.popInt(); int divisor = frame.popInt(); @@ -1082,7 +1079,6 @@ frame.pushDouble(divisor / dividend); } - private void remInt(InterpreterFrame frame) { int dividend = frame.popInt(); int divisor = frame.popInt(); @@ -1144,8 +1140,7 @@ } private int lookupSwitch(InterpreterFrame frame, BytecodeStream bs) { - return lookupSearch( - new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt()); + return lookupSearch(new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt()); } /** @@ -1166,7 +1161,7 @@ return switchHelper.bci() + switchHelper.offsetAt(mid); // key found } } - return switchHelper.defaultTarget(); // key not found. + return switchHelper.defaultTarget(); // key not found. } private int tableSwitch(InterpreterFrame frame, BytecodeStream bs) { @@ -1195,8 +1190,8 @@ return constantPool.lookupType(cpi, opcode).resolve(frame.getMethod().holder()); } - private ResolvedJavaType resolveType(InterpreterFrame frame, Class<?> javaClass) { - return vm.getRuntime().getResolvedJavaType(javaClass).resolve(frame.getMethod().holder()); + private ResolvedJavaType resolveType(InterpreterFrame frame, Class< ? > javaClass) { + return metaAccessProvider.getResolvedJavaType(javaClass).resolve(frame.getMethod().holder()); } private ResolvedJavaMethod resolveMethod(InterpreterFrame frame, int opcode, char cpi) { @@ -1212,9 +1207,7 @@ } private void instanceOf(InterpreterFrame frame, char cpi) { - frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi). - toJava().isInstance(frame.popObject()) - ? 1 : 0); + frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).toJava().isInstance(frame.popObject()) ? 1 : 0); } private void pushCPConstant(InterpreterFrame frame, char cpi) { @@ -1224,7 +1217,7 @@ if (constant instanceof Constant) { Constant c = ((Constant) constant); switch (c.kind) { - case Int : + case Int: frame.pushInt(c.asInt()); break; case Float: @@ -1233,10 +1226,10 @@ case Object: frame.pushObject(c.asObject()); break; - case Double : + case Double: frame.pushDouble(c.asDouble()); break; - case Long : + case Long: frame.pushLong(c.asLong()); break; default: @@ -1285,6 +1278,7 @@ } return value; } + private InterpreterFrame invokeStatic(InterpreterFrame frame, char cpi) throws Throwable { return invoke(frame, resolveMethod(frame, Bytecodes.INVOKESTATIC, cpi), null); } @@ -1319,104 +1313,91 @@ return invoke(frame, m, nullCheck(frame.peekReceiver(m))); } - private void invokeReflective(InterpreterFrame frame, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable { - Class<?>[] parameterTypes = resolveMethodArguments(method); - Object[] parameters = popArgumentsAsObject(frame, method); - Class<?> javaClass = method.holder().toJava(); - - Object parentObject = null; - if (hasReceiver) { - parentObject = frame.popObject(); - nullCheck(parentObject); - } - Object returnValue = null; + private Object[] popArgumentsAsObject(InterpreterFrame frame, ResolvedJavaMethod method, boolean hasReceiver) { + Signature signature = method.signature(); + int argumentCount = method.signature().argumentCount(hasReceiver); + Object[] parameters = new Object[argumentCount]; - if (redirect(method)) { - if (TRACE) { - traceCall(frame, "Delegate " + method); - } - try { - returnValue = methodDelegates.get(method).invoke(frame, method, parentObject, parameters); - } catch (Throwable e) { - throw e; - } - } else { - if (TRACE) { - traceCall(frame, "Reflective " + method); - } - try { - Method javaMethod = javaClass.getDeclaredMethod(method.name(), parameterTypes); - javaMethod.setAccessible(true); - returnValue = javaMethod.invoke(parentObject, parameters); - } catch (InvocationTargetException e) { - e.printStackTrace(System.out); - throw e.getTargetException(); - } catch (NoSuchMethodException | SecurityException e) { - throw new AbstractMethodError(); - } + int lastSignatureIndex = hasReceiver ? 1 : 0; + for (int i = argumentCount - 1; i >= lastSignatureIndex; i--) { + ResolvedJavaType type = signature.argumentTypeAt(i - lastSignatureIndex, method.holder()).resolve(method.holder()); + parameters[i] = popAsObject(frame, type.kind()); } - pushAsObject(frame, method.signature().returnKind(), returnValue); - } - - private Object[] popArgumentsAsObject(InterpreterFrame frame, ResolvedJavaMethod method) { - Signature signature = method.signature(); - int argumentCount = method.signature().argumentCount(false); - Object[] parameters = new Object[argumentCount]; - for (int i = argumentCount - 1; i >= 0; i--) { - ResolvedJavaType type = signature.argumentTypeAt(i, method.holder()).resolve(method.holder()); - parameters[i] = popAsObject(frame, type.kind()); + if (hasReceiver) { + parameters[0] = frame.popObject(); } return parameters; } - private Class<?>[] resolveMethodArguments(ResolvedJavaMethod method) { - Signature signature = method.signature(); - int argumentCount = signature.argumentCount(false); - Class<?>[] parameterTypes = new Class[argumentCount]; - - for (int i = 0; i < argumentCount; i++) { - JavaType type = signature.argumentTypeAt(i, method.holder()); - ResolvedJavaType resolvedType = type.resolve(method.holder()); - parameterTypes[i] = resolvedType.toJava(); - } - return parameterTypes; - } - - private InterpreterFrame invoke(InterpreterFrame parent, ResolvedJavaMethod method, Object receiver) throws Throwable { - if (stackFrameDepth >= maxStackFrames) { + private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable { + if (caller.depth() >= maxStackFrames) { throw new StackOverflowError("Maximum callstack of " + maxStackFrames + " exceeded."); } - if (redirect(method)) { - invokeReflective(parent, method, receiver != null); - // returning null results in a jump to the next instruction - // since the method is already successfully invoked. - return null; + if (Modifier.isNative(method.accessFlags())) { + return invokeNativeMethodViaVM(caller, method, receiver != null); } else { - if (Modifier.isNative(method.accessFlags())) { - invokeReflective(parent, method, receiver != null); - return null; + MethodRedirectionInfo redirectedMethod = methodDelegates.get(method); + if (redirectedMethod != null) { + return invokeRedirectedMethodViaVM(caller, method, redirectedMethod, receiver != null); } else { - return parent.create(method, receiver != null); + return invokeOptimized(caller, method, receiver != null); } } } - private boolean redirect(ResolvedJavaMethod method) { - return methodDelegates.containsKey(method); + private InterpreterFrame invokeNativeMethodViaVM(InterpreterFrame caller, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable { + assert !methodDelegates.containsKey(method) : "must not be redirected"; + if (TRACE) { + traceCall(caller, "Native " + method); + } + + // mark the current thread as high level and execute the native method + Object[] parameters = popArgumentsAsObject(caller, method, hasReceiver); + Object returnValue = runtimeInterface.invoke(method, parameters); + pushAsObject(caller, method.signature().returnKind(), returnValue); + + return null; } + private InterpreterFrame invokeRedirectedMethodViaVM(InterpreterFrame caller, ResolvedJavaMethod originalMethod, MethodRedirectionInfo redirectionInfo, boolean hasReceiver) throws Throwable { + assert methodDelegates.containsKey(originalMethod) : "must be redirected"; + if (TRACE) { + traceCall(caller, "Delegate " + originalMethod); + } + + // current thread is low level and we also execute the target method in the low-level interpreter + Object[] originalCalleeParameters = popArgumentsAsObject(caller, originalMethod, hasReceiver); + Object[] parameters = new Object[]{caller, originalMethod, originalCalleeParameters}; + Object returnValue = redirectionInfo.getTargetMethod().invoke(redirectionInfo.getReceiver(), parameters); + pushAsObject(caller, originalMethod.signature().returnKind(), returnValue); + + return null; + } + + private InterpreterFrame invokeOptimized(InterpreterFrame parent, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable { + return parent.create(method, hasReceiver); + } private Object allocateMultiArray(InterpreterFrame frame, char cpi, int dimension) { - ResolvedJavaType type = resolveType(frame, Bytecodes.MULTIANEWARRAY, cpi); + ResolvedJavaType type = getLastDimensionType(resolveType(frame, Bytecodes.MULTIANEWARRAY, cpi)); + int[] dimensions = new int[dimension]; - for (int i = 0; i < dimension; i++) { + for (int i = dimension - 1; i >= 0; i--) { dimensions[i] = frame.popInt(); } return Array.newInstance(type.toJava(), dimensions); } + private ResolvedJavaType getLastDimensionType(ResolvedJavaType type) { + ResolvedJavaType result = type; + while (result.isArrayClass()) { + result = result.componentType(); + } + return result; + } + private Object allocateArray(InterpreterFrame frame, char cpi) { ResolvedJavaType type = resolveType(frame, Bytecodes.ANEWARRAY, cpi); return Array.newInstance(type.toJava(), frame.popInt()); @@ -1425,21 +1406,21 @@ private Object allocateNativeArray(InterpreterFrame frame, byte cpi) { // the constants for the cpi are loosely defined and no real cpi indices. switch (cpi) { - case 4 : + case 4: return new byte[frame.popInt()]; - case 8 : + case 8: return new byte[frame.popInt()]; - case 5 : + case 5: return new char[frame.popInt()]; - case 7 : + case 7: return new double[frame.popInt()]; - case 6 : + case 6: return new float[frame.popInt()]; - case 10 : + case 10: return new int[frame.popInt()]; - case 11 : + case 11: return new long[frame.popInt()]; - case 9 : + case 9: return new short[frame.popInt()]; default: assert false : "unexpected case"; @@ -1448,7 +1429,7 @@ } private Object allocateInstance(InterpreterFrame frame, char cpi) throws InstantiationException { - return vm.newObject(resolveType(frame, Bytecodes.NEW, cpi)); + return runtimeInterface.newObject(resolveType(frame, Bytecodes.NEW, cpi)); } private void iinc(InterpreterFrame frame, BytecodeStream bs) { @@ -1466,52 +1447,52 @@ private void putFieldStatic(InterpreterFrame frame, ResolvedJavaField field) { switch (field.kind()) { - case Boolean : - case Byte : - case Char : - case Short : - case Int : - vm.setFieldInt(frame.popInt(), null, field); + case Boolean: + case Byte: + case Char: + case Short: + case Int: + runtimeInterface.setFieldInt(frame.popInt(), null, field); break; - case Double : - vm.setFieldDouble(frame.popDouble(), null, field); + case Double: + runtimeInterface.setFieldDouble(frame.popDouble(), null, field); break; - case Float : - vm.setFieldFloat(frame.popFloat(), null, field); + case Float: + runtimeInterface.setFieldFloat(frame.popFloat(), null, field); break; - case Long : - vm.setFieldLong(frame.popLong(), null, field); + case Long: + runtimeInterface.setFieldLong(frame.popLong(), null, field); break; - case Object : - vm.setField(frame.popObject(), null, field); + case Object: + runtimeInterface.setFieldObject(frame.popObject(), null, field); break; - default : + default: assert false : "unexpected case"; } } private void putFieldVirtual(InterpreterFrame frame, ResolvedJavaField field) { switch (field.kind()) { - case Boolean : - case Byte : - case Char : - case Short : - case Int : - vm.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field); + case Boolean: + case Byte: + case Char: + case Short: + case Int: + runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field); break; - case Double : - vm.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field); + case Double: + runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field); break; - case Float : - vm.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field); + case Float: + runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field); break; - case Long : - vm.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field); + case Long: + runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field); break; - case Object : - vm.setField(frame.popObject(), nullCheck(frame.popObject()), field); + case Object: + runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field); break; - default : + default: assert false : "unexpected case"; } } @@ -1519,63 +1500,70 @@ private void getField(InterpreterFrame frame, Object base, int opcode, char cpi) { ResolvedJavaField field = resolveField(frame, opcode, cpi); switch (field.kind()) { - case Boolean : - case Byte : - case Char : - case Short : - case Int : - frame.pushInt(vm.getFieldInt(base, field)); + case Boolean: + frame.pushInt(runtimeInterface.getFieldBoolean(base, field) ? 1 : 0); + break; + case Byte: + frame.pushInt(runtimeInterface.getFieldByte(base, field)); break; - case Double : - frame.pushDouble(vm.getFieldDouble(base, field)); + case Char: + frame.pushInt(runtimeInterface.getFieldChar(base, field)); + break; + case Short: + frame.pushInt(runtimeInterface.getFieldShort(base, field)); break; - case Float : - frame.pushFloat(vm.getFieldFloat(base, field)); + case Int: + frame.pushInt(runtimeInterface.getFieldInt(base, field)); + break; + case Double: + frame.pushDouble(runtimeInterface.getFieldDouble(base, field)); break; - case Long : - frame.pushLong(vm.getFieldLong(base, field)); + case Float: + frame.pushFloat(runtimeInterface.getFieldFloat(base, field)); break; - case Object : - frame.pushObject(vm.getField(base, field)); + case Long: + frame.pushLong(runtimeInterface.getFieldLong(base, field)); break; - default : + case Object: + frame.pushObject(runtimeInterface.getFieldObject(base, field)); + break; + default: assert false : "unexpected case"; } } - private int pushAsObject(InterpreterFrame frame, Kind typeKind, Object value) { - switch(typeKind) { - case Int : + switch (typeKind) { + case Int: frame.pushInt((int) value); break; - case Long : + case Long: frame.pushLong((long) value); return 2; - case Boolean : + case Boolean: frame.pushInt(((boolean) value) ? 1 : 0); break; - case Byte : + case Byte: frame.pushInt((byte) value); break; - case Char : + case Char: frame.pushInt((char) value); break; - case Double : + case Double: frame.pushDouble((double) value); return 2; - case Float : + case Float: frame.pushFloat((float) value); break; - case Short : + case Short: frame.pushInt((short) value); break; - case Object : + case Object: frame.pushObject(value); break; - case Void : + case Void: return 0; - default : + default: assert false : "case not specified"; } return 1; @@ -1583,27 +1571,27 @@ private Object popAsObject(InterpreterFrame frame, Kind typeKind) { switch (typeKind) { - case Boolean : + case Boolean: return frame.popInt() == 1 ? true : false; - case Byte : + case Byte: return (byte) frame.popInt(); - case Char : + case Char: return (char) frame.popInt(); - case Double : + case Double: return frame.popDouble(); - case Int : + case Int: return frame.popInt(); - case Float : + case Float: return frame.popFloat(); - case Long : + case Long: return frame.popLong(); - case Short : + case Short: return (short) frame.popInt(); - case Object : + case Object: return frame.popObject(); - case Void : + case Void: return null; - default : + default: assert false : "unexpected case"; } return null; @@ -1611,13 +1599,13 @@ private ResolvedJavaMethod resolveRootMethod() { try { - return vm.getRuntime().getResolvedJavaMethod(BytecodeInterpreter.class.getDeclaredMethod("execute", Method.class, Object[].class)); + return metaAccessProvider.getResolvedJavaMethod(BytecodeInterpreter.class.getDeclaredMethod("execute", Method.class, Object[].class)); } catch (Exception e) { throw new RuntimeException(e); } } - private static Method findMethod(Class<?> clazz, String name, Class<?> ... parameters) { + private static Method findMethod(Class< ? > clazz, String name, Class< ? >... parameters) { try { return clazz.getDeclaredMethod(name, parameters); } catch (Exception e) { @@ -1655,4 +1643,32 @@ return null; } + private class MethodRedirectionInfo { + + private InterpreterCallable receiver; + private Method method; + + public MethodRedirectionInfo(InterpreterCallable instance) { + this.receiver = instance; + this.method = resolveMethod(instance); + } + + public InterpreterCallable getReceiver() { + return receiver; + } + + public Method getTargetMethod() { + return method; + } + + private Method resolveMethod(InterpreterCallable instance) { + try { + return instance.getClass().getMethod(InterpreterCallable.INTERPRETER_CALLABLE_INVOKE_NAME, InterpreterCallable.INTERPRETER_CALLABLE_INVOKE_SIGNATURE); + } catch (NoSuchMethodException e) { + throw new InterpreterException(e); + } catch (SecurityException e) { + throw new InterpreterException(e); + } + } + } }
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java Thu Jul 05 16:54:45 2012 +0200 @@ -26,7 +26,10 @@ public interface InterpreterCallable { + // static final fields + String INTERPRETER_CALLABLE_INVOKE_NAME = "invoke"; + Class<?>[] INTERPRETER_CALLABLE_INVOKE_SIGNATURE = {InterpreterFrame.class, ResolvedJavaMethod.class, Object[].class}; - Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object base, Object[] arguments) throws Throwable; - + // methods + Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable; }
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java Thu Jul 05 16:54:45 2012 +0200 @@ -37,21 +37,23 @@ private static final int SINGLE = 1; /** Pointer to the top-most stack frame element. */ + private int depth; private int tos; public InterpreterFrame(ResolvedJavaMethod method, int additionalStackSpace) { - this(method, null, additionalStackSpace); + this(method, null, additionalStackSpace, 0); } - private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace) { + private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace, int depth) { super(method.maxLocals() + method.maxStackSize() + BASE_LENGTH + additionalStackSpace, parent); setMethod(method); setBCI(0); + this.depth = depth; this.tos = BASE_LENGTH; } public InterpreterFrame create(ResolvedJavaMethod method, boolean hasReceiver) { - InterpreterFrame frame = new InterpreterFrame(method, this, 0); + InterpreterFrame frame = new InterpreterFrame(method, this, 0, this.depth + 1); int length = method.signature().argumentSlots(hasReceiver); frame.pushVoid(method.maxLocals()); @@ -67,6 +69,10 @@ return BASE_LENGTH + index; } + public int depth() { + return depth; + } + private int stackTos() { return BASE_LENGTH + getMethod().maxLocals(); } @@ -245,6 +251,7 @@ } private void decrementTos(int size) { + assert tos - size >= stackTos(); tos -= size; }
--- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/VMAdapter.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,313 +0,0 @@ -/* - * Copyright (c) 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.interpreter; - -import java.lang.reflect.*; - -import sun.misc.*; - -import com.oracle.graal.api.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.meta.*; - - -/** - * This class encapsulates all vm specific methods for the {@link BytecodeInterpreter}. - */ -public class VMAdapter { - - private static final Unsafe unsafe = loadUnsafe(); - - protected VMAdapter() { - } - - public MetaAccessProvider getRuntime() { - return Graal.getRuntime().getCapability(MetaAccessProvider.class); - } - - public void monitorEnter(Object value) { - nullCheck(value); - unsafe.monitorEnter(value); - } - - public void monitorExit(Object value) { - nullCheck(value); - unsafe.monitorExit(value); - } - - public Object newObject(ResolvedJavaType type) throws InstantiationException { - return unsafe.allocateInstance(type.toJava()); - } - - public Object getField(Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - return unsafe.getObjectVolatile(resolveBase(base, field), offset); - } else { - return unsafe.getObject(resolveBase(base, field), offset); - } - } - - public int getFieldInt(Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - return unsafe.getIntVolatile(resolveBase(base, field), offset); - } else { - return unsafe.getInt(resolveBase(base, field), offset); - } - } - - public long getFieldLong(Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - return unsafe.getLongVolatile(resolveBase(base, field), offset); - } else { - return unsafe.getLong(resolveBase(base, field), offset); - } - } - - public double getFieldDouble(Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - return unsafe.getDoubleVolatile(resolveBase(base, field), offset); - } else { - return unsafe.getDouble(resolveBase(base, field), offset); - } - } - - public float getFieldFloat(Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - return unsafe.getFloatVolatile(resolveBase(base, field), offset); - } else { - return unsafe.getFloat(resolveBase(base, field), offset); - } - } - - public void setField(Object value, Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - unsafe.putObjectVolatile(resolveBase(base, field), offset, value); - } else { - unsafe.putObject(resolveBase(base, field), offset, value); - } - } - - public void setFieldInt(int value, Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - unsafe.putIntVolatile(resolveBase(base, field), offset, value); - } else { - unsafe.putInt(resolveBase(base, field), offset, value); - } - } - - - public void setFieldFloat(float value, Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - unsafe.putFloatVolatile(resolveBase(base, field), offset, value); - } else { - unsafe.putFloat(resolveBase(base, field), offset, value); - } - } - - public void setFieldDouble(double value, Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - unsafe.putDoubleVolatile(resolveBase(base, field), offset, value); - } else { - unsafe.putDouble(resolveBase(base, field), offset, value); - } - } - - public void setFieldLong(long value, Object base, ResolvedJavaField field) { - long offset = resolveOffset(field); - if (isVolatile(field)) { - unsafe.putDoubleVolatile(resolveBase(base, field), offset, value); - } else { - unsafe.putDouble(resolveBase(base, field), offset, value); - } - } - - public byte getArrayByte(long index, Object array) { - checkArray(array, index); - return unsafe.getByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index); - } - - public char getArrayChar(long index, Object array) { - checkArray(array, index); - return unsafe.getChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index); - } - - public short getArrayShort(long index, Object array) { - checkArray(array, index); - return unsafe.getShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index); - } - - public int getArrayInt(long index, Object array) { - checkArray(array, index); - return unsafe.getInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index); - } - - public long getArrayLong(long index, Object array) { - checkArray(array, index); - return unsafe.getLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index); - } - - public double getArrayDouble(long index, Object array) { - checkArray(array, index); - return unsafe.getDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index); - } - - public float getArrayFloat(long index, Object array) { - checkArray(array, index); - return unsafe.getFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index); - } - - public Object getArrayObject(long index, Object array) { - checkArray(array, index); - return unsafe.getObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index); - } - - public void setArrayByte(byte value, long index, Object array) { - checkArray(array, index); - if (array instanceof boolean[]) { - checkArrayType(array, boolean.class); - } else { - checkArrayType(array, byte.class); - } - unsafe.putByte(array, Unsafe.ARRAY_BYTE_BASE_OFFSET + Unsafe.ARRAY_BYTE_INDEX_SCALE * index, value); - } - - public void setArrayChar(char value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, char.class); - unsafe.putChar(array, Unsafe.ARRAY_CHAR_BASE_OFFSET + Unsafe.ARRAY_CHAR_INDEX_SCALE * index, value); - } - - public void setArrayShort(short value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, short.class); - unsafe.putShort(array, Unsafe.ARRAY_SHORT_BASE_OFFSET + Unsafe.ARRAY_SHORT_INDEX_SCALE * index, value); - } - - public void setArrayInt(int value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, int.class); - unsafe.putInt(array, Unsafe.ARRAY_INT_BASE_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * index, value); - } - - public void setArrayLong(long value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, long.class); - unsafe.putLong(array, Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * index, value); - } - - public void setArrayFloat(float value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, float.class); - unsafe.putFloat(array, Unsafe.ARRAY_FLOAT_BASE_OFFSET + Unsafe.ARRAY_FLOAT_INDEX_SCALE * index, value); - } - - public void setArrayDouble(double value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, double.class); - unsafe.putDouble(array, Unsafe.ARRAY_DOUBLE_BASE_OFFSET + Unsafe.ARRAY_DOUBLE_INDEX_SCALE * index, value); - } - - public void setArrayObject(Object value, long index, Object array) { - checkArray(array, index); - checkArrayType(array, value != null ? value.getClass() : null); - unsafe.putObject(array, Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * index, value); - } - - private static void nullCheck(Object value) { - if (value == null) { - throw new NullPointerException(); - } - } - - private void checkArrayType(Object array, Class<?> arrayType) { - if (arrayType == null) { - return; - } - ResolvedJavaType type = getRuntime().getResolvedJavaType(array.getClass()).componentType(); - if (!type.toJava().isAssignableFrom(arrayType)) { - throw new ArrayStoreException(arrayType.getName()); - } - } - - private void checkArray(Object array, long index) { - nullCheck(array); - ResolvedJavaType type = getRuntime().getResolvedJavaType(array.getClass()); - if (!type.isArrayClass()) { - throw new ArrayStoreException(array.getClass().getName()); - } - if (index < 0 || index >= arrayLength(array)) { - throw new ArrayIndexOutOfBoundsException((int) index); - } - } - - private static int arrayLength(Object array) { - assert array != null; - return Array.getLength(array); - } - - private static boolean isVolatile(ResolvedJavaField field) { - return Modifier.isVolatile(field.accessFlags()); - } - - private static long resolveOffset(ResolvedJavaField field) { - return ((HotSpotResolvedJavaField) field).offset(); - } - - private static Object resolveBase(Object base, ResolvedJavaField field) { - Object accessorBase = base; - if (accessorBase == null) { - accessorBase = field.holder().toJava(); - } - return accessorBase; - } - - private static Unsafe loadUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - private static final VMAdapter instance = new VMAdapter(); - public static VMAdapter getInstance() { - return instance; - } - - -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeDisassembler.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 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.java; + +import static com.oracle.graal.bytecode.Bytecodes.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.bytecode.*; + +/** + * Utility for producing a {@code javap}-like disassembly of bytecode. + */ +public class BytecodeDisassembler { + + /** + * Specifies if the disassembly for a single instruction can span multiple lines. + */ + private final boolean multiline; + + public BytecodeDisassembler(boolean multiline) { + this.multiline = multiline; + } + + public BytecodeDisassembler() { + this(true); + } + + /** + * Disassembles the bytecode of a given method in a {@code javap}-like format. + * + * @return {@code null} if {@code method} has no bytecode (e.g., it is native or abstract) + */ + public String disassemble(ResolvedJavaMethod method) { + if (method.code() == null) { + return null; + } + ConstantPool cp = method.getConstantPool(); + BytecodeStream stream = new BytecodeStream(method.code()); + StringBuilder buf = new StringBuilder(); + int opcode = stream.currentBC(); + while (opcode != Bytecodes.END) { + int bci = stream.currentBCI(); + String mnemonic = Bytecodes.nameOf(opcode); + buf.append(String.format("%4d: %-14s", bci, mnemonic)); + if (stream.nextBCI() > bci + 1) { + switch (opcode) { + case BIPUSH : buf.append(stream.readByte()); break; + case SIPUSH : buf.append(stream.readShort()); break; + case NEW : + case CHECKCAST : + case INSTANCEOF : + case ANEWARRAY : { + int cpi = stream.readCPI(); + JavaType type = cp.lookupType(cpi, opcode); + buf.append(String.format("#%-10d // %s", cpi, MetaUtil.toJavaName(type))); + break; + } + case GETSTATIC : + case PUTSTATIC : + case GETFIELD : + case PUTFIELD : { + int cpi = stream.readCPI(); + JavaField field = cp.lookupField(cpi, opcode); + String fieldDesc = field.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:%T", field) : MetaUtil.format("%H.%n:%T", field); + buf.append(String.format("#%-10d // %s", cpi, fieldDesc)); + break; + } + case INVOKEVIRTUAL : + case INVOKESPECIAL : + case INVOKESTATIC : { + int cpi = stream.readCPI(); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + String calleeDesc = callee.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee); + buf.append(String.format("#%-10d // %s", cpi, calleeDesc)); + break; + } + case INVOKEINTERFACE: { + int cpi = stream.readCPI(); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + String calleeDesc = callee.holder().name().equals(method.holder().name()) ? MetaUtil.format("%n:(%P)%R", callee) : MetaUtil.format("%H.%n:(%P)%R", callee); + buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), calleeDesc)); + break; + } + case LDC : + case LDC_W : + case LDC2_W : { + int cpi = stream.readCPI(); + Object constant = cp.lookupConstant(cpi); + String desc = null; + if (constant instanceof Constant) { + Constant c = ((Constant) constant); + switch (c.kind) { + case Int : + desc = String.valueOf(c.asInt()); + break; + case Float: + desc = String.valueOf(c.asFloat()); + break; + case Object: + desc = Kind.Object.format(c.asObject()); + break; + case Double : + desc = String.valueOf(c.asDouble()); + break; + case Long : + desc = String.valueOf(c.asLong()); + break; + default: + desc = c.toString(); + break; + } + } else { + desc = constant.toString(); + } + if (!multiline) { + desc.replaceAll("\\n", ""); + } + buf.append(String.format("#%-10d // %s", cpi, desc)); + break; + } + case RET : + case ILOAD : + case LLOAD : + case FLOAD : + case DLOAD : + case ALOAD : + case ISTORE : + case LSTORE : + case FSTORE : + case DSTORE : + case ASTORE : { + buf.append(String.format("%d", stream.readLocalIndex())); + break; + } + case IFEQ : + case IFNE : + case IFLT : + case IFGE : + case IFGT : + case IFLE : + case IF_ICMPEQ : + case IF_ICMPNE : + case IF_ICMPLT : + case IF_ICMPGE : + case IF_ICMPGT : + case IF_ICMPLE : + case IF_ACMPEQ : + case IF_ACMPNE : + case GOTO : + case JSR : + case IFNULL : + case IFNONNULL : + case GOTO_W : + case JSR_W : { + buf.append(String.format("%d", stream.readBranchDest())); + break; + } + case LOOKUPSWITCH : + case TABLESWITCH : { + BytecodeSwitch bswitch = opcode == LOOKUPSWITCH ? new BytecodeLookupSwitch(stream, bci) : new BytecodeTableSwitch(stream, bci); + if (multiline) { + buf.append("{ // " + bswitch.numberOfCases()); + for (int i = 0; i < bswitch.numberOfCases(); i++) { + buf.append(String.format("%n %7d: %d", bswitch.keyAt(i), bswitch.targetAt(i))); + } + buf.append(String.format("%n default: %d", bswitch.defaultTarget())); + buf.append(String.format("%n }")); + } else { + buf.append("[" + bswitch.numberOfCases()).append("] {"); + for (int i = 0; i < bswitch.numberOfCases(); i++) { + buf.append(String.format("%d: %d", bswitch.keyAt(i), bswitch.targetAt(i))); + if (i != bswitch.numberOfCases() - 1) { + buf.append(", "); + } + } + buf.append(String.format("} default: %d", bswitch.defaultTarget())); + } + break; + } + case NEWARRAY : { + int code = stream.readLocalIndex(); + // Checkstyle: stop + switch (code) { + case 4: buf.append("boolean"); break; + case 5: buf.append("char"); break; + case 6: buf.append("float"); break; + case 7: buf.append("double"); break; + case 8: buf.append("byte"); break; + case 9: buf.append("short"); break; + case 10: buf.append("int"); break; + case 11: buf.append("long"); break; + } + // Checkstyle: resume + + break; + } + case MULTIANEWARRAY : { + int cpi = stream.readCPI(); + JavaType type = cp.lookupType(cpi, opcode); + buf.append(String.format("#%-10s // %s", cpi + ", " + stream.readUByte(bci + 3), MetaUtil.toJavaName(type))); + break; + } + } + } + buf.append(String.format("%n")); + stream.next(); + opcode = stream.currentBC(); + } + return buf.toString(); + } +}
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -30,8 +30,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.meta.JavaType.*; -import com.oracle.graal.api.meta.JavaTypeProfile.*; +import com.oracle.graal.api.meta.JavaType.Representation; +import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.phases.*; @@ -649,7 +649,7 @@ ResolvedJavaType resolvedType = (ResolvedJavaType) type; ConstantNode hub = appendConstant(resolvedType.getEncoding(JavaType.Representation.ObjectHub)); InstanceOfNode instanceOfNode = new InstanceOfNode(hub, (ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); - frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode), currentGraph))); + frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode)))); } else { BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved, graphId)); @@ -693,10 +693,10 @@ // Checkstyle: resume } - private void genNewTypeArray(int typeCode) { + private void genNewPrimitiveArray(int typeCode) { Kind kind = arrayTypeCodeToKind(typeCode); ResolvedJavaType elementType = runtime.getResolvedJavaType(kind); - NewTypeArrayNode nta = currentGraph.add(new NewTypeArrayNode(frameState.ipop(), elementType)); + NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(frameState.ipop(), elementType)); frameState.apush(append(nta)); } @@ -965,7 +965,11 @@ return; } - MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, targetMethod.signature().returnType(method.holder()))); + JavaType returnType = targetMethod.signature().returnType(method.holder()); + if (graphBuilderConfig.eagerResolvingForSnippets()) { + returnType = returnType.resolve(targetMethod.holder()); + } + MethodCallTargetNode callTarget = currentGraph.add(new MethodCallTargetNode(invokeKind, targetMethod, args, returnType)); // be conservative if information was not recorded (could result in endless recompiles otherwise) if (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == ExceptionSeen.FALSE) { ValueNode result = appendWithBCI(currentGraph.add(new InvokeNode(callTarget, bci(), graphId))); @@ -1705,7 +1709,7 @@ case INVOKESTATIC : cpi = stream.readCPI(); genInvokeStatic(lookupMethod(cpi, opcode)); break; case INVOKEINTERFACE: cpi = stream.readCPI(); genInvokeInterface(lookupMethod(cpi, opcode)); break; case NEW : genNewInstance(stream.readCPI()); break; - case NEWARRAY : genNewTypeArray(stream.readLocalIndex()); break; + case NEWARRAY : genNewPrimitiveArray(stream.readLocalIndex()); break; case ANEWARRAY : genNewObjectArray(stream.readCPI()); break; case ARRAYLENGTH : genArrayLength(); break; case ATHROW : genThrow(); break;
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy01.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy01.java Thu Jul 05 16:54:45 2012 +0200 @@ -31,6 +31,10 @@ public static Object[] src = new Object[]{null, null}; public static Object[] dest = new Object[]{null, null}; + static { + // Ensure System is resolved + System.arraycopy(src, 0, src, 0, src.length); + } public static int test(int srcPos, int destPos, int length) { System.arraycopy(src, srcPos, dest, destPos, length);
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java Thu Jul 05 16:54:45 2012 +0200 @@ -32,6 +32,10 @@ public static int[] src = new int[]{0, 1, 2, 3, 4, 5}; public static int[] dest0 = new int[]{5, 4, 3, 2, 1, 0}; public static int[] dest = new int[]{5, 4, 3, 2, 1, 0}; + static { + // Ensure System is resolved + System.arraycopy(src, 0, src, 0, src.length); + } @Before public void setUp() {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java Thu Jul 05 16:54:45 2012 +0200 @@ -32,6 +32,10 @@ public static byte[] src = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; public static byte[] dest0 = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; public static byte[] dest = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + static { + // Ensure System is resolved + System.arraycopy(src, 0, src, 0, src.length); + } @Before public void setUp() {
--- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy04.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy04.java Thu Jul 05 16:54:45 2012 +0200 @@ -31,6 +31,10 @@ public static byte[] array = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; public static byte[] array0 = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + static { + // Ensure System is resolved + System.arraycopy(array, 0, array, 0, array.length); + } @Before public void setUp() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy05.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2011, 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.jtt.optimize; + +import org.junit.*; + +/* + * Tests calls to the array copy method. + */ +public class ArrayCopy05 { + + public static char[] array = new char[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + public static char[] array0 = new char[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + static { + // Ensure System is resolved + System.arraycopy(array, 0, array, 0, array.length); + } + + @Before + public void setUp() { + System.currentTimeMillis(); + for (int i = 0; i < array.length; i++) { + array[i] = array0[i]; + } + } + + public static char[] test(int srcPos, int destPos, int length) { + System.arraycopy(array, srcPos, array, destPos, length); + return array; + } + + @Test + public void run0() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 0)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run1() throws Throwable { + test(0, 0, -1); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run2() throws Throwable { + test(-1, 0, 0); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run3() throws Throwable { + test(0, -1, 0); + } + + @Test + public void run4() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 2)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run5() throws Throwable { + test(0, 1, 11); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run6() throws Throwable { + test(1, 0, 11); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run7() throws Throwable { + test(1, 1, -1); + } + + @Test + public void run8() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 1, 2)); + } + + @Test + public void run9() throws Throwable { + Assert.assertArrayEquals(new char[] {1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 0, 2)); + } + + @Test + public void run10() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 2)); + } + + @Test + public void run11() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 6)); + } + + @Test + public void run12() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10}, test(0, 1, 5)); + } + + @Test + public void run13() throws Throwable { + Assert.assertArrayEquals(new char[] {1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10}, test(1, 0, 5)); + } + + @Test + public void run14() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 5)); + } + + @Test + public void run15() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 11)); + } + + @Test + public void run16() throws Throwable { + Assert.assertArrayEquals(new char[] {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, test(0, 1, 10)); + } + + @Test + public void run17() throws Throwable { + Assert.assertArrayEquals(new char[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10}, test(1, 0, 10)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy06.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2011, 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.jtt.optimize; + +import org.junit.*; + +/* + * Tests calls to the array copy method. + */ +public class ArrayCopy06 { + + public static short[] array = new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + public static short[] array0 = new short[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + static { + // Ensure System is resolved + System.arraycopy(array, 0, array, 0, array.length); + } + + @Before + public void setUp() { + System.currentTimeMillis(); + for (int i = 0; i < array.length; i++) { + array[i] = array0[i]; + } + } + + public static short[] test(int srcPos, int destPos, int length) { + System.arraycopy(array, srcPos, array, destPos, length); + return array; + } + + @Test + public void run0() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 0)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run1() throws Throwable { + test(0, 0, -1); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run2() throws Throwable { + test(-1, 0, 0); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run3() throws Throwable { + test(0, -1, 0); + } + + @Test + public void run4() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 2)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run5() throws Throwable { + test(0, 1, 11); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run6() throws Throwable { + test(1, 0, 11); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run7() throws Throwable { + test(1, 1, -1); + } + + @Test + public void run8() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 1, 2)); + } + + @Test + public void run9() throws Throwable { + Assert.assertArrayEquals(new short[] {1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 0, 2)); + } + + @Test + public void run10() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 2)); + } + + @Test + public void run11() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 6)); + } + + @Test + public void run12() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10}, test(0, 1, 5)); + } + + @Test + public void run13() throws Throwable { + Assert.assertArrayEquals(new short[] {1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10}, test(1, 0, 5)); + } + + @Test + public void run14() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(1, 1, 5)); + } + + @Test + public void run15() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 11)); + } + + @Test + public void run16() throws Throwable { + Assert.assertArrayEquals(new short[] {0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, test(0, 1, 10)); + } + + @Test + public void run17() throws Throwable { + Assert.assertArrayEquals(new short[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10}, test(1, 0, 10)); + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -146,7 +146,7 @@ return; } if (trueValue.isConstant() && falseValue.isConstant()) { - MaterializeNode materialize = MaterializeNode.create(compare(), graph(), trueValue, falseValue); + MaterializeNode materialize = MaterializeNode.create(compare(), trueValue, falseValue); ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize); removeEmptyIf(tool); return;
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -27,18 +27,59 @@ public final class MaterializeNode extends ConditionalNode { + private static CompareNode createCompareNode(Condition condition, ValueNode x, ValueNode y) { + assert x.kind() == y.kind(); + assert condition.isCanonical() : "condition is not canonical: " + condition; + + assert !x.kind().isFloatOrDouble(); + CompareNode comparison; + if (condition == Condition.EQ) { + if (x.kind().isObject()) { + comparison = new ObjectEqualsNode(x, y); + } else { + assert x.kind().stackKind().isInt() || x.kind().isLong(); + comparison = new IntegerEqualsNode(x, y); + } + } else if (condition == Condition.LT) { + assert x.kind().stackKind().isInt() || x.kind().isLong(); + comparison = new IntegerLessThanNode(x, y); + } else { + assert condition == Condition.BT; + assert x.kind().stackKind().isInt() || x.kind().isLong(); + comparison = new IntegerBelowThanNode(x, y); + } + + return x.graph().unique(comparison); + } + + private MaterializeNode(Condition condition, ValueNode x, ValueNode y) { + this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph())); + } + private MaterializeNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) { super(condition, trueValue, falseValue); } - public static MaterializeNode create(BooleanNode condition, Graph graph, ValueNode trueValue, ValueNode falseValue) { + public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) { + Graph graph = condition.graph(); MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue); return graph.unique(result); } - public static MaterializeNode create(BooleanNode condition, Graph graph) { - return create(condition, graph, ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph)); + public static MaterializeNode create(BooleanNode condition) { + return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph())); } + @NodeIntrinsic + @SuppressWarnings("unused") + public static boolean materialize(@ConstantNodeParameter Condition condition, int x, int y) { + throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); + } + + @NodeIntrinsic + @SuppressWarnings("unused") + public static boolean materialize(@ConstantNodeParameter Condition condition, long x, long y) { + throw new UnsupportedOperationException("This method may only be compiled with the Graal compiler"); + } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -158,17 +158,17 @@ public final ObjectStamp objectStamp() { assert verifyStamp(ObjectStamp.class); - return (ObjectStamp) stamp; + return (ObjectStamp) stamp(); } public final IntegerStamp integerStamp() { assert verifyStamp(IntegerStamp.class); - return (IntegerStamp) stamp; + return (IntegerStamp) stamp(); } public final FloatStamp floatStamp() { assert verifyStamp(FloatStamp.class); - return (FloatStamp) stamp; + return (FloatStamp) stamp(); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -80,7 +79,7 @@ } - private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, CodeCacheProvider runtime, Condition cond) { + private ValueNode optimizeConditional(Constant constant, ConditionalNode conditionalNode, MetaAccessProvider runtime, Condition cond) { Constant trueConstant = conditionalNode.trueValue().asConstant(); Constant falseConstant = conditionalNode.falseValue().asConstant();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -58,8 +58,8 @@ lessComp = graph.unique(new IntegerLessThanNode(x(), y())); } - MaterializeNode equalValue = MaterializeNode.create(equalComp, graph, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)); - MaterializeNode value = MaterializeNode.create(lessComp, graph, ConstantNode.forInt(-1, graph), equalValue); + MaterializeNode equalValue = MaterializeNode.create(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)); + MaterializeNode value = MaterializeNode.create(lessComp, ConstantNode.forInt(-1, graph), equalValue); graph.replaceFloating(this, value); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/BoxingMethodPool.java Thu Jul 05 16:54:45 2012 +0200 @@ -24,18 +24,17 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; public class BoxingMethodPool { private final Set<JavaMethod> specialMethods = new HashSet<>(); - private final CodeCacheProvider runtime; + private final MetaAccessProvider runtime; private final ResolvedJavaMethod[] boxingMethods = new ResolvedJavaMethod[Kind.values().length]; private final ResolvedJavaMethod[] unboxingMethods = new ResolvedJavaMethod[Kind.values().length]; private final ResolvedJavaField[] boxFields = new ResolvedJavaField[Kind.values().length]; - public BoxingMethodPool(CodeCacheProvider runtime) { + public BoxingMethodPool(MetaAccessProvider runtime) { this.runtime = runtime; initialize(); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -60,7 +59,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - CodeCacheProvider runtime = tool.runtime(); + MetaAccessProvider runtime = tool.runtime(); if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) { if (this.location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) { Object value = object().asConstant().asObject();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadHubNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.JavaType.*; import com.oracle.graal.nodes.*; @@ -49,7 +48,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - CodeCacheProvider runtime = tool.runtime(); + MetaAccessProvider runtime = tool.runtime(); if (runtime != null) { ObjectStamp stamp = object.objectStamp();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -43,7 +42,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - CodeCacheProvider runtime = tool.runtime(); + MetaAccessProvider runtime = tool.runtime(); if (runtime != null && object() != null && object().isConstant() && object().kind() == Kind.Object) { if (location() == LocationNode.FINAL_LOCATION && location().getClass() == LocationNode.class) { Object value = object().asConstant().asObject();
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ArrayLengthNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -51,7 +50,7 @@ assert length != null; return length; } - CodeCacheProvider runtime = tool.runtime(); + MetaAccessProvider runtime = tool.runtime(); if (runtime != null && array().isConstant() && !array().isNullConstant()) { Constant constantValue = array().asConstant(); if (constantValue != null && constantValue.isNonNull()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadFieldNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes.java; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -55,7 +54,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - CodeCacheProvider runtime = tool.runtime(); + MetaAccessProvider runtime = tool.runtime(); if (runtime != null) { Constant constant = null; if (isStatic()) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -24,7 +24,6 @@ import java.lang.reflect.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; @@ -61,7 +60,7 @@ @Override public ValueNode canonical(CanonicalizerTool tool) { - CodeCacheProvider runtime = tool.runtime(); + MetaAccessProvider runtime = tool.runtime(); if (runtime != null && index().isConstant() && array().isConstant() && !array().isNullConstant()) { Constant arrayConst = array().asConstant(); if (tool.isImmutable(arrayConst)) {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -36,7 +36,7 @@ /** * The {@code NewArrayNode} class is the base of all instructions that allocate arrays. */ -public abstract class NewArrayNode extends FixedWithNextNode implements EscapeAnalyzable, TypeFeedbackProvider { +public abstract class NewArrayNode extends FixedWithNextNode implements Lowerable, EscapeAnalyzable, TypeFeedbackProvider { @Input private ValueNode length; @@ -86,6 +86,11 @@ return ESCAPE; } + @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + private static final EscapeOp ESCAPE = new EscapeOp() { @Override
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 2011, 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.nodes.java; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * The {@code NewPrimitiveArrayNode} class definition. + */ +public final class NewPrimitiveArrayNode extends NewArrayNode implements LIRLowerable { + + private final ResolvedJavaType elementType; + + public NewPrimitiveArrayNode(ValueNode length, ResolvedJavaType elementType) { + super(StampFactory.exactNonNull(elementType.arrayOf()), length); + this.elementType = elementType; + } + + @Override + public ResolvedJavaType elementType() { + return elementType; + } + + @Override + public void generate(LIRGeneratorTool gen) { + gen.visitNewPrimitiveArray(this); + } +}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewTypeArrayNode.java Thu Jul 05 16:54:00 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2009, 2011, 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.nodes.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * The {@code NewTypeArrayNode} class definition. - */ -public final class NewTypeArrayNode extends NewArrayNode implements LIRLowerable { - - private final ResolvedJavaType elementType; - - public NewTypeArrayNode(ValueNode length, ResolvedJavaType elementType) { - super(StampFactory.exactNonNull(elementType.arrayOf()), length); - this.elementType = elementType; - } - - @Override - public ResolvedJavaType elementType() { - return elementType; - } - - @Override - public void generate(LIRGeneratorTool gen) { - gen.visitNewTypeArray(this); - } -}
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/CanonicalizerTool.java Thu Jul 05 16:54:45 2012 +0200 @@ -29,7 +29,7 @@ public interface CanonicalizerTool { TargetDescription target(); Assumptions assumptions(); - CodeCacheProvider runtime(); + MetaAccessProvider runtime(); /** * Determines if a given constant is an object/array whose current
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Thu Jul 05 16:54:45 2012 +0200 @@ -112,7 +112,7 @@ public abstract void visitMonitorEnter(MonitorEnterNode i); public abstract void visitMonitorExit(MonitorExitNode i); public abstract void visitNewInstance(NewInstanceNode i); - public abstract void visitNewTypeArray(NewTypeArrayNode i); + public abstract void visitNewPrimitiveArray(NewPrimitiveArrayNode i); public abstract void visitNewObjectArray(NewObjectArrayNode i); public abstract void visitNewMultiArray(NewMultiArrayNode i); public abstract void visitExceptionObject(ExceptionObjectNode i);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BasicIdealGraphPrinter.java Thu Jul 05 16:54:45 2012 +0200 @@ -134,6 +134,12 @@ stream.println(" ]]></bytecodes>"); } + protected void printBytecodes(String disassembly) { + beginBytecodes(); + stream.println(disassembly); + endBytecodes(); + } + protected void endMethod() { stream.println(" </method>"); }
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Thu Jul 05 16:54:45 2012 +0200 @@ -24,6 +24,7 @@ import java.io.*; import java.util.*; +import java.util.concurrent.atomic.*; import com.oracle.graal.alloc.util.*; import com.oracle.graal.api.code.*; @@ -46,6 +47,7 @@ public class CFGPrinterObserver implements DebugDumpHandler { private CFGPrinter cfgPrinter; + private File cfgFile; private ResolvedJavaMethod curMethod; private List<String> curDecorators = Collections.emptyList(); @@ -63,7 +65,7 @@ * in the current debug scope and opens a new compilation scope if this pair * does not match the current method and decorator pair. */ - private void checkMethodScope() { + private boolean checkMethodScope() { ResolvedJavaMethod method = null; ArrayList<String> decorators = new ArrayList<>(); for (Object o : Debug.context()) { @@ -83,14 +85,22 @@ } } + if (method == null) { + return false; + } + if (method != curMethod || !curDecorators.equals(decorators)) { cfgPrinter.printCompilation(method); - TTY.println("CFGPrinter: Dumping method %s", method); + TTY.println("CFGPrinter: Dumping method %s to %s", method, cfgFile); curMethod = method; curDecorators = decorators; } + return true; } + private static final long timestamp = System.currentTimeMillis(); + private static final AtomicInteger uniqueId = new AtomicInteger(); + public void dumpSandboxed(Object object, String message) { GraalCompiler compiler = Debug.contextLookup(GraalCompiler.class); if (compiler == null) { @@ -98,17 +108,19 @@ } if (cfgPrinter == null) { - File file = new File("compilations-" + System.currentTimeMillis() + ".cfg"); + cfgFile = new File("compilations-" + timestamp + "_" + uniqueId.incrementAndGet() + ".cfg"); try { - OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); + OutputStream out = new BufferedOutputStream(new FileOutputStream(cfgFile)); cfgPrinter = new CFGPrinter(out); } catch (FileNotFoundException e) { - throw new GraalInternalError("Could not open " + file.getAbsolutePath()); + throw new GraalInternalError("Could not open " + cfgFile.getAbsolutePath()); } - TTY.println("CFGPrinter: Output to file %s", file); + TTY.println("CFGPrinter: Output to file %s", cfgFile); } - checkMethodScope(); + if (!checkMethodScope()) { + return; + } cfgPrinter.target = compiler.target; if (object instanceof LIR) { @@ -126,7 +138,9 @@ if (object instanceof BciBlockMapping) { BciBlockMapping blockMap = (BciBlockMapping) object; cfgPrinter.printCFG(message, blockMap); - cfgPrinter.printBytecodes(runtime.disassemble(blockMap.method)); + if (blockMap.method.code() != null) { + cfgPrinter.printBytecodes(new BytecodeDisassembler(false).disassemble(blockMap.method)); + } } else if (object instanceof LIR) { cfgPrinter.printCFG(message, cfgPrinter.lir.codeEmittingOrder());
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java Thu Jul 05 16:54:45 2012 +0200 @@ -27,12 +27,12 @@ import java.util.Map.Entry; import com.oracle.graal.api.meta.*; -import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.schedule.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.NodeClass.Position; +import com.oracle.graal.java.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; @@ -57,23 +57,8 @@ printProperty("name", name); endProperties(); beginMethod(name, shortName, bci); - if (method != null) { - beginBytecodes(); - BytecodeStream bytecodes = new BytecodeStream(method.code()); - while (bytecodes.currentBC() != Bytecodes.END) { - int startBCI = bytecodes.currentBCI(); - String mnemonic = Bytecodes.nameOf(bytecodes.currentBC()); - int[] extra = null; - if (bytecodes.nextBCI() > startBCI + 1) { - extra = new int[bytecodes.nextBCI() - (startBCI + 1)]; - for (int i = 0; i < extra.length; i++) { - extra[i] = bytecodes.readUByte(startBCI + 1 + i); - } - } - printBytecode(startBCI, mnemonic, extra); - bytecodes.next(); - } - endBytecodes(); + if (method != null && method.code() != null) { + printBytecodes(new BytecodeDisassembler(false).disassemble(method)); } endMethod(); }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Thu Jul 05 16:54:45 2012 +0200 @@ -58,11 +58,26 @@ boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller); /** - * The default inlining policy which inlines everything except for - * constructors of {@link Throwable} classes. + * The default inlining policy which inlines everything except for methods + * in any of the following categories. + * <ul> + * <li>{@linkplain Fold foldable} methods</li> + * <li>{@linkplain NodeIntrinsic node intrinsics}</li> + * <li>native methods</li> + * <li>constructors of {@link Throwable} classes</li> + * </ul> */ InliningPolicy Default = new InliningPolicy() { public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { + if (Modifier.isNative(method.accessFlags())) { + return false; + } + if (method.getAnnotation(Fold.class) != null) { + return false; + } + if (method.getAnnotation(NodeIntrinsic.class) != null) { + return false; + } if (Throwable.class.isAssignableFrom(method.holder().toJava())) { if (method.name().equals("<init>")) { return false;
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Thu Jul 05 16:54:45 2012 +0200 @@ -37,7 +37,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.snippets.Snippet.InliningPolicy; /** @@ -45,7 +44,7 @@ */ public class SnippetInstaller { - private final GraalCodeCacheProvider runtime; + private final MetaAccessProvider runtime; private final TargetDescription target; private final BoxingMethodPool pool; @@ -57,7 +56,7 @@ */ private final Map<ResolvedJavaMethod, StructuredGraph> graphCache; - public SnippetInstaller(GraalCodeCacheProvider runtime, TargetDescription target) { + public SnippetInstaller(MetaAccessProvider runtime, TargetDescription target) { this.runtime = runtime; this.target = target; this.pool = new BoxingMethodPool(runtime); @@ -137,6 +136,8 @@ public StructuredGraph makeGraph(final ResolvedJavaMethod method, final InliningPolicy policy) { StructuredGraph graph = parseGraph(method, policy); + new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); + Debug.dump(graph, "%s: Final", method.name()); return graph; @@ -165,7 +166,7 @@ new SnippetVerificationPhase().apply(graph); - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.callTarget(); @@ -181,7 +182,7 @@ } } - new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); new WordTypeRewriterPhase(target.wordKind, runtime.getResolvedJavaType(target.wordKind)).apply(graph);
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -25,7 +25,6 @@ import java.lang.reflect.*; import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.graph.*; @@ -39,18 +38,41 @@ public class SnippetIntrinsificationPhase extends Phase { - private final CodeCacheProvider runtime; + private final MetaAccessProvider runtime; private final BoxingMethodPool pool; + private final boolean intrinsificationOrFoldingCanBeDeferred; - public SnippetIntrinsificationPhase(CodeCacheProvider runtime, BoxingMethodPool pool) { + /** + * @param intrinsificationOrFoldingCanBeDeferred if true, then {@link NonConstantParameterError}s are not fatal + */ + public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool, boolean intrinsificationOrFoldingCanBeDeferred) { this.runtime = runtime; this.pool = pool; + this.intrinsificationOrFoldingCanBeDeferred = intrinsificationOrFoldingCanBeDeferred; } @Override protected void run(StructuredGraph graph) { for (Invoke i : graph.getInvokes()) { - tryIntrinsify(i); + try { + tryIntrinsify(i); + } catch (NonConstantParameterError t) { + if (!intrinsificationOrFoldingCanBeDeferred) { + throw t; + } + } + } + } + + /** + * Exception raised when an argument to a {@linkplain Fold foldable} or + * {@link NodeIntrinsic} method is not a constant. + */ + @SuppressWarnings("serial") + public static class NonConstantParameterError extends Error { + + public NonConstantParameterError(String message) { + super(message); } } @@ -119,7 +141,9 @@ } ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i)); if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { - assert argument instanceof ConstantNode : "parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument; + if (!(argument instanceof ConstantNode)) { + throw new NonConstantParameterError("parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.callTarget().targetMethod() + " at " + sourceLocation(invoke.node()) + ": " + argument); + } ConstantNode constantNode = (ConstantNode) argument; Constant constant = constantNode.asConstant(); Object o = constant.boxedValue();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Thu Jul 05 16:54:45 2012 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -175,6 +176,18 @@ } /** + * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. + */ + public static boolean hasConstantParameter(ResolvedJavaMethod method) { + for (ConstantParameter p : MetaUtil.getParameterAnnotations(ConstantParameter.class, method)) { + if (p != null) { + return true; + } + } + return false; + } + + /** * Creates a snippet template. */ public SnippetTemplate(CodeCacheProvider runtime, SnippetTemplate.Key key) { @@ -182,7 +195,7 @@ assert Modifier.isStatic(method.accessFlags()) : "snippet method must be static: " + method; Signature signature = method.signature(); - // Copy snippet graph, replacing @Constant parameters with given arguments + // Copy snippet graph, replacing constant parameters with given arguments StructuredGraph snippetGraph = (StructuredGraph) method.compilerStorage().get(Graph.class); StructuredGraph snippetCopy = new StructuredGraph(snippetGraph.name, snippetGraph.method()); IdentityHashMap<Node, Node> replacements = new IdentityHashMap<>(); @@ -201,7 +214,8 @@ replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy)); } else { Parameter p = MetaUtil.getParameterAnnotation(Parameter.class, i, method); - assert p != null : method + ": parameter " + i + " must be annotated with either @Constant or @Parameter"; + assert p != null : method + ": parameter " + i + " must be annotated with either @" + ConstantParameter.class.getSimpleName() + + " or @" + Parameter.class.getSimpleName(); String name = p.value(); if (p.multiple()) { Object multiple = key.get(name); @@ -219,6 +233,9 @@ Debug.dump(snippetCopy, "Before specialization"); if (!replacements.isEmpty()) { + // Do deferred intrinsification of node intrinsics + new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); + new CanonicalizerPhase(null, runtime, null, 0, null).apply(snippetCopy); } @@ -386,6 +403,7 @@ replacements.put((LocalNode) parameter, (ValueNode) argument); } else { Kind kind = ((LocalNode) parameter).kind(); + assert argument != null || kind.isObject() : this + " cannot accept null for non-object parameter named " + name; Constant constant = Constant.forBoxed(kind, argument); replacements.put((LocalNode) parameter, ConstantNode.forConstant(constant, runtime, replaceeGraph)); } @@ -478,10 +496,10 @@ sep = ", "; if (value instanceof LocalNode) { LocalNode local = (LocalNode) value; - buf.append(local.kind().name()).append(' ').append(name); + buf.append(local.kind().javaName).append(' ').append(name); } else { LocalNode[] locals = (LocalNode[]) value; - String kind = locals.length == 0 ? "?" : locals[0].kind().name(); + String kind = locals.length == 0 ? "?" : locals[0].kind().javaName; buf.append(kind).append('[').append(locals.length).append("] ").append(name); } }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetVerificationPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.snippets.Word.*; @@ -87,6 +88,11 @@ argc++; } } + } else if (usage instanceof ObjectEqualsNode) { + ObjectEqualsNode compare = (ObjectEqualsNode) usage; + if (compare.x() == node || compare.y() == node) { + verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and now-word type in use of '==' or '!='"); + } } else if (usage instanceof ArrayLengthNode) { verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value"); } else if (usage instanceof PhiNode) {
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Thu Jul 05 16:54:45 2012 +0200 @@ -68,6 +68,17 @@ } } + // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are words + for (ObjectEqualsNode objectEqualsNode : graph.getNodes().filter(ObjectEqualsNode.class).snapshot()) { + ValueNode x = objectEqualsNode.x(); + ValueNode y = objectEqualsNode.y(); + if (x.kind() == wordKind || y.kind() == wordKind) { + assert x.kind() == wordKind; + assert y.kind() == wordKind; + graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); + } + } + for (MethodCallTargetNode callTargetNode : graph.getNodes(MethodCallTargetNode.class).snapshot()) { ResolvedJavaMethod targetMethod = callTargetNode.targetMethod(); Operation operation = targetMethod.getAnnotation(Word.Operation.class); @@ -188,7 +199,7 @@ ValueNode a = mirror ? right : left; ValueNode b = mirror ? left : right; - MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b)), graph); + MaterializeNode materialize = MaterializeNode.create(graph.unique(new IntegerBelowThanNode(a, b))); ValueNode op; if (condition.canonicalNegate()) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewArrayTest.java Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2011, 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.tests; + +import org.junit.*; + +/** + * Tests the implementation of {@code [A]NEWARRAY}. + */ +public class NewArrayTest extends GraalCompilerTest { + + @Override + protected void assertEquals(Object expected, Object actual) { + Assert.assertTrue(expected != null); + Assert.assertTrue(actual != null); + super.assertEquals(expected.getClass(), actual.getClass()); + if (expected instanceof int[]) { + Assert.assertArrayEquals((int[]) expected, (int[]) actual); + } else if (expected instanceof byte[]) { + Assert.assertArrayEquals((byte[]) expected, (byte[]) actual); + } else if (expected instanceof char[]) { + Assert.assertArrayEquals((char[]) expected, (char[]) actual); + } else if (expected instanceof short[]) { + Assert.assertArrayEquals((short[]) expected, (short[]) actual); + } else if (expected instanceof float[]) { + Assert.assertArrayEquals((float[]) expected, (float[]) actual, 0.0f); + } else if (expected instanceof long[]) { + Assert.assertArrayEquals((long[]) expected, (long[]) actual); + } else if (expected instanceof double[]) { + Assert.assertArrayEquals((double[]) expected, (double[]) actual, 0.0d); + } else if (expected instanceof Object[]) { + Assert.assertArrayEquals((Object[]) expected, (Object[]) actual); + } else { + Assert.fail("non-array value encountered: " + expected); + } + } + + @Test + public void test1() { + for (String type : new String[] {"Byte", "Char", "Short", "Int", "Float", "Long", "Double", "String"}) { + test("new" + type + "Array7"); + test("new" + type + "ArrayMinus7"); + test("new" + type + "Array", 7); + test("new" + type + "Array", -7); + test("new" + type + "Array", Integer.MAX_VALUE); + test("new" + type + "Array", Integer.MIN_VALUE); + } + } + + public static Object newCharArray7() { + return new char[7]; + } + + public static Object newCharArrayMinus7() { + return new char[-7]; + } + + public static Object newCharArray(int length) { + return new char[length]; + } + + public static Object newShortArray7() { + return new short[7]; + } + + public static Object newShortArrayMinus7() { + return new short[-7]; + } + + public static Object newShortArray(int length) { + return new short[length]; + } + + public static Object newFloatArray7() { + return new float[7]; + } + + public static Object newFloatArrayMinus7() { + return new float[-7]; + } + + public static Object newFloatArray(int length) { + return new float[length]; + } + + public static Object newLongArray7() { + return new long[7]; + } + + public static Object newLongArrayMinus7() { + return new long[-7]; + } + + public static Object newLongArray(int length) { + return new long[length]; + } + + public static Object newDoubleArray7() { + return new double[7]; + } + + public static Object newDoubleArrayMinus7() { + return new double[-7]; + } + + public static Object newDoubleArray(int length) { + return new double[length]; + } + + public static Object newIntArray7() { + return new int[7]; + } + + public static Object newIntArrayMinus7() { + return new int[-7]; + } + + public static Object newIntArray(int length) { + return new int[length]; + } + + public static Object newByteArray7() { + return new byte[7]; + } + + public static Object newByteArrayMinus7() { + return new byte[-7]; + } + + public static Object newByteArray(int length) { + return new byte[length]; + } + + public static Object newStringArray7() { + return new String[7]; + } + + public static Object newStringArrayMinus7() { + return new String[-7]; + } + + public static Object newStringArray(int length) { + return new String[length]; + } +}
--- a/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java Thu Jul 05 16:54:00 2012 +0200 +++ b/graal/com.oracle.max.criutils/src/com/oracle/max/criutils/UnsignedMath.java Thu Jul 05 16:54:45 2012 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.max.criutils; +//JaCoCo Exclude + /** * Utilities for unsigned comparisons. * All methods have correct, but slow, standard Java implementations so that
--- a/mx/commands.py Thu Jul 05 16:54:00 2012 +0200 +++ b/mx/commands.py Thu Jul 05 16:54:45 2012 +0200 @@ -587,7 +587,9 @@ # Exclude all compiler tests and snippets excludes = ['com.oracle.graal.compiler.tests.*'] for p in mx.projects(): - _find_classes_with_annotations(excludes, p, None, ['@Snippet', '@ClassSubstitution'], includeInnerClasses=True) + excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution'], includeInnerClasses=True) + excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True) + agentOptions = { 'append' : 'true' if _jacoco == 'append' else 'false', 'bootclasspath' : 'true', @@ -598,47 +600,15 @@ exe = join(jdk, 'bin', mx.exe_suffix('java')) return mx.run([exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) -def _find_classes_with_annotations(classes, p, pkgRoot, annotations, includeInnerClasses=False): +def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False): """ Scan the sources of project 'p' for Java source files containing a line starting with 'annotation' - (ignoring preceding whitespace) and add the fully qualified class name - to 'classes' for each Java source file matched. + (ignoring preceding whitespace) and return the fully qualified class name for each Java + source file matched in a list. """ - for a in annotations: - assert a.startswith('@') - pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$") - for srcDir in p.source_dirs(): - outputDir = p.output_dir() - for root, _, files in os.walk(srcDir): - for name in files: - if name.endswith('.java') and name != 'package-info.java': - annotationFound = False - with open(join(root, name)) as f: - pkg = None - for line in f: - if line.startswith("package "): - match = pkgDecl.match(line) - if match: - pkg = match.group(1) - else: - stripped = line.strip() - for a in annotations: - if stripped == a or stripped.startswith(a + '('): - annotationFound = True - break - if annotationFound: - break - if annotationFound: - basename = name[:-len('.java')] - assert pkg is not None - if pkgRoot is None or pkg.startswith(pkgRoot): - pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep)) - for e in os.listdir(pkgOutputDir): - if includeInnerClasses: - if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')): - classes.append(pkg + '.' + e[:-len('.class')]) - elif e == basename + '.class': - classes.append(pkg + '.' + basename) + + matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0 + return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses) def _run_tests(args, harnessName, harness): pos = [a for a in args if a[0] != '-' and a[0] != '@' ] @@ -653,8 +623,7 @@ for p in mx.projects(): if getattr(p, 'testHarness', None) == harnessName: - classes = [] - _find_classes_with_annotations(classes, p, None, ['@Test']) + classes = _find_classes_with_annotations(p, None, ['@Test']) if len(pos) != 0: classes = [c for c in classes if containsAny(c, pos)] @@ -739,7 +708,7 @@ parser = ArgumentParser(prog='mx gate'); parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code') - parser.add_argument('-n', '--omit-native-build', action='store_false', dest='buildNative', help='omit cleaning and building native code') + parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code') parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM') parser.add_argument('--jacocout', help='specify the output directory for jacoco report') @@ -755,7 +724,7 @@ t = Task('Clean') cleanArgs = [] - if not args.buildNative: + if not args.cleanNative: cleanArgs.append('--no-native') if not args.cleanJava: cleanArgs.append('--no-java') @@ -768,10 +737,9 @@ for vmbuild in ['fastdebug', 'product']: _vmbuild = vmbuild - if args.buildNative: - t = Task('BuildHotSpotGraal:' + vmbuild) - buildvms(['--vms', 'graal', '--builds', vmbuild]) - tasks.append(t.stop()) + t = Task('BuildHotSpotGraal:' + vmbuild) + buildvms(['--vms', 'graal', '--builds', vmbuild]) + tasks.append(t.stop()) t = Task('BootstrapWithSystemAssertions:' + vmbuild) vm(['-esa', '-version']) @@ -823,7 +791,7 @@ tasks.append(t.stop()) # Prevent Graal modifications from breaking the standard builds - if args.buildNative and args.buildNonGraal: + if args.buildNonGraal: t = Task('BuildHotSpotVarieties') buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product']) tasks.append(t.stop())
--- a/mxtool/mx.py Thu Jul 05 16:54:00 2012 +0200 +++ b/mxtool/mx.py Thu Jul 05 16:54:45 2012 +0200 @@ -261,6 +261,46 @@ if not self.native: cp.append(self.output_dir()) + def find_classes_with_matching_source_line(self, pkgRoot, function, includeInnerClasses=False): + """ + Scan the sources of this project for Java source files containing a line for which + 'function' returns true. The fully qualified class name of each existing class + corresponding to a matched source file is returned in a list. + """ + classes = [] + pkgDecl = re.compile(r"^package\s+([a-zA-Z_][\w\.]*)\s*;$") + for srcDir in self.source_dirs(): + outputDir = self.output_dir() + for root, _, files in os.walk(srcDir): + for name in files: + if name.endswith('.java') and name != 'package-info.java': + matchFound = False + with open(join(root, name)) as f: + pkg = None + for line in f: + if line.startswith("package "): + match = pkgDecl.match(line) + if match: + pkg = match.group(1) + if function(line.strip()): + matchFound = True + if pkg and matchFound: + break + + if matchFound: + basename = name[:-len('.java')] + assert pkg is not None + if pkgRoot is None or pkg.startswith(pkgRoot): + pkgOutputDir = join(outputDir, pkg.replace('.', os.path.sep)) + for e in os.listdir(pkgOutputDir): + if includeInnerClasses: + if e.endswith('.class') and (e.startswith(basename) or e.startswith(basename + '$')): + classes.append(pkg + '.' + e[:-len('.class')]) + elif e == basename + '.class': + classes.append(pkg + '.' + basename) + return classes + + class Library(Dependency): def __init__(self, suite, name, path, mustExist, urls): Dependency.__init__(self, suite, name)
--- a/src/cpu/x86/vm/jniTypes_x86.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/cpu/x86/vm/jniTypes_x86.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -127,6 +127,12 @@ static inline oop get_obj (intptr_t *from) { return *(oop *) from; } static inline jfloat get_float (intptr_t *from) { return *(jfloat *) from; } static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); } + + static inline jint get_int (intptr_t *from, int& pos) { return get_int(from + pos++); } + static inline jlong get_long (intptr_t *from, int& pos) { return get_long(from + pos); pos += 2; } + static inline oop get_obj (intptr_t *from, int& pos) { return get_obj(from + pos++); } + static inline jfloat get_float (intptr_t *from, int& pos) { return get_float(from + pos++); } + static inline jdouble get_double(intptr_t *from, int& pos) { return get_double(from + pos); pos += 2; } #undef _JNI_SLOT_OFFSET };
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -1340,7 +1340,7 @@ methodOopDesc::invocation_counter_offset() + InvocationCounter::counter_offset()); const Address access_flags(rbx, methodOopDesc::access_flags_offset()); - + // get parameter size (always needed) __ load_unsigned_short(rcx, size_of_parameters);
--- a/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java Thu Jul 05 16:54:45 2012 +0200 @@ -49,7 +49,7 @@ public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) { super(Children.LEAF); - this.setDisplayName(bytecode.getBci() + " " + bytecode.getName()); + String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands(); bciValue = bytecode.getBci() + " " + bciValue; bciValue = bciValue.trim(); @@ -62,8 +62,14 @@ for (InputNode n : nodeList) { nodes.add(n); } - this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)"); + displayName += " (" + nodes.size() + " nodes)"; } + + if (bytecode.getComment() != null) { + displayName += " // " + bytecode.getComment(); + } + + this.setDisplayName(displayName); } @Override
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java Thu Jul 05 16:54:45 2012 +0200 @@ -31,11 +31,15 @@ private int bci; private String name; + private String operands; + private String comment; private InputMethod inlined; - public InputBytecode(int bci, String name) { + public InputBytecode(int bci, String name, String operands, String comment) { this.bci = bci; this.name = name; + this.operands = operands; + this.comment = comment; } public InputMethod getInlined() { @@ -53,4 +57,12 @@ public String getName() { return name; } + + public String getOperands() { + return operands; + } + + public String getComment() { + return comment; + } }
--- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Thu Jul 05 16:54:45 2012 +0200 @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @@ -109,31 +111,38 @@ } public void setBytecodes(String text) { - + Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?"); String[] strings = text.split("\n"); - int oldNumber = -1; + int oldBci = -1; for (String s : strings) { - - if (s.length() > 0 && Character.isDigit(s.charAt(0))) { - s = s.trim(); - int spaceIndex = s.indexOf(' '); - String numberString = s.substring(0, spaceIndex); - String tmpName = s.substring(spaceIndex + 1, s.length()); + s = s.trim(); + if (s.length() != 0) { + final Matcher matcher = instruction.matcher(s); + if (matcher.matches()) { + String bciString = matcher.group(1); + String opcode = matcher.group(2); + String operands = matcher.group(3).trim(); + String comment = matcher.group(4); + if (comment != null) { + comment = comment.trim(); + } - int number = -1; - number = Integer.parseInt(numberString); + int bci = Integer.parseInt(bciString); - // assert correct order of bytecodes - assert number > oldNumber; + // assert correct order of bytecodes + assert bci > oldBci; + + InputBytecode bc = new InputBytecode(bci, opcode, operands, comment); + bytecodes.add(bc); - InputBytecode bc = new InputBytecode(number, tmpName); - bytecodes.add(bc); - - for (InputMethod m : inlined) { - if (m.getBci() == number) { - bc.setInlined(m); - break; + for (InputMethod m : inlined) { + if (m.getBci() == bci) { + bc.setInlined(m); + break; + } } + } else { + System.out.println("no match: " + s); } } }
--- a/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/tools/IdealGraphVisualizer/nbproject/project.properties Thu Jul 05 16:54:45 2012 +0200 @@ -40,5 +40,5 @@ # Disable assertions for RequestProcessor to prevent annoying messages in case # of multiple SceneAnimator update tasks in the default RequestProcessor. -run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx2g +run.args.extra = -J-server -J-da:org.openide.util.RequestProcessor -J-Xms2g -J-Xmx4g debug.args.extra = -J-server -J-da:org.openide.util.RequestProcessor
--- a/src/share/vm/classfile/javaClasses.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -255,6 +255,7 @@ public: // Instance creation static oop create(); + static int java_thread_offset_in_bytes() { return _eetop_offset; } // Returns the JavaThread associated with the thread obj static JavaThread* thread(oop java_thread); // Set JavaThread for instance
--- a/src/share/vm/classfile/vmSymbols.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -352,6 +352,10 @@ template(callbackInternal_name, "callbackInternal") \ template(callback_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \ template(MethodInvalidatedException, "com/oracle/graal/api/meta/InstalledCode$MethodInvalidatedException") \ + /* graal.api.interpreter */ \ + template(com_oracle_graal_api_interpreter_Interpreter, "com/oracle/graal/api/interpreter/Interpreter") \ + template(interpreter_execute_name, "execute") \ + template(interpreter_execute_signature, "(Lcom/oracle/graal/api/meta/ResolvedJavaMethod;[Ljava/lang/Object;)Ljava/lang/Object;") \ \ \ /* common method and field names */ \
--- a/src/share/vm/graal/graalCodeInstaller.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,6 +21,9 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP +#define SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP + /* * This class handles the conversion from a InstalledCode to a CodeBlob or an nmethod. */ @@ -112,3 +115,4 @@ }; +#endif // SHARE_VM_GRAAL_GRAAL_CODE_INSTALLER_HPP
--- a/src/share/vm/graal/graalCompiler.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -273,7 +273,7 @@ HotSpotResolvedJavaType::set_accessFlags(obj, klass->access_flags().as_int()); HotSpotResolvedJavaType::set_isInterface(obj, klass->is_interface()); HotSpotResolvedJavaType::set_superCheckOffset(obj, klass->super_check_offset()); - HotSpotResolvedJavaType::set_prototypeHeader(obj, (jlong) klass->prototype_header()); + HotSpotResolvedJavaType::set_initialMarkWord(obj, (jlong) klass->prototype_header()); HotSpotResolvedJavaType::set_isInstanceClass(obj, klass->oop_is_instance()); if (klass->oop_is_javaArray()) {
--- a/src/share/vm/graal/graalCompiler.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,6 +21,9 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_COMPILER_HPP +#define SHARE_VM_GRAAL_GRAAL_COMPILER_HPP + #include "compiler/abstractCompiler.hpp" #define LEAF_GRAPH_ARRAY_SIZE (8192) @@ -110,5 +113,4 @@ #define TRACE_graal_4 if (!(TraceGraal >= 4 && (tty->print(" TraceGraal-4: "), true))) ; else tty->print_cr #define TRACE_graal_5 if (!(TraceGraal >= 5 && (tty->print(" TraceGraal-5: "), true))) ; else tty->print_cr - - +#endif // SHARE_VM_GRAAL_GRAAL_COMPILER_HPP
--- a/src/share/vm/graal/graalCompilerToVM.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -790,6 +790,7 @@ set_int(env, config, "vmPageSize", os::vm_page_size()); set_int(env, config, "stackShadowPages", StackShadowPages); set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); + set_int(env, config, "markOffset", oopDesc::mark_offset_in_bytes()); set_int(env, config, "superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); set_int(env, config, "secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); set_int(env, config, "secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); @@ -802,7 +803,7 @@ set_int(env, config, "instanceHeaderPrototypeOffset", in_bytes(Klass::prototype_header_offset())); set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); - set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset())); + set_int(env, config, "threadMultiNewArrayStorageOffset", in_bytes(JavaThread::graal_multinewarray_storage_offset())); set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset())); set_int(env, config, "methodDataOopDataOffset", in_bytes(methodDataOopDesc::data_offset())); @@ -874,12 +875,6 @@ break; } - jintArray arrayOffsets = env->NewIntArray(basicTypeCount); - for (int i=0; i<basicTypeCount; i++) { - jint offset = arrayOopDesc::base_offset_in_bytes(basicTypes[i]); - env->SetIntArrayRegion(arrayOffsets, i, 1, &offset); - } - set_int_array(env, config, "arrayOffsets", arrayOffsets); set_int(env, config, "arrayClassElementOffset", in_bytes(objArrayKlass::element_klass_offset())); return config; } @@ -934,25 +929,6 @@ return JNIHandles::make_local(result()); } -// public String disassembleJava(HotSpotResolvedJavaMethod method); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_disassembleJava(JNIEnv *env, jobject, jobject hotspot_method) { - TRACE_graal_3("CompilerToVM::disassembleJava"); - - // Important: The bytecode printing functions are all NOT PRODUCT code, so this method returns an empty string for a product VM build. - - VM_ENTRY_MARK; - ResourceMark rm; - HandleMark hm; - - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - // Note: cannot use resource-allocated stringStream because print_code_on has its own ResourceMark. - bufferedStream(st); - method->print_codes_on(&st); - - Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); - return JNIHandles::make_local(result()); -} - // public StackTraceElement JavaMethod_toStackTraceElement(HotSpotResolvedJavaMethod method, int bci); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_JavaMethod_1toStackTraceElement(JNIEnv *env, jobject, jobject hotspot_method, int bci) { TRACE_graal_3("CompilerToVM::JavaMethod_toStackTraceElement"); @@ -966,48 +942,6 @@ return JNIHandles::make_local(element); } -class JavaArgumentPusher : public SignatureIterator { - protected: - JavaCallArguments* _jca; - arrayOop _args; - int _index; - - oop next_arg(BasicType expectedType) { - assert(_index < _args->length(), "out of bounds"); - oop arg = ((oop*) _args->base(T_OBJECT))[_index++]; - assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); - return arg; - } - - public: - JavaArgumentPusher(Symbol* signature, JavaCallArguments* jca, arrayOop args, bool is_static) : SignatureIterator(signature) { - this->_return_type = T_ILLEGAL; - _jca = jca; - _index = 0; - _args = args; - if (!is_static) { - _jca->push_oop(next_arg(T_OBJECT)); - } - iterate(); - assert(_index == args->length(), "arg count mismatch with signature"); - } - - inline void do_bool() { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); } - inline void do_char() { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); } - inline void do_short() { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); } - inline void do_byte() { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); } - inline void do_int() { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); } - - inline void do_long() { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); } - inline void do_float() { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); } - inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); } - - inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); } - inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); } - inline void do_array(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); } - inline void do_void() { } -}; - // public Object executeCompiledMethodVarargs(HotSpotCompiledMethod method, Object... args); JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_executeCompiledMethodVarargs(JNIEnv *env, jobject, jobject method, jobject args) { TRACE_graal_3("CompilerToVM::executeCompiledMethod"); @@ -1021,7 +955,7 @@ Symbol* signature = mh->signature(); JavaCallArguments jca; - JavaArgumentPusher jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); + JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); JavaValue result(jap.get_ret_type()); nmethod* nm = (nmethod*) HotSpotCompiledMethod::nmethod(method); @@ -1182,7 +1116,6 @@ {CC"getConfiguration", CC"()"CONFIG, FN_PTR(getConfiguration)}, {CC"installMethod", CC"("TARGET_METHOD"Z"HS_CODE_INFO")"HS_COMP_METHOD, FN_PTR(installMethod)}, {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, - {CC"disassembleJava", CC"("RESOLVED_METHOD")"STRING, FN_PTR(disassembleJava)}, {CC"JavaMethod_toStackTraceElement", CC"("RESOLVED_METHOD"I)"STACK_TRACE_ELEMENT, FN_PTR(JavaMethod_1toStackTraceElement)}, {CC"executeCompiledMethod", CC"("HS_COMP_METHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)}, {CC"executeCompiledMethodVarargs", CC"("HS_COMP_METHOD "["OBJECT")"OBJECT, FN_PTR(executeCompiledMethodVarargs)},
--- a/src/share/vm/graal/graalCompilerToVM.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,13 +21,59 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_COMPILER_TO_VM_HPP +#define SHARE_VM_GRAAL_GRAAL_COMPILER_TO_VM_HPP + #include "prims/jni.h" extern JNINativeMethod CompilerToVM_methods[]; int CompilerToVM_methods_count(); +methodOop getMethodFromHotSpotMethod(jobject hotspotMethod); methodOop getMethodFromHotSpotMethod(oop hotspotMethod); +class JavaArgumentUnboxer : public SignatureIterator { + protected: + JavaCallArguments* _jca; + arrayOop _args; + int _index; + + oop next_arg(BasicType expectedType) { + assert(_index < _args->length(), "out of bounds"); + oop arg = ((oop*) _args->base(T_OBJECT))[_index++]; + assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); + return arg; + } + + public: + JavaArgumentUnboxer(Symbol* signature, JavaCallArguments* jca, arrayOop args, bool is_static) : SignatureIterator(signature) { + this->_return_type = T_ILLEGAL; + _jca = jca; + _index = 0; + _args = args; + if (!is_static) { + _jca->push_oop(next_arg(T_OBJECT)); + } + iterate(); + assert(_index == args->length(), "arg count mismatch with signature"); + } + + inline void do_bool() { if (!is_return_type()) _jca->push_int(next_arg(T_BOOLEAN)->bool_field(java_lang_boxing_object::value_offset_in_bytes(T_BOOLEAN))); } + inline void do_char() { if (!is_return_type()) _jca->push_int(next_arg(T_CHAR)->char_field(java_lang_boxing_object::value_offset_in_bytes(T_CHAR))); } + inline void do_short() { if (!is_return_type()) _jca->push_int(next_arg(T_SHORT)->short_field(java_lang_boxing_object::value_offset_in_bytes(T_SHORT))); } + inline void do_byte() { if (!is_return_type()) _jca->push_int(next_arg(T_BYTE)->byte_field(java_lang_boxing_object::value_offset_in_bytes(T_BYTE))); } + inline void do_int() { if (!is_return_type()) _jca->push_int(next_arg(T_INT)->int_field(java_lang_boxing_object::value_offset_in_bytes(T_INT))); } + + inline void do_long() { if (!is_return_type()) _jca->push_long(next_arg(T_LONG)->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG))); } + inline void do_float() { if (!is_return_type()) _jca->push_float(next_arg(T_FLOAT)->float_field(java_lang_boxing_object::value_offset_in_bytes(T_FLOAT))); } + inline void do_double() { if (!is_return_type()) _jca->push_double(next_arg(T_DOUBLE)->double_field(java_lang_boxing_object::value_offset_in_bytes(T_DOUBLE))); } + + inline void do_object() { _jca->push_oop(next_arg(T_OBJECT)); } + inline void do_object(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); } + inline void do_array(int begin, int end) { if (!is_return_type()) _jca->push_oop(next_arg(T_OBJECT)); } + inline void do_void() { } +}; + // nothing here - no need to define the jni method implementations in a header file - +#endif // SHARE_VM_GRAAL_GRAAL_COMPILER_TO_VM_HPP
--- a/src/share/vm/graal/graalEnv.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalEnv.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -139,4 +139,3 @@ }; #endif // SHARE_VM_GRAAL_GRAALENV_HPP -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalInterpreterToVM.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "prims/jni.h" +#include "graal/graalInterpreterToVM.hpp" +#include "graal/graalCompiler.hpp" +#include "graal/graalCompilerToVM.hpp" + +#ifdef HIGH_LEVEL_INTERPRETER + +// public Object invoke(HotSpotResolvedJavaMethod method, boolean highLevel, Object... args); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_HotSpotRuntimeInterpreterInterface_invoke(JNIEnv *env, jobject, jobject method, jobject args) { + TRACE_graal_3("InterpreterToVM::invoke"); + + VM_ENTRY_MARK; + HandleMark hm; + + assert(method != NULL, "just checking"); + assert(thread->is_Java_thread(), "must be"); + methodHandle mh = getMethodFromHotSpotMethod(method); + + JavaCallArguments jca; + JavaArgumentUnboxer jap(mh->signature(), &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static()); + +#ifndef PRODUCT + if (PrintHighLevelInterpreterVMTransitions) { + ResourceMark rm; + tty->print_cr("High level interpreter -> VM (%s)", mh->name_and_sig_as_C_string()); + } +#endif + + JavaValue result(jap.get_ret_type()); + thread->set_high_level_interpreter_in_vm(true); + JavaCalls::call(&result, mh, &jca, THREAD); + thread->set_high_level_interpreter_in_vm(false); + +#ifndef PRODUCT + if (PrintHighLevelInterpreterVMTransitions) { + ResourceMark rm; + tty->print_cr("VM (%s) -> high level interpreter", mh->name_and_sig_as_C_string()); + } +#endif + + if (thread->has_pending_exception()) { + return NULL; + } + + if (jap.get_ret_type() == T_VOID) { + return NULL; + } else if (jap.get_ret_type() == T_OBJECT || jap.get_ret_type() == T_ARRAY) { + return JNIHandles::make_local((oop) result.get_jobject()); + } else { + oop o = java_lang_boxing_object::create(jap.get_ret_type(), (jvalue *) result.get_value_addr(), CHECK_NULL); + return JNIHandles::make_local(o); + } +} + +#define CC (char*) /*cast a literal from (const char*)*/ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_HotSpotRuntimeInterpreterInterface_##f)) + +#define RESOLVED_METHOD "Lcom/oracle/graal/api/meta/ResolvedJavaMethod;" +#define OBJECT "Ljava/lang/Object;" + +JNINativeMethod InterpreterToVM_methods[] = { + {CC"invoke", CC"("RESOLVED_METHOD "["OBJECT")"OBJECT, FN_PTR(invoke)} +}; + +int InterpreterToVM_methods_count() { + return sizeof(InterpreterToVM_methods) / sizeof(JNINativeMethod); +} + +#endif // HIGH_LEVEL_INTERPRETER
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalInterpreterToVM.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 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. + */ + +#ifdef HIGH_LEVEL_INTERPRETER +#ifndef SHARE_VM_GRAAL_GRAAL_INTERPRETER_TO_VM_HPP +#define SHARE_VM_GRAAL_GRAAL_INTERPRETER_TO_VM_HPP + +#include "prims/jni.h" + +extern JNINativeMethod InterpreterToVM_methods[]; +int InterpreterToVM_methods_count(); + +// nothing here - no need to define the jni method implementations in a header file + +#endif // SHARE_VM_GRAAL_GRAAL_INTERPRETER_TO_VM_HPP +#endif // HIGH_LEVEL_INTERPRETER
--- a/src/share/vm/graal/graalJavaAccess.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,6 +21,9 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_JAVA_ACCESS_HPP +#define SHARE_VM_GRAAL_GRAAL_JAVA_ACCESS_HPP + void graal_compute_offsets(); #include "classfile/systemDictionary.hpp" @@ -49,7 +52,7 @@ oop_field(HotSpotResolvedJavaType, javaMirror, "Ljava/lang/Class;") \ oop_field(HotSpotResolvedJavaType, simpleName, "Ljava/lang/String;") \ int_field(HotSpotResolvedJavaType, accessFlags) \ - long_field(HotSpotResolvedJavaType, prototypeHeader) \ + long_field(HotSpotResolvedJavaType, initialMarkWord) \ boolean_field(HotSpotResolvedJavaType, hasFinalizer) \ boolean_field(HotSpotResolvedJavaType, hasFinalizableSubclass) \ int_field(HotSpotResolvedJavaType, superCheckOffset) \ @@ -294,3 +297,5 @@ #undef STATIC_OOP_FIELD void compute_offset(int &dest_offset, klassOop klass_oop, const char* name, const char* signature, bool static_field); + +#endif // SHARE_VM_GRAAL_GRAAL_JAVA_ACCESS_HPP
--- a/src/share/vm/graal/graalRuntime.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -27,5 +27,6 @@ // JVM_InitializeGraalRuntime JVM_ENTRY(jobject, JVM_InitializeGraalRuntime(JNIEnv *env, jclass graalclass)) + VMToCompiler::compilerInstance(); return VMToCompiler::compilerPermObject(); JVM_END \ No newline at end of file
--- a/src/share/vm/graal/graalRuntime.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,6 +21,9 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP +#define SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP + class GraalRuntime : public AllStatic { private: @@ -29,4 +32,6 @@ public: static jobject instance() { return _runtimeObject; } -}; \ No newline at end of file +}; + +#endif // SHARE_VM_GRAAL_GRAAL_RUNTIME_HPP
--- a/src/share/vm/graal/graalVMToCompiler.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,6 +21,9 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP +#define SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP + #include "memory/allocation.hpp" #include "oops/oop.hpp" #include "runtime/handles.hpp" @@ -122,3 +125,4 @@ } } +#endif // SHARE_VM_GRAAL_GRAAL_VM_TO_COMPILER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMToInterpreter.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,280 @@ +/* + * Copyright (c) 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. + */ + +#include "precompiled.hpp" +#include "graal/graalVMToInterpreter.hpp" +#include "graal/graalInterpreterToVM.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" +#include "graal/graalCompiler.hpp" + +#ifdef HIGH_LEVEL_INTERPRETER + +// those are *global* handles +jobject VMToInterpreter::_interpreterPermObject = NULL; +jobject VMToInterpreter::_interpreterPermKlass = NULL; + +class JavaArgumentBoxer : public SignatureIterator { + protected: + JavaCallArguments* _args; + Thread* _thread; + objArrayHandle _obj_array; + int _index; + int _position; + + public: + JavaArgumentBoxer(Symbol* signature, objArrayHandle obj_array, JavaCallArguments* args, bool is_static, TRAPS) : SignatureIterator(signature) { + _obj_array = obj_array; + _args = args; + _index = _position = 0; + _thread = THREAD; + if (!is_static) { + push(next_object(T_OBJECT)); + } + iterate(); + assert(_index == _obj_array->length(), "arg count mismatch with signature"); + } + + inline void do_bool() { + if (!is_return_type()) { + jvalue value; + value.z = (jboolean)_args->get_int(_position); + push(java_lang_boxing_object::create(T_BOOLEAN, &value, _thread)); + } + } + inline void do_char() { + if (!is_return_type()) { + jvalue value; + value.c = (jchar)_args->get_int(_position); + push(java_lang_boxing_object::create(T_CHAR, &value, _thread)); + } + } + inline void do_short() { + if (!is_return_type()) { + jvalue value; + value.s = (jshort)_args->get_int(_position); + push(java_lang_boxing_object::create(T_SHORT, &value, _thread)); + } + } + inline void do_byte() { + if (!is_return_type()) { + jvalue value; + value.b = (jbyte)_args->get_int(_position); + push(java_lang_boxing_object::create(T_BYTE, &value, _thread)); + } + } + inline void do_int() { + if (!is_return_type()) { + jvalue value; + value.i = (jint)_args->get_int(_position); + push(java_lang_boxing_object::create(T_INT, &value, _thread)); + } + } + + inline void do_long() { + if (!is_return_type()) { + jvalue value; + value.j = (jlong)_args->get_long(_position); + push(java_lang_boxing_object::create(T_LONG, &value, _thread)); + } + } + + inline void do_float() { + if (!is_return_type()) { + jvalue value; + value.f = (jfloat)_args->get_float(_position); + push(java_lang_boxing_object::create(T_FLOAT, &value, _thread)); + } + } + + inline void do_double() { + if (!is_return_type()) { + jvalue value; + value.d = (jdouble)_args->get_double(_position); + push(java_lang_boxing_object::create(T_DOUBLE, &value, _thread)); + } + } + + inline void do_object(int begin, int end) { if (!is_return_type()) push(next_object(T_OBJECT)); } + inline void do_array(int begin, int end) { if (!is_return_type()) push(next_object(T_ARRAY)); } + inline void do_void() { } + + inline oop next_object(BasicType type) { + assert(type == T_OBJECT || type == T_ARRAY, "must be"); + return *(_args->get_raw_oop(_position)); + } + + inline void push(oop obj) { + _obj_array->obj_at_put(_index, obj); + _index++; + } +}; + +bool VMToInterpreter::allocate_interpreter(const char* interpreter_class_name, const char* interpreter_arguments, TRAPS) { + assert(_interpreterPermObject == NULL && _interpreterPermKlass == NULL, "no need to allocate twice"); + + HandleMark hm; + // load the interpreter class using its fully qualified class name + Symbol* class_name = SymbolTable::lookup(interpreter_class_name, (int)strlen(interpreter_class_name), CHECK_false); + instanceKlassHandle interpreter_klass = SystemDictionary::resolve_or_null(class_name, SystemDictionary::java_system_loader(), NULL, CHECK_false); + if (interpreter_klass.is_null()) { + tty->print_cr("Could not load HighLevelInterpreterClass '%s'", interpreter_class_name); + return false; + } + + // allocate an interpreter instance + interpreter_klass->initialize(CHECK_false); + instanceHandle interpreter_instance = interpreter_klass->allocate_instance_handle(CHECK_false); + + // initialize the interpreter instance + Handle args; + if (interpreter_arguments != NULL) { + args = java_lang_String::create_from_platform_dependent_str(interpreter_arguments, CHECK_false); + } + + JavaValue result(T_BOOLEAN); + JavaCalls::call_virtual(&result, interpreter_instance, interpreter_klass, vmSymbols::initialize_name(), vmSymbols::setOption_signature(), args, CHECK_false); + if (result.get_jboolean() != JNI_TRUE) { + tty->print_cr("Could not invoke '%s::initialize(String)'", interpreter_class_name); + return false; + } + + // store the instance globally and keep it alive + _interpreterPermObject = JNIHandles::make_global(interpreter_instance); + _interpreterPermKlass = JNIHandles::make_global(interpreter_klass); + + // register the native functions that are needed by the interpreter + { + assert(THREAD->is_Java_thread(), "must be"); + JavaThread* thread = (JavaThread*) THREAD; + ThreadToNativeFromVM trans(thread); + JNIEnv *env = thread->jni_environment(); + jclass klass = env->FindClass("com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface"); + if (klass == NULL) { + tty->print_cr("Could not find class HotSpotRuntimeInterpreterInterface"); + return false; + } + env->RegisterNatives(klass, InterpreterToVM_methods, InterpreterToVM_methods_count()); + if (thread->has_pending_exception()) { + tty->print_cr("Could not register HotSpotRuntimeInterpreterInterface native methods"); + return false; + } + } + + return true; +} + +Handle VMToInterpreter::interpreter_instance() { + return Handle(JNIHandles::resolve_non_null(_interpreterPermObject)); +} + +KlassHandle VMToInterpreter::interpreter_klass() { + return KlassHandle(JNIHandles::resolve_non_null(_interpreterPermKlass)); +} + +void VMToInterpreter::execute(JavaValue* result, methodHandle* m, JavaCallArguments* args, BasicType expected_result_type, TRAPS) { + assert(interpreter_instance().not_null(), "must be allocated before the first call"); + assert(THREAD->is_Java_thread(), "must be"); + assert(m != NULL, "must be"); + assert(args != NULL, "must be"); + + JavaThread* thread = (JavaThread*)THREAD; + methodHandle method = *m; + int parameter_count = ArgumentCount(method->signature()).size() + (method->is_static() ? 0 : 1); + objArrayHandle args_array = oopFactory::new_objArray(SystemDictionary::Object_klass(), parameter_count, CHECK); + JavaArgumentBoxer jab(method->signature(), args_array, args, method->is_static(), thread); + Handle hotspot_method = GraalCompiler::createHotSpotResolvedJavaMethod(method, CHECK); + + JavaValue boxed_result(T_OBJECT); + JavaCallArguments boxed_args; + boxed_args.set_receiver(interpreter_instance()); + boxed_args.push_oop(hotspot_method); + boxed_args.push_oop(args_array); + +#ifndef PRODUCT + if (PrintHighLevelInterpreterVMTransitions) { + ResourceMark m; + tty->print_cr("VM -> high level interpreter (%s)", method->name_and_sig_as_C_string()); + } +#endif + + thread->set_high_level_interpreter_in_vm(false); + JavaCalls::call_virtual(&boxed_result, interpreter_klass(), vmSymbols::interpreter_execute_name(), vmSymbols::interpreter_execute_signature(), &boxed_args, thread); + thread->set_high_level_interpreter_in_vm(true); + +#ifndef PRODUCT + if (PrintHighLevelInterpreterVMTransitions) { + ResourceMark m; + tty->print_cr("High level interpreter (%s) -> VM", method->name_and_sig_as_C_string()); + } +#endif + + if (HAS_PENDING_EXCEPTION) { + return; + } + + // unbox the result if necessary + if (is_java_primitive(expected_result_type)) { + unbox_primitive(&boxed_result, result); + } else if (expected_result_type == T_OBJECT || expected_result_type == T_ARRAY) { + result->set_jobject(boxed_result.get_jobject()); + } +} + +void VMToInterpreter::unbox_primitive(JavaValue* boxed, JavaValue* result) { + oop box = JNIHandles::resolve(boxed->get_jobject()); + + jvalue value; + BasicType type = java_lang_boxing_object::get_value(box, &value); + switch (type) { + case T_BOOLEAN: + result->set_jint(value.z); + break; + case T_CHAR: + result->set_jint(value.c); + break; + case T_FLOAT: + result->set_jfloat(value.f); + break; + case T_DOUBLE: + result->set_jdouble(value.d); + break; + case T_BYTE: + result->set_jint(value.b); + break; + case T_SHORT: + result->set_jint(value.s); + break; + case T_INT: + result->set_jint(value.i); + break; + case T_LONG: + result->set_jlong(value.j); + break; + default: + ShouldNotReachHere(); + break; + } +} + +#endif // HIGH_LEVEL_INTERPRETER
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMToInterpreter.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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. + */ + +#include "memory/allocation.hpp" +#include "oops/oop.hpp" +#include "runtime/handles.hpp" +#include "runtime/thread.hpp" +#include "classfile/javaClasses.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/javaCalls.hpp" + +#ifdef HIGH_LEVEL_INTERPRETER +#ifndef SHARE_VM_GRAAL_GRAAL_VM_TO_INTERPRETER_HPP +#define SHARE_VM_GRAAL_GRAAL_VM_TO_INTERPRETER_HPP + +class VMToInterpreter : public AllStatic { + +private: + static jobject _interpreterPermObject; + static jobject _interpreterPermKlass; + + static Handle interpreter_instance(); + static KlassHandle interpreter_klass(); + static void unbox_primitive(JavaValue* boxed, JavaValue* result); + +public: + static bool allocate_interpreter(const char* interpreter_class_name, const char* interpreter_arguments, TRAPS); + + // invokes the interpreter method execute(ResolvedJavaMethod method, Object... arguments) + static void execute(JavaValue* result, methodHandle* m, JavaCallArguments* args, BasicType expected_result_type, TRAPS); +}; + +#endif // SHARE_VM_GRAAL_GRAAL_VM_TO_INTERPRETER_HPP +#endif // HIGH_LEVEL_INTERPRETER
--- a/src/share/vm/graal/graalVmIds.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/graal/graalVmIds.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -21,6 +21,9 @@ * questions. */ +#ifndef SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP +#define SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP + #include "memory/allocation.hpp" #include "utilities/growableArray.hpp" #include "oops/oop.hpp" @@ -80,3 +83,4 @@ return obj->long_field(java_lang_boxing_object::value_offset_in_bytes(T_LONG)); } +#endif // SHARE_VM_GRAAL_GRAAL_VM_IDS_HPP
--- a/src/share/vm/prims/jni.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/prims/jni.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -32,6 +32,9 @@ #ifdef GRAAL #include "graal/graalCompiler.hpp" #endif +#ifdef HIGH_LEVEL_INTERPRETER +#include "graal/graalVMToInterpreter.hpp" +#endif #ifndef SERIALGC #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #endif // SERIALGC @@ -1317,6 +1320,7 @@ } +static bool first_time_InvokeMain = true; static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { methodHandle method(THREAD, JNIHandles::resolve_jmethod_id(method_id)); @@ -1325,6 +1329,8 @@ // the jni parser ResourceMark rm(THREAD); int number_of_parameters = method->size_of_parameters(); + + // Invoke the method. Result is returned as oop. JavaCallArguments java_args(number_of_parameters); args->set_java_argument_object(&java_args); @@ -1332,16 +1338,35 @@ // Fill out JavaCallArguments object args->iterate( Fingerprinter(method).fingerprint() ); - // Initialize result type + // Initialize result type (must be done after args->iterate()) result->set_type(args->get_ret_type()); - // Invoke the method. Result is returned as oop. +#ifdef HIGH_LEVEL_INTERPRETER + // TODO (chaeubl): this is quite a hack. The launcher should take care about that instead. + bool invoked_main_method = false; + if (HighLevelInterpreterClass != NULL && first_time_InvokeMain && method->name() == vmSymbols::main_name() && method->result_type() == T_VOID) { + assert(THREAD->is_Java_thread(), "other threads must not call into java"); + JavaThread* thread = (JavaThread*)THREAD; + first_time_InvokeMain = false; + invoked_main_method = true; + thread->set_high_level_interpreter_in_vm(true); + } +#endif + JavaCalls::call(result, method, &java_args, CHECK); // Convert result if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) { result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); } + +#ifdef HIGH_LEVEL_INTERPRETER + if (invoked_main_method) { + assert(THREAD->is_Java_thread(), "other threads must not call into java"); + JavaThread* thread = (JavaThread*)THREAD; + thread->set_high_level_interpreter_in_vm(false); + } +#endif } @@ -5144,6 +5169,16 @@ compiler->initialize(); #endif +#ifdef HIGH_LEVEL_INTERPRETER + if (HighLevelInterpreterClass != NULL) { + bool result = VMToInterpreter::allocate_interpreter(HighLevelInterpreterClass, HighLevelInterpreterArguments, thread); + if (!result) { + vm_abort(false); + return JNI_ERR; + } + } +#endif + // Tracks the time application was running before GC RuntimeService::record_application_start();
--- a/src/share/vm/runtime/deoptimization.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/runtime/deoptimization.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -1291,6 +1291,7 @@ if (TraceDeoptimization) { tty->print_cr(" bci=%d pc=%d, relative_pc=%d, method=%s", trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name()->as_C_string()); +#ifdef GRAAL if (thread->graal_deopt_info() != NULL) { oop deopt_info = thread->graal_deopt_info(); if (java_lang_String::is_instance(deopt_info)) { @@ -1303,6 +1304,7 @@ } thread->set_graal_deopt_info(NULL); } +#endif } methodHandle trap_method = trap_scope->method();
--- a/src/share/vm/runtime/globals.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/runtime/globals.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -631,6 +631,15 @@ develop(bool, InlineAtomicLong, true, \ "inline sun.misc.AtomicLong") \ \ + product(ccstr, HighLevelInterpreterClass, NULL, \ + "fully qualified class name of the high-level interpreter") \ + \ + product(ccstr, HighLevelInterpreterArguments, NULL, \ + "arguments that are passed to the high-level interpreter") \ + \ + notproduct(bool, PrintHighLevelInterpreterVMTransitions, false, \ + "print transitions between VM and high-level interpreter") \ + \ develop(bool, InlineThreadNatives, true, \ "inline Thread.currentThread, etc") \ \
--- a/src/share/vm/runtime/javaCalls.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/runtime/javaCalls.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -39,6 +39,9 @@ #include "runtime/mutexLocker.hpp" #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" +#ifdef HIGH_LEVEL_INTERPRETER +# include "graal/graalVMToInterpreter.hpp" +#endif #ifdef TARGET_OS_FAMILY_linux # include "thread_linux.inline.hpp" #endif @@ -437,7 +440,14 @@ ShouldNotReachHere(); #endif } - + +#ifdef HIGH_LEVEL_INTERPRETER + if (thread->high_level_interpreter_in_vm() && !method->is_native() && Interpreter::contains(entry_point)) { + assert(nm == NULL || !nm->is_alive(), "otherwise nm should be invoked"); + VMToInterpreter::execute(result, m, args, result->get_type(), thread); + oop_result_flag = false; // result already holds the correct value + } else +#endif // do call { JavaCallWrapper link(method, receiver, result, CHECK); { HandleMark hm(thread); // HandleMark used by HandleMarkCleaner @@ -473,7 +483,6 @@ } } - //-------------------------------------------------------------------------------------- // Implementation of JavaCallArguments
--- a/src/share/vm/runtime/javaCalls.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/runtime/javaCalls.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -159,6 +159,12 @@ inline void push_float(float f) { _is_oop[_size] = false; JNITypes::put_float(f, _value, _size); } + inline oop* get_raw_oop(int& pos) { return (oop*)JNITypes::get_obj(_value, pos); } + inline jint get_int(int& pos) { return JNITypes::get_int(_value, pos); } + inline jdouble get_double(int& pos) { return JNITypes::get_double(_value, pos); } + inline jlong get_long(int& pos) { return JNITypes::get_long(_value, pos); } + inline jfloat get_float(int& pos) { return JNITypes::get_float(_value, pos); } + // receiver Handle receiver() { assert(_size > 0, "must at least be one argument"); @@ -191,7 +197,7 @@ class JavaCalls: AllStatic { static void call_helper(JavaValue* result, methodHandle* method, nmethod* nm, JavaCallArguments* args, TRAPS); - public: +public: // Optimized Constuctor call static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS);
--- a/src/share/vm/runtime/thread.cpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/runtime/thread.cpp Thu Jul 05 16:54:45 2012 +0200 @@ -1303,8 +1303,13 @@ _in_deopt_handler = 0; _doing_unsafe_access = false; _stack_guard_state = stack_guard_unused; +#ifdef GRAAL _graal_deopt_info = NULL; _graal_alternate_call_target = NULL; +#endif +#ifdef HIGH_LEVEL_INTERPRETER + _high_level_interpreter_in_vm = false; +#endif _exception_oop = NULL; _exception_pc = 0; _exception_handler_pc = 0; @@ -2622,7 +2627,9 @@ f->do_oop((oop*) &_threadObj); f->do_oop((oop*) &_vm_result); f->do_oop((oop*) &_vm_result_2); +#ifdef GRAAL f->do_oop((oop*) &_graal_deopt_info); +#endif f->do_oop((oop*) &_exception_oop); f->do_oop((oop*) &_pending_async_exception);
--- a/src/share/vm/runtime/thread.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/runtime/thread.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -866,11 +866,16 @@ private: +#ifdef GRAAL // graal needs some place to put the dimensions - jint graal_multinewarray_storage[256]; + jint _graal_multinewarray_storage[256]; volatile oop _graal_deopt_info; address _graal_alternate_call_target; +#endif +#ifdef HIGH_LEVEL_INTERPRETER + bool _high_level_interpreter_in_vm; +#endif StackGuardState _stack_guard_state; @@ -1234,10 +1239,16 @@ MemRegion deferred_card_mark() const { return _deferred_card_mark; } void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } +#ifdef GRAAL oop graal_deopt_info() const { return _graal_deopt_info; } void set_graal_deopt_info(oop o) { _graal_deopt_info = o; } - + void set_graal_alternate_call_target(address a) { _graal_alternate_call_target = a; } +#endif +#ifdef HIGH_LEVEL_INTERPRETER + bool high_level_interpreter_in_vm() { return _high_level_interpreter_in_vm; } + void set_high_level_interpreter_in_vm(bool value) { _high_level_interpreter_in_vm = value; } +#endif // Exception handling for compiled methods oop exception_oop() const { return _exception_oop; } @@ -1318,15 +1329,20 @@ static ByteSize thread_state_offset() { return byte_offset_of(JavaThread, _thread_state ); } static ByteSize saved_exception_pc_offset() { return byte_offset_of(JavaThread, _saved_exception_pc ); } static ByteSize osthread_offset() { return byte_offset_of(JavaThread, _osthread ); } +#ifdef GRAAL static ByteSize graal_deopt_info_offset() { return byte_offset_of(JavaThread, _graal_deopt_info ); } static ByteSize graal_alternate_call_target_offset() { return byte_offset_of(JavaThread, _graal_alternate_call_target); } + static ByteSize graal_multinewarray_storage_offset() { return byte_offset_of(JavaThread, _graal_multinewarray_storage); } +#endif +#ifdef HIGH_LEVEL_INTERPRETER + static ByteSize high_level_interpreter_in_vm_offset() { return byte_offset_of(JavaThread, _high_level_interpreter_in_vm); } +#endif static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop ); } static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); } static ByteSize stack_guard_state_offset() { return byte_offset_of(JavaThread, _stack_guard_state ); } static ByteSize suspend_flags_offset() { return byte_offset_of(JavaThread, _suspend_flags ); } - static ByteSize graal_multinewarray_storage_offset() { return byte_offset_of(JavaThread, graal_multinewarray_storage); } static ByteSize do_not_unlock_if_synchronized_offset() { return byte_offset_of(JavaThread, _do_not_unlock_if_synchronized); } static ByteSize should_post_on_exceptions_flag_offset() {
--- a/src/share/vm/utilities/globalDefinitions.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/utilities/globalDefinitions.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -106,9 +106,9 @@ // log2_intptr(sizeof(class JavaThread)) - log2_intptr(64); // see os::set_memory_serialize_page() #ifdef _LP64 -const int SerializePageShiftCount = 5; +const int SerializePageShiftCount = GRAAL_ONLY(5) NOT_GRAAL(4); #else -const int SerializePageShiftCount = 4; +const int SerializePageShiftCount = GRAAL_ONLY(4) NOT_GRAAL(3); #endif // An opaque struct of heap-word width, so that HeapWord* can be a generic
--- a/src/share/vm/utilities/macros.hpp Thu Jul 05 16:54:00 2012 +0200 +++ b/src/share/vm/utilities/macros.hpp Thu Jul 05 16:54:45 2012 +0200 @@ -80,7 +80,15 @@ #else #define GRAAL_ONLY(code) #define NOT_GRAAL(code) code -#endif +#endif // GRAAL + +#ifdef HIGH_LEVEL_INTERPRETER +#define HIGH_LEVEL_INTERPRETER_ONLY(code) code +#define NOT_HIGH_LEVEL_INTERPRETER(code) +#else +#define HIGH_LEVEL_INTERPRETER_ONLY(code) +#define NOT_HIGH_LEVEL_INTERPRETER(code) code +#endif // HIGH_LEVEL_INTERPRETER #ifdef TIERED #define TIERED_ONLY(code) code