# HG changeset patch # User Peter B. Kessler # Date 1448930470 28800 # Node ID 02b6e8f05130973f8039f210aa32065e6e2376ff # Parent 99b21d7f7ed64356d38ef4f175019df2d765aa63# Parent 319230b97fafd5676b8014292b73bc54848c2254 Merge. diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java --- a/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.api.directives.test/src/com/oracle/graal/api/directives/test/ControlFlowAnchorDirectiveTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -167,6 +167,7 @@ while (ret > 1) { GraalDirectives.controlFlowAnchor(); if (ret % 2 == 0) { + GraalDirectives.controlFlowAnchor(); ret /= 2; } else { ret = 3 * ret + 1; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java --- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SnippetReflectionProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -182,5 +182,5 @@ * @return the value that should be bound to the parameter when invoking the constructor or null * if this provider cannot provide a value of the requested type */ - Object getInjectedNodeIntrinsicParameter(ResolvedJavaType type); + T getInjectedNodeIntrinsicParameter(Class type); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -75,6 +75,7 @@ byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); compResult.setTargetCode(targetCode, targetCode.length); compResult.setTotalFrameSize(0); + compResult.close(); InstalledCode code = codeCache.addCode(method, compResult, null, null); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFile.java --- a/graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFile.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFile.java Mon Nov 30 16:41:10 2015 -0800 @@ -122,7 +122,7 @@ * Map from a machine code position to a comment for the operands of the instruction at the * position. */ - public final Map operandComments = new TreeMap<>(); + public final Map> operandComments = new TreeMap<>(); public final byte[] code; @@ -180,8 +180,10 @@ } } - for (Map.Entry e : operandComments.entrySet()) { - ps.printf("OperandComment %d %s %s%n", e.getKey(), e.getValue(), SECTION_DELIM); + for (Map.Entry> e : operandComments.entrySet()) { + for (String c : e.getValue()) { + ps.printf("OperandComment %d %s %s%n", e.getKey(), c, SECTION_DELIM); + } } ps.flush(); } @@ -218,12 +220,15 @@ } /** - * Sets an operand comment for a given position. - * - * @return the previous operand comment for {@code pos} + * Adds an operand comment for a given position. */ - public String addOperandComment(int pos, String comment) { - return operandComments.put(pos, encodeString(comment)); + public void addOperandComment(int pos, String comment) { + List list = comments.get(pos); + if (list == null) { + list = new ArrayList<>(1); + comments.put(pos, list); + } + list.add(encodeString(comment)); } /** diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFileDisassemblerProvider.java --- a/graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFileDisassemblerProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.code/src/com/oracle/graal/code/HexCodeFileDisassemblerProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -117,8 +117,7 @@ } private static void addOperandComment(HexCodeFile hcf, int pos, String comment) { - String oldValue = hcf.addOperandComment(pos, comment); - assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue; + hcf.addOperandComment(pos, comment); } /** diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeMatchRules.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeMatchRules.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeMatchRules.java Mon Nov 30 16:41:10 2015 -0800 @@ -126,7 +126,7 @@ if (value.isConstant()) { JavaConstant constant = value.asJavaConstant(); - if (constant != null && kind == AMD64Kind.QWORD && !NumUtil.isInt(constant.asLong())) { + if (constant != null && kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { // Only imm32 as long return null; } @@ -146,14 +146,7 @@ LabelRef falseLabel = getLIRBlock(ifNode.falseSuccessor()); boolean unorderedIsTrue = compare.unorderedIsTrue(); double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); - Value other; - JavaConstant constant = value.asJavaConstant(); - if (constant != null) { - other = gen.emitJavaConstant(constant); - } else { - other = operand(value); - } - + Value other = operand(value); AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); getLIRGeneratorTool().emitCompareBranchMemory(kind, other, address, getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability); return null; @@ -268,6 +261,8 @@ @MatchRule("(If (FloatLessThan=compare value FloatingRead=access))") @MatchRule("(If (PointerEquals=compare value Read=access))") @MatchRule("(If (PointerEquals=compare value FloatingRead=access))") + @MatchRule("(If (ObjectEquals=compare value Read=access))") + @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, Access access) { return emitCompareBranchMemory(root, compare, value, access); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64SuitesProvider.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64SuitesProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64SuitesProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,10 +24,10 @@ import static com.oracle.graal.compiler.common.BackendOptions.ShouldOptimizeStackToStackMoves; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.java.DefaultSuitesProvider; import com.oracle.graal.lir.amd64.phases.StackMoveOptimizationPhase; import com.oracle.graal.lir.phases.LIRSuites; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.tiers.CompilerConfiguration; public class AMD64SuitesProvider extends DefaultSuitesProvider { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCSuitesProvider.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCSuitesProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCSuitesProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -22,8 +22,8 @@ */ package com.oracle.graal.compiler.sparc; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.java.DefaultSuitesProvider; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.tiers.CompilerConfiguration; import com.oracle.graal.phases.tiers.Suites; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CheckGraalInvariants.java Mon Nov 30 16:41:10 2015 -0800 @@ -68,14 +68,14 @@ import com.oracle.graal.debug.GraalDebugConfig; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeClass; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.PhiNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.VerifyPhase; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CountedLoopTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CountedLoopTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CountedLoopTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,22 +22,23 @@ */ package com.oracle.graal.compiler.test; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; import com.oracle.graal.api.directives.GraalDirectives; import com.oracle.graal.graph.NodeClass; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.loop.InductionVariable; import com.oracle.graal.loop.LoopsData; import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.spi.LIRLowerable; import com.oracle.graal.nodes.spi.NodeLIRBuilderTool; @@ -232,13 +233,6 @@ public void generate(NodeLIRBuilderTool gen) { gen.setResult(this, gen.operand(iv)); } - - @NodeIntrinsic - public static native int get(@ConstantNodeParameter IVProperty property, int iv); - } - - protected static int getIntrinsic(IVProperty property, int iv) { - return IVPropertyNode.get(property, iv); } @Override @@ -246,11 +240,18 @@ Plugins plugins = super.getDefaultGraphBuilderPlugins(); Registration r = new Registration(plugins.getInvocationPlugins(), CountedLoopTest.class); - ResolvedJavaMethod intrinsic = getResolvedJavaMethod("getIntrinsic"); r.register2("get", IVProperty.class, int.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { - b.intrinsify(targetMethod, intrinsic, new ValueNode[]{arg1, arg2}); - return true; + IVProperty property = null; + if (arg1.isConstant()) { + property = getSnippetReflection().asObject(IVProperty.class, arg1.asJavaConstant()); + } + if (property != null) { + b.addPush(JavaKind.Int, new IVPropertyNode(property, arg2)); + return true; + } else { + return false; + } } }); @@ -268,4 +269,37 @@ return true; } + public static Result incrementNeqSnippet(int limit) { + int i; + int posLimit = ((limit - 1) & 0xFFFF) + 1; // make sure limit is always strictly positive + Result ret = new Result(); + for (i = 0; i != posLimit; i++) { + GraalDirectives.controlFlowAnchor(); + ret.extremum = get(InductionVariable::extremumNode, i); + } + ret.exitValue = get(InductionVariable::exitValueNode, i); + return ret; + } + + @Test + public void decrementNeq() { + test("decrementNeqSnippet", 256); + } + + public static Result decrementNeqSnippet(int limit) { + int i; + int posLimit = ((limit - 1) & 0xFFFF) + 1; // make sure limit is always strictly positive + Result ret = new Result(); + for (i = posLimit; i != 0; i--) { + GraalDirectives.controlFlowAnchor(); + ret.extremum = get(InductionVariable::extremumNode, i); + } + ret.exitValue = get(InductionVariable::exitValueNode, i); + return ret; + } + + @Test + public void incrementNeq() { + test("incrementNeqSnippet", 256); + } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -37,10 +37,10 @@ import org.junit.Test; import com.oracle.graal.debug.Debug; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.nodes.java.RegisterFinalizerNode; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.common.CanonicalizerPhase; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -80,11 +80,6 @@ import com.oracle.graal.debug.TTY; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeMap; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.java.ComputeLoopFrequenciesClosure; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.lir.asm.CompilationResultBuilderFactory; @@ -99,6 +94,11 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.cfg.Block; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.LoweringProvider; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.nodes.virtual.VirtualObjectNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -37,11 +37,11 @@ import org.junit.Test; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.lir.asm.CompilationResultBuilderFactory; import com.oracle.graal.nodes.FullInfopointNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.tiers.HighTierContext; @@ -83,7 +83,7 @@ final StructuredGraph graph = parseDebug(method, AllowAssumptions.from(OptAssumptions.getValue())); int graphLineSPs = 0; for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { - if (ipn.getReason() == InfopointReason.LINE_NUMBER) { + if (ipn.getReason() == InfopointReason.BYTECODE_POSITION) { ++graphLineSPs; } } @@ -95,7 +95,7 @@ int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); - if (sp.reason == InfopointReason.LINE_NUMBER) { + if (sp.reason == InfopointReason.BYTECODE_POSITION) { ++lineSPs; } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StaticInterfaceFieldTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StaticInterfaceFieldTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StaticInterfaceFieldTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,12 +36,12 @@ import com.oracle.graal.debug.Debug; import com.oracle.graal.debug.DebugConfigScope; import com.oracle.graal.debug.DelegatingDebugConfig; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.VerifyPhase; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/UnbalancedMonitorsTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/UnbalancedMonitorsTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/UnbalancedMonitorsTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -31,12 +31,12 @@ import org.junit.Test; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.OptimisticOptimizations; /** diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -33,11 +33,11 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.DebugDumpScope; import com.oracle.graal.graph.Node; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.nodes.FullInfopointNode; import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.common.CanonicalizerPhase; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/tutorial/StaticAnalysis.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -42,9 +42,6 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeMap; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.ConstantNode; @@ -56,6 +53,9 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.ValuePhiNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.java.LoadFieldNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.java.NewArrayNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Nov 30 16:41:10 2015 -0800 @@ -345,7 +345,6 @@ FrameMap frameMap = lirGenRes.getFrameMap(); CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); - crb.finish(); if (assumptions != null && !assumptions.isEmpty()) { compilationResult.setAssumptions(assumptions.toArray()); } @@ -353,7 +352,7 @@ compilationResult.setMethods(rootMethod, inlinedMethods); compilationResult.setBytecodeSize(bytecodeSize); } - + crb.finish(); if (Debug.isMeterEnabled()) { List ldp = compilationResult.getDataPatches(); JavaKind[] kindValues = JavaKind.values(); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Mon Nov 30 16:41:10 2015 -0800 @@ -451,7 +451,7 @@ BytecodePosition position = node.getNodeContext(BytecodePosition.class); if (position != null && (lastPosition == null || !lastPosition.equals(position))) { lastPosition = position; - recordSimpleInfopoint(InfopointReason.LINE_NUMBER, position); + recordSimpleInfopoint(InfopointReason.BYTECODE_POSITION, position); } } if (node instanceof LIRLowerable) { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Nov 30 16:41:10 2015 -0800 @@ -576,6 +576,26 @@ } } + public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + } + + public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { + log(DEFAULT_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { + if (ENABLED) { + DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + } + public static void logv(String format, Object... args) { logv(DEFAULT_LOG_LEVEL, format, args); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -163,7 +163,11 @@ * annotated method can be replaced with an instance of the node class denoted by * {@link #value()}. For this reason, the signature of the annotated method must match the * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a - * factory method named {@code "create"} in the node class. + * constructor in the node class. + *

+ * If the node class has a static method {@code intrinsify} with a matching signature plus a + * {@code GraphBuilderContext} as first argument, this method is called instead of creating the + * node. */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.METHOD) diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ForeignCallPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import com.oracle.graal.compiler.common.spi.ForeignCallDescriptor; -import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; -import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.extended.ForeignCallNode; - -/** - * {@link InvocationPlugin} for converting a method call directly to a foreign call. - */ -public final class ForeignCallPlugin implements InvocationPlugin { - private final ForeignCallsProvider foreignCalls; - private final ForeignCallDescriptor descriptor; - - public ForeignCallPlugin(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor) { - this.foreignCalls = foreignCalls; - this.descriptor = descriptor; - } - - public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { - ForeignCallNode foreignCall = new ForeignCallNode(foreignCalls, descriptor, args); - foreignCall.setBci(b.bci()); - b.addPush(targetMethod.getSignature().getReturnKind(), foreignCall); - return true; - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderConfiguration.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.graphbuilderconf; - -import java.util.Arrays; - -import jdk.vm.ci.meta.ResolvedJavaType; - -import com.oracle.graal.compiler.common.GraalOptions; -import com.oracle.graal.nodes.FullInfopointNode; -import com.oracle.graal.nodes.SimpleInfopointNode; - -public class GraphBuilderConfiguration { - - public static class Plugins { - private final InvocationPlugins invocationPlugins; - private NodePlugin[] nodePlugins; - private ParameterPlugin[] parameterPlugins; - private InlineInvokePlugin[] inlineInvokePlugins; - private LoopExplosionPlugin loopExplosionPlugin; - - /** - * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in - * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default} - * {@linkplain #getInvocationPlugins() invocation plugins} in this object. - */ - public Plugins(Plugins copyFrom) { - this.invocationPlugins = new InvocationPlugins(copyFrom.invocationPlugins); - this.nodePlugins = copyFrom.nodePlugins; - this.parameterPlugins = copyFrom.parameterPlugins; - this.inlineInvokePlugins = copyFrom.inlineInvokePlugins; - this.loopExplosionPlugin = copyFrom.loopExplosionPlugin; - } - - /** - * Creates a new set of plugins. - * - * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in - * this object - */ - public Plugins(InvocationPlugins invocationPlugins) { - this.invocationPlugins = invocationPlugins; - this.nodePlugins = new NodePlugin[0]; - this.parameterPlugins = new ParameterPlugin[0]; - this.inlineInvokePlugins = new InlineInvokePlugin[0]; - } - - public InvocationPlugins getInvocationPlugins() { - return invocationPlugins; - } - - public NodePlugin[] getNodePlugins() { - return nodePlugins; - } - - public void appendNodePlugin(NodePlugin plugin) { - nodePlugins = Arrays.copyOf(nodePlugins, nodePlugins.length + 1); - nodePlugins[nodePlugins.length - 1] = plugin; - } - - public void prependNodePlugin(NodePlugin plugin) { - NodePlugin[] newPlugins = new NodePlugin[nodePlugins.length + 1]; - System.arraycopy(nodePlugins, 0, newPlugins, 1, nodePlugins.length); - newPlugins[0] = plugin; - nodePlugins = newPlugins; - } - - public void clearNodePlugin() { - nodePlugins = new NodePlugin[0]; - } - - public ParameterPlugin[] getParameterPlugins() { - return parameterPlugins; - } - - public void appendParameterPlugin(ParameterPlugin plugin) { - parameterPlugins = Arrays.copyOf(parameterPlugins, parameterPlugins.length + 1); - parameterPlugins[parameterPlugins.length - 1] = plugin; - } - - public void prependParameterPlugin(ParameterPlugin plugin) { - ParameterPlugin[] newPlugins = new ParameterPlugin[parameterPlugins.length + 1]; - System.arraycopy(parameterPlugins, 0, newPlugins, 1, parameterPlugins.length); - newPlugins[0] = plugin; - parameterPlugins = newPlugins; - } - - public void clearParameterPlugin() { - parameterPlugins = new ParameterPlugin[0]; - } - - public InlineInvokePlugin[] getInlineInvokePlugins() { - return inlineInvokePlugins; - } - - public void appendInlineInvokePlugin(InlineInvokePlugin plugin) { - inlineInvokePlugins = Arrays.copyOf(inlineInvokePlugins, inlineInvokePlugins.length + 1); - inlineInvokePlugins[inlineInvokePlugins.length - 1] = plugin; - } - - public void prependInlineInvokePlugin(InlineInvokePlugin plugin) { - InlineInvokePlugin[] newPlugins = new InlineInvokePlugin[inlineInvokePlugins.length + 1]; - System.arraycopy(inlineInvokePlugins, 0, newPlugins, 1, inlineInvokePlugins.length); - newPlugins[0] = plugin; - inlineInvokePlugins = newPlugins; - } - - public void clearInlineInvokePlugins() { - inlineInvokePlugins = new InlineInvokePlugin[0]; - } - - public LoopExplosionPlugin getLoopExplosionPlugin() { - return loopExplosionPlugin; - } - - public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) { - this.loopExplosionPlugin = plugin; - } - } - - private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{}; - - private final boolean eagerResolving; - private final boolean omitAllExceptionEdges; - private final boolean omitAssertions; - private final ResolvedJavaType[] skippedExceptionTypes; - private final DebugInfoMode debugInfoMode; - private final boolean clearNonLiveLocals; - private boolean useProfiling; - private final Plugins plugins; - - public static enum DebugInfoMode { - SafePointsOnly, - /** - * This mode inserts {@link SimpleInfopointNode}s in places where no safepoints would be - * inserted: inlining boundaries, and line number switches. - *

- * In this mode the infopoint only have a location (method and bytecode index) and no - * values. - *

- * This is useful to have better program counter to bci mapping and has no influence on the - * generated code. However it can increase the amount of metadata and does not allow access - * to accessing values at runtime. - */ - Simple, - /** - * In this mode, {@link FullInfopointNode}s are generated in the same locations as in - * {@link #Simple} mode but the infopoints have access to the runtime values. - *

- * This is relevant when code is to be generated for native, machine-code level debugging - * but can have a limit the amount of optimization applied to the code. - */ - Full, - } - - protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, boolean omitAssertions, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, - boolean clearNonLiveLocals, Plugins plugins) { - this.eagerResolving = eagerResolving; - this.omitAllExceptionEdges = omitAllExceptionEdges; - this.omitAssertions = omitAssertions; - this.debugInfoMode = debugInfoMode; - this.skippedExceptionTypes = skippedExceptionTypes; - this.clearNonLiveLocals = clearNonLiveLocals; - this.useProfiling = true; - this.plugins = plugins; - } - - /** - * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in - * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the - * {@link InvocationPlugins} in the copy. - */ - public GraphBuilderConfiguration copy() { - Plugins newPlugins = new Plugins(plugins); - GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, newPlugins); - result.useProfiling = useProfiling; - return result; - } - - public boolean getUseProfiling() { - return useProfiling; - } - - public void setUseProfiling(boolean b) { - this.useProfiling = b; - } - - public GraphBuilderConfiguration withEagerResolving(boolean newEagerResolving) { - return new GraphBuilderConfiguration(newEagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins); - } - - public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins); - } - - public GraphBuilderConfiguration withOmitAllExceptionEdges(boolean newOmitAllExceptionEdges) { - return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins); - } - - public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) { - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newOmitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins); - } - - public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) { - ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length); - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, newDebugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins); - } - - public GraphBuilderConfiguration withClearNonLiveLocals(boolean newClearNonLiveLocals) { - return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, newClearNonLiveLocals, plugins); - } - - public ResolvedJavaType[] getSkippedExceptionTypes() { - return skippedExceptionTypes; - } - - public boolean eagerResolving() { - return eagerResolving; - } - - public boolean omitAllExceptionEdges() { - return omitAllExceptionEdges; - } - - public boolean omitAssertions() { - return omitAssertions; - } - - public boolean insertNonSafepointDebugInfo() { - return debugInfoMode.ordinal() >= DebugInfoMode.Simple.ordinal(); - } - - public boolean insertFullDebugInfo() { - return debugInfoMode.ordinal() >= DebugInfoMode.Full.ordinal(); - } - - public boolean insertSimpleDebugInfo() { - return debugInfoMode == DebugInfoMode.Simple; - } - - public boolean clearNonLiveLocals() { - return clearNonLiveLocals; - } - - public static GraphBuilderConfiguration getDefault(Plugins plugins) { - return new GraphBuilderConfiguration(false, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); - } - - public static GraphBuilderConfiguration getInfopointDefault(Plugins plugins) { - return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); - } - - public static GraphBuilderConfiguration getEagerDefault(Plugins plugins) { - return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); - } - - public static GraphBuilderConfiguration getInfopointEagerDefault(Plugins plugins) { - return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); - } - - public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) { - return new GraphBuilderConfiguration(true, true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); - } - - public static GraphBuilderConfiguration getFullDebugDefault(Plugins plugins) { - return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); - } - - /** - * Returns {@code true} if it is an error for a class/field/method resolution to fail. The - * default is the same result as returned by {@link #eagerResolving()}. However, it may be - * overridden to allow failure even when {@link #eagerResolving} is {@code true}. - */ - public boolean unresolvedIsError() { - return eagerResolving; - } - - public Plugins getPlugins() { - return plugins; - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderContext.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import static com.oracle.graal.compiler.common.type.StampFactory.objectNonNull; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -import com.oracle.graal.compiler.common.type.ObjectStamp; -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.compiler.common.type.StampFactory; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; -import com.oracle.graal.nodes.FixedGuardNode; -import com.oracle.graal.nodes.PiNode; -import com.oracle.graal.nodes.StateSplit; -import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.calc.IsNullNode; -import com.oracle.graal.nodes.spi.StampProvider; -import com.oracle.graal.nodes.type.StampTool; - -/** - * Used by a {@link GraphBuilderPlugin} to interface with an object that parses the bytecode of a - * single {@linkplain #getMethod() method} as part of building a {@linkplain #getGraph() graph} . - */ -public interface GraphBuilderContext { - - /** - * Raw operation for adding a node to the graph when neither {@link #add} nor - * {@link #addPush(JavaKind, ValueNode)} can be used. - * - * @return either the node added or an equivalent node - */ - T append(T value); - - /** - * Adds the given node to the graph and also adds recursively all referenced inputs. - * - * @param value the node to be added to the graph - * @return either the node added or an equivalent node - */ - T recursiveAppend(T value); - - /** - * Pushes a given value to the frame state stack using an explicit kind. This should be used - * when {@code value.getJavaKind()} is different from the kind that the bytecode instruction - * currently being parsed pushes to the stack. - * - * @param kind the kind to use when type checking this operation - * @param value the value to push to the stack. The value must already have been - * {@linkplain #append(ValueNode) appended}. - */ - void push(JavaKind kind, ValueNode value); - - /** - * Adds a node to the graph. If the returned node is a {@link StateSplit} with a null - * {@linkplain StateSplit#stateAfter() frame state}, the frame state is initialized. - * - * @param value the value to add to the graph and push to the stack. The - * {@code value.getJavaKind()} kind is used when type checking this operation. - * @return a node equivalent to {@code value} in the graph - */ - default T add(T value) { - if (value.graph() != null) { - assert !(value instanceof StateSplit) || ((StateSplit) value).stateAfter() != null; - return value; - } - T equivalentValue = append(value); - if (equivalentValue instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) equivalentValue; - if (stateSplit.stateAfter() == null && stateSplit.hasSideEffect()) { - setStateAfter(stateSplit); - } - } - return equivalentValue; - } - - /** - * Adds a node with a non-void kind to the graph, pushes it to the stack. If the returned node - * is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the - * frame state is initialized. - * - * @param kind the kind to use when type checking this operation - * @param value the value to add to the graph and push to the stack - * @return a node equivalent to {@code value} in the graph - */ - default T addPush(JavaKind kind, T value) { - T equivalentValue = value.graph() != null ? value : append(value); - push(kind, equivalentValue); - if (equivalentValue instanceof StateSplit) { - StateSplit stateSplit = (StateSplit) equivalentValue; - if (stateSplit.stateAfter() == null && stateSplit.hasSideEffect()) { - setStateAfter(stateSplit); - } - } - return equivalentValue; - } - - /** - * Handles an invocation that a plugin determines can replace the original invocation (i.e., the - * one for which the plugin was applied). This applies all standard graph builder processing to - * the replaced invocation including applying any relevant plugins. - * - * @param invokeKind the kind of the replacement invocation - * @param targetMethod the target of the replacement invocation - * @param args the arguments to the replacement invocation - * @param forceInlineEverything specifies if all invocations encountered in the scope of - * handling the replaced invoke are to be force inlined - */ - void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean forceInlineEverything); - - /** - * Intrinsifies an invocation of a given method by inlining the bytecodes of a given - * substitution method. - * - * @param targetMethod the method being intrinsified - * @param substitute the intrinsic implementation - * @param args the arguments with which to inline the invocation - */ - void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args); - - StampProvider getStampProvider(); - - MetaAccessProvider getMetaAccess(); - - default Assumptions getAssumptions() { - return getGraph().getAssumptions(); - } - - ConstantReflectionProvider getConstantReflection(); - - /** - * Gets the graph being constructed. - */ - StructuredGraph getGraph(); - - /** - * Creates a snap shot of the current frame state with the BCI of the instruction after the one - * currently being parsed and assigns it to a given {@linkplain StateSplit#hasSideEffect() side - * effect} node. - * - * @param sideEffect a side effect node just appended to the graph - */ - void setStateAfter(StateSplit sideEffect); - - /** - * Gets the parsing context for the method that inlines the method being parsed by this context. - */ - GraphBuilderContext getParent(); - - /** - * Gets the first ancestor parsing context that is not parsing a - * {@linkplain #parsingIntrinsic() intrinsic}. - */ - default GraphBuilderContext getNonIntrinsicAncestor() { - GraphBuilderContext ancestor = getParent(); - while (ancestor != null && ancestor.parsingIntrinsic()) { - ancestor = ancestor.getParent(); - } - return ancestor; - } - - /** - * Gets the method being parsed by this context. - */ - ResolvedJavaMethod getMethod(); - - /** - * Gets the index of the bytecode instruction currently being parsed. - */ - int bci(); - - /** - * Gets the kind of invocation currently being parsed. - */ - InvokeKind getInvokeKind(); - - /** - * Gets the return type of the invocation currently being parsed. - */ - JavaType getInvokeReturnType(); - - default Stamp getInvokeReturnStamp() { - JavaType returnType = getInvokeReturnType(); - if (returnType.getJavaKind() == JavaKind.Object && returnType instanceof ResolvedJavaType) { - return StampFactory.declared((ResolvedJavaType) returnType); - } else { - return StampFactory.forKind(returnType.getJavaKind()); - } - } - - /** - * Gets the inline depth of this context. A return value of 0 implies that this is the context - * for the parse root. - */ - default int getDepth() { - GraphBuilderContext parent = getParent(); - return parent == null ? 0 : 1 + parent.getDepth(); - } - - /** - * Determines if this parsing context is within the bytecode of an intrinsic or a method inlined - * by an intrinsic. - */ - default boolean parsingIntrinsic() { - return getIntrinsic() != null; - } - - /** - * Gets the intrinsic of the current parsing context or {@code null} if not - * {@link #parsingIntrinsic() parsing an intrinsic}. - */ - IntrinsicContext getIntrinsic(); - - BailoutException bailout(String string); - - /** - * Gets a version of a given value that has a {@linkplain StampTool#isPointerNonNull(ValueNode) - * non-null} stamp. - */ - default ValueNode nullCheckedValue(ValueNode value) { - if (!StampTool.isPointerNonNull(value.stamp())) { - IsNullNode condition = getGraph().unique(new IsNullNode(value)); - ObjectStamp receiverStamp = (ObjectStamp) value.stamp(); - Stamp stamp = receiverStamp.join(objectNonNull()); - FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true)); - PiNode nonNullReceiver = getGraph().unique(new PiNode(value, stamp)); - nonNullReceiver.setGuard(fixedGuard); - // TODO: Propogating the non-null into the frame state would - // remove subsequent null-checks on the same value. However, - // it currently causes an assertion failure when merging states. - // - // frameState.replace(value, nonNullReceiver); - return nonNullReceiver; - } - return value; - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/GraphBuilderPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -/** - * Marker interface for graph builder plugins. - */ -public interface GraphBuilderPlugin { -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InlineInvokePlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InlineInvokePlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.ValueNode; - -/** - * Plugin for specifying what is inlined during graph parsing. This plugin is also notified - * {@link #notifyBeforeInline before} and {@link #notifyAfterInline} the inlining, as well as of - * {@link #notifyNotInlined non-inlined} invocations (i.e., those for which an {@link Invoke} node - * is created). - */ -public interface InlineInvokePlugin extends GraphBuilderPlugin { - - /** - * Result of a {@link #shouldInlineInvoke inlining decision}. - */ - public static class InlineInfo { - - /** - * Denotes a call site that must not be inlined and should be implemented by a node that - * does not speculate on the call not raising an exception. - */ - public static final InlineInfo DO_NOT_INLINE_WITH_EXCEPTION = new InlineInfo(null, false); - - /** - * Denotes a call site must not be inlined and can be implemented by a node that speculates - * the call will not throw an exception. - */ - public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo(null, false); - - private final ResolvedJavaMethod methodToInline; - private final boolean isIntrinsic; - - public InlineInfo(ResolvedJavaMethod methodToInline, boolean isIntrinsic) { - this.methodToInline = methodToInline; - this.isIntrinsic = isIntrinsic; - } - - /** - * Returns the method to be inlined, or {@code null} if the call site must not be inlined. - */ - public ResolvedJavaMethod getMethodToInline() { - return methodToInline; - } - - /** - * Specifies if {@link #methodToInline} is an intrinsic for the original method (i.e., the - * {@code method} passed to {@link InlineInvokePlugin#shouldInlineInvoke}). - */ - public boolean isIntrinsic() { - return isIntrinsic; - } - } - - /** - * Determines whether a call to a given method is to be inlined. The return value is a - * tri-state: - *

- * Non-null return value with a non-null {@link InlineInfo#getMethodToInline method}: That - * {@link InlineInfo#getMethodToInline method} is inlined. Note that it can be a different - * method than the one specified here as the parameter, which allows method substitutions. - *

- * Non-null return value with a null {@link InlineInfo#getMethodToInline method}, e.g., - * {@link InlineInfo#DO_NOT_INLINE_WITH_EXCEPTION}: The method is not inlined, and other plugins - * with a lower priority cannot overwrite this decision. - *

- * Null return value: This plugin made no decision, other plugins with a lower priority are - * asked. - * - * @param b the context - * @param method the target method of an invoke - * @param args the arguments to the invoke - * @param returnType the return type derived from {@code method}'s signature - */ - default InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { - return null; - } - - /** - * Notification that a method is about to be inlined. - * - * @param methodToInline the inlined method - */ - default void notifyBeforeInline(ResolvedJavaMethod methodToInline) { - } - - /** - * Notification that a method was inlined. - * - * @param methodToInline the inlined method - */ - default void notifyAfterInline(ResolvedJavaMethod methodToInline) { - } - - /** - * Notifies this plugin of the {@link Invoke} node created for a method that was not inlined per - * {@link #shouldInlineInvoke}. - * - * @param b the context - * @param method the method that was not inlined - * @param invoke the invoke node created for the call to {@code method} - */ - default void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/IntrinsicContext.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/IntrinsicContext.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; -import static jdk.vm.ci.code.BytecodeFrame.AFTER_BCI; -import static jdk.vm.ci.code.BytecodeFrame.BEFORE_BCI; -import static jdk.vm.ci.code.BytecodeFrame.INVALID_FRAMESTATE_BCI; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import com.oracle.graal.nodes.AbstractMergeNode; -import com.oracle.graal.nodes.FrameState; -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.StateSplit; -import com.oracle.graal.nodes.StructuredGraph; - -/** - * An intrinsic is a substitute implementation of a Java method (or a bytecode in the case of - * snippets) that is itself implemented in Java. This interface provides information about the - * intrinsic currently being processed by the graph builder. - * - * When in the scope of an intrinsic, the graph builder does not check the value kinds flowing - * through the JVM state since intrinsics can employ non-Java kinds to represent values such as raw - * machine words and pointers. - */ -public class IntrinsicContext { - - /** - * Gets the method being intrinsified. - */ - final ResolvedJavaMethod method; - - /** - * Gets the method providing the intrinsic implementation. - */ - final ResolvedJavaMethod intrinsic; - - public ResolvedJavaMethod getOriginalMethod() { - return method; - } - - public ResolvedJavaMethod getIntrinsicMethod() { - return intrinsic; - } - - /** - * Determines if a call within the compilation scope of this intrinsic represents a call to the - * {@linkplain #getOriginalMethod() original} method. This denotes the path where a partial - * intrinsification falls back to the original method. - */ - public boolean isCallToOriginal(ResolvedJavaMethod targetMethod) { - return method.equals(targetMethod) || intrinsic.equals(targetMethod); - } - - final CompilationContext compilationContext; - - public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, CompilationContext compilationContext) { - this.method = method; - this.intrinsic = intrinsic; - this.compilationContext = compilationContext; - assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)"); - } - - public boolean isPostParseInlined() { - return compilationContext.equals(INLINE_AFTER_PARSING); - } - - public boolean isCompilationRoot() { - return compilationContext.equals(ROOT_COMPILATION); - } - - /** - * Denotes the compilation context in which an intrinsic is being parsed. - */ - public enum CompilationContext { - /** - * An intrinsic is being processed when parsing an invoke bytecode that calls the - * intrinsified method. - */ - INLINE_DURING_PARSING, - - /** - * An intrinsic is being processed when inlining an {@link Invoke} in an existing graph. - */ - INLINE_AFTER_PARSING, - - /** - * An intrinsic is the root of compilation. - */ - ROOT_COMPILATION - } - - /** - * Models the state of a graph in terms of {@link StateSplit#hasSideEffect() side effects} that - * are control flow predecessors of the current point in a graph. - */ - public interface SideEffectsState { - - /** - * Determines if the current program point is preceded by one or more side effects. - */ - boolean isAfterSideEffect(); - - /** - * Gets the side effects preceding the current program point. - */ - Iterable sideEffects(); - - /** - * Records a side effect for the current program point. - */ - void addSideEffect(StateSplit sideEffect); - } - - public FrameState createFrameState(StructuredGraph graph, SideEffectsState sideEffects, StateSplit forStateSplit) { - assert forStateSplit != graph.start(); - if (forStateSplit.hasSideEffect()) { - if (sideEffects.isAfterSideEffect()) { - // Only the last side effect on any execution path in a replacement - // can inherit the stateAfter of the replaced node - FrameState invalid = graph.add(new FrameState(INVALID_FRAMESTATE_BCI)); - for (StateSplit lastSideEffect : sideEffects.sideEffects()) { - lastSideEffect.setStateAfter(invalid); - } - } - sideEffects.addSideEffect(forStateSplit); - return graph.add(new FrameState(AFTER_BCI)); - } else { - if (forStateSplit instanceof AbstractMergeNode) { - // Merge nodes always need a frame state - if (sideEffects.isAfterSideEffect()) { - // A merge after one or more side effects - return graph.add(new FrameState(AFTER_BCI)); - } else { - // A merge before any side effects - return graph.add(new FrameState(BEFORE_BCI)); - } - } else { - // Other non-side-effects do not need a state - return null; - } - } - } - - @Override - public String toString() { - return "Intrinsic{original: " + method.format("%H.%n(%p)") + ", intrinsic: " + intrinsic.format("%H.%n(%p)") + ", context: " + compilationContext + "}"; - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import java.lang.invoke.MethodHandle; -import java.lang.reflect.Method; - -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import com.oracle.graal.nodes.Invoke; -import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.type.StampTool; - -/** - * Plugin for handling a specific method invocation. - */ -public interface InvocationPlugin extends GraphBuilderPlugin { - - /** - * The receiver in a non-static method. The class literal for this interface must be used with - * {@link InvocationPlugins#put(InvocationPlugin, boolean, boolean, boolean, Class, String, Class...)} - * to denote the receiver argument for such a non-static method. - */ - public interface Receiver { - /** - * Gets the receiver value, null checking it first if necessary. - * - * @return the receiver value with a {@linkplain StampTool#isPointerNonNull(ValueNode) - * non-null} stamp - */ - ValueNode get(); - - /** - * Determines if the receiver is constant. - */ - default boolean isConstant() { - return false; - } - } - - /** - * Determines if this plugin is for a method with a polymorphic signature (e.g. - * {@link MethodHandle#invokeExact(Object...)}). - */ - default boolean isSignaturePolymorphic() { - return false; - } - - /** - * Determines if this plugin can only be used when inlining the method is it associated with. - * That is, this plugin cannot be used when the associated method is the compilation root. - */ - default boolean inlineOnly() { - return isSignaturePolymorphic(); - } - - /** - * Handles invocation of a signature polymorphic method. - * - * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static - * @param argsIncludingReceiver all arguments to the invocation include the raw receiver in - * position 0 if {@code targetMethod} is not static - * @see #execute - */ - default boolean applyPolymorphic(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode... argsIncludingReceiver) { - return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); - } - - /** - * @see #execute - */ - default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver) { - return defaultHandler(b, targetMethod, receiver); - } - - /** - * @see #execute - */ - default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg) { - return defaultHandler(b, targetMethod, receiver, arg); - } - - /** - * @see #execute - */ - default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2) { - return defaultHandler(b, targetMethod, receiver, arg1, arg2); - } - - /** - * @see #execute - */ - default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3) { - return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3); - } - - /** - * @see #execute - */ - default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { - return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4); - } - - /** - * @see #execute - */ - default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4, ValueNode arg5) { - return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); - } - - /** - * Executes this plugin against a set of invocation arguments. - * - * The default implementation in {@link InvocationPlugin} dispatches to the {@code apply(...)} - * method that matches the number of arguments or to {@link #applyPolymorphic} if {@code plugin} - * is {@linkplain #isSignaturePolymorphic() signature polymorphic}. - * - * @param targetMethod the method for which this plugin is being applied - * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static - * @param argsIncludingReceiver all arguments to the invocation include the receiver in position - * 0 if {@code targetMethod} is not static - * @return {@code true} if this plugin handled the invocation of {@code targetMethod} - * {@code false} if the graph builder should process the invoke further (e.g., by - * inlining it or creating an {@link Invoke} node). A plugin that does not handle an - * invocation must not modify the graph being constructed. - */ - default boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { - if (isSignaturePolymorphic()) { - return applyPolymorphic(b, targetMethod, receiver, argsIncludingReceiver); - } else if (receiver != null) { - assert !targetMethod.isStatic(); - assert argsIncludingReceiver.length > 0; - if (argsIncludingReceiver.length == 1) { - return apply(b, targetMethod, receiver); - } else if (argsIncludingReceiver.length == 2) { - return apply(b, targetMethod, receiver, argsIncludingReceiver[1]); - } else if (argsIncludingReceiver.length == 3) { - return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2]); - } else if (argsIncludingReceiver.length == 4) { - return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); - } else if (argsIncludingReceiver.length == 5) { - return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); - } else { - return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); - } - } else { - assert targetMethod.isStatic(); - if (argsIncludingReceiver.length == 0) { - return apply(b, targetMethod, null); - } else if (argsIncludingReceiver.length == 1) { - return apply(b, targetMethod, null, argsIncludingReceiver[0]); - } else if (argsIncludingReceiver.length == 2) { - return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1]); - } else if (argsIncludingReceiver.length == 3) { - return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2]); - } else if (argsIncludingReceiver.length == 4) { - return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); - } else if (argsIncludingReceiver.length == 5) { - return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); - } else { - return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); - } - - } - } - - /** - * Handles an invocation when a specific {@code apply} method is not available. - */ - default boolean defaultHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, @SuppressWarnings("unused") InvocationPlugin.Receiver receiver, - ValueNode... args) { - throw new JVMCIError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); - } - - default StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { - Class c = getClass(); - for (Method m : c.getDeclaredMethods()) { - if (m.getName().equals("apply")) { - return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); - } else if (m.getName().equals("defaultHandler")) { - return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); - } - } - throw new JVMCIError("could not find method named \"apply\" or \"defaultHandler\" in " + c.getName()); - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/InvocationPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,604 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import static java.lang.String.format; - -import java.lang.reflect.Executable; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import com.oracle.graal.graph.Node; -import com.oracle.graal.graph.iterators.NodeIterable; -import com.oracle.graal.nodes.ValueNode; - -/** - * Manages a set of {@link InvocationPlugin}s. - */ -public class InvocationPlugins { - - public static class InvocationPluginReceiver implements InvocationPlugin.Receiver { - private final GraphBuilderContext parser; - private ValueNode[] args; - private ValueNode value; - - public InvocationPluginReceiver(GraphBuilderContext parser) { - this.parser = parser; - } - - @Override - public ValueNode get() { - assert args != null : "Cannot get the receiver of a static method"; - if (value == null) { - value = parser.nullCheckedValue(args[0]); - if (value != args[0]) { - args[0] = value; - } - } - return value; - } - - @Override - public boolean isConstant() { - return args[0].isConstant(); - } - - public InvocationPluginReceiver init(ResolvedJavaMethod targetMethod, ValueNode[] newArgs) { - if (!targetMethod.isStatic()) { - this.args = newArgs; - this.value = null; - return this; - } - return null; - } - } - - /** - * Utility for - * {@linkplain InvocationPlugins#register(InvocationPlugin, Class, String, Class...) - * registration} of invocation plugins. - */ - public static class Registration { - - private final InvocationPlugins plugins; - private final Class declaringClass; - private boolean allowOverwrite; - - /** - * Creates an object for registering {@link InvocationPlugin}s for methods declared by a - * given class. - * - * @param plugins where to register the plugins - * @param declaringClass the class declaring the methods for which plugins will be - * registered via this object - */ - public Registration(InvocationPlugins plugins, Class declaringClass) { - this.plugins = plugins; - this.declaringClass = declaringClass; - } - - /** - * Creates an object for registering {@link InvocationPlugin}s for methods declared by a - * given class. - * - * @param plugins where to register the plugins - * @param declaringClassName the name of the class class declaring the methods for which - * plugins will be registered via this object - */ - public Registration(InvocationPlugins plugins, String declaringClassName) { - this.plugins = plugins; - try { - this.declaringClass = Class.forName(declaringClassName); - } catch (ClassNotFoundException ex) { - throw JVMCIError.shouldNotReachHere(ex); - } - } - - /** - * Configures this registration to allow or disallow overwriting of invocation plugins. - */ - public Registration setAllowOverwrite(boolean allowOverwrite) { - this.allowOverwrite = allowOverwrite; - return this; - } - - /** - * Registers a plugin for a method with no arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register0(String name, InvocationPlugin plugin) { - plugins.register(plugin, false, allowOverwrite, declaringClass, name); - } - - /** - * Registers a plugin for a method with 1 argument. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register1(String name, Class arg, InvocationPlugin plugin) { - plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg); - } - - /** - * Registers a plugin for a method with 2 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { - plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2); - } - - /** - * Registers a plugin for a method with 3 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { - plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2, arg3); - } - - /** - * Registers a plugin for a method with 4 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { - plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2, arg3, arg4); - } - - /** - * Registers a plugin for a method with 5 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void register5(String name, Class arg1, Class arg2, Class arg3, Class arg4, Class arg5, InvocationPlugin plugin) { - plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2, arg3, arg4, arg5); - } - - /** - * Registers a plugin for an optional method with no arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void registerOptional0(String name, InvocationPlugin plugin) { - plugins.register(plugin, true, allowOverwrite, declaringClass, name); - } - - /** - * Registers a plugin for an optional method with 1 argument. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void registerOptional1(String name, Class arg, InvocationPlugin plugin) { - plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg); - } - - /** - * Registers a plugin for an optional method with 2 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void registerOptional2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { - plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg1, arg2); - } - - /** - * Registers a plugin for an optional method with 3 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void registerOptional3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { - plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg1, arg2, arg3); - } - - /** - * Registers a plugin for an optional method with 4 arguments. - * - * @param name the name of the method - * @param plugin the plugin to be registered - */ - public void registerOptional4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { - plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg1, arg2, arg3, arg4); - } - - /** - * Registers a plugin that implements a method based on the bytecode of a substitute method. - * - * @param substituteDeclaringClass the class declaring the substitute method - * @param name the name of both the original and substitute method - * @param argumentTypes the argument types of the method. Element 0 of this array must be - * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method - * is non-static. Upon returning, element 0 will have been rewritten to - * {@code declaringClass} - */ - public void registerMethodSubstitution(Class substituteDeclaringClass, String name, Class... argumentTypes) { - registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); - } - - /** - * Registers a plugin that implements a method based on the bytecode of a substitute method. - * - * @param substituteDeclaringClass the class declaring the substitute method - * @param name the name of both the original method - * @param substituteName the name of the substitute method - * @param argumentTypes the argument types of the method. Element 0 of this array must be - * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method - * is non-static. Upon returning, element 0 will have been rewritten to - * {@code declaringClass} - */ - public void registerMethodSubstitution(Class substituteDeclaringClass, String name, String substituteName, Class... argumentTypes) { - MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(substituteDeclaringClass, substituteName, argumentTypes); - plugins.register(plugin, false, allowOverwrite, declaringClass, name, argumentTypes); - } - } - - /** - * Key for a method. - */ - static class MethodKey { - final boolean isStatic; - - /** - * This method is optional. This is used for new API methods not present in previous JDK - * versions. - */ - final boolean isOptional; - - final Class declaringClass; - final String name; - final Class[] argumentTypes; - final InvocationPlugin value; - - MethodKey(InvocationPlugin data, boolean isStatic, boolean isOptional, Class declaringClass, String name, Class... argumentTypes) { - assert isStatic || argumentTypes[0] == declaringClass; - this.value = data; - this.isStatic = isStatic; - this.isOptional = isOptional; - this.declaringClass = declaringClass; - this.name = name; - this.argumentTypes = argumentTypes; - assert isOptional || resolveJava() != null; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MethodKey) { - MethodKey that = (MethodKey) obj; - boolean res = this.name.equals(that.name) && this.declaringClass.equals(that.declaringClass) && Arrays.equals(this.argumentTypes, that.argumentTypes); - assert !res || this.isStatic == that.isStatic; - return res; - } - return false; - } - - public int getDeclaredParameterCount() { - return isStatic ? argumentTypes.length : argumentTypes.length - 1; - } - - @Override - public int hashCode() { - // Replay compilation mandates use of stable hash codes - return declaringClass.getName().hashCode() ^ name.hashCode(); - } - - private ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) { - Executable method = resolveJava(); - if (method == null) { - return null; - } - return metaAccess.lookupJavaMethod(method); - } - - private Executable resolveJava() { - try { - Executable res; - Class[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length); - if (name.equals("")) { - res = declaringClass.getDeclaredConstructor(parameterTypes); - } else { - res = declaringClass.getDeclaredMethod(name, parameterTypes); - } - assert Modifier.isStatic(res.getModifiers()) == isStatic; - return res; - } catch (NoSuchMethodException | SecurityException e) { - if (isOptional) { - return null; - } - throw new InternalError(e); - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(declaringClass.getName()).append('.').append(name).append('('); - for (Class p : argumentTypes) { - if (sb.charAt(sb.length() - 1) != '(') { - sb.append(", "); - } - sb.append(p.getSimpleName()); - } - return sb.append(')').toString(); - } - } - - private final MetaAccessProvider metaAccess; - - /** - * Initial list of entries. - */ - private final List registrations = new ArrayList<>(INITIAL_CAPACITY); - - /** - * Entry map that is initialized upon first call to {@link #get(ResolvedJavaMethod)}. - * - * Note: this must be volatile since double-checked locking is used to initialize it - */ - private volatile Map entries; - - private static final int INITIAL_CAPACITY = 64; - - /** - * Adds an entry to this map for a specified method. - * - * @param value value to be associated with the specified method - * @param isStatic specifies if the method is static - * @param isOptional specifies if the method is optional - * @param declaringClass the class declaring the method - * @param name the name of the method - * @param argumentTypes the argument types of the method. Element 0 of this array must be - * {@code declaringClass} iff the method is non-static. - * @return an object representing the method - */ - MethodKey put(InvocationPlugin value, boolean isStatic, boolean isOptional, boolean allowOverwrite, Class declaringClass, String name, Class... argumentTypes) { - assert isStatic || argumentTypes[0] == declaringClass; - MethodKey methodKey = new MethodKey(value, isStatic, isOptional, declaringClass, name, argumentTypes); - assert entries == null : "registration is closed"; - assert allowOverwrite || !registrations.contains(methodKey) : "a value is already registered for " + methodKey; - registrations.add(methodKey); - return methodKey; - } - - /** - * Determines if a method denoted by a given {@link MethodKey} is in this map. - */ - boolean containsKey(MethodKey key) { - return registrations.contains(key); - } - - InvocationPlugin get(ResolvedJavaMethod method) { - if (entries == null) { - initializeMap(); - } - - return entries.get(method); - } - - /** - * Disallows new registrations of new plugins, and creates the internal tables for method - * lookup. - */ - public void closeRegistration() { - if (entries == null) { - initializeMap(); - } - } - - void initializeMap() { - if (registrations.isEmpty()) { - entries = Collections.emptyMap(); - } else { - Map newEntries = new HashMap<>(); - for (MethodKey methodKey : registrations) { - ResolvedJavaMethod m = methodKey.resolve(metaAccess); - newEntries.put(m, methodKey.value); - } - entries = newEntries; - } - } - - public int size() { - return registrations.size(); - } - - /** - * The plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} before searching in - * this object. - */ - protected final InvocationPlugins parent; - - private InvocationPlugins(InvocationPlugins parent, MetaAccessProvider metaAccess) { - this.metaAccess = metaAccess; - InvocationPlugins p = parent; - this.parent = p; - } - - /** - * Creates a set of invocation plugins with a non-null {@linkplain #getParent() parent}. - */ - public InvocationPlugins(InvocationPlugins parent) { - this(parent, parent.getMetaAccess()); - } - - public MetaAccessProvider getMetaAccess() { - return metaAccess; - } - - public InvocationPlugins(MetaAccessProvider metaAccess) { - this(null, metaAccess); - } - - private void register(InvocationPlugin plugin, boolean isOptional, boolean allowOverwrite, Class declaringClass, String name, Class... argumentTypes) { - boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class; - if (!isStatic) { - argumentTypes[0] = declaringClass; - } - MethodKey methodInfo = put(plugin, isStatic, isOptional, allowOverwrite, declaringClass, name, argumentTypes); - assert Checker.check(this, methodInfo, plugin); - } - - /** - * Registers an invocation plugin for a given method. There must be no plugin currently - * registered for {@code method}. - * - * @param argumentTypes the argument types of the method. Element 0 of this array must be the - * {@link Class} value for {@link InvocationPlugin.Receiver} iff the method is - * non-static. Upon returning, element 0 will have been rewritten to - * {@code declaringClass} - */ - public void register(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { - register(plugin, false, false, declaringClass, name, argumentTypes); - } - - /** - * Registers an invocation plugin for a given, optional method. There must be no plugin - * currently registered for {@code method}. - * - * @param argumentTypes the argument types of the method. Element 0 of this array must be the - * {@link Class} value for {@link InvocationPlugin.Receiver} iff the method is - * non-static. Upon returning, element 0 will have been rewritten to - * {@code declaringClass} - */ - public void registerOptional(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { - register(plugin, true, false, declaringClass, name, argumentTypes); - } - - /** - * Gets the plugin for a given method. - * - * @param method the method to lookup - * @return the plugin associated with {@code method} or {@code null} if none exists - */ - public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - if (parent != null) { - InvocationPlugin plugin = parent.lookupInvocation(method); - if (plugin != null) { - return plugin; - } - } - return get(method); - } - - /** - * Gets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} - * before searching in this object. - */ - public InvocationPlugins getParent() { - return parent; - } - - @Override - public String toString() { - return registrations.stream().map(MethodKey::toString).collect(Collectors.joining(", ")) + " / parent: " + this.parent; - } - - private static class Checker { - private static final int MAX_ARITY = 5; - /** - * The set of all {@link InvocationPlugin#apply} method signatures. - */ - static final Class[][] SIGS; - - static { - ArrayList[]> sigs = new ArrayList<>(MAX_ARITY); - for (Method method : InvocationPlugin.class.getDeclaredMethods()) { - if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { - Class[] sig = method.getParameterTypes(); - assert sig[0] == GraphBuilderContext.class; - assert sig[1] == ResolvedJavaMethod.class; - assert sig[2] == InvocationPlugin.Receiver.class; - assert Arrays.asList(sig).subList(3, sig.length).stream().allMatch(c -> c == ValueNode.class); - while (sigs.size() < sig.length - 2) { - sigs.add(null); - } - sigs.set(sig.length - 3, sig); - } - } - assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null), - ValueNode.class.getSimpleName()); - SIGS = sigs.toArray(new Class[sigs.size()][]); - } - - public static boolean check(InvocationPlugins plugins, MethodKey method, InvocationPlugin plugin) { - InvocationPlugins p = plugins.parent; - while (p != null) { - assert !p.containsKey(method) : "a plugin is already registered for " + method; - p = p.parent; - } - if (plugin instanceof ForeignCallPlugin) { - return true; - } - if (plugin instanceof MethodSubstitutionPlugin) { - MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin; - msplugin.getJavaSubstitute(); - return true; - } - int arguments = method.getDeclaredParameterCount(); - assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method); - for (Method m : plugin.getClass().getDeclaredMethods()) { - if (m.getName().equals("apply")) { - Class[] parameterTypes = m.getParameterTypes(); - if (Arrays.equals(SIGS[arguments], parameterTypes)) { - return true; - } - } - } - throw new AssertionError(format("graph builder plugin for %s not found", method)); - } - } - - /** - * Checks a set of nodes added to the graph by an {@link InvocationPlugin}. - * - * @param b the graph builder that applied the plugin - * @param plugin a plugin that was just applied - * @param newNodes the nodes added to the graph by {@code plugin} - * @throws AssertionError if any check fail - */ - public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIterable newNodes) { - if (parent != null) { - parent.checkNewNodes(b, plugin, newNodes); - } - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/LoopExplosionPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/LoopExplosionPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public interface LoopExplosionPlugin extends GraphBuilderPlugin { - boolean shouldExplodeLoops(ResolvedJavaMethod method); - - boolean shouldMergeExplosions(ResolvedJavaMethod method); -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/MethodSubstitutionPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.stream.Collectors; - -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Launcher; - -import com.oracle.graal.nodes.ValueNode; - -/** - * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a - * {@linkplain #getSubstitute(MetaAccessProvider) substitute} method. A substitute method must be - * static even if the substituted method is not. - */ -public final class MethodSubstitutionPlugin implements InvocationPlugin { - - private ResolvedJavaMethod cachedSubstitute; - - /** - * The class in which the substitute method is declared. - */ - private final Class declaringClass; - - /** - * The name of the original and substitute method. - */ - private final String name; - - /** - * The parameter types of the substitute method. - */ - private final Class[] parameters; - - private final boolean originalIsStatic; - - /** - * Creates a method substitution plugin. - * - * @param declaringClass the class in which the substitute method is declared - * @param name the name of the substitute method - * @param parameters the parameter types of the substitute method. If the original method is not - * static, then {@code parameters[0]} must be the {@link Class} value denoting - * {@link InvocationPlugin.Receiver} - */ - public MethodSubstitutionPlugin(Class declaringClass, String name, Class... parameters) { - this.declaringClass = declaringClass; - this.name = name; - this.parameters = parameters; - this.originalIsStatic = parameters.length == 0 || parameters[0] != InvocationPlugin.Receiver.class; - } - - /** - * Creates a method substitution plugin. - * - * @param declaringClass the class in which the substitute method is declared - * @param name the name of the substitute method - * @param parameters the parameter types of the substitute method - */ - public MethodSubstitutionPlugin(boolean originalIsStatic, Class declaringClass, String name, Class... parameters) { - this.declaringClass = declaringClass; - this.name = name; - this.parameters = parameters; - this.originalIsStatic = originalIsStatic; - } - - public boolean inlineOnly() { - // Conservatively assume MacroNodes may be used in a substitution - return true; - } - - /** - * Gets the substitute method, resolving it first if necessary. - */ - public ResolvedJavaMethod getSubstitute(MetaAccessProvider metaAccess) { - if (cachedSubstitute == null) { - cachedSubstitute = metaAccess.lookupJavaMethod(getJavaSubstitute()); - } - return cachedSubstitute; - } - - /** - * Gets the reflection API version of the substitution method. - */ - Method getJavaSubstitute() throws JVMCIError { - Method substituteMethod = lookupSubstitute(); - int modifiers = substituteMethod.getModifiers(); - if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { - throw new JVMCIError("Substitution method must not be abstract or native: " + substituteMethod); - } - if (!Modifier.isStatic(modifiers)) { - throw new JVMCIError("Substitution method must be static: " + substituteMethod); - } - return substituteMethod; - } - - /** - * Determines if a given method is the substitute method of this plugin. - */ - private boolean isSubstitute(Method m) { - if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) { - if (parameters.length == m.getParameterCount()) { - Class[] mparams = m.getParameterTypes(); - int start = 0; - if (!originalIsStatic) { - start = 1; - if (!mparams[0].isAssignableFrom(parameters[0])) { - return false; - } - } - for (int i = start; i < mparams.length; i++) { - if (mparams[i] != parameters[i]) { - return false; - } - } - } - return true; - } - return false; - } - - /** - * Gets the substitute method of this plugin. - */ - private Method lookupSubstitute() { - for (Method m : declaringClass.getDeclaredMethods()) { - if (isSubstitute(m)) { - return m; - } - } - throw new JVMCIError("No method found specified by %s", this); - } - - /** - * Resolves a name to a class. - * - * @param className the name of the class to resolve - * @param optional if true, resolution failure returns null - * @return the resolved class or null if resolution fails and {@code optional} is true - */ - public static Class resolveClass(String className, boolean optional) { - try { - // Need to use launcher class path to handle classes - // that are not on the boot class path - ClassLoader cl = Launcher.getLauncher().getClassLoader(); - return Class.forName(className, false, cl); - } catch (ClassNotFoundException e) { - if (optional) { - return null; - } - throw new JVMCIError("Could not resolve type " + className); - } - } - - @Override - public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { - ResolvedJavaMethod subst = getSubstitute(b.getMetaAccess()); - if (receiver != null) { - receiver.get(); - } - b.intrinsify(targetMethod, subst, argsIncludingReceiver); - return true; - } - - public StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { - Class c = getClass(); - for (Method m : c.getDeclaredMethods()) { - if (m.getName().equals("execute")) { - return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); - } - } - throw new JVMCIError("could not find method named \"execute\" in " + c.getName()); - } - - @Override - public String toString() { - return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), name, - Arrays.asList(parameters).stream().map(c -> c.getSimpleName()).collect(Collectors.joining(", "))); - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/NodePlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/NodePlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,213 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaTypeProfile; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; - -import com.oracle.graal.nodes.ValueNode; - -public interface NodePlugin extends GraphBuilderPlugin { - /** - * Handle the parsing of a method invocation bytecode to a method that can be bound statically. - * If the method returns true, it must {@link GraphBuilderContext#push push} a value as the - * result of the method invocation using the {@link Signature#getReturnKind return kind} of the - * method. - * - * @param b the context - * @param method the statically bound, invoked method - * @param args the arguments of the method invocation - * @return true if the plugin handles the invocation, false otherwise - */ - default boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - return false; - } - - /** - * Handle the parsing of a GETFIELD bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value using the - * {@link ResolvedJavaField#getJavaKind() kind} of the field. - * - * @param b the context - * @param object the receiver object for the field access - * @param field the accessed field - * @return true if the plugin handles the field access, false otherwise - */ - default boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { - return false; - } - - /** - * Handle the parsing of a GETSTATIC bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value using the - * {@link ResolvedJavaField#getJavaKind() kind} of the field. - * - * @param b the context - * @param field the accessed field - * @return true if the plugin handles the field access, false otherwise - */ - default boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { - return false; - } - - /** - * Handle the parsing of a PUTFIELD bytecode. - * - * @param b the context - * @param object the receiver object for the field access - * @param field the accessed field - * @param value the value to be stored into the field - * @return true if the plugin handles the field access, false otherwise - */ - default boolean handleStoreField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field, ValueNode value) { - return false; - } - - /** - * Handle the parsing of a PUTSTATIC bytecode. - * - * @param b the context - * @param field the accessed field - * @param value the value to be stored into the field - * @return true if the plugin handles the field access, false otherwise. - */ - default boolean handleStoreStaticField(GraphBuilderContext b, ResolvedJavaField field, ValueNode value) { - return false; - } - - /** - * Handle the parsing of an array load bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value using the provided elementKind. - * - * @param b the context - * @param array the accessed array - * @param index the index for the array access - * @param elementKind the element kind of the accessed array - * @return true if the plugin handles the array access, false otherwise. - */ - default boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind) { - return false; - } - - /** - * Handle the parsing of an array store bytecode. - * - * @param b the context - * @param array the accessed array - * @param index the index for the array access - * @param elementKind the element kind of the accessed array - * @param value the value to be stored into the array - * @return true if the plugin handles the array access, false otherwise. - */ - default boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind, ValueNode value) { - return false; - } - - /** - * Handle the parsing of a CHECKCAST bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value with the result of the cast using - * {@link JavaKind#Object}. - * - * @param b the context - * @param object the object to be type checked - * @param type the type that the object is checked against - * @param profile the profiling information for the type check, or null if no profiling - * information is available - * @return true if the plugin handles the cast, false otherwise - */ - default boolean handleCheckCast(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) { - return false; - } - - /** - * Handle the parsing of a INSTANCEOF bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value with the result of the instanceof using - * {@link JavaKind#Int}. - * - * @param b the context - * @param object the object to be type checked - * @param type the type that the object is checked against - * @param profile the profiling information for the type check, or null if no profiling - * information is available - * @return true if the plugin handles the instanceof, false otherwise - */ - default boolean handleInstanceOf(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) { - return false; - } - - /** - * Handle the parsing of a NEW bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value with the result of the allocation using - * {@link JavaKind#Object}. - * - * @param b the context - * @param type the type to be instantiated - * @return true if the plugin handles the bytecode, false otherwise - */ - default boolean handleNewInstance(GraphBuilderContext b, ResolvedJavaType type) { - return false; - } - - /** - * Handle the parsing of a NEWARRAY and ANEWARRAY bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value with the result of the allocation using - * {@link JavaKind#Object}. - * - * @param b the context - * @param elementType the element type of the array to be instantiated - * @param length the length of the new array - * @return true if the plugin handles the bytecode, false otherwise - */ - default boolean handleNewArray(GraphBuilderContext b, ResolvedJavaType elementType, ValueNode length) { - return false; - } - - /** - * Handle the parsing of a MULTIANEWARRAY bytecode. If the method returns true, it must - * {@link GraphBuilderContext#push push} a value with the result of the allocation using - * {@link JavaKind#Object}. - * - * @param b the context - * @param type the type of the outermost array to be instantiated - * @param dimensions the array of lengths for all the dimensions to be instantiated - * @return true if the plugin handles the bytecode, false otherwise - */ - default boolean handleNewMultiArray(GraphBuilderContext b, ResolvedJavaType type, ValueNode[] dimensions) { - return false; - } - - /** - * If the plugin {@link GraphBuilderContext#push pushes} a value with a different - * {@link JavaKind} than specified by the bytecode, it must override this method and return - * {@code true}. This disables assertion checking for value kinds. - * - * @param b the context - */ - default boolean canChangeStackKind(GraphBuilderContext b) { - return false; - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ParameterPlugin.java --- a/graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/ParameterPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2015, 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.graphbuilderconf; - -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.nodes.calc.FloatingNode; - -public interface ParameterPlugin extends GraphBuilderPlugin { - FloatingNode interceptParameter(GraphBuilderContext b, int index, Stamp stamp); -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java --- a/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.amd64.test/src/com/oracle/graal/hotspot/amd64/test/DataPatchInConstantsTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -29,18 +29,17 @@ import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Assume; import org.junit.Before; import org.junit.Test; -import com.oracle.graal.api.replacements.ClassSubstitution; -import com.oracle.graal.api.replacements.MethodSubstitution; import com.oracle.graal.asm.amd64.AMD64Address; import com.oracle.graal.asm.amd64.AMD64MacroAssembler; import com.oracle.graal.graph.NodeClass; import com.oracle.graal.hotspot.nodes.CompressionNode; -import com.oracle.graal.hotspot.nodes.CompressionNode.CompressionOp; import com.oracle.graal.hotspot.nodes.type.NarrowOopStamp; import com.oracle.graal.hotspot.test.HotSpotGraalCompilerTest; import com.oracle.graal.lir.LIRInstruction; @@ -51,6 +50,10 @@ import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.FixedWithNextNode; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.spi.LIRLowerable; import com.oracle.graal.nodes.spi.NodeLIRBuilderTool; @@ -135,30 +138,28 @@ test("compareSnippet"); } - private static boolean initReplacements = false; - - @Before - public void initReplacements() { - if (!initReplacements) { - getReplacements().registerSubstitutions(DataPatchInConstantsTest.class, DataPatchInConstantsTestSubstitutions.class); - initReplacements = true; - } - } + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + Registration r = new Registration(plugins.getInvocationPlugins(), DataPatchInConstantsTest.class); - @ClassSubstitution(DataPatchInConstantsTest.class) - private static class DataPatchInConstantsTestSubstitutions { + r.register1("loadThroughPatch", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + b.addPush(JavaKind.Object, new LoadThroughPatchNode(arg)); + return true; + } + }); - @MethodSubstitution - public static Object loadThroughPatch(Object obj) { - return LoadThroughPatchNode.load(obj); - } + r.register1("loadThroughCompressedPatch", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + ValueNode compressed = b.add(CompressionNode.compress(arg, config().getOopEncoding())); + ValueNode patch = b.add(new LoadThroughPatchNode(compressed)); + b.addPush(JavaKind.Object, CompressionNode.uncompress(patch, config().getOopEncoding())); + return true; + } + }); - @MethodSubstitution - public static Object loadThroughCompressedPatch(Object obj) { - Object compressed = CompressionNode.compression(CompressionOp.Compress, obj, config().getOopEncoding()); - Object patch = LoadThroughPatchNode.load(compressed); - return CompressionNode.compression(CompressionOp.Uncompress, patch, config().getOopEncoding()); - } + return plugins; } @NodeInfo @@ -181,9 +182,6 @@ gen.append(new LoadThroughPatchOp(input.asConstant(), stamp() instanceof NarrowOopStamp, ret)); generator.setResult(this, ret); } - - @NodeIntrinsic - public static native Object load(Object obj); } private static final class LoadThroughPatchOp extends LIRInstruction { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Nov 30 16:41:10 2015 -0800 @@ -45,7 +45,6 @@ import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.amd64.AMD64SuitesProvider; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.hotspot.DefaultHotSpotGraalCompilerFactory; import com.oracle.graal.hotspot.HotSpotBackend; import com.oracle.graal.hotspot.HotSpotBackendFactory; @@ -63,9 +62,11 @@ import com.oracle.graal.hotspot.meta.HotSpotStampProvider; import com.oracle.graal.hotspot.meta.HotSpotSuitesProvider; import com.oracle.graal.hotspot.word.HotSpotWordTypes; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.tiers.CompilerConfiguration; import com.oracle.graal.phases.util.Providers; import com.oracle.graal.replacements.amd64.AMD64GraphBuilderPlugins; +import com.oracle.graal.word.WordTypes; @ServiceProvider(HotSpotBackendFactory.class) public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { @@ -112,15 +113,15 @@ HotSpotStampProvider stampProvider = new HotSpotStampProvider(); Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider); + try (InitTimer rt = timer("create WordTypes")) { + wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); + } try (InitTimer rt = timer("create SnippetReflection provider")) { - snippetReflection = createSnippetReflection(graalRuntime, constantReflection); + snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); } try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(config, p, snippetReflection); } - try (InitTimer rt = timer("create WordTypes")) { - wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); - } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { plugins = createGraphBuilderPlugins(config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); @@ -166,8 +167,8 @@ registers.getHeapBaseRegister())); } - protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection) { - return new HotSpotSnippetReflectionProvider(runtime, constantReflection); + protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { + return new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); } protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls, diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Nov 30 16:41:10 2015 -0800 @@ -324,11 +324,9 @@ RegisterConfig regConfig = frameMap.getRegisterConfig(); HotSpotVMConfig config = config(); Label unverifiedStub = installedCodeOwner == null || installedCodeOwner.isStatic() ? null : new Label(); - boolean hasUnsafeAccess = crb.compilationResult.hasUnsafeAccess(); - int i = 0; - do { + for (int i = 0; i < 2; i++) { if (i > 0) { - crb.reset(); + crb.resetForEmittingCode(); lir.resetLabels(); resetDelayedControlTransfers(lir); } @@ -358,9 +356,7 @@ // Emit code for the LIR crb.emit(lir); - } while (i++ < 1); - // Restore the unsafeAccess flag - crb.compilationResult.setHasUnsafeAccess(hasUnsafeAccess); + } profileInstructions(lir, crb); HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Nov 30 16:41:10 2015 -0800 @@ -42,7 +42,6 @@ import com.oracle.graal.compiler.sparc.SPARCAddressLowering; import com.oracle.graal.compiler.sparc.SPARCSuitesProvider; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.hotspot.DefaultHotSpotGraalCompilerFactory; import com.oracle.graal.hotspot.HotSpotBackend; import com.oracle.graal.hotspot.HotSpotBackendFactory; @@ -59,6 +58,7 @@ import com.oracle.graal.hotspot.meta.HotSpotStampProvider; import com.oracle.graal.hotspot.meta.HotSpotSuitesProvider; import com.oracle.graal.hotspot.word.HotSpotWordTypes; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.LoweringProvider; import com.oracle.graal.phases.tiers.CompilerConfiguration; import com.oracle.graal.phases.util.Providers; @@ -88,9 +88,9 @@ LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, constantReflection, target); HotSpotStampProvider stampProvider = new HotSpotStampProvider(); Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null, stampProvider); - HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection); + HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); + HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, config, target); - HotSpotWordTypes wordTypes = new HotSpotWordTypes(metaAccess, target.wordJavaKind); Plugins plugins = createGraphBuilderPlugins(config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, codeCache); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -31,6 +31,8 @@ import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; import static com.oracle.graal.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; import static com.oracle.graal.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; +import static com.oracle.graal.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; +import static jdk.vm.ci.code.CallingConvention.Type.NativeCall; import static jdk.vm.ci.meta.LocationIdentity.any; import static jdk.vm.ci.meta.Value.ILLEGAL; import static jdk.vm.ci.sparc.SPARC.i0; @@ -87,6 +89,11 @@ link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS), config)); } + if (config.useCRC32Intrinsics) { + // This stub does callee saving + registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); + } + super.initialize(providers); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/DataPatchTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -30,17 +30,12 @@ import org.junit.Before; import org.junit.Test; +import com.oracle.graal.api.directives.GraalDirectives; import com.oracle.graal.api.replacements.ClassSubstitution; import com.oracle.graal.api.replacements.MethodSubstitution; import com.oracle.graal.compiler.test.GraalCompilerTest; -import com.oracle.graal.graph.NodeClass; import com.oracle.graal.hotspot.nodes.CompressionNode; import com.oracle.graal.hotspot.nodes.CompressionNode.CompressionOp; -import com.oracle.graal.nodeinfo.NodeInfo; -import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.calc.FloatingNode; -import com.oracle.graal.nodes.spi.LIRLowerable; -import com.oracle.graal.nodes.spi.NodeLIRBuilderTool; public class DataPatchTest extends GraalCompilerTest { @@ -93,27 +88,8 @@ @MethodSubstitution public static Object compressUncompress(Object obj) { Object compressed = CompressionNode.compression(CompressionOp.Compress, obj, config.getOopEncoding()); - Object proxy = ConstantFoldBarrier.wrap(compressed); + Object proxy = GraalDirectives.opaque(compressed); return CompressionNode.compression(CompressionOp.Uncompress, proxy, config.getOopEncoding()); } } - - @NodeInfo - private static final class ConstantFoldBarrier extends FloatingNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(ConstantFoldBarrier.class); - @Input protected ValueNode input; - - public ConstantFoldBarrier(ValueNode input) { - super(TYPE, input.stamp()); - this.input = input; - } - - public void generate(NodeLIRBuilderTool generator) { - generator.setResult(this, generator.operand(input)); - } - - @NodeIntrinsic - public static native Object wrap(Object object); - } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ForeignCallDeoptimizeTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ForeignCallDeoptimizeTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/ForeignCallDeoptimizeTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -22,50 +22,42 @@ */ package com.oracle.graal.hotspot.test; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; + import org.junit.Test; -import com.oracle.graal.api.replacements.ClassSubstitution; -import com.oracle.graal.api.replacements.MethodSubstitution; -import com.oracle.graal.api.test.Graal; -import com.oracle.graal.compiler.common.spi.ForeignCallDescriptor; +import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; import com.oracle.graal.compiler.test.GraalCompilerTest; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl; +import com.oracle.graal.hotspot.meta.HotSpotProviders; +import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.extended.ForeignCallNode; -import com.oracle.graal.nodes.spi.Replacements; -import com.oracle.graal.runtime.RuntimeProvider; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; /** * Tests that deoptimization upon exception handling works. */ public class ForeignCallDeoptimizeTest extends GraalCompilerTest { - private static boolean substitutionsInstalled; + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + ForeignCallsProvider foreignCalls = ((HotSpotProviders) getProviders()).getForeignCalls(); - public ForeignCallDeoptimizeTest() { - if (!substitutionsInstalled) { - Replacements replacements = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getReplacements(); - replacements.registerSubstitutions(ForeignCallDeoptimizeTest.class, Substitutions.class); - substitutionsInstalled = true; - } - } + Plugins ret = super.getDefaultGraphBuilderPlugins(); + ret.getInvocationPlugins().register(new InvocationPlugin() { - @ClassSubstitution(ForeignCallDeoptimizeTest.class) - static class Substitutions { - - @MethodSubstitution(isStatic = true) - static int testCallInt(int value) { - return testDeoptimizeCallInt(HotSpotForeignCallsProviderImpl.TEST_DEOPTIMIZE_CALL_INT, value); - } + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + ForeignCallNode node = new ForeignCallNode(foreignCalls, HotSpotForeignCallsProviderImpl.TEST_DEOPTIMIZE_CALL_INT, arg); + b.addPush(JavaKind.Int, node); + return true; + } + }, ForeignCallDeoptimizeTest.class, "testCallInt", int.class); + return ret; } - /** - * Exercise deoptimization inside of a non leaf runtime call. - */ - @NodeIntrinsic(ForeignCallNode.class) - static native int testDeoptimizeCallInt(@ConstantNodeParameter ForeignCallDescriptor descriptor, int value); - public static int testCallInt(int value) { return value; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotCryptoSubstitutionTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.test; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import java.io.ByteArrayOutputStream; @@ -44,14 +44,14 @@ import org.junit.Assert; import org.junit.Test; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; import com.oracle.graal.hotspot.meta.HotSpotGraphBuilderPlugins; import com.oracle.graal.hotspot.meta.HotSpotProviders; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.OptimisticOptimizations; /** diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/JVMCIErrorTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/JVMCIErrorTest.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2015, 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.test; - -import java.util.function.Consumer; - -import jdk.vm.ci.code.CompilationResult; -import jdk.vm.ci.code.CompilationResult.ConstantReference; -import jdk.vm.ci.code.CompilationResult.DataPatch; -import jdk.vm.ci.code.CompilationResult.DataSectionReference; -import jdk.vm.ci.code.CompilationResult.Infopoint; -import jdk.vm.ci.code.CompilationResult.Reference; -import jdk.vm.ci.code.DataSection.Data; -import jdk.vm.ci.code.DataSection.DataBuilder; -import jdk.vm.ci.code.InfopointReason; -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.hotspot.HotSpotConstant; -import jdk.vm.ci.meta.Assumptions.Assumption; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.VMConstant; - -import org.junit.Test; - -import com.oracle.graal.compiler.test.GraalCompilerTest; - -public class JVMCIErrorTest extends GraalCompilerTest { - - public static void testMethod() { - } - - private void test(Consumer modify) { - ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - CompilationResult compResult = compile(method, null); - - modify.accept(compResult); - - getCodeCache().addCode(method, compResult, null, null); - } - - @Test(expected = JVMCIError.class) - public void testInvalidAssumption() { - test(r -> r.setAssumptions(new Assumption[]{new InvalidAssumption()})); - } - - private static class InvalidAssumption extends Assumption { - } - - @Test(expected = JVMCIError.class) - public void testInvalidAlignment() { - test(r -> r.getDataSection().insertData(new Data(7, 1, DataBuilder.zero(1)))); - } - - @Test(expected = JVMCIError.class) - public void testInvalidDataSectionReference() { - test(r -> { - DataSectionReference ref = r.getDataSection().insertData(new Data(1, 1, DataBuilder.zero(1))); - Data data = new Data(1, 1, (buffer, patch) -> { - patch.accept(new DataPatch(buffer.position(), ref)); - buffer.put((byte) 0); - }); - r.getDataSection().insertData(data); - }); - } - - @Test(expected = JVMCIError.class) - public void testInvalidNarrowMethodInDataSection() { - test(r -> { - ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - HotSpotConstant c = (HotSpotConstant) method.getEncoding(); - Data data = new Data(4, 4, (buffer, patch) -> { - patch.accept(new DataPatch(buffer.position(), new ConstantReference((VMConstant) c.compress()))); - buffer.putInt(0); - }); - r.getDataSection().insertData(data); - }); - } - - @Test(expected = JVMCIError.class) - public void testInvalidConstantInDataSection() { - test(r -> { - Data data = new Data(1, 1, (buffer, patch) -> { - patch.accept(new DataPatch(buffer.position(), new ConstantReference(new InvalidVMConstant()))); - }); - r.getDataSection().insertData(data); - }); - } - - @Test(expected = JVMCIError.class) - public void testInvalidConstantInCode() { - test(r -> r.recordDataPatch(0, new ConstantReference(new InvalidVMConstant()))); - } - - private static class InvalidVMConstant implements VMConstant { - - public boolean isDefaultForKind() { - return false; - } - - public String toValueString() { - return null; - } - } - - @Test(expected = JVMCIError.class) - public void testInvalidReference() { - test(r -> r.recordDataPatch(0, new InvalidReference())); - } - - private static class InvalidReference extends Reference { - - @Override - public int hashCode() { - return 0; - } - - @Override - public boolean equals(Object obj) { - return false; - } - } - - @Test(expected = JVMCIError.class) - public void testOutOfBoundsDataSectionReference() { - test(r -> { - DataSectionReference ref = new DataSectionReference(); - ref.setOffset(0x1000); - r.recordDataPatch(0, ref); - }); - } - - @Test(expected = JVMCIError.class) - public void testInvalidMark() { - test(r -> r.recordMark(0, new Object())); - } - - @Test(expected = JVMCIError.class) - public void testInvalidMarkInt() { - test(r -> r.recordMark(0, -1)); - } - - @Test(expected = JVMCIError.class) - public void testUnknownInfopointReason() { - test(r -> r.addInfopoint(new Infopoint(0, null, InfopointReason.UNKNOWN))); - } - - @Test(expected = JVMCIError.class) - public void testInfopointMissingDebugInfo() { - test(r -> r.addInfopoint(new Infopoint(0, null, InfopointReason.METHOD_START))); - } - - @Test(expected = JVMCIError.class) - public void testSafepointMissingDebugInfo() { - test(r -> r.addInfopoint(new Infopoint(0, null, InfopointReason.SAFEPOINT))); - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalCompiler.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.common.GraalOptions.OptAssumptions; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import static jdk.vm.ci.code.CallingConvention.Type.JavaCallee; import static jdk.vm.ci.code.CodeUtil.getCallingConvention; import jdk.vm.ci.code.CallingConvention; @@ -47,9 +47,6 @@ import com.oracle.graal.debug.TTY; import com.oracle.graal.debug.TopLevelDebugConfig; import com.oracle.graal.debug.internal.DebugScope; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; import com.oracle.graal.hotspot.meta.HotSpotProviders; import com.oracle.graal.hotspot.meta.HotSpotSuitesProvider; import com.oracle.graal.hotspot.phases.OnStackReplacementPhase; @@ -58,6 +55,9 @@ import com.oracle.graal.lir.phases.LIRSuites; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.OptimisticOptimizations.Optimization; @@ -137,10 +137,10 @@ // all code after the OSR loop is never executed. optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); } - CompilationResult result = GraalCompiler.compileGraph(graph, cc, method, providers, backend, getGraphBuilderSuite(providers, isOSR), optimisticOpts, profilingInfo, suites, lirSuites, - new CompilationResult(), CompilationResultBuilderFactory.Default); - + CompilationResult result = new CompilationResult(); result.setEntryBCI(entryBCI); + GraalCompiler.compileGraph(graph, cc, method, providers, backend, getGraphBuilderSuite(providers, isOSR), optimisticOpts, profilingInfo, suites, lirSuites, result, + CompilationResultBuilderFactory.Default); if (!isOSR) { ProfilingInfo profile = method.getProfilingInfo(); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/DefaultHotSpotLoweringProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -63,6 +63,7 @@ import com.oracle.graal.graph.NodeInputList; import com.oracle.graal.hotspot.HotSpotGraalRuntimeProvider; import com.oracle.graal.hotspot.nodes.CompressionNode; +import com.oracle.graal.hotspot.nodes.CompressionNode.CompressionOp; import com.oracle.graal.hotspot.nodes.ComputeObjectAddressNode; import com.oracle.graal.hotspot.nodes.G1ArrayRangePostWriteBarrier; import com.oracle.graal.hotspot.nodes.G1ArrayRangePreWriteBarrier; @@ -101,6 +102,7 @@ import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.LoweredCallTargetNode; import com.oracle.graal.nodes.ParameterNode; +import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.SafepointNode; import com.oracle.graal.nodes.StartNode; import com.oracle.graal.nodes.StructuredGraph; @@ -362,10 +364,11 @@ MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget(); NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); - GuardingNode receiverNullCheck = null; if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { - receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); - invoke.setGuard(receiverNullCheck); + GuardingNode receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); + PiNode nonNullReceiver = graph.unique(new PiNode(receiver, ((ObjectStamp) receiver.stamp()).join(StampFactory.objectNonNull()), (ValueNode) receiverNullCheck)); + parameters.set(0, nonNullReceiver); + receiver = nonNullReceiver; } JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); @@ -375,7 +378,7 @@ ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { JavaKind wordKind = runtime.getTarget().wordJavaKind; - ValueNode hub = createReadHub(graph, receiver, receiverNullCheck, tool); + ValueNode hub = createReadHub(graph, receiver, tool); ReadNode metaspaceMethod = createReadVirtualMethod(graph, hub, hsMethod, receiverType); // We use LocationNode.ANY_LOCATION for the reads that access the @@ -410,11 +413,11 @@ } @Override - protected ValueNode implicitLoadConvert(StructuredGraph graph, JavaKind kind, ValueNode value, boolean compressible) { + protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) { if (kind == JavaKind.Object && compressible && config().useCompressedOops) { - return CompressionNode.uncompress(value, config().getOopEncoding()); + return new CompressionNode(CompressionOp.Uncompress, value, config().getOopEncoding()); } - return super.implicitLoadConvert(graph, kind, value, compressible); + return super.implicitLoadConvert(kind, value, compressible); } @Override @@ -425,11 +428,11 @@ } @Override - protected ValueNode implicitStoreConvert(StructuredGraph graph, JavaKind kind, ValueNode value, boolean compressible) { + protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) { if (kind == JavaKind.Object && compressible && config().useCompressedOops) { - return CompressionNode.compress(value, config().getOopEncoding()); + return new CompressionNode(CompressionOp.Compress, value, config().getOopEncoding()); } - return super.implicitStoreConvert(graph, kind, value, compressible); + return super.implicitStoreConvert(kind, value, compressible); } @Override @@ -584,9 +587,9 @@ } @Override - protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard, LoweringTool tool) { + protected ValueNode createReadHub(StructuredGraph graph, ValueNode object, LoweringTool tool) { if (tool.getLoweringStage() != LoweringTool.StandardLoweringStage.LOW_TIER) { - return graph.unique(new LoadHubNode(tool.getStampProvider(), object, guard != null ? guard.asNode() : null)); + return graph.unique(new LoadHubNode(tool.getStampProvider(), object)); } assert !object.isConstant() || object.isNullConstant(); @@ -596,7 +599,7 @@ } AddressNode address = createOffsetAddress(graph, object, config().hubOffset); - FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, HUB_LOCATION, null, hubStamp, guard, BarrierType.NONE)); + FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, HUB_LOCATION, null, hubStamp, null, BarrierType.NONE)); if (config().useCompressedClassPointers) { return CompressionNode.uncompress(memoryRead, config().getKlassEncoding()); } else { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -39,18 +39,11 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.options.StableOptionValue; +import jdk.vm.ci.service.Services; import sun.reflect.Reflection; import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; -import com.oracle.graal.graphbuilderconf.ForeignCallPlugin; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; -import com.oracle.graal.graphbuilderconf.MethodSubstitutionPlugin; import com.oracle.graal.hotspot.nodes.ClassCastNode; import com.oracle.graal.hotspot.nodes.CurrentJavaThreadNode; import com.oracle.graal.hotspot.replacements.AESCryptSubstitutions; @@ -68,6 +61,15 @@ import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.ForeignCallPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; +import com.oracle.graal.nodes.graphbuilderconf.MethodSubstitutionPlugin; +import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; import com.oracle.graal.nodes.memory.HeapAccess.BarrierType; import com.oracle.graal.nodes.memory.address.AddressNode; import com.oracle.graal.nodes.memory.address.OffsetAddressNode; @@ -75,7 +77,7 @@ import com.oracle.graal.nodes.util.GraphUtil; import com.oracle.graal.replacements.InlineDuringParsingPlugin; import com.oracle.graal.replacements.MethodHandlePlugin; -import com.oracle.graal.replacements.NodeIntrinsificationPhase; +import com.oracle.graal.replacements.NodeIntrinsificationProvider; import com.oracle.graal.replacements.NodeIntrinsificationPlugin; import com.oracle.graal.replacements.ReplacementsImpl; import com.oracle.graal.replacements.StandardGraphBuilderPlugins; @@ -100,8 +102,8 @@ InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, metaAccess); Plugins plugins = new Plugins(invocationPlugins); - NodeIntrinsificationPhase nodeIntrinsificationPhase = new NodeIntrinsificationPhase(metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider); - NodeIntrinsificationPlugin nodeIntrinsificationPlugin = new NodeIntrinsificationPlugin(metaAccess, nodeIntrinsificationPhase, wordTypes, false); + NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes); + NodeIntrinsificationPlugin nodeIntrinsificationPlugin = new NodeIntrinsificationPlugin(); HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin, nodeIntrinsificationPlugin); @@ -125,6 +127,10 @@ registerCRC32Plugins(invocationPlugins, config); StandardGraphBuilderPlugins.registerInvocationPlugins(metaAccess, invocationPlugins, true); + for (NodeIntrinsicPluginFactory factory : Services.load(NodeIntrinsicPluginFactory.class)) { + factory.registerPlugin(invocationPlugins, nodeIntrinsificationProvider); + } + return plugins; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInvocationPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -30,12 +30,12 @@ import com.oracle.graal.compiler.common.GraalOptions; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.iterators.NodeIterable; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.hotspot.phases.AheadOfTimeVerificationPhase; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.FrameState; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; import com.oracle.graal.nodes.type.StampTool; import com.oracle.graal.replacements.nodes.MacroNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNodePlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNodePlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotNodePlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -34,13 +34,13 @@ import com.oracle.graal.api.replacements.Fold; import com.oracle.graal.compiler.common.type.Stamp; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.NodePlugin; -import com.oracle.graal.graphbuilderconf.ParameterPlugin; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.NodePlugin; +import com.oracle.graal.nodes.graphbuilderconf.ParameterPlugin; import com.oracle.graal.replacements.NodeIntrinsificationPlugin; import com.oracle.graal.replacements.WordOperationPlugin; import com.oracle.graal.word.Word; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -27,8 +27,8 @@ import jdk.vm.ci.meta.MetaAccessProvider; import com.oracle.graal.api.replacements.SnippetReflectionProvider; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.hotspot.word.HotSpotWordTypes; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.LoweringProvider; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.phases.tiers.SuitesProvider; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSnippetReflectionProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -28,20 +28,22 @@ import jdk.vm.ci.hotspot.HotSpotVMConfig; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.hotspot.HotSpotGraalRuntimeProvider; +import com.oracle.graal.word.WordTypes; public class HotSpotSnippetReflectionProvider implements SnippetReflectionProvider { private final HotSpotGraalRuntimeProvider runtime; private final HotSpotConstantReflectionProvider constantReflection; + private final WordTypes wordTypes; - public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection) { + public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { this.runtime = runtime; this.constantReflection = constantReflection; + this.wordTypes = wordTypes; } @Override @@ -88,29 +90,28 @@ } // Lazily initialized - private ResolvedJavaType wordTypesType; - private ResolvedJavaType runtimeType; - private ResolvedJavaType configType; + private Class wordTypesType; + private Class runtimeType; + private Class configType; - public Object getInjectedNodeIntrinsicParameter(ResolvedJavaType type) { + public T getInjectedNodeIntrinsicParameter(Class type) { // Need to test all fields since there no guarantee under the JMM // about the order in which these fields are written. HotSpotVMConfig config = config(); if (configType == null || wordTypesType == null || configType == null) { - MetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess(); - wordTypesType = metaAccess.lookupJavaType(runtime.getHostProviders().getWordTypes().getClass()); - runtimeType = metaAccess.lookupJavaType(runtime.getClass()); - configType = metaAccess.lookupJavaType(config.getClass()); + wordTypesType = wordTypes.getClass(); + runtimeType = runtime.getClass(); + configType = config.getClass(); } if (type.isAssignableFrom(wordTypesType)) { - return runtime.getHostProviders().getWordTypes(); + return type.cast(wordTypes); } if (type.isAssignableFrom(runtimeType)) { - return runtime; + return type.cast(runtime); } if (type.isAssignableFrom(configType)) { - return config; + return type.cast(config); } return null; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -28,8 +28,6 @@ import jdk.vm.ci.options.DerivedOptionValue; import jdk.vm.ci.options.DerivedOptionValue.OptionSupplier; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.DebugInfoMode; import com.oracle.graal.hotspot.HotSpotBackend; import com.oracle.graal.hotspot.HotSpotGraalRuntimeProvider; import com.oracle.graal.hotspot.HotSpotInstructionProfiling; @@ -44,6 +42,8 @@ import com.oracle.graal.nodes.SimplifyingGraphDecoder; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.DebugInfoMode; import com.oracle.graal.phases.BasePhase; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.common.AddressLoweringPhase; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotWordOperationPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -35,7 +35,6 @@ import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.common.type.Stamp; import com.oracle.graal.compiler.common.type.StampFactory; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.hotspot.nodes.LoadIndexedPointerNode; import com.oracle.graal.hotspot.nodes.type.KlassPointerStamp; import com.oracle.graal.hotspot.nodes.type.MetaspacePointerStamp; @@ -48,6 +47,7 @@ import com.oracle.graal.nodes.calc.ConditionalNode; import com.oracle.graal.nodes.calc.IsNullNode; import com.oracle.graal.nodes.calc.PointerEqualsNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.nodes.java.LoadIndexedNode; import com.oracle.graal.nodes.memory.HeapAccess.BarrierType; import com.oracle.graal.nodes.memory.ReadNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AcquiredCASLockNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/AcquiredCASLockNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 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.compiler.common.type.StampFactory; +import com.oracle.graal.graph.NodeClass; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.FixedWithNextNode; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.spi.LIRLowerable; +import com.oracle.graal.nodes.spi.NodeLIRBuilderTool; + +/** + * Marks the control flow path where an object acquired a lightweight lock based on an atomic + * compare-and-swap (CAS) of the mark word in the object's header. + */ +@NodeInfo +public final class AcquiredCASLockNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AcquiredCASLockNode.class); + + @Input ValueNode object; + + public AcquiredCASLockNode(ValueNode object) { + super(TYPE, StampFactory.forVoid()); + this.object = object; + } + + public ValueNode object() { + return object; + } + + public void generate(NodeLIRBuilderTool generator) { + // This is just a marker node so it generates nothing + } + + @NodeIntrinsic + public static native void mark(Object object); +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CRC32Substitutions.java Mon Nov 30 16:41:10 2015 -0800 @@ -48,7 +48,7 @@ * Gets the address of {@code StubRoutines::x86::_crc_table} in {@code stubRoutines_x86.hpp}. */ @Fold - private static long crcTableAddress() { + static long crcTableAddress() { return config().crcTableAddress; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -41,6 +41,7 @@ import com.oracle.graal.hotspot.nodes.SnippetAnchorNode; import com.oracle.graal.hotspot.word.KlassPointer; import com.oracle.graal.nodes.DeoptimizeNode; +import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.extended.GuardingNode; @@ -64,7 +65,7 @@ isNull.inc(); } else { GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (!checkUnknownSubType(hub, objectHub)) { DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CipherBlockChainingSubstitutions.java Mon Nov 30 16:41:10 2015 -0800 @@ -71,7 +71,7 @@ } @Fold - private static Class getAESCryptClass() { + static Class getAESCryptClass() { return AESCryptSubstitutions.AESCryptClass; } @@ -79,7 +79,7 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); return inLength; } else { @@ -91,7 +91,7 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); return inLength; } else { @@ -103,7 +103,7 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); return inLength; } else { @@ -115,7 +115,7 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); return inLength; } else { @@ -131,7 +131,7 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); return inLength; } else { @@ -146,7 +146,7 @@ Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); return inLength; } else { @@ -157,7 +157,7 @@ private static void crypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset, Object embeddedCipher, boolean encrypt, boolean withOriginalKey) { AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object aesCipher = PiNode.piCastNonNull(embeddedCipher, AESCryptSubstitutions.AESCryptClass); + Object aesCipher = getAESCryptClass().cast(embeddedCipher); Object kObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassGetHubNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -91,7 +91,7 @@ } if (clazz instanceof GetClassNode) { GetClassNode getClass = (GetClassNode) clazz; - return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject(), null); + return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject()); } if (clazz instanceof HubGetClassNode) { // replace _klass._java_mirror._klass -> _klass diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Nov 30 16:41:10 2015 -0800 @@ -195,14 +195,14 @@ public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd"); @Fold - private static int threadTlabEndOffset() { + static int threadTlabEndOffset() { return config().threadTlabEndOffset(); } public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart"); @Fold - private static int threadTlabStartOffset() { + static int threadTlabStartOffset() { return config().threadTlabStartOffset(); } @@ -212,7 +212,7 @@ * @see HotSpotVMConfig#pendingExceptionOffset */ @Fold - private static int threadPendingExceptionOffset() { + static int threadPendingExceptionOffset() { return config().pendingExceptionOffset; } @@ -222,14 +222,14 @@ * @see HotSpotVMConfig#pendingDeoptimizationOffset */ @Fold - private static int threadPendingDeoptimizationOffset() { + static int threadPendingDeoptimizationOffset() { return config().pendingDeoptimizationOffset; } public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult"); @Fold - private static int objectResultOffset() { + static int objectResultOffset() { return config().threadObjectResultOffset; } @@ -503,7 +503,7 @@ }; @Fold - private static int hubOffset() { + static int hubOffset() { return config().hubOffset; } @@ -750,9 +750,6 @@ private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); @NodeIntrinsic(value = LoadHubNode.class) - public static native KlassPointer loadHubIntrinsic(Object object, GuardingNode anchor); - - @NodeIntrinsic(value = LoadHubNode.class) public static native KlassPointer loadHubIntrinsic(Object object); @Fold diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -60,6 +60,7 @@ import com.oracle.graal.hotspot.word.KlassPointer; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.DeoptimizeNode; +import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.TypeCheckHints; import com.oracle.graal.nodes.ValueNode; @@ -106,7 +107,7 @@ return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); // if we get an exact match: succeed immediately ExplodeLoopNode.explodeLoop(); for (int i = 0; i < hints.length; i++) { @@ -136,7 +137,7 @@ return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) { exactMiss.inc(); return falseValue; @@ -155,7 +156,7 @@ return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) { displayMiss.inc(); return falseValue; @@ -174,7 +175,7 @@ return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); // if we get an exact match: succeed immediately ExplodeLoopNode.explodeLoop(); for (int i = 0; i < hints.length; i++) { @@ -203,7 +204,7 @@ } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer hub = ClassGetHubNode.readClass(mirror, anchorNode); - KlassPointer objectHub = loadHubIntrinsic(object, anchorNode); + KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (hub.isNull() || !checkUnknownSubType(hub, objectHub)) { return falseValue; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -46,7 +46,6 @@ import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; -import static com.oracle.graal.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.probability; @@ -75,6 +74,7 @@ import com.oracle.graal.graph.iterators.NodeIterable; import com.oracle.graal.hotspot.meta.HotSpotProviders; import com.oracle.graal.hotspot.meta.HotSpotRegistersProvider; +import com.oracle.graal.hotspot.nodes.AcquiredCASLockNode; import com.oracle.graal.hotspot.nodes.CurrentLockNode; import com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode; import com.oracle.graal.hotspot.nodes.FastAcquireBiasedLockNode; @@ -91,6 +91,7 @@ import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.debug.DynamicCounterNode; +import com.oracle.graal.nodes.extended.BranchProbabilityNode; import com.oracle.graal.nodes.extended.ForeignCallNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.java.MonitorExitNode; @@ -128,25 +129,25 @@ * JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object) * size:32 ------------------------------------------>| (CMS free block) * PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object) - * + * * 64 bits: * -------- * unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object) * JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object) * PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object) * size:64 ----------------------------------------------------->| (CMS free block) - * + * * unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object) * JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object) * narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object) * unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block) - * + * * - hash contains the identity hash value: largest value is * 31 bits, see os::random(). Also, 64-bit vm's require * a hash value no bigger than 32 bits because they will not * properly generate a mask larger than that: see library_call.cpp * and c1_CodePatterns_sparc.cpp. - * + * * - the biased lock pattern is used to bias a lock toward a given * thread. When this pattern is set in the low three bits, the lock * is either biased toward a given thread or "anonymously" biased, @@ -155,12 +156,12 @@ * be performed by that thread without using atomic operations. * When a lock's bias is revoked, it reverts back to the normal * locking scheme described below. - * + * * Note that we are overloading the meaning of the "unlocked" state * of the header. Because we steal a bit from the age we can * guarantee that the bias pattern will never be seen for a truly * unlocked object. - * + * * Note also that the biased state contains the age bits normally * contained in the object header. Large increases in scavenge * times were seen when these bits were absent and an arbitrary age @@ -171,18 +172,18 @@ * a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM)) * to make room for the age bits & the epoch bits (used in support of * biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs). - * + * * [JavaThread* | epoch | age | 1 | 01] lock is biased toward given thread * [0 | epoch | age | 1 | 01] lock is anonymously biased - * + * * - the two lock bits are used to describe three states: locked/unlocked and monitor. - * + * * [ptr | 00] locked ptr points to real header on stack * [header | 0 | 01] unlocked regular object header * [ptr | 10] monitor inflated lock (header is wapped out) * [ptr | 11] marked used by markSweep to mark an object * not valid at any other time - * + * * We assume that stack/thread pointers have the lowest two bits cleared. * * @@ -202,7 +203,7 @@ private static final boolean PROFILE_CONTEXT = false; @Fold - private static boolean doProfile() { + static boolean doProfile() { return Options.ProfileMonitors.getValue(); } @@ -250,7 +251,7 @@ trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); trace(trace, " thread: 0x%016lx\n", thread); trace(trace, " tmp: 0x%016lx\n", tmp); - if (probability(FREQUENT_PROBABILITY, tmp.equal(0))) { + if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, tmp.equal(0))) { // Object is already biased to current thread -> done traceObject(trace, "+lock{bias:existing}", object, true); lockBiasExisting.inc(); @@ -259,7 +260,7 @@ } // Now check to see whether biasing is enabled for this object - if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern())))) { + if (probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern())))) { // Biasing not enabled -> fall through to lightweight locking unbiasable.inc(); } else { @@ -360,7 +361,7 @@ // Test if the object's mark word is unlocked, and if so, store the // (address of) the lock slot into the object's mark word. Word currentMark = compareAndSwap(OffsetAddressNode.address(object, markOffset()), unlockedMark, lock, MARK_WORD_LOCATION); - if (currentMark.notEqual(unlockedMark)) { + if (probability(BranchProbabilityNode.SLOW_PATH_PROBABILITY, currentMark.notEqual(unlockedMark))) { trace(trace, " currentMark: 0x%016lx\n", currentMark); // The mark word in the object header was not the same. // Either the object is locked by another thread or is already locked @@ -394,6 +395,7 @@ } else { traceObject(trace, "+lock{cas}", object, true); lockCas.inc(); + AcquiredCASLockNode.mark(object); } } @@ -426,7 +428,7 @@ // the bias bit would be clear. final Word mark = loadWordFromObject(object, markOffset()); trace(trace, " mark: 0x%016lx\n", mark); - if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern())))) { + if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern())))) { endLockScope(); decCounter(); traceObject(trace, "-lock{bias}", object, false); @@ -441,7 +443,7 @@ final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(), DISPLACED_MARK_WORD_LOCATION); trace(trace, " displacedMark: 0x%016lx\n", displacedMark); - if (displacedMark.equal(0)) { + if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { // Recursive locking => done traceObject(trace, "-lock{recursive}", object, false); unlockCasRecursive.inc(); @@ -669,7 +671,7 @@ private static native void monitorenterStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); @NodeIntrinsic(ForeignCallNode.class) - private static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); + public static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); /** * Counters for the various paths for acquiring a lock. The counters whose names start with diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -138,7 +138,7 @@ public static final ProfileMode PROFILE_MODE = ProfileMode.AllocatedTypes; @Fold - private static String createName(String path, String typeContext) { + static String createName(String path, String typeContext) { switch (PROFILE_MODE) { case AllocatingMethods: return ""; @@ -155,7 +155,7 @@ } @Fold - private static boolean doProfile() { + static boolean doProfile() { return ProfileAllocations.getValue(); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/RuntimeStringSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/RuntimeStringSnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/RuntimeStringSnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -49,7 +49,7 @@ public class RuntimeStringSnippets implements Snippets { @Fold - private static long valueOffset() { + static long valueOffset() { try { return UNSAFE.objectFieldOffset(String.class.getDeclaredField("value")); } catch (Exception e) { @@ -58,7 +58,7 @@ } @Fold - private static long hashOffset() { + static long hashOffset() { try { return UNSAFE.objectFieldOffset(String.class.getDeclaredField("hash")); } catch (Exception e) { @@ -67,7 +67,7 @@ } @Fold - private static long arrayBaseOffset() { + static long arrayBaseOffset() { return UNSAFE.arrayBaseOffset(char[].class); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -62,6 +62,7 @@ import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.InvokeNode; import com.oracle.graal.nodes.NamedLocationIdentity; +import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.extended.UnsafeLoadNode; @@ -173,8 +174,8 @@ public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass, @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { if (length > 0) { - KlassPointer srcHub = loadHub(nonNullSrc); - KlassPointer destHub = loadHub(nonNullDest); + KlassPointer srcHub = loadHub(PiNode.asNonNullObject(nonNullSrc)); + KlassPointer destHub = loadHub(PiNode.asNonNullObject(nonNullDest)); if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) { counter.inc(); copiedCounter.add(length); @@ -284,7 +285,7 @@ } @Fold - private static LocationIdentity getArrayLocation(JavaKind kind) { + static LocationIdentity getArrayLocation(JavaKind kind) { return NamedLocationIdentity.getArrayLocation(kind); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java Mon Nov 30 16:41:10 2015 -0800 @@ -144,7 +144,7 @@ } @Fold - private static LocationIdentity getArrayLocation(JavaKind kind) { + static LocationIdentity getArrayLocation(JavaKind kind) { return NamedLocationIdentity.getArrayLocation(kind); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -154,7 +154,7 @@ * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for * total size of the interpreter frames plus shadow page size. Bang one page at a time * because large sizes can bang beyond yellow and red zones. - * + * * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. */ final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); @@ -228,7 +228,7 @@ } @Fold - private static int stackShadowPages() { + static int stackShadowPages() { return config().useStackBanging ? config().stackShadowPages : 0; } @@ -241,57 +241,57 @@ */ @Deprecated @Fold - private static int stackBias() { + static int stackBias() { return config().stackBias; } @Fold - private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { + static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; } @Fold - private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { + static int deoptimizationUnrollBlockCallerAdjustmentOffset() { return config().deoptimizationUnrollBlockCallerAdjustmentOffset; } @Fold - private static int deoptimizationUnrollBlockNumberOfFramesOffset() { + static int deoptimizationUnrollBlockNumberOfFramesOffset() { return config().deoptimizationUnrollBlockNumberOfFramesOffset; } @Fold - private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { + static int deoptimizationUnrollBlockTotalFrameSizesOffset() { return config().deoptimizationUnrollBlockTotalFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockUnpackKindOffset() { + static int deoptimizationUnrollBlockUnpackKindOffset() { return config().deoptimizationUnrollBlockUnpackKindOffset; } @Fold - private static int deoptimizationUnrollBlockFrameSizesOffset() { + static int deoptimizationUnrollBlockFrameSizesOffset() { return config().deoptimizationUnrollBlockFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockFramePcsOffset() { + static int deoptimizationUnrollBlockFramePcsOffset() { return config().deoptimizationUnrollBlockFramePcsOffset; } @Fold - private static int deoptimizationUnrollBlockInitialInfoOffset() { + static int deoptimizationUnrollBlockInitialInfoOffset() { return config().deoptimizationUnrollBlockInitialInfoOffset; } @Fold - private static int deoptimizationUnpackDeopt() { + static int deoptimizationUnpackDeopt() { return config().deoptimizationUnpackDeopt; } @Fold - private static int deoptimizationUnpackUncommonTrap() { + static int deoptimizationUnpackUncommonTrap() { return config().deoptimizationUnpackUncommonTrap; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ExceptionHandlerStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -133,7 +133,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logExceptionHandlerStub"); } @@ -146,7 +146,7 @@ */ @Fold @SuppressWarnings("all") - private static boolean assertionsEnabled() { + static boolean assertionsEnabled() { boolean enabled = false; assert enabled = true; return enabled || cAssertionsEnabled(); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -84,7 +84,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logNewArrayStub"); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -126,7 +126,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logNewInstanceStub"); } @@ -294,7 +294,7 @@ } @Fold - private static boolean forceSlowPath() { + static boolean forceSlowPath() { return Boolean.getBoolean("graal.newInstanceStub.forceSlowPath"); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.stubs; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Method; @@ -34,15 +34,15 @@ import com.oracle.graal.debug.Debug; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; import com.oracle.graal.hotspot.HotSpotForeignCallLinkage; import com.oracle.graal.hotspot.meta.HotSpotProviders; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.LoweringTool; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.common.CanonicalizerPhase; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/StubUtil.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -47,6 +47,7 @@ import com.oracle.graal.hotspot.nodes.StubForeignCallNode; import com.oracle.graal.hotspot.nodes.VMErrorNode; import com.oracle.graal.hotspot.word.KlassPointer; +import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.extended.GuardingNode; import com.oracle.graal.replacements.Log; import com.oracle.graal.word.Pointer; @@ -241,7 +242,7 @@ fatal("oop not in heap: %p", oop.rawValue()); } - KlassPointer klass = loadHubIntrinsic(object, anchorNode); + KlassPointer klass = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (klass.isNull()) { fatal("klass for oop %p is null", oop.rawValue()); } @@ -251,22 +252,22 @@ } @Fold - private static long verifyOopCounterAddress() { + static long verifyOopCounterAddress() { return config().verifyOopCounterAddress; } @Fold - private static long verifyOopMask() { + static long verifyOopMask() { return config().verifyOopMask; } @Fold - private static long verifyOopBits() { + static long verifyOopBits() { return config().verifyOopBits; } @Fold - private static int hubOffset() { + static int hubOffset() { return config().hubOffset; } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UncommonTrapStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -156,7 +156,7 @@ } @Fold - private static int stackShadowPages() { + static int stackShadowPages() { return config().useStackBanging ? config().stackShadowPages : 0; } @@ -169,52 +169,52 @@ */ @Deprecated @Fold - private static int stackBias() { + static int stackBias() { return config().stackBias; } @Fold - private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { + static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; } @Fold - private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { + static int deoptimizationUnrollBlockCallerAdjustmentOffset() { return config().deoptimizationUnrollBlockCallerAdjustmentOffset; } @Fold - private static int deoptimizationUnrollBlockNumberOfFramesOffset() { + static int deoptimizationUnrollBlockNumberOfFramesOffset() { return config().deoptimizationUnrollBlockNumberOfFramesOffset; } @Fold - private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { + static int deoptimizationUnrollBlockTotalFrameSizesOffset() { return config().deoptimizationUnrollBlockTotalFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockFrameSizesOffset() { + static int deoptimizationUnrollBlockFrameSizesOffset() { return config().deoptimizationUnrollBlockFrameSizesOffset; } @Fold - private static int deoptimizationUnrollBlockFramePcsOffset() { + static int deoptimizationUnrollBlockFramePcsOffset() { return config().deoptimizationUnrollBlockFramePcsOffset; } @Fold - private static int deoptimizationUnrollBlockInitialInfoOffset() { + static int deoptimizationUnrollBlockInitialInfoOffset() { return config().deoptimizationUnrollBlockInitialInfoOffset; } @Fold - private static int deoptimizationUnpackDeopt() { + static int deoptimizationUnpackDeopt() { return config().deoptimizationUnpackDeopt; } @Fold - private static int deoptimizationUnpackUncommonTrap() { + static int deoptimizationUnpackUncommonTrap() { return config().deoptimizationUnpackUncommonTrap; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/UnwindExceptionToCallerStub.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -96,7 +96,7 @@ } @Fold - private static boolean logging() { + static boolean logging() { return Boolean.getBoolean("graal.logUnwindExceptionToCallerStub"); } @@ -109,7 +109,7 @@ */ @Fold @SuppressWarnings("all") - private static boolean assertionsEnabled() { + static boolean assertionsEnabled() { boolean enabled = false; assert enabled = true; return enabled || cAssertionsEnabled(); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java Mon Nov 30 16:41:10 2015 -0800 @@ -231,12 +231,12 @@ import static com.oracle.graal.compiler.common.GraalOptions.ResolveClassBeforeStaticInvoke; import static com.oracle.graal.compiler.common.GraalOptions.StressInvokeWithExceptionNode; import static com.oracle.graal.compiler.common.type.StampFactory.objectNonNull; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING; import static com.oracle.graal.java.BytecodeParserOptions.DumpDuringGraphBuilding; import static com.oracle.graal.java.BytecodeParserOptions.FailedLoopExplosionIsFatal; import static com.oracle.graal.java.BytecodeParserOptions.MaximumLoopExplosionCount; import static com.oracle.graal.java.BytecodeParserOptions.TraceInlineDuringParsing; import static com.oracle.graal.java.BytecodeParserOptions.TraceParserPlugins; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING; import static com.oracle.graal.nodes.type.StampTool.isPointerNonNull; import static java.lang.String.format; import static jdk.vm.ci.common.JVMCIError.guarantee; @@ -312,15 +312,6 @@ import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.NodeBitMap; import com.oracle.graal.graph.iterators.NodeIterable; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; -import com.oracle.graal.graphbuilderconf.LoopExplosionPlugin; -import com.oracle.graal.graphbuilderconf.NodePlugin; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.java.BciBlockMapping.ExceptionDispatchBlock; import com.oracle.graal.nodeinfo.InputType; @@ -393,6 +384,15 @@ import com.oracle.graal.nodes.extended.GuardedNode; import com.oracle.graal.nodes.extended.GuardingNode; import com.oracle.graal.nodes.extended.IntegerSwitchNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.LoopExplosionPlugin; +import com.oracle.graal.nodes.graphbuilderconf.NodePlugin; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; import com.oracle.graal.nodes.java.ArrayLengthNode; import com.oracle.graal.nodes.java.CheckCastNode; import com.oracle.graal.nodes.java.ExceptionObjectNode; @@ -1387,7 +1387,7 @@ protected void genThrow() { if (GraalOptions.OldInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) { - genInfoPointNode(InfopointReason.LINE_NUMBER, null); + genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); } ValueNode exception = frameState.pop(JavaKind.Object); @@ -2638,7 +2638,7 @@ if (GraalOptions.OldInfopoints.getValue() && graphBuilderConfig.insertNonSafepointDebugInfo() && !parsingIntrinsic()) { currentLineNumber = lnt != null ? lnt.getLineNumber(bci) : (graphBuilderConfig.insertFullDebugInfo() ? -1 : bci); if (currentLineNumber != previousLineNumber) { - genInfoPointNode(InfopointReason.LINE_NUMBER, null); + genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); previousLineNumber = currentLineNumber; } } @@ -3430,7 +3430,7 @@ if (skippedExceptionTypes != null) { for (ResolvedJavaType exceptionType : skippedExceptionTypes) { if (exceptionType.isAssignableFrom(resolvedType)) { - append(new DeoptimizeNode(DeoptimizationAction.None, TransferToInterpreter)); + append(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, TransferToInterpreter)); return; } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -25,9 +25,9 @@ import jdk.vm.ci.options.DerivedOptionValue; import jdk.vm.ci.options.DerivedOptionValue.OptionSupplier; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.lir.phases.LIRSuites; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.tiers.CompilerConfiguration; import com.oracle.graal.phases.tiers.HighTierContext; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java Mon Nov 30 16:41:10 2015 -0800 @@ -54,8 +54,6 @@ import com.oracle.graal.compiler.common.type.Stamp; import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.debug.Debug; -import com.oracle.graal.graphbuilderconf.IntrinsicContext.SideEffectsState; -import com.oracle.graal.graphbuilderconf.ParameterPlugin; import com.oracle.graal.java.BciBlockMapping.BciBlock; import com.oracle.graal.nodeinfo.Verbosity; import com.oracle.graal.nodes.AbstractMergeNode; @@ -71,6 +69,8 @@ import com.oracle.graal.nodes.ValuePhiNode; import com.oracle.graal.nodes.ValueProxyNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.ParameterPlugin; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.SideEffectsState; import com.oracle.graal.nodes.java.MonitorIdNode; import com.oracle.graal.nodes.util.GraphUtil; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, 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 @@ -26,9 +26,9 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; import com.oracle.graal.nodes.spi.StampProvider; import com.oracle.graal.phases.BasePhase; import com.oracle.graal.phases.OptimisticOptimizations; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir.jtt/src/com/oracle/graal/lir/jtt/LIRTest.java --- a/graal/com.oracle.graal.lir.jtt/src/com/oracle/graal/lir/jtt/LIRTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir.jtt/src/com/oracle/graal/lir/jtt/LIRTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,14 +38,14 @@ import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.graph.NodeClass; import com.oracle.graal.graph.NodeInputList; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.jtt.JTTTest; import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.FixedWithNextNode; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; import com.oracle.graal.nodes.spi.LIRLowerable; import com.oracle.graal.nodes.spi.NodeLIRBuilderTool; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceInterval.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceInterval.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceInterval.java Mon Nov 30 16:41:10 2015 -0800 @@ -266,21 +266,9 @@ NoSpillStore, /** - * One spill move has already been inserted. - */ - OneSpillStore, - - /** - * The interval is spilled multiple times or is spilled in a loop. Place the store somewhere - * on the dominator path between the definition and the usages. + * A spill move has already been inserted. */ - SpillInDominator, - - /** - * The interval should be stored immediately after its definition to prevent multiple - * redundant stores. - */ - StoreAtDefinition, + SpillStore, /** * The interval starts in memory (e.g. method parameter), so a store is never necessary. @@ -293,7 +281,7 @@ */ NoOptimization; - public static final EnumSet ALWAYS_IN_MEMORY = EnumSet.of(SpillInDominator, StoreAtDefinition, StartInMemory); + public static final EnumSet IN_MEMORY = EnumSet.of(SpillStore, StartInMemory); } /** @@ -526,7 +514,9 @@ } public void setSpillDefinitionPos(int pos) { - assert spillState() == SpillState.SpillInDominator || spillState() == SpillState.NoDefinitionFound || spillDefinitionPos() == -1 : "cannot set the position twice"; + assert spillState() == SpillState.NoDefinitionFound || spillState() == SpillState.NoSpillStore || spillDefinitionPos() == -1 : "cannot set the position twice"; + int to = to(); + assert pos < to : String.format("Cannot spill %s at %d", this, pos); splitParent().spillDefinitionPos = pos; } @@ -535,7 +525,8 @@ * {@code opId}. */ public boolean inMemoryAt(int opId) { - return SpillState.ALWAYS_IN_MEMORY.contains(spillState()) && !canMaterialize() && opId > spillDefinitionPos(); + SpillState spillSt = spillState(); + return spillSt == SpillState.StartInMemory || (spillSt == SpillState.SpillStore && opId > spillDefinitionPos() && !canMaterialize()); } void removeFirstUsePos() { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScan.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScan.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScan.java Mon Nov 30 16:41:10 2015 -0800 @@ -61,6 +61,7 @@ import com.oracle.graal.lir.LIRInstruction; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.ValueConsumer; import com.oracle.graal.lir.Variable; import com.oracle.graal.lir.VirtualStackSlot; @@ -488,6 +489,12 @@ return opId == 0 || blockForId(opId) != blockForId(opId - 1); } + boolean isBlockEnd(int opId) { + boolean isBlockBegin = isBlockBegin(opId + 2); + assert isBlockBegin == (instructionForId(opId & (~1)) instanceof BlockEndOp); + return isBlockBegin; + } + boolean coversBlockBegin(int opId1, int opId2) { return blockForId(opId1) != blockForId(opId2); } @@ -515,7 +522,7 @@ // * Phase 5: actual register allocation - private static boolean isSorted(T[] intervals) { + private static boolean isSortedByFrom(T[] intervals) { int from = -1; for (T interval : intervals) { assert interval != null; @@ -525,6 +532,16 @@ return true; } + private static boolean isSortedBySpillPos(TraceInterval[] intervals) { + int from = -1; + for (TraceInterval interval : intervals) { + assert interval != null; + assert from <= interval.spillDefinitionPos(); + from = interval.spillDefinitionPos(); + } + return true; + } + private static TraceInterval addToList(TraceInterval first, TraceInterval prev, TraceInterval interval) { TraceInterval newFirst = first; if (prev != null) { @@ -535,8 +552,17 @@ return newFirst; } - TraceInterval createUnhandledList(IntervalPredicate isList1) { - assert isSorted(sortedIntervals) : "interval list is not sorted"; + TraceInterval createUnhandledListByFrom(IntervalPredicate isList1) { + assert isSortedByFrom(sortedIntervals) : "interval list is not sorted"; + return createUnhandledList(isList1); + } + + TraceInterval createUnhandledListBySpillPos(IntervalPredicate isList1) { + assert isSortedBySpillPos(sortedIntervals) : "interval list is not sorted"; + return createUnhandledList(isList1); + } + + private TraceInterval createUnhandledList(IntervalPredicate isList1) { TraceInterval list1 = TraceInterval.EndMarker; @@ -576,7 +602,7 @@ } FixedInterval createFixedUnhandledList() { - assert isSorted(sortedFixedIntervals) : "interval list is not sorted"; + assert isSortedByFrom(sortedFixedIntervals) : "interval list is not sorted"; FixedInterval list1 = FixedInterval.EndMarker; @@ -686,6 +712,12 @@ sortedIntervals = combinedList; } + void sortIntervalsBySpillPos() { + // TODO (JE): better algorithm? + // conventional sort-algorithm for new intervals + Arrays.sort(sortedIntervals, (TraceInterval a, TraceInterval b) -> a.spillDefinitionPos() - b.spillDefinitionPos()); + } + // wrapper for Interval.splitChildAtOpId that performs a bailout in product mode // instead of returning null public TraceInterval splitChildAtOpId(TraceInterval interval, int opId, LIRInstruction.OperandMode mode) { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanEliminateSpillMovePhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanEliminateSpillMovePhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanEliminateSpillMovePhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -39,6 +39,7 @@ import com.oracle.graal.debug.Indent; import com.oracle.graal.lir.LIRInsertionBuffer; import com.oracle.graal.lir.LIRInstruction; +import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.LoadConstantOp; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.StandardOp.ValueMoveOp; @@ -49,11 +50,11 @@ final class TraceLinearScanEliminateSpillMovePhase extends TraceLinearScanAllocationPhase { - private static final IntervalPredicate mustStoreAtDefinition = new TraceLinearScan.IntervalPredicate() { + private static final IntervalPredicate spilledIntervals = new TraceLinearScan.IntervalPredicate() { @Override public boolean apply(TraceInterval i) { - return i.isSplitParent() && i.spillState() == SpillState.StoreAtDefinition; + return i.isSplitParent() && SpillState.IN_MEMORY.contains(i.spillState()); } }; @@ -72,15 +73,23 @@ @SuppressWarnings("try") private static void eliminateSpillMoves(TraceLinearScan allocator, boolean shouldEliminateSpillMoves, TraceBuilderResult traceBuilderResult) { try (Indent indent = Debug.logAndIndent("Eliminating unnecessary spill moves: Trace%d", traceBuilderResult.getTraceForBlock(allocator.sortedBlocks().get(0)))) { + allocator.sortIntervalsBySpillPos(); /* * collect all intervals that must be stored after their definition. The list is sorted * by Interval.spillDefinitionPos. */ - TraceInterval interval = allocator.createUnhandledList(mustStoreAtDefinition); + TraceInterval interval = allocator.createUnhandledListBySpillPos(spilledIntervals); if (DetailedAsserts.getValue()) { checkIntervals(interval); } + if (Debug.isLogEnabled()) { + try (Indent indent2 = Debug.logAndIndent("Sorted intervals")) { + for (TraceInterval i = interval; i != null; i = i.next) { + Debug.log("%5d: %s", i.spillDefinitionPos(), i); + } + } + } LIRInsertionBuffer insertionBuffer = new LIRInsertionBuffer(); for (AbstractBlockBase block : allocator.sortedBlocks()) { @@ -93,70 +102,75 @@ for (int j = 0; j < numInst; j++) { LIRInstruction op = instructions.get(j); int opId = op.id(); + try (Indent indent2 = Debug.logAndIndent("%5d %s", opId, op)) { - if (opId == -1) { - MoveOp move = (MoveOp) op; - /* - * Remove move from register to stack if the stack slot is guaranteed to - * be correct. Only moves that have been inserted by LinearScan can be - * removed. - */ - if (shouldEliminateSpillMoves && canEliminateSpillMove(allocator, block, move, lastOpId)) { + if (opId == -1) { + MoveOp move = (MoveOp) op; /* - * Move target is a stack slot that is always correct, so eliminate - * instruction. + * Remove move from register to stack if the stack slot is + * guaranteed to be correct. Only moves that have been inserted by + * LinearScan can be removed. */ - if (Debug.isLogEnabled()) { - if (move instanceof ValueMoveOp) { - ValueMoveOp vmove = (ValueMoveOp) move; - Debug.log("eliminating move from interval %d (%s) to %d (%s) in block %s", allocator.operandNumber(vmove.getInput()), vmove.getInput(), - allocator.operandNumber(vmove.getResult()), vmove.getResult(), block); - } else { - LoadConstantOp load = (LoadConstantOp) move; - Debug.log("eliminating constant load from %s to %d (%s) in block %s", load.getConstant(), allocator.operandNumber(load.getResult()), load.getResult(), block); + if (shouldEliminateSpillMoves && canEliminateSpillMove(allocator, block, move, lastOpId)) { + /* + * Move target is a stack slot that is always correct, so + * eliminate instruction. + */ + if (Debug.isLogEnabled()) { + if (move instanceof ValueMoveOp) { + ValueMoveOp vmove = (ValueMoveOp) move; + Debug.log("eliminating move from interval %d (%s) to %d (%s) in block %s", allocator.operandNumber(vmove.getInput()), vmove.getInput(), + allocator.operandNumber(vmove.getResult()), vmove.getResult(), block); + } else { + LoadConstantOp load = (LoadConstantOp) move; + Debug.log("eliminating constant load from %s to %d (%s) in block %s", load.getConstant(), allocator.operandNumber(load.getResult()), load.getResult(), + block); + } } + + // null-instructions are deleted by assignRegNum + instructions.set(j, null); } - // null-instructions are deleted by assignRegNum - instructions.set(j, null); - } - - } else { - lastOpId = opId; - /* - * Insert move from register to stack just after the beginning of the - * interval. - */ - assert interval == TraceInterval.EndMarker || interval.spillDefinitionPos() >= opId : "invalid order"; - assert interval == TraceInterval.EndMarker || (interval.isSplitParent() && interval.spillState() == SpillState.StoreAtDefinition) : "invalid interval"; + } else { + lastOpId = opId; + /* + * Insert move from register to stack just after the beginning of + * the interval. + */ + // assert interval == TraceInterval.EndMarker || + // interval.spillDefinitionPos() >= opId : "invalid order"; + assert interval == TraceInterval.EndMarker || (interval.isSplitParent() && SpillState.IN_MEMORY.contains(interval.spillState())) : "invalid interval"; - while (interval != TraceInterval.EndMarker && interval.spillDefinitionPos() == opId) { - if (!interval.canMaterialize()) { - if (!insertionBuffer.initialized()) { - /* - * prepare insertion buffer (appended when all instructions - * in the block are processed) - */ - insertionBuffer.init(instructions); - } + while (interval != TraceInterval.EndMarker && interval.spillDefinitionPos() == opId) { + Debug.log("handle %s", interval); + if (!interval.canMaterialize()) { + if (!insertionBuffer.initialized()) { + /* + * prepare insertion buffer (appended when all + * instructions in the block are processed) + */ + insertionBuffer.init(instructions); + } - AllocatableValue fromLocation = interval.location(); - AllocatableValue toLocation = TraceLinearScan.canonicalSpillOpr(interval); - if (!fromLocation.equals(toLocation)) { + AllocatableValue fromLocation = interval.getSplitChildAtOpId(opId, OperandMode.DEF, allocator).location(); + AllocatableValue toLocation = TraceLinearScan.canonicalSpillOpr(interval); + if (!fromLocation.equals(toLocation)) { - assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + - interval.spillState(); - assert isStackSlotValue(toLocation) : "to operand must be a stack slot"; + assert isRegister(fromLocation) : "from operand must be a register but is: " + fromLocation + " toLocation=" + toLocation + " spillState=" + + interval.spillState(); + assert isStackSlotValue(toLocation) : "to operand must be a stack slot"; - LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation); - insertionBuffer.append(j + 1, move); + LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation); + insertionBuffer.append(j + 1, move); - if (Debug.isLogEnabled()) { - Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); + if (Debug.isLogEnabled()) { + Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId); + } } } + interval = interval.next; } - interval = interval.next; } } } // end of instruction iteration @@ -202,13 +216,14 @@ while (temp != TraceInterval.EndMarker) { assert temp.spillDefinitionPos() >= 0 : "invalid spill definition pos"; if (prev != null) { - assert temp.from() >= prev.from() : "intervals not sorted"; + // assert temp.from() >= prev.from() : "intervals not sorted"; assert temp.spillDefinitionPos() >= prev.spillDefinitionPos() : "when intervals are sorted by from : then they must also be sorted by spillDefinitionPos"; } assert temp.spillSlot() != null || temp.canMaterialize() : "interval has no spill slot assigned"; assert temp.spillDefinitionPos() >= temp.from() : "invalid order"; - assert temp.spillDefinitionPos() <= temp.from() + 2 : "only intervals defined once at their start-pos can be optimized"; + // assert temp.spillDefinitionPos() <= temp.from() + 2 : + // "only intervals defined once at their start-pos can be optimized"; if (Debug.isLogEnabled()) { Debug.log("interval %d (from %d to %d) must be stored at %d", temp.operandNumber, temp.from(), temp.to(), temp.spillDefinitionPos()); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanLifetimeAnalysisPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanLifetimeAnalysisPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanLifetimeAnalysisPhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -330,8 +330,11 @@ op.forEachRegisterHint(targetValue, mode, (registerHint, valueMode, valueFlags) -> { if (TraceLinearScan.isVariableOrRegister(registerHint)) { - AllocatableValue fromValue; - AllocatableValue toValue; + /* + * TODO (je): clean up + */ + final AllocatableValue fromValue; + final AllocatableValue toValue; /* hints always point from def to use */ if (hintAtDef) { fromValue = (AllocatableValue) registerHint; @@ -340,14 +343,21 @@ fromValue = (AllocatableValue) targetValue; toValue = (AllocatableValue) registerHint; } + Debug.log("addRegisterHint %s to %s", fromValue, toValue); + final TraceInterval to; + final IntervalHint from; if (isRegister(toValue)) { - /* fixed register: no need for a hint */ - return null; + if (isRegister(fromValue)) { + // fixed to fixed move + return null; + } + from = getIntervalHint(toValue); + to = allocator.getOrCreateInterval(fromValue); + } else { + to = allocator.getOrCreateInterval(toValue); + from = getIntervalHint(fromValue); } - TraceInterval to = allocator.getOrCreateInterval(toValue); - IntervalHint from = getIntervalHint(fromValue); - to.setLocationHint(from); if (Debug.isLogEnabled()) { Debug.log("operation at opId %d: added hint from interval %s to %s", op.id(), from, to); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanRegisterAllocationPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanRegisterAllocationPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanRegisterAllocationPhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -48,7 +48,7 @@ private static void allocateRegisters(TraceLinearScan allocator) { try (Indent indent = Debug.logAndIndent("allocate registers")) { FixedInterval precoloredIntervals = allocator.createFixedUnhandledList(); - TraceInterval notPrecoloredIntervals = allocator.createUnhandledList(TraceLinearScan.IS_VARIABLE_INTERVAL); + TraceInterval notPrecoloredIntervals = allocator.createUnhandledListByFrom(TraceLinearScan.IS_VARIABLE_INTERVAL); // allocate cpu registers TraceLinearScanWalker lsw = new TraceLinearScanWalker(allocator, precoloredIntervals, notPrecoloredIntervals); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/trace/TraceLinearScanWalker.java Mon Nov 30 16:41:10 2015 -0800 @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; import java.util.List; import jdk.vm.ci.code.BailoutException; @@ -59,6 +60,7 @@ private final int[] usePos; private final int[] blockPos; + private final BitSet isInMemory; private List[] spillIntervals; @@ -94,12 +96,14 @@ super(allocator, unhandledFixedFirst, unhandledAnyFirst); moveResolver = allocator.createMoveResolver(); - spillIntervals = Util.uncheckedCast(new List[allocator.getRegisters().length]); - for (int i = 0; i < allocator.getRegisters().length; i++) { + int numRegs = allocator.getRegisters().length; + spillIntervals = Util.uncheckedCast(new List[numRegs]); + for (int i = 0; i < numRegs; i++) { spillIntervals[i] = EMPTY_LIST; } - usePos = new int[allocator.getRegisters().length]; - blockPos = new int[allocator.getRegisters().length]; + usePos = new int[numRegs]; + blockPos = new int[numRegs]; + isInMemory = new BitSet(numRegs); } private void initUseLists(boolean onlyProcessUsePos) { @@ -110,6 +114,7 @@ if (!onlyProcessUsePos) { blockPos[i] = Integer.MAX_VALUE; spillIntervals[i].clear(); + isInMemory.clear(i); } } } @@ -149,6 +154,10 @@ spillIntervals[i] = list; } list.add(interval); + // set is in memory flag + if (interval.inMemoryAt(currentPosition)) { + isInMemory.set(i); + } } } } @@ -319,16 +328,16 @@ return optimalSplitPos; } + @SuppressWarnings({"unused"}) private int findOptimalSplitPos(TraceInterval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) { - int optimalSplitPos = findOptimalSplitPos0(interval, minSplitPos, maxSplitPos, doLoopOptimization); + int optimalSplitPos = findOptimalSplitPos0(minSplitPos, maxSplitPos); if (Debug.isLogEnabled()) { Debug.log("optimal split position: %d", optimalSplitPos); } return optimalSplitPos; } - @SuppressWarnings({"unused"}) - private int findOptimalSplitPos0(TraceInterval interval, int minSplitPos, int maxSplitPos, boolean doLoopOptimization) { + private int findOptimalSplitPos0(int minSplitPos, int maxSplitPos) { // TODO (je) implement if (minSplitPos == maxSplitPos) { // trivial case, no optimization of split position possible @@ -557,39 +566,30 @@ } } - // called during register allocation + /** + * Change spill state of an interval. + * + * Note: called during register allocation. + * + * @param spillPos position of the spill + */ private void changeSpillState(TraceInterval interval, int spillPos) { if (TraceLinearScan.Options.LIROptTraceRAEliminateSpillMoves.getValue()) { switch (interval.spillState()) { - case NoSpillStore: { - int defLoopDepth = allocator.blockForId(interval.spillDefinitionPos()).getLoopDepth(); - int spillLoopDepth = allocator.blockForId(spillPos).getLoopDepth(); + case NoSpillStore: + final int minSpillPos = interval.spillDefinitionPos(); + final int maxSpillPost = spillPos; + + final int optimalSpillPos = findOptimalSpillPos(minSpillPos, maxSpillPost); - if (defLoopDepth < spillLoopDepth) { - /* - * The loop depth of the spilling position is higher then the loop depth at - * the definition of the interval. Move write to memory out of loop. - */ - // store at definition of the interval - interval.setSpillState(SpillState.StoreAtDefinition); - } else { - /* - * The interval is currently spilled only once, so for now there is no - * reason to store the interval at the definition. - */ - interval.setSpillState(SpillState.OneSpillStore); - } + // assert !allocator.isBlockBegin(optimalSpillPos); + assert !allocator.isBlockEnd(optimalSpillPos); + assert (optimalSpillPos & 1) == 0 : "Spill pos must be even"; + + interval.setSpillDefinitionPos(optimalSpillPos); + interval.setSpillState(SpillState.SpillStore); break; - } - - case OneSpillStore: { - // It is better to store it to memory at the definition. - interval.setSpillState(SpillState.StoreAtDefinition); - break; - } - - case SpillInDominator: - case StoreAtDefinition: + case SpillStore: case StartInMemory: case NoOptimization: case NoDefinitionFound: @@ -605,6 +605,87 @@ } /** + * @param minSpillPos minimal spill position + * @param maxSpillPos maximal spill position + */ + private int findOptimalSpillPos(int minSpillPos, int maxSpillPos) { + // TODO (JE): implement + int optimalSpillPos = findOptimalSpillPos0(minSpillPos, maxSpillPos) & (~1); + if (Debug.isLogEnabled()) { + Debug.log("optimal spill position: %d", optimalSpillPos); + } + return optimalSpillPos; + } + + private int findOptimalSpillPos0(int minSpillPos, int maxSpillPos) { + // TODO (je) implement + if (minSpillPos == maxSpillPos) { + // trivial case, no optimization of split position possible + if (Debug.isLogEnabled()) { + Debug.log("min-pos and max-pos are equal, no optimization possible"); + } + return minSpillPos; + + } + assert minSpillPos < maxSpillPos : "must be true then"; + assert minSpillPos >= 0 : "cannot access minSplitPos - 1 otherwise"; + + AbstractBlockBase minBlock = allocator.blockForId(minSpillPos); + AbstractBlockBase maxBlock = allocator.blockForId(maxSpillPos); + + assert minBlock.getLinearScanNumber() <= maxBlock.getLinearScanNumber() : "invalid order"; + if (minBlock == maxBlock) { + // split position cannot be moved to block boundary : so split as late as possible + if (Debug.isLogEnabled()) { + Debug.log("cannot move split pos to block boundary because minPos and maxPos are in same block"); + } + return maxSpillPos; + + } + // search optimal block boundary between minSplitPos and maxSplitPos + if (Debug.isLogEnabled()) { + Debug.log("moving split pos to optimal block boundary between block B%d and B%d", minBlock.getId(), maxBlock.getId()); + } + + // currently using the same heuristic as for splitting + return findOptimalSpillPos(minBlock, maxBlock, maxSpillPos); + } + + private int findOptimalSpillPos(AbstractBlockBase minBlock, AbstractBlockBase maxBlock, int maxSplitPos) { + int fromBlockNr = minBlock.getLinearScanNumber(); + int toBlockNr = maxBlock.getLinearScanNumber(); + + assert 0 <= fromBlockNr && fromBlockNr < blockCount() : "out of range"; + assert 0 <= toBlockNr && toBlockNr < blockCount() : "out of range"; + assert fromBlockNr < toBlockNr : "must cross block boundary"; + + /* + * Try to split at end of maxBlock. If this would be after maxSplitPos, then use the begin + * of maxBlock. We use last instruction -2 because we want to insert the move before the + * block end op. + */ + int optimalSplitPos = allocator.getLastLirInstructionId(maxBlock) - 2; + if (optimalSplitPos > maxSplitPos) { + optimalSplitPos = allocator.getFirstLirInstructionId(maxBlock); + } + + // minimal block probability + double minProbability = maxBlock.probability(); + for (int i = toBlockNr - 1; i >= fromBlockNr; i--) { + AbstractBlockBase cur = blockAt(i); + + if (cur.probability() < minProbability) { + // Block with lower probability found. Split at the end of this block. + minProbability = cur.probability(); + optimalSplitPos = allocator.getLastLirInstructionId(cur) - 2; + } + } + assert optimalSplitPos > allocator.maxOpId() || allocator.isBlockBegin(optimalSplitPos) || allocator.isBlockEnd(optimalSplitPos + 2) : "algorithm must move split pos to block boundary"; + + return optimalSplitPos; + } + + /** * This is called for every interval that is assigned to a stack slot. */ private static void handleSpillSlot(TraceInterval interval) { @@ -787,43 +868,55 @@ if (availableReg.equals(ignore)) { // this register must be ignored } else if (usePos[number] > regNeededUntil) { - if (reg == null || (usePos[number] > usePos[reg.number])) { + /* + * If the use position is the same, prefer registers (active intervals) + * where the value is already on the stack. + */ + if (reg == null || (usePos[number] > usePos[reg.number]) || (usePos[number] == usePos[reg.number] && (!isInMemory.get(reg.number) && isInMemory.get(number)))) { reg = availableReg; } } } + if (Debug.isLogEnabled()) { + Debug.log("Register Selected: %s", reg); + } + int regUsePos = (reg == null ? 0 : usePos[reg.number]); if (regUsePos <= firstShouldHaveUsage) { - if (Debug.isLogEnabled()) { - Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); - } - - if (firstUsage <= interval.from() + 1) { - if (registerPriority.equals(RegisterPriority.LiveAtLoopEnd)) { - /* - * Tool of last resort: we can not spill the current interval so we try - * to spill an active interval that has a usage but do not require a - * register. - */ - Debug.log("retry with register priority must have register"); - continue; + /* Check if there is another interval that is already in memory. */ + if (reg == null || interval.inMemoryAt(currentPosition) || !isInMemory.get(reg.number)) { + if (Debug.isLogEnabled()) { + Debug.log("able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); } - String description = "cannot spill interval (" + interval + ") that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + - ", interval.from()=" + interval.from() + "; already used candidates: " + Arrays.toString(availableRegs); - /* - * assign a reasonable register and do a bailout in product mode to avoid - * errors - */ - allocator.assignSpillSlot(interval); - Debug.dump(allocator.getLIR(), description); - allocator.printIntervals(description); - throw new OutOfRegistersException("LinearScan: no register found", description); + + if (firstUsage <= interval.from() + 1) { + if (registerPriority.equals(RegisterPriority.LiveAtLoopEnd)) { + /* + * Tool of last resort: we can not spill the current interval so we + * try to spill an active interval that has a usage but do not + * require a register. + */ + Debug.log("retry with register priority must have register"); + continue; + } + String description = "cannot spill interval (" + interval + ") that is used in first instruction (possible reason: no register found) firstUsage=" + firstUsage + + ", interval.from()=" + interval.from() + "; already used candidates: " + Arrays.toString(availableRegs); + /* + * assign a reasonable register and do a bailout in product mode to + * avoid errors + */ + allocator.assignSpillSlot(interval); + Debug.dump(allocator.getLIR(), description); + allocator.printIntervals(description); + throw new OutOfRegistersException("LinearScan: no register found", description); + } + + splitAndSpillInterval(interval); + return; } - - splitAndSpillInterval(interval); - return; } + // common case: break out of the loop break; } @@ -854,9 +947,9 @@ try (Indent indent2 = Debug.logAndIndent("state of registers:")) { for (Register reg : availableRegs) { int i = reg.number; - try (Indent indent3 = Debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, intervals: ", i, usePos[i], blockPos[i])) { + try (Indent indent3 = Debug.logAndIndent("reg %d: usePos: %d, blockPos: %d, inMemory: %b, intervals: ", i, usePos[i], blockPos[i], isInMemory.get(i))) { for (int j = 0; j < spillIntervals[i].size(); j++) { - Debug.log("%s ", spillIntervals[i].get(j)); + Debug.log("%s", spillIntervals[i].get(j)); } } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Nov 30 16:41:10 2015 -0800 @@ -147,7 +147,7 @@ /** * Sets the {@linkplain CompilationResult#setTargetCode(byte[], int) code} and * {@linkplain CompilationResult#recordExceptionHandler(int, int) exception handler} fields of - * the compilation result. + * the compilation result and then {@linkplain #closeCompilationResult() closes} it. */ public void finish() { int position = asm.position(); @@ -160,6 +160,14 @@ compilationResult.recordExceptionHandler(codeOffset, ei.exceptionEdge.label().position()); } } + closeCompilationResult(); + } + + /** + * Calls {@link CompilationResult#close()} on {@link #compilationResult}. + */ + protected void closeCompilationResult() { + compilationResult.close(); } public void recordExceptionHandlers(int pcOffset, LIRFrameState info) { @@ -417,9 +425,9 @@ } } - public void reset() { + public void resetForEmittingCode() { asm.reset(); - compilationResult.reset(); + compilationResult.resetForEmittingCode(); if (exceptionInfoList != null) { exceptionInfoList.clear(); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerator.java Mon Nov 30 16:41:10 2015 -0800 @@ -276,7 +276,7 @@ if (op instanceof SimpleInfopointOp) { currentInfo = null; } else if (currentInfo != null) { - lirForBlock.add(new SimpleInfopointOp(InfopointReason.LINE_NUMBER, currentInfo)); + lirForBlock.add(new SimpleInfopointOp(InfopointReason.BYTECODE_POSITION, currentInfo)); currentInfo = null; } lirForBlock.add(op); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.loop.phases/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java --- a/graal/com.oracle.graal.loop.phases/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.loop.phases/src/com/oracle/graal/loop/phases/LoopSafepointEliminationPhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -53,7 +53,7 @@ } } } - for (LoopEx loop : loops.countedLoops()) { + for (LoopEx loop : loops.loops()) { for (LoopEndNode loopEnd : loop.loopBegin().loopEnds()) { Block b = loops.getCFG().blockFor(loopEnd); blocks: while (b != loop.loop().getHeader()) { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Mon Nov 30 16:41:10 2015 -0800 @@ -258,7 +258,6 @@ } else { return false; } - oneOff = true; break; } case LE: diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/ArrayDuplicationBenchmark.java --- a/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/ArrayDuplicationBenchmark.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/ArrayDuplicationBenchmark.java Mon Nov 30 16:41:10 2015 -0800 @@ -33,7 +33,7 @@ import org.openjdk.jmh.annotations.TearDown; @State(Scope.Thread) -public class ArrayDuplicationBenchmark { +public class ArrayDuplicationBenchmark extends GraalBenchmark { /** How large should the test-arrays be. */ private static final int TESTSIZE = 300; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/SimpleSyncBenchmark.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/SimpleSyncBenchmark.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, 2015, 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.microbenchmarks.graal; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +/** + * Benchmarks cost of non-contended synchronization. + */ +public class SimpleSyncBenchmark extends GraalBenchmark { + + public static class Person { + public int age; + + public Person(int age) { + this.age = age; + } + + public synchronized int getAge() { + return age; + } + + public synchronized void setAge(int age) { + this.age = age; + } + + public synchronized void setAgeIfNonZero(int age) { + if (age != 0) { + this.age = age; + } + } + } + + @State(Scope.Benchmark) + public static class ThreadState { + Person person = new Person(22); + int newAge = 45; + } + + @Benchmark + @Warmup(iterations = 20) + public void setAgeCond(ThreadState state) { + Person person = state.person; + person.setAgeIfNonZero(state.newAge); + } + + @Benchmark + @Warmup(iterations = 20) + public int getAge(ThreadState state) { + Person person = state.person; + return person.getAge(); + } + + @Benchmark + @Warmup(iterations = 20) + public int getAndIncAge(ThreadState state) { + Person person = state.person; + int oldAge = person.getAge(); + person.setAge(oldAge + 1); + return oldAge; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/TestJMH.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/TestJMH.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 2015, 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.microbenchmarks.graal; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Warmup; + +@Warmup(iterations = 1) +@Measurement(iterations = 1) +@Fork(1) +/** + * This dummy class is used to verify that the JMH microbenchmarking environment is set up properly. + */ +public class TestJMH { + + @Benchmark + public void testJMH() { + // This method was intentionally left blank. + } + +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/GraalUtil.java --- a/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/GraalUtil.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.microbenchmarks/src/com/oracle/graal/microbenchmarks/graal/util/GraalUtil.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -29,11 +29,11 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import com.oracle.graal.graph.Node; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.tiers.HighTierContext; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ConstantNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -463,21 +463,25 @@ } public static ConstantNode defaultForKind(JavaKind kind, StructuredGraph graph) { + return unique(graph, defaultForKind(kind)); + } + + public static ConstantNode defaultForKind(JavaKind kind) { switch (kind) { case Boolean: case Byte: case Char: case Short: case Int: - return ConstantNode.forInt(0, graph); + return ConstantNode.forInt(0); case Double: - return ConstantNode.forDouble(0.0, graph); + return ConstantNode.forDouble(0.0); case Float: - return ConstantNode.forFloat(0.0f, graph); + return ConstantNode.forFloat(0.0f); case Long: - return ConstantNode.forLong(0L, graph); + return ConstantNode.forLong(0L); case Object: - return ConstantNode.forConstant(JavaConstant.NULL_POINTER, null, graph); + return ConstantNode.forConstant(JavaConstant.NULL_POINTER, null); default: return null; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -36,6 +36,9 @@ import com.oracle.graal.graph.spi.CanonicalizerTool; import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.extended.UnsafeLoadNode; +import com.oracle.graal.nodes.java.LoadFieldNode; +import com.oracle.graal.nodes.java.LoadIndexedNode; import com.oracle.graal.nodes.spi.LIRLowerable; import com.oracle.graal.nodes.spi.NodeLIRBuilderTool; import com.oracle.graal.nodes.spi.ValueProxy; @@ -79,6 +82,10 @@ this.piStamp = stamp; } + public PiNode(ValueNode object, ValueNode anchor) { + this(object, object.stamp().join(StampFactory.objectNonNull()), anchor); + } + public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { this(object, StampFactory.object(toType, exactType, nonNull || StampTool.isPointerNonNull(object.stamp()), true)); } @@ -116,19 +123,43 @@ return this; } inferStamp(); - if (stamp().equals(object().stamp())) { - return object(); + ValueNode o = object(); + + // The pi node does not give any additional information => skip it. + if (stamp().equals(o.stamp())) { + return o; } - if (getGuard() != null) { - for (PiNode otherPi : getGuard().asNode().usages().filter(PiNode.class)) { - if (object() == otherPi.object() && stamp().equals(otherPi.stamp())) { - /* - * Two PiNodes with the same guard and same result, so return the one with the - * more precise piStamp. - */ - Stamp newStamp = piStamp.join(otherPi.piStamp); - if (newStamp.equals(otherPi.piStamp)) { - return otherPi; + + GuardingNode g = getGuard(); + if (g == null) { + + // Try to merge the pi node with a load node. + if (o instanceof LoadFieldNode) { + LoadFieldNode loadFieldNode = (LoadFieldNode) o; + loadFieldNode.setStamp(loadFieldNode.stamp().improveWith(this.piStamp)); + return loadFieldNode; + } else if (o instanceof UnsafeLoadNode) { + UnsafeLoadNode unsafeLoadNode = (UnsafeLoadNode) o; + unsafeLoadNode.setStamp(unsafeLoadNode.stamp().improveWith(this.piStamp)); + return unsafeLoadNode; + } else if (o instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexedNode = (LoadIndexedNode) o; + loadIndexedNode.setStamp(loadIndexedNode.stamp().improveWith(this.piStamp)); + return loadIndexedNode; + } + } else { + for (Node n : g.asNode().usages()) { + if (n instanceof PiNode) { + PiNode otherPi = (PiNode) n; + if (o == otherPi.object() && stamp().equals(otherPi.stamp())) { + /* + * Two PiNodes with the same guard and same result, so return the one with + * the more precise piStamp. + */ + Stamp newStamp = piStamp.join(otherPi.piStamp); + if (newStamp.equals(otherPi.piStamp)) { + return otherPi; + } } } } @@ -148,6 +179,13 @@ return asNonNullClassIntrinsic(object, Class.class, true, true); } + /** + * Casts an object to have an exact, non-null stamp representing {@link Class}. + */ + public static Class asNonNullObject(Object object) { + return asNonNullClassIntrinsic(object, Object.class, false, true); + } + @NodeIntrinsic(PiNode.class) private static native Class asNonNullClassIntrinsic(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull); @@ -158,13 +196,20 @@ public static native Object piCast(Object object, @ConstantNodeParameter Stamp stamp); /** - * Changes the stamp of an object and ensures the newly stamped value does float above a given - * anchor. + * Changes the stamp of an object and ensures the newly stamped value does not float above a + * given anchor. */ @NodeIntrinsic public static native Object piCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); /** + * Changes the stamp of an object and ensures the newly stamped value is non-null and does not + * float above a given anchor. + */ + @NodeIntrinsic + public static native Object piCastNonNull(Object object, GuardingNode anchor); + + /** * Changes the stamp of an object to represent a given type and to indicate that the object is * not null. */ diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimplifyingGraphDecoder.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimplifyingGraphDecoder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SimplifyingGraphDecoder.java Mon Nov 30 16:41:10 2015 -0800 @@ -28,10 +28,15 @@ import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; +import com.oracle.graal.compiler.common.type.Stamp; import com.oracle.graal.graph.Graph; import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.NodeClass; import com.oracle.graal.graph.spi.Canonicalizable; import com.oracle.graal.graph.spi.CanonicalizerTool; +import com.oracle.graal.nodeinfo.NodeInfo; +import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.extended.GuardingNode; import com.oracle.graal.nodes.extended.IntegerSwitchNode; import com.oracle.graal.nodes.spi.StampProvider; import com.oracle.graal.nodes.util.GraphUtil; @@ -71,6 +76,20 @@ } } + @NodeInfo + static class CanonicalizeToNullNode extends FloatingNode implements Canonicalizable, GuardingNode { + public static final NodeClass TYPE = NodeClass.create(CanonicalizeToNullNode.class); + + protected CanonicalizeToNullNode(Stamp stamp) { + super(TYPE, stamp); + } + + @Override + public Node canonical(CanonicalizerTool tool) { + return null; + } + } + public SimplifyingGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, boolean canonicalizeReads, Architecture architecture) { super(architecture); this.metaAccess = metaAccess; @@ -149,43 +168,75 @@ } } + } else if (node instanceof FixedGuardNode) { + FixedGuardNode guard = (FixedGuardNode) node; + if (guard.getCondition() instanceof LogicConstantNode) { + LogicConstantNode condition = (LogicConstantNode) guard.getCondition(); + Node canonical; + if (condition.getValue() == guard.isNegated()) { + DeoptimizeNode deopt = new DeoptimizeNode(guard.getAction(), guard.getReason(), guard.getSpeculation()); + if (guard.stateBefore() != null) { + deopt.setStateBefore(guard.stateBefore()); + } + canonical = deopt; + } else { + /* + * The guard is unnecessary, but we cannot remove the node completely yet + * because there might be nodes that use it as a guard input. Therefore, we + * replace it with a more lightweight node (which is floating and has no + * inputs). + */ + canonical = new CanonicalizeToNullNode(node.stamp); + } + handleCanonicaliation(methodScope, loopScope, nodeOrderId, node, canonical); + } + } else if (node instanceof Canonicalizable) { Node canonical = ((Canonicalizable) node).canonical(new PECanonicalizerTool()); - if (canonical == null) { - /* - * This is a possible return value of canonicalization. However, we might need to - * add additional usages later on for which we need a node. Therefore, we just do - * nothing and leave the node in place. - */ - } else if (canonical != node) { - if (!canonical.isAlive()) { - assert !canonical.isDeleted(); - canonical = methodScope.graph.addOrUniqueWithInputs(canonical); - if (canonical instanceof FixedWithNextNode) { - methodScope.graph.addBeforeFixed(node, (FixedWithNextNode) canonical); - } else if (canonical instanceof ControlSinkNode) { - FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor(); - predecessor.setNext((ControlSinkNode) canonical); - node.safeDelete(); - for (Node successor : node.successors()) { - successor.safeDelete(); - } - - } else { - assert !(canonical instanceof FixedNode); - } - } - if (!node.isDeleted()) { - GraphUtil.unlinkFixedNode((FixedWithNextNode) node); - node.replaceAtUsages(canonical); - node.safeDelete(); - } - assert lookupNode(loopScope, nodeOrderId) == node; - registerNode(loopScope, nodeOrderId, canonical, true, false); + if (canonical != node) { + handleCanonicaliation(methodScope, loopScope, nodeOrderId, node, canonical); } } } + private void handleCanonicaliation(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node, Node c) { + Node canonical = c; + + if (canonical == null) { + /* + * This is a possible return value of canonicalization. However, we might need to add + * additional usages later on for which we need a node. Therefore, we just do nothing + * and leave the node in place. + */ + return; + } + + if (!canonical.isAlive()) { + assert !canonical.isDeleted(); + canonical = methodScope.graph.addOrUniqueWithInputs(canonical); + if (canonical instanceof FixedWithNextNode) { + methodScope.graph.addBeforeFixed(node, (FixedWithNextNode) canonical); + } else if (canonical instanceof ControlSinkNode) { + FixedWithNextNode predecessor = (FixedWithNextNode) node.predecessor(); + predecessor.setNext((ControlSinkNode) canonical); + node.safeDelete(); + for (Node successor : node.successors()) { + successor.safeDelete(); + } + + } else { + assert !(canonical instanceof FixedNode); + } + } + if (!node.isDeleted()) { + GraphUtil.unlinkFixedNode((FixedWithNextNode) node); + node.replaceAtUsages(canonical); + node.safeDelete(); + } + assert lookupNode(loopScope, nodeOrderId) == node; + registerNode(loopScope, nodeOrderId, canonical, true, false); + } + @Override protected Node handleFloatingNodeBeforeAdd(MethodScope methodScope, LoopScope loopScope, Node node) { if (node instanceof Canonicalizable) { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -27,6 +27,8 @@ import com.oracle.graal.compiler.common.calc.Condition; import com.oracle.graal.compiler.common.type.IntegerStamp; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.graph.NodeClass; import com.oracle.graal.graph.spi.Canonicalizable; import com.oracle.graal.graph.spi.CanonicalizerTool; @@ -83,7 +85,33 @@ @Override public boolean inferStamp() { - return updateStamp(trueValue.stamp().meet(falseValue.stamp())); + Stamp valueStamp = trueValue.stamp().meet(falseValue.stamp()); + if (condition instanceof IntegerLessThanNode) { + IntegerLessThanNode lessThan = (IntegerLessThanNode) condition; + if (lessThan.getX() == trueValue && lessThan.getY() == falseValue) { + // this encodes a min operation + JavaConstant constant = lessThan.getX().asJavaConstant(); + if (constant == null) { + constant = lessThan.getY().asJavaConstant(); + } + if (constant != null) { + IntegerStamp bounds = StampFactory.forInteger(constant.getJavaKind(), constant.getJavaKind().getMinValue(), constant.asLong()); + valueStamp = valueStamp.join(bounds); + } + } else if (lessThan.getX() == falseValue && lessThan.getY() == trueValue) { + // this encodes a max operation + JavaConstant constant = lessThan.getX().asJavaConstant(); + if (constant == null) { + constant = lessThan.getY().asJavaConstant(); + } + if (constant != null) { + IntegerStamp bounds = StampFactory.forInteger(constant.getJavaKind(), constant.asLong(), constant.getJavaKind().getMaxValue()); + valueStamp = valueStamp.join(bounds); + } + } + + } + return updateStamp(valueStamp); } public ValueNode trueValue() { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Mon Nov 30 16:41:10 2015 -0800 @@ -297,7 +297,7 @@ } } - if (graph.hasValueProxies()) { + if (graph.getGuardsStage() != GuardsStage.AFTER_FSA) { // The following loop can add new blocks to the end of the loop's block list. int size = loop.getBlocks().size(); for (int i = 0; i < size; ++i) { @@ -353,7 +353,7 @@ if (block.getLoop() == loop) { nextState = stepOut; } else { - assert block.loop == loop.getParent(); + assert block.loop == loop.getParent() : block; block.loop = c.loop; assert !c.loop.getBlocks().contains(block); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -42,6 +42,7 @@ import com.oracle.graal.nodes.DeoptimizingNode; import com.oracle.graal.nodes.FrameState; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; import com.oracle.graal.nodes.memory.AbstractMemoryCheckpoint; import com.oracle.graal.nodes.memory.MemoryCheckpoint; import com.oracle.graal.nodes.spi.LIRLowerable; @@ -61,11 +62,36 @@ protected final ForeignCallDescriptor descriptor; protected int bci = BytecodeFrame.UNKNOWN_BCI; - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, + ValueNode... arguments) { + ForeignCallNode node = new ForeignCallNode(foreignCalls, descriptor, arguments); + node.setStamp(returnStamp); + + /* + * Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the case + * that the foreign call can deoptimize. As with all deoptimization, we need a state in a + * non-intrinsic method. + */ + GraphBuilderContext nonIntrinsicAncestor = b.getNonIntrinsicAncestor(); + if (nonIntrinsicAncestor != null) { + node.setBci(nonIntrinsicAncestor.bci()); + } + + JavaKind returnKind = returnStamp.getStackKind(); + if (returnKind == JavaKind.Void) { + b.add(node); + } else { + b.addPush(returnKind, node); + } + + return true; + } + + public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { this(TYPE, foreignCalls, descriptor, arguments); } - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List arguments) { + public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp, List arguments) { super(TYPE, stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; @@ -73,7 +99,7 @@ assert descriptor.getArgumentTypes().length == this.arguments.size() : "wrong number of arguments to " + this; } - public ForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { + public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, Stamp stamp) { super(TYPE, stamp); this.arguments = new NodeInputList<>(this); this.descriptor = descriptor; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -34,9 +34,9 @@ import com.oracle.graal.graph.spi.CanonicalizerTool; import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.ConstantNode; -import com.oracle.graal.nodes.FloatingGuardedNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.calc.FloatingNode; import com.oracle.graal.nodes.spi.Lowerable; import com.oracle.graal.nodes.spi.LoweringTool; import com.oracle.graal.nodes.spi.StampProvider; @@ -47,7 +47,7 @@ * Loads an object's hub. The object is not null-checked by this operation. */ @NodeInfo -public final class LoadHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, Virtualizable { +public final class LoadHubNode extends FloatingNode implements Lowerable, Canonicalizable, Virtualizable { public static final NodeClass TYPE = NodeClass.create(LoadHubNode.class); @Input ValueNode value; @@ -67,20 +67,15 @@ if (synonym != null) { return synonym; } - return new LoadHubNode(stamp, value, null); + return new LoadHubNode(stamp, value); } public LoadHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode value) { - this(stampProvider, value, null); + this(hubStamp(stampProvider, value), value); } - public LoadHubNode(@InjectedNodeParameter StampProvider stampProvider, ValueNode value, ValueNode guard) { - this(hubStamp(stampProvider, value), value, guard); - } - - public LoadHubNode(Stamp stamp, ValueNode value, ValueNode guard) { - super(TYPE, stamp, (GuardingNode) guard); - assert value != guard; + public LoadHubNode(Stamp stamp, ValueNode value) { + super(TYPE, stamp); this.value = value; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCopyNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -25,93 +25,24 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.LocationIdentity; -import com.oracle.graal.compiler.common.type.StampFactory; -import com.oracle.graal.graph.NodeClass; -import com.oracle.graal.nodeinfo.InputType; -import com.oracle.graal.nodeinfo.NodeInfo; -import com.oracle.graal.nodes.FixedWithNextNode; -import com.oracle.graal.nodes.FrameState; -import com.oracle.graal.nodes.StateSplit; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; /** * Copy a value at a location specified as an offset relative to a source object to another location * specified as an offset relative to destination object. No null checks are performed. - * - * This node must be replaced during processing of node intrinsics with an {@link UnsafeLoadNode} - * and {@link UnsafeStoreNode} pair. */ -@NodeInfo -public final class UnsafeCopyNode extends FixedWithNextNode implements StateSplit { - - public static final NodeClass TYPE = NodeClass.create(UnsafeCopyNode.class); - @Input ValueNode sourceObject; - @Input ValueNode destinationObject; - @Input ValueNode sourceOffset; - @Input ValueNode destinationOffset; - protected final JavaKind accessKind; - protected final LocationIdentity locationIdentity; - @OptionalInput(InputType.State) FrameState stateAfter; - - public UnsafeCopyNode(ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, LocationIdentity locationIdentity) { - this(sourceObject, sourceOffset, destinationObject, destinationOffset, accessKind, locationIdentity, null); - } - - public UnsafeCopyNode(ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, LocationIdentity locationIdentity, - FrameState stateAfter) { - super(TYPE, StampFactory.forVoid()); - this.sourceObject = sourceObject; - this.sourceOffset = sourceOffset; - this.destinationObject = destinationObject; - this.destinationOffset = destinationOffset; - this.accessKind = accessKind; - this.locationIdentity = locationIdentity; - this.stateAfter = stateAfter; - assert accessKind != JavaKind.Void && accessKind != JavaKind.Illegal; - } - - public ValueNode sourceObject() { - return sourceObject; - } +public final class UnsafeCopyNode { - public ValueNode destinationObject() { - return destinationObject; - } - - public LocationIdentity getLocationIdentity() { - return locationIdentity; - } - - public ValueNode sourceOffset() { - return sourceOffset; - } - - public ValueNode destinationOffset() { - return destinationOffset; - } - - public JavaKind accessKind() { - return accessKind; - } - - public FrameState stateAfter() { - return stateAfter; - } - - public void setStateAfter(FrameState x) { - assert x == null || x.isAlive() : "frame state must be in a graph"; - updateUsages(stateAfter, x); - stateAfter = x; - } - - public boolean hasSideEffect() { + public static boolean intrinsify(GraphBuilderContext b, ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, + LocationIdentity locationIdentity) { + UnsafeLoadNode value = b.add(new UnsafeLoadNode(sourceObject, sourceOffset, accessKind, locationIdentity)); + b.add(new UnsafeStoreNode(destinationObject, destinationOffset, value, accessKind, locationIdentity)); return true; } - public FrameState getState() { - return stateAfter; - } - @NodeIntrinsic public static native void copy(Object srcObject, long srcOffset, Object destObject, long destOffset, @ConstantNodeParameter JavaKind kind, @ConstantNodeParameter LocationIdentity locationIdentity); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/ForeignCallPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/ForeignCallPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.compiler.common.spi.ForeignCallDescriptor; +import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.extended.ForeignCallNode; + +/** + * {@link InvocationPlugin} for converting a method call directly to a foreign call. + */ +public final class ForeignCallPlugin implements InvocationPlugin { + private final ForeignCallsProvider foreignCalls; + private final ForeignCallDescriptor descriptor; + + public ForeignCallPlugin(ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor) { + this.foreignCalls = foreignCalls; + this.descriptor = descriptor; + } + + public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) { + ForeignCallNode foreignCall = new ForeignCallNode(foreignCalls, descriptor, args); + foreignCall.setBci(b.bci()); + b.addPush(targetMethod.getSignature().getReturnKind(), foreignCall); + return true; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GeneratedInvocationPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GeneratedInvocationPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.nodes.ValueNode; + +public abstract class GeneratedInvocationPlugin implements InvocationPlugin { + + public abstract boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args); +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GraphBuilderConfiguration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GraphBuilderConfiguration.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2011, 2015, 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.graphbuilderconf; + +import java.util.Arrays; + +import jdk.vm.ci.meta.ResolvedJavaType; + +import com.oracle.graal.compiler.common.GraalOptions; +import com.oracle.graal.nodes.FullInfopointNode; +import com.oracle.graal.nodes.SimpleInfopointNode; + +public class GraphBuilderConfiguration { + + public static class Plugins { + private final InvocationPlugins invocationPlugins; + private NodePlugin[] nodePlugins; + private ParameterPlugin[] parameterPlugins; + private InlineInvokePlugin[] inlineInvokePlugins; + private LoopExplosionPlugin loopExplosionPlugin; + + /** + * Creates a copy of a given set of plugins. The {@link InvocationPlugins} in + * {@code copyFrom} become the {@linkplain InvocationPlugins#getParent() default} + * {@linkplain #getInvocationPlugins() invocation plugins} in this object. + */ + public Plugins(Plugins copyFrom) { + this.invocationPlugins = new InvocationPlugins(copyFrom.invocationPlugins); + this.nodePlugins = copyFrom.nodePlugins; + this.parameterPlugins = copyFrom.parameterPlugins; + this.inlineInvokePlugins = copyFrom.inlineInvokePlugins; + this.loopExplosionPlugin = copyFrom.loopExplosionPlugin; + } + + /** + * Creates a new set of plugins. + * + * @param invocationPlugins the {@linkplain #getInvocationPlugins() invocation plugins} in + * this object + */ + public Plugins(InvocationPlugins invocationPlugins) { + this.invocationPlugins = invocationPlugins; + this.nodePlugins = new NodePlugin[0]; + this.parameterPlugins = new ParameterPlugin[0]; + this.inlineInvokePlugins = new InlineInvokePlugin[0]; + } + + public InvocationPlugins getInvocationPlugins() { + return invocationPlugins; + } + + public NodePlugin[] getNodePlugins() { + return nodePlugins; + } + + public void appendNodePlugin(NodePlugin plugin) { + nodePlugins = Arrays.copyOf(nodePlugins, nodePlugins.length + 1); + nodePlugins[nodePlugins.length - 1] = plugin; + } + + public void prependNodePlugin(NodePlugin plugin) { + NodePlugin[] newPlugins = new NodePlugin[nodePlugins.length + 1]; + System.arraycopy(nodePlugins, 0, newPlugins, 1, nodePlugins.length); + newPlugins[0] = plugin; + nodePlugins = newPlugins; + } + + public void clearNodePlugin() { + nodePlugins = new NodePlugin[0]; + } + + public ParameterPlugin[] getParameterPlugins() { + return parameterPlugins; + } + + public void appendParameterPlugin(ParameterPlugin plugin) { + parameterPlugins = Arrays.copyOf(parameterPlugins, parameterPlugins.length + 1); + parameterPlugins[parameterPlugins.length - 1] = plugin; + } + + public void prependParameterPlugin(ParameterPlugin plugin) { + ParameterPlugin[] newPlugins = new ParameterPlugin[parameterPlugins.length + 1]; + System.arraycopy(parameterPlugins, 0, newPlugins, 1, parameterPlugins.length); + newPlugins[0] = plugin; + parameterPlugins = newPlugins; + } + + public void clearParameterPlugin() { + parameterPlugins = new ParameterPlugin[0]; + } + + public InlineInvokePlugin[] getInlineInvokePlugins() { + return inlineInvokePlugins; + } + + public void appendInlineInvokePlugin(InlineInvokePlugin plugin) { + inlineInvokePlugins = Arrays.copyOf(inlineInvokePlugins, inlineInvokePlugins.length + 1); + inlineInvokePlugins[inlineInvokePlugins.length - 1] = plugin; + } + + public void prependInlineInvokePlugin(InlineInvokePlugin plugin) { + InlineInvokePlugin[] newPlugins = new InlineInvokePlugin[inlineInvokePlugins.length + 1]; + System.arraycopy(inlineInvokePlugins, 0, newPlugins, 1, inlineInvokePlugins.length); + newPlugins[0] = plugin; + inlineInvokePlugins = newPlugins; + } + + public void clearInlineInvokePlugins() { + inlineInvokePlugins = new InlineInvokePlugin[0]; + } + + public LoopExplosionPlugin getLoopExplosionPlugin() { + return loopExplosionPlugin; + } + + public void setLoopExplosionPlugin(LoopExplosionPlugin plugin) { + this.loopExplosionPlugin = plugin; + } + } + + private static final ResolvedJavaType[] EMPTY = new ResolvedJavaType[]{}; + + private final boolean eagerResolving; + private final boolean omitAllExceptionEdges; + private final boolean omitAssertions; + private final ResolvedJavaType[] skippedExceptionTypes; + private final DebugInfoMode debugInfoMode; + private final boolean clearNonLiveLocals; + private boolean useProfiling; + private final Plugins plugins; + + public static enum DebugInfoMode { + SafePointsOnly, + /** + * This mode inserts {@link SimpleInfopointNode}s in places where no safepoints would be + * inserted: inlining boundaries, and line number switches. + *

+ * In this mode the infopoint only have a location (method and bytecode index) and no + * values. + *

+ * This is useful to have better program counter to bci mapping and has no influence on the + * generated code. However it can increase the amount of metadata and does not allow access + * to accessing values at runtime. + */ + Simple, + /** + * In this mode, {@link FullInfopointNode}s are generated in the same locations as in + * {@link #Simple} mode but the infopoints have access to the runtime values. + *

+ * This is relevant when code is to be generated for native, machine-code level debugging + * but can have a limit the amount of optimization applied to the code. + */ + Full, + } + + protected GraphBuilderConfiguration(boolean eagerResolving, boolean omitAllExceptionEdges, boolean omitAssertions, DebugInfoMode debugInfoMode, ResolvedJavaType[] skippedExceptionTypes, + boolean clearNonLiveLocals, Plugins plugins) { + this.eagerResolving = eagerResolving; + this.omitAllExceptionEdges = omitAllExceptionEdges; + this.omitAssertions = omitAssertions; + this.debugInfoMode = debugInfoMode; + this.skippedExceptionTypes = skippedExceptionTypes; + this.clearNonLiveLocals = clearNonLiveLocals; + this.useProfiling = true; + this.plugins = plugins; + } + + /** + * Creates a copy of this configuration with all its plugins. The {@link InvocationPlugins} in + * this configuration become the {@linkplain InvocationPlugins#getParent() parent} of the + * {@link InvocationPlugins} in the copy. + */ + public GraphBuilderConfiguration copy() { + Plugins newPlugins = new Plugins(plugins); + GraphBuilderConfiguration result = new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, newPlugins); + result.useProfiling = useProfiling; + return result; + } + + public boolean getUseProfiling() { + return useProfiling; + } + + public void setUseProfiling(boolean b) { + this.useProfiling = b; + } + + public GraphBuilderConfiguration withEagerResolving(boolean newEagerResolving) { + return new GraphBuilderConfiguration(newEagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins); + } + + public GraphBuilderConfiguration withSkippedExceptionTypes(ResolvedJavaType[] newSkippedExceptionTypes) { + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins); + } + + public GraphBuilderConfiguration withOmitAllExceptionEdges(boolean newOmitAllExceptionEdges) { + return new GraphBuilderConfiguration(eagerResolving, newOmitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins); + } + + public GraphBuilderConfiguration withOmitAssertions(boolean newOmitAssertions) { + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, newOmitAssertions, debugInfoMode, skippedExceptionTypes, clearNonLiveLocals, plugins); + } + + public GraphBuilderConfiguration withDebugInfoMode(DebugInfoMode newDebugInfoMode) { + ResolvedJavaType[] newSkippedExceptionTypes = skippedExceptionTypes == EMPTY ? EMPTY : Arrays.copyOf(skippedExceptionTypes, skippedExceptionTypes.length); + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, newDebugInfoMode, newSkippedExceptionTypes, clearNonLiveLocals, plugins); + } + + public GraphBuilderConfiguration withClearNonLiveLocals(boolean newClearNonLiveLocals) { + return new GraphBuilderConfiguration(eagerResolving, omitAllExceptionEdges, omitAssertions, debugInfoMode, skippedExceptionTypes, newClearNonLiveLocals, plugins); + } + + public ResolvedJavaType[] getSkippedExceptionTypes() { + return skippedExceptionTypes; + } + + public boolean eagerResolving() { + return eagerResolving; + } + + public boolean omitAllExceptionEdges() { + return omitAllExceptionEdges; + } + + public boolean omitAssertions() { + return omitAssertions; + } + + public boolean insertNonSafepointDebugInfo() { + return debugInfoMode.ordinal() >= DebugInfoMode.Simple.ordinal(); + } + + public boolean insertFullDebugInfo() { + return debugInfoMode.ordinal() >= DebugInfoMode.Full.ordinal(); + } + + public boolean insertSimpleDebugInfo() { + return debugInfoMode == DebugInfoMode.Simple; + } + + public boolean clearNonLiveLocals() { + return clearNonLiveLocals; + } + + public static GraphBuilderConfiguration getDefault(Plugins plugins) { + return new GraphBuilderConfiguration(false, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); + } + + public static GraphBuilderConfiguration getInfopointDefault(Plugins plugins) { + return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); + } + + public static GraphBuilderConfiguration getEagerDefault(Plugins plugins) { + return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); + } + + public static GraphBuilderConfiguration getInfopointEagerDefault(Plugins plugins) { + return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Simple, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); + } + + public static GraphBuilderConfiguration getSnippetDefault(Plugins plugins) { + return new GraphBuilderConfiguration(true, true, false, DebugInfoMode.SafePointsOnly, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); + } + + public static GraphBuilderConfiguration getFullDebugDefault(Plugins plugins) { + return new GraphBuilderConfiguration(true, false, false, DebugInfoMode.Full, EMPTY, GraalOptions.OptClearNonLiveLocals.getValue(), plugins); + } + + /** + * Returns {@code true} if it is an error for a class/field/method resolution to fail. The + * default is the same result as returned by {@link #eagerResolving()}. However, it may be + * overridden to allow failure even when {@link #eagerResolving} is {@code true}. + */ + public boolean unresolvedIsError() { + return eagerResolving; + } + + public Plugins getPlugins() { + return plugins; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GraphBuilderContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GraphBuilderContext.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import static com.oracle.graal.compiler.common.type.StampFactory.objectNonNull; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + +import com.oracle.graal.compiler.common.type.ObjectStamp; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.nodes.CallTargetNode.InvokeKind; +import com.oracle.graal.nodes.FixedGuardNode; +import com.oracle.graal.nodes.PiNode; +import com.oracle.graal.nodes.StateSplit; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.calc.IsNullNode; +import com.oracle.graal.nodes.spi.StampProvider; +import com.oracle.graal.nodes.type.StampTool; + +/** + * Used by a {@link GraphBuilderPlugin} to interface with an object that parses the bytecode of a + * single {@linkplain #getMethod() method} as part of building a {@linkplain #getGraph() graph} . + */ +public interface GraphBuilderContext { + + /** + * Raw operation for adding a node to the graph when neither {@link #add} nor + * {@link #addPush(JavaKind, ValueNode)} can be used. + * + * @return either the node added or an equivalent node + */ + T append(T value); + + /** + * Adds the given node to the graph and also adds recursively all referenced inputs. + * + * @param value the node to be added to the graph + * @return either the node added or an equivalent node + */ + T recursiveAppend(T value); + + /** + * Pushes a given value to the frame state stack using an explicit kind. This should be used + * when {@code value.getJavaKind()} is different from the kind that the bytecode instruction + * currently being parsed pushes to the stack. + * + * @param kind the kind to use when type checking this operation + * @param value the value to push to the stack. The value must already have been + * {@linkplain #append(ValueNode) appended}. + */ + void push(JavaKind kind, ValueNode value); + + /** + * Adds a node to the graph. If the returned node is a {@link StateSplit} with a null + * {@linkplain StateSplit#stateAfter() frame state}, the frame state is initialized. + * + * @param value the value to add to the graph and push to the stack. The + * {@code value.getJavaKind()} kind is used when type checking this operation. + * @return a node equivalent to {@code value} in the graph + */ + default T add(T value) { + if (value.graph() != null) { + assert !(value instanceof StateSplit) || ((StateSplit) value).stateAfter() != null; + return value; + } + T equivalentValue = append(value); + if (equivalentValue instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) equivalentValue; + if (stateSplit.stateAfter() == null && stateSplit.hasSideEffect()) { + setStateAfter(stateSplit); + } + } + return equivalentValue; + } + + /** + * Adds a node with a non-void kind to the graph, pushes it to the stack. If the returned node + * is a {@link StateSplit} with a null {@linkplain StateSplit#stateAfter() frame state}, the + * frame state is initialized. + * + * @param kind the kind to use when type checking this operation + * @param value the value to add to the graph and push to the stack + * @return a node equivalent to {@code value} in the graph + */ + default T addPush(JavaKind kind, T value) { + T equivalentValue = value.graph() != null ? value : append(value); + push(kind, equivalentValue); + if (equivalentValue instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) equivalentValue; + if (stateSplit.stateAfter() == null && stateSplit.hasSideEffect()) { + setStateAfter(stateSplit); + } + } + return equivalentValue; + } + + /** + * Handles an invocation that a plugin determines can replace the original invocation (i.e., the + * one for which the plugin was applied). This applies all standard graph builder processing to + * the replaced invocation including applying any relevant plugins. + * + * @param invokeKind the kind of the replacement invocation + * @param targetMethod the target of the replacement invocation + * @param args the arguments to the replacement invocation + * @param forceInlineEverything specifies if all invocations encountered in the scope of + * handling the replaced invoke are to be force inlined + */ + void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean forceInlineEverything); + + /** + * Intrinsifies an invocation of a given method by inlining the bytecodes of a given + * substitution method. + * + * @param targetMethod the method being intrinsified + * @param substitute the intrinsic implementation + * @param args the arguments with which to inline the invocation + */ + void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args); + + StampProvider getStampProvider(); + + MetaAccessProvider getMetaAccess(); + + default Assumptions getAssumptions() { + return getGraph().getAssumptions(); + } + + ConstantReflectionProvider getConstantReflection(); + + /** + * Gets the graph being constructed. + */ + StructuredGraph getGraph(); + + /** + * Creates a snap shot of the current frame state with the BCI of the instruction after the one + * currently being parsed and assigns it to a given {@linkplain StateSplit#hasSideEffect() side + * effect} node. + * + * @param sideEffect a side effect node just appended to the graph + */ + void setStateAfter(StateSplit sideEffect); + + /** + * Gets the parsing context for the method that inlines the method being parsed by this context. + */ + GraphBuilderContext getParent(); + + /** + * Gets the first ancestor parsing context that is not parsing a + * {@linkplain #parsingIntrinsic() intrinsic}. + */ + default GraphBuilderContext getNonIntrinsicAncestor() { + GraphBuilderContext ancestor = getParent(); + while (ancestor != null && ancestor.parsingIntrinsic()) { + ancestor = ancestor.getParent(); + } + return ancestor; + } + + /** + * Gets the method being parsed by this context. + */ + ResolvedJavaMethod getMethod(); + + /** + * Gets the index of the bytecode instruction currently being parsed. + */ + int bci(); + + /** + * Gets the kind of invocation currently being parsed. + */ + InvokeKind getInvokeKind(); + + /** + * Gets the return type of the invocation currently being parsed. + */ + JavaType getInvokeReturnType(); + + default Stamp getInvokeReturnStamp() { + JavaType returnType = getInvokeReturnType(); + if (returnType.getJavaKind() == JavaKind.Object && returnType instanceof ResolvedJavaType) { + return StampFactory.declared((ResolvedJavaType) returnType); + } else { + return StampFactory.forKind(returnType.getJavaKind()); + } + } + + /** + * Gets the inline depth of this context. A return value of 0 implies that this is the context + * for the parse root. + */ + default int getDepth() { + GraphBuilderContext parent = getParent(); + return parent == null ? 0 : 1 + parent.getDepth(); + } + + /** + * Determines if this parsing context is within the bytecode of an intrinsic or a method inlined + * by an intrinsic. + */ + default boolean parsingIntrinsic() { + return getIntrinsic() != null; + } + + /** + * Gets the intrinsic of the current parsing context or {@code null} if not + * {@link #parsingIntrinsic() parsing an intrinsic}. + */ + IntrinsicContext getIntrinsic(); + + BailoutException bailout(String string); + + /** + * Gets a version of a given value that has a {@linkplain StampTool#isPointerNonNull(ValueNode) + * non-null} stamp. + */ + default ValueNode nullCheckedValue(ValueNode value) { + if (!StampTool.isPointerNonNull(value.stamp())) { + IsNullNode condition = getGraph().unique(new IsNullNode(value)); + ObjectStamp receiverStamp = (ObjectStamp) value.stamp(); + Stamp stamp = receiverStamp.join(objectNonNull()); + FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true)); + PiNode nonNullReceiver = getGraph().unique(new PiNode(value, stamp)); + nonNullReceiver.setGuard(fixedGuard); + // TODO: Propogating the non-null into the frame state would + // remove subsequent null-checks on the same value. However, + // it currently causes an assertion failure when merging states. + // + // frameState.replace(value, nonNullReceiver); + return nonNullReceiver; + } + return value; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GraphBuilderPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/GraphBuilderPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +/** + * Marker interface for graph builder plugins. + */ +public interface GraphBuilderPlugin { +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InlineInvokePlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InlineInvokePlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.ValueNode; + +/** + * Plugin for specifying what is inlined during graph parsing. This plugin is also notified + * {@link #notifyBeforeInline before} and {@link #notifyAfterInline} the inlining, as well as of + * {@link #notifyNotInlined non-inlined} invocations (i.e., those for which an {@link Invoke} node + * is created). + */ +public interface InlineInvokePlugin extends GraphBuilderPlugin { + + /** + * Result of a {@link #shouldInlineInvoke inlining decision}. + */ + public static class InlineInfo { + + /** + * Denotes a call site that must not be inlined and should be implemented by a node that + * does not speculate on the call not raising an exception. + */ + public static final InlineInfo DO_NOT_INLINE_WITH_EXCEPTION = new InlineInfo(null, false); + + /** + * Denotes a call site must not be inlined and can be implemented by a node that speculates + * the call will not throw an exception. + */ + public static final InlineInfo DO_NOT_INLINE_NO_EXCEPTION = new InlineInfo(null, false); + + private final ResolvedJavaMethod methodToInline; + private final boolean isIntrinsic; + + public InlineInfo(ResolvedJavaMethod methodToInline, boolean isIntrinsic) { + this.methodToInline = methodToInline; + this.isIntrinsic = isIntrinsic; + } + + /** + * Returns the method to be inlined, or {@code null} if the call site must not be inlined. + */ + public ResolvedJavaMethod getMethodToInline() { + return methodToInline; + } + + /** + * Specifies if {@link #methodToInline} is an intrinsic for the original method (i.e., the + * {@code method} passed to {@link InlineInvokePlugin#shouldInlineInvoke}). + */ + public boolean isIntrinsic() { + return isIntrinsic; + } + } + + /** + * Determines whether a call to a given method is to be inlined. The return value is a + * tri-state: + *

+ * Non-null return value with a non-null {@link InlineInfo#getMethodToInline method}: That + * {@link InlineInfo#getMethodToInline method} is inlined. Note that it can be a different + * method than the one specified here as the parameter, which allows method substitutions. + *

+ * Non-null return value with a null {@link InlineInfo#getMethodToInline method}, e.g., + * {@link InlineInfo#DO_NOT_INLINE_WITH_EXCEPTION}: The method is not inlined, and other plugins + * with a lower priority cannot overwrite this decision. + *

+ * Null return value: This plugin made no decision, other plugins with a lower priority are + * asked. + * + * @param b the context + * @param method the target method of an invoke + * @param args the arguments to the invoke + * @param returnType the return type derived from {@code method}'s signature + */ + default InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args, JavaType returnType) { + return null; + } + + /** + * Notification that a method is about to be inlined. + * + * @param methodToInline the inlined method + */ + default void notifyBeforeInline(ResolvedJavaMethod methodToInline) { + } + + /** + * Notification that a method was inlined. + * + * @param methodToInline the inlined method + */ + default void notifyAfterInline(ResolvedJavaMethod methodToInline) { + } + + /** + * Notifies this plugin of the {@link Invoke} node created for a method that was not inlined per + * {@link #shouldInlineInvoke}. + * + * @param b the context + * @param method the method that was not inlined + * @param invoke the invoke node created for the call to {@code method} + */ + default void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/IntrinsicContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/IntrinsicContext.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; +import static jdk.vm.ci.code.BytecodeFrame.AFTER_BCI; +import static jdk.vm.ci.code.BytecodeFrame.BEFORE_BCI; +import static jdk.vm.ci.code.BytecodeFrame.INVALID_FRAMESTATE_BCI; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.nodes.AbstractMergeNode; +import com.oracle.graal.nodes.FrameState; +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.StateSplit; +import com.oracle.graal.nodes.StructuredGraph; + +/** + * An intrinsic is a substitute implementation of a Java method (or a bytecode in the case of + * snippets) that is itself implemented in Java. This interface provides information about the + * intrinsic currently being processed by the graph builder. + * + * When in the scope of an intrinsic, the graph builder does not check the value kinds flowing + * through the JVM state since intrinsics can employ non-Java kinds to represent values such as raw + * machine words and pointers. + */ +public class IntrinsicContext { + + /** + * Gets the method being intrinsified. + */ + final ResolvedJavaMethod method; + + /** + * Gets the method providing the intrinsic implementation. + */ + final ResolvedJavaMethod intrinsic; + + public ResolvedJavaMethod getOriginalMethod() { + return method; + } + + public ResolvedJavaMethod getIntrinsicMethod() { + return intrinsic; + } + + /** + * Determines if a call within the compilation scope of this intrinsic represents a call to the + * {@linkplain #getOriginalMethod() original} method. This denotes the path where a partial + * intrinsification falls back to the original method. + */ + public boolean isCallToOriginal(ResolvedJavaMethod targetMethod) { + return method.equals(targetMethod) || intrinsic.equals(targetMethod); + } + + final CompilationContext compilationContext; + + public IntrinsicContext(ResolvedJavaMethod method, ResolvedJavaMethod intrinsic, CompilationContext compilationContext) { + this.method = method; + this.intrinsic = intrinsic; + this.compilationContext = compilationContext; + assert !isCompilationRoot() || method.hasBytecodes() : "Cannot root compile intrinsic for native or abstract method " + method.format("%H.%n(%p)"); + } + + public boolean isPostParseInlined() { + return compilationContext.equals(INLINE_AFTER_PARSING); + } + + public boolean isCompilationRoot() { + return compilationContext.equals(ROOT_COMPILATION); + } + + /** + * Denotes the compilation context in which an intrinsic is being parsed. + */ + public enum CompilationContext { + /** + * An intrinsic is being processed when parsing an invoke bytecode that calls the + * intrinsified method. + */ + INLINE_DURING_PARSING, + + /** + * An intrinsic is being processed when inlining an {@link Invoke} in an existing graph. + */ + INLINE_AFTER_PARSING, + + /** + * An intrinsic is the root of compilation. + */ + ROOT_COMPILATION + } + + /** + * Models the state of a graph in terms of {@link StateSplit#hasSideEffect() side effects} that + * are control flow predecessors of the current point in a graph. + */ + public interface SideEffectsState { + + /** + * Determines if the current program point is preceded by one or more side effects. + */ + boolean isAfterSideEffect(); + + /** + * Gets the side effects preceding the current program point. + */ + Iterable sideEffects(); + + /** + * Records a side effect for the current program point. + */ + void addSideEffect(StateSplit sideEffect); + } + + public FrameState createFrameState(StructuredGraph graph, SideEffectsState sideEffects, StateSplit forStateSplit) { + assert forStateSplit != graph.start(); + if (forStateSplit.hasSideEffect()) { + if (sideEffects.isAfterSideEffect()) { + // Only the last side effect on any execution path in a replacement + // can inherit the stateAfter of the replaced node + FrameState invalid = graph.add(new FrameState(INVALID_FRAMESTATE_BCI)); + for (StateSplit lastSideEffect : sideEffects.sideEffects()) { + lastSideEffect.setStateAfter(invalid); + } + } + sideEffects.addSideEffect(forStateSplit); + return graph.add(new FrameState(AFTER_BCI)); + } else { + if (forStateSplit instanceof AbstractMergeNode) { + // Merge nodes always need a frame state + if (sideEffects.isAfterSideEffect()) { + // A merge after one or more side effects + return graph.add(new FrameState(AFTER_BCI)); + } else { + // A merge before any side effects + return graph.add(new FrameState(BEFORE_BCI)); + } + } else { + // Other non-side-effects do not need a state + return null; + } + } + } + + @Override + public String toString() { + return "Intrinsic{original: " + method.format("%H.%n(%p)") + ", intrinsic: " + intrinsic.format("%H.%n(%p)") + ", context: " + compilationContext + "}"; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InvocationPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InvocationPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Method; + +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.nodes.Invoke; +import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.type.StampTool; + +/** + * Plugin for handling a specific method invocation. + */ +public interface InvocationPlugin extends GraphBuilderPlugin { + + /** + * The receiver in a non-static method. The class literal for this interface must be used with + * {@link InvocationPlugins#put(InvocationPlugin, boolean, boolean, boolean, Class, String, Class...)} + * to denote the receiver argument for such a non-static method. + */ + public interface Receiver { + /** + * Gets the receiver value, null checking it first if necessary. + * + * @return the receiver value with a {@linkplain StampTool#isPointerNonNull(ValueNode) + * non-null} stamp + */ + ValueNode get(); + + /** + * Determines if the receiver is constant. + */ + default boolean isConstant() { + return false; + } + } + + /** + * Determines if this plugin is for a method with a polymorphic signature (e.g. + * {@link MethodHandle#invokeExact(Object...)}). + */ + default boolean isSignaturePolymorphic() { + return false; + } + + /** + * Determines if this plugin can only be used when inlining the method is it associated with. + * That is, this plugin cannot be used when the associated method is the compilation root. + */ + default boolean inlineOnly() { + return isSignaturePolymorphic(); + } + + /** + * Handles invocation of a signature polymorphic method. + * + * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static + * @param argsIncludingReceiver all arguments to the invocation include the raw receiver in + * position 0 if {@code targetMethod} is not static + * @see #execute + */ + default boolean applyPolymorphic(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode... argsIncludingReceiver) { + return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver) { + return defaultHandler(b, targetMethod, receiver); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg) { + return defaultHandler(b, targetMethod, receiver, arg); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2) { + return defaultHandler(b, targetMethod, receiver, arg1, arg2); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3) { + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4); + } + + /** + * @see #execute + */ + default boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4, ValueNode arg5) { + return defaultHandler(b, targetMethod, receiver, arg1, arg2, arg3, arg4, arg5); + } + + /** + * Executes this plugin against a set of invocation arguments. + * + * The default implementation in {@link InvocationPlugin} dispatches to the {@code apply(...)} + * method that matches the number of arguments or to {@link #applyPolymorphic} if {@code plugin} + * is {@linkplain #isSignaturePolymorphic() signature polymorphic}. + * + * @param targetMethod the method for which this plugin is being applied + * @param receiver access to the receiver, {@code null} if {@code targetMethod} is static + * @param argsIncludingReceiver all arguments to the invocation include the receiver in position + * 0 if {@code targetMethod} is not static + * @return {@code true} if this plugin handled the invocation of {@code targetMethod} + * {@code false} if the graph builder should process the invoke further (e.g., by + * inlining it or creating an {@link Invoke} node). A plugin that does not handle an + * invocation must not modify the graph being constructed. + */ + default boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { + if (isSignaturePolymorphic()) { + return applyPolymorphic(b, targetMethod, receiver, argsIncludingReceiver); + } else if (receiver != null) { + assert !targetMethod.isStatic(); + assert argsIncludingReceiver.length > 0; + if (argsIncludingReceiver.length == 1) { + return apply(b, targetMethod, receiver); + } else if (argsIncludingReceiver.length == 2) { + return apply(b, targetMethod, receiver, argsIncludingReceiver[1]); + } else if (argsIncludingReceiver.length == 3) { + return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2]); + } else if (argsIncludingReceiver.length == 4) { + return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); + } else if (argsIncludingReceiver.length == 5) { + return apply(b, targetMethod, receiver, argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); + } else { + return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); + } + } else { + assert targetMethod.isStatic(); + if (argsIncludingReceiver.length == 0) { + return apply(b, targetMethod, null); + } else if (argsIncludingReceiver.length == 1) { + return apply(b, targetMethod, null, argsIncludingReceiver[0]); + } else if (argsIncludingReceiver.length == 2) { + return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1]); + } else if (argsIncludingReceiver.length == 3) { + return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2]); + } else if (argsIncludingReceiver.length == 4) { + return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3]); + } else if (argsIncludingReceiver.length == 5) { + return apply(b, targetMethod, null, argsIncludingReceiver[0], argsIncludingReceiver[1], argsIncludingReceiver[2], argsIncludingReceiver[3], argsIncludingReceiver[4]); + } else { + return defaultHandler(b, targetMethod, receiver, argsIncludingReceiver); + } + + } + } + + /** + * Handles an invocation when a specific {@code apply} method is not available. + */ + default boolean defaultHandler(@SuppressWarnings("unused") GraphBuilderContext b, ResolvedJavaMethod targetMethod, @SuppressWarnings("unused") InvocationPlugin.Receiver receiver, + ValueNode... args) { + throw new JVMCIError("Invocation plugin for %s does not handle invocations with %d arguments", targetMethod.format("%H.%n(%p)"), args.length); + } + + default StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { + Class c = getClass(); + for (Method m : c.getDeclaredMethods()) { + if (m.getName().equals("apply")) { + return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); + } else if (m.getName().equals("defaultHandler")) { + return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); + } + } + throw new JVMCIError("could not find method named \"apply\" or \"defaultHandler\" in " + c.getName()); + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InvocationPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/InvocationPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,604 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import static java.lang.String.format; + +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +import com.oracle.graal.graph.Node; +import com.oracle.graal.graph.iterators.NodeIterable; +import com.oracle.graal.nodes.ValueNode; + +/** + * Manages a set of {@link InvocationPlugin}s. + */ +public class InvocationPlugins { + + public static class InvocationPluginReceiver implements InvocationPlugin.Receiver { + private final GraphBuilderContext parser; + private ValueNode[] args; + private ValueNode value; + + public InvocationPluginReceiver(GraphBuilderContext parser) { + this.parser = parser; + } + + @Override + public ValueNode get() { + assert args != null : "Cannot get the receiver of a static method"; + if (value == null) { + value = parser.nullCheckedValue(args[0]); + if (value != args[0]) { + args[0] = value; + } + } + return value; + } + + @Override + public boolean isConstant() { + return args[0].isConstant(); + } + + public InvocationPluginReceiver init(ResolvedJavaMethod targetMethod, ValueNode[] newArgs) { + if (!targetMethod.isStatic()) { + this.args = newArgs; + this.value = null; + return this; + } + return null; + } + } + + /** + * Utility for + * {@linkplain InvocationPlugins#register(InvocationPlugin, Class, String, Class...) + * registration} of invocation plugins. + */ + public static class Registration { + + private final InvocationPlugins plugins; + private final Class declaringClass; + private boolean allowOverwrite; + + /** + * Creates an object for registering {@link InvocationPlugin}s for methods declared by a + * given class. + * + * @param plugins where to register the plugins + * @param declaringClass the class declaring the methods for which plugins will be + * registered via this object + */ + public Registration(InvocationPlugins plugins, Class declaringClass) { + this.plugins = plugins; + this.declaringClass = declaringClass; + } + + /** + * Creates an object for registering {@link InvocationPlugin}s for methods declared by a + * given class. + * + * @param plugins where to register the plugins + * @param declaringClassName the name of the class class declaring the methods for which + * plugins will be registered via this object + */ + public Registration(InvocationPlugins plugins, String declaringClassName) { + this.plugins = plugins; + try { + this.declaringClass = Class.forName(declaringClassName); + } catch (ClassNotFoundException ex) { + throw JVMCIError.shouldNotReachHere(ex); + } + } + + /** + * Configures this registration to allow or disallow overwriting of invocation plugins. + */ + public Registration setAllowOverwrite(boolean allowOverwrite) { + this.allowOverwrite = allowOverwrite; + return this; + } + + /** + * Registers a plugin for a method with no arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register0(String name, InvocationPlugin plugin) { + plugins.register(plugin, false, allowOverwrite, declaringClass, name); + } + + /** + * Registers a plugin for a method with 1 argument. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register1(String name, Class arg, InvocationPlugin plugin) { + plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg); + } + + /** + * Registers a plugin for a method with 2 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { + plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2); + } + + /** + * Registers a plugin for a method with 3 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { + plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2, arg3); + } + + /** + * Registers a plugin for a method with 4 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { + plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2, arg3, arg4); + } + + /** + * Registers a plugin for a method with 5 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void register5(String name, Class arg1, Class arg2, Class arg3, Class arg4, Class arg5, InvocationPlugin plugin) { + plugins.register(plugin, false, allowOverwrite, declaringClass, name, arg1, arg2, arg3, arg4, arg5); + } + + /** + * Registers a plugin for an optional method with no arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerOptional0(String name, InvocationPlugin plugin) { + plugins.register(plugin, true, allowOverwrite, declaringClass, name); + } + + /** + * Registers a plugin for an optional method with 1 argument. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerOptional1(String name, Class arg, InvocationPlugin plugin) { + plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg); + } + + /** + * Registers a plugin for an optional method with 2 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerOptional2(String name, Class arg1, Class arg2, InvocationPlugin plugin) { + plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg1, arg2); + } + + /** + * Registers a plugin for an optional method with 3 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerOptional3(String name, Class arg1, Class arg2, Class arg3, InvocationPlugin plugin) { + plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg1, arg2, arg3); + } + + /** + * Registers a plugin for an optional method with 4 arguments. + * + * @param name the name of the method + * @param plugin the plugin to be registered + */ + public void registerOptional4(String name, Class arg1, Class arg2, Class arg3, Class arg4, InvocationPlugin plugin) { + plugins.register(plugin, true, allowOverwrite, declaringClass, name, arg1, arg2, arg3, arg4); + } + + /** + * Registers a plugin that implements a method based on the bytecode of a substitute method. + * + * @param substituteDeclaringClass the class declaring the substitute method + * @param name the name of both the original and substitute method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method + * is non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void registerMethodSubstitution(Class substituteDeclaringClass, String name, Class... argumentTypes) { + registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); + } + + /** + * Registers a plugin that implements a method based on the bytecode of a substitute method. + * + * @param substituteDeclaringClass the class declaring the substitute method + * @param name the name of both the original method + * @param substituteName the name of the substitute method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method + * is non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void registerMethodSubstitution(Class substituteDeclaringClass, String name, String substituteName, Class... argumentTypes) { + MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(substituteDeclaringClass, substituteName, argumentTypes); + plugins.register(plugin, false, allowOverwrite, declaringClass, name, argumentTypes); + } + } + + /** + * Key for a method. + */ + static class MethodKey { + final boolean isStatic; + + /** + * This method is optional. This is used for new API methods not present in previous JDK + * versions. + */ + final boolean isOptional; + + final Class declaringClass; + final String name; + final Class[] argumentTypes; + final InvocationPlugin value; + + MethodKey(InvocationPlugin data, boolean isStatic, boolean isOptional, Class declaringClass, String name, Class... argumentTypes) { + assert isStatic || argumentTypes[0] == declaringClass; + this.value = data; + this.isStatic = isStatic; + this.isOptional = isOptional; + this.declaringClass = declaringClass; + this.name = name; + this.argumentTypes = argumentTypes; + assert isOptional || resolveJava() != null; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MethodKey) { + MethodKey that = (MethodKey) obj; + boolean res = this.name.equals(that.name) && this.declaringClass.equals(that.declaringClass) && Arrays.equals(this.argumentTypes, that.argumentTypes); + assert !res || this.isStatic == that.isStatic; + return res; + } + return false; + } + + public int getDeclaredParameterCount() { + return isStatic ? argumentTypes.length : argumentTypes.length - 1; + } + + @Override + public int hashCode() { + // Replay compilation mandates use of stable hash codes + return declaringClass.getName().hashCode() ^ name.hashCode(); + } + + private ResolvedJavaMethod resolve(MetaAccessProvider metaAccess) { + Executable method = resolveJava(); + if (method == null) { + return null; + } + return metaAccess.lookupJavaMethod(method); + } + + private Executable resolveJava() { + try { + Executable res; + Class[] parameterTypes = isStatic ? argumentTypes : Arrays.copyOfRange(argumentTypes, 1, argumentTypes.length); + if (name.equals("")) { + res = declaringClass.getDeclaredConstructor(parameterTypes); + } else { + res = declaringClass.getDeclaredMethod(name, parameterTypes); + } + assert Modifier.isStatic(res.getModifiers()) == isStatic; + return res; + } catch (NoSuchMethodException | SecurityException e) { + if (isOptional) { + return null; + } + throw new InternalError(e); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(declaringClass.getName()).append('.').append(name).append('('); + for (Class p : argumentTypes) { + if (sb.charAt(sb.length() - 1) != '(') { + sb.append(", "); + } + sb.append(p.getSimpleName()); + } + return sb.append(')').toString(); + } + } + + private final MetaAccessProvider metaAccess; + + /** + * Initial list of entries. + */ + private final List registrations = new ArrayList<>(INITIAL_CAPACITY); + + /** + * Entry map that is initialized upon first call to {@link #get(ResolvedJavaMethod)}. + * + * Note: this must be volatile since double-checked locking is used to initialize it + */ + private volatile Map entries; + + private static final int INITIAL_CAPACITY = 64; + + /** + * Adds an entry to this map for a specified method. + * + * @param value value to be associated with the specified method + * @param isStatic specifies if the method is static + * @param isOptional specifies if the method is optional + * @param declaringClass the class declaring the method + * @param name the name of the method + * @param argumentTypes the argument types of the method. Element 0 of this array must be + * {@code declaringClass} iff the method is non-static. + * @return an object representing the method + */ + MethodKey put(InvocationPlugin value, boolean isStatic, boolean isOptional, boolean allowOverwrite, Class declaringClass, String name, Class... argumentTypes) { + assert isStatic || argumentTypes[0] == declaringClass; + MethodKey methodKey = new MethodKey(value, isStatic, isOptional, declaringClass, name, argumentTypes); + assert entries == null : "registration is closed"; + assert allowOverwrite || !registrations.contains(methodKey) : "a value is already registered for " + methodKey; + registrations.add(methodKey); + return methodKey; + } + + /** + * Determines if a method denoted by a given {@link MethodKey} is in this map. + */ + boolean containsKey(MethodKey key) { + return registrations.contains(key); + } + + InvocationPlugin get(ResolvedJavaMethod method) { + if (entries == null) { + initializeMap(); + } + + return entries.get(method); + } + + /** + * Disallows new registrations of new plugins, and creates the internal tables for method + * lookup. + */ + public void closeRegistration() { + if (entries == null) { + initializeMap(); + } + } + + void initializeMap() { + if (registrations.isEmpty()) { + entries = Collections.emptyMap(); + } else { + Map newEntries = new HashMap<>(); + for (MethodKey methodKey : registrations) { + ResolvedJavaMethod m = methodKey.resolve(metaAccess); + newEntries.put(m, methodKey.value); + } + entries = newEntries; + } + } + + public int size() { + return registrations.size(); + } + + /** + * The plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} before searching in + * this object. + */ + protected final InvocationPlugins parent; + + private InvocationPlugins(InvocationPlugins parent, MetaAccessProvider metaAccess) { + this.metaAccess = metaAccess; + InvocationPlugins p = parent; + this.parent = p; + } + + /** + * Creates a set of invocation plugins with a non-null {@linkplain #getParent() parent}. + */ + public InvocationPlugins(InvocationPlugins parent) { + this(parent, parent.getMetaAccess()); + } + + public MetaAccessProvider getMetaAccess() { + return metaAccess; + } + + public InvocationPlugins(MetaAccessProvider metaAccess) { + this(null, metaAccess); + } + + private void register(InvocationPlugin plugin, boolean isOptional, boolean allowOverwrite, Class declaringClass, String name, Class... argumentTypes) { + boolean isStatic = argumentTypes.length == 0 || argumentTypes[0] != InvocationPlugin.Receiver.class; + if (!isStatic) { + argumentTypes[0] = declaringClass; + } + MethodKey methodInfo = put(plugin, isStatic, isOptional, allowOverwrite, declaringClass, name, argumentTypes); + assert Checker.check(this, methodInfo, plugin); + } + + /** + * Registers an invocation plugin for a given method. There must be no plugin currently + * registered for {@code method}. + * + * @param argumentTypes the argument types of the method. Element 0 of this array must be the + * {@link Class} value for {@link InvocationPlugin.Receiver} iff the method is + * non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void register(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { + register(plugin, false, false, declaringClass, name, argumentTypes); + } + + /** + * Registers an invocation plugin for a given, optional method. There must be no plugin + * currently registered for {@code method}. + * + * @param argumentTypes the argument types of the method. Element 0 of this array must be the + * {@link Class} value for {@link InvocationPlugin.Receiver} iff the method is + * non-static. Upon returning, element 0 will have been rewritten to + * {@code declaringClass} + */ + public void registerOptional(InvocationPlugin plugin, Class declaringClass, String name, Class... argumentTypes) { + register(plugin, true, false, declaringClass, name, argumentTypes); + } + + /** + * Gets the plugin for a given method. + * + * @param method the method to lookup + * @return the plugin associated with {@code method} or {@code null} if none exists + */ + public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { + if (parent != null) { + InvocationPlugin plugin = parent.lookupInvocation(method); + if (plugin != null) { + return plugin; + } + } + return get(method); + } + + /** + * Gets the invocation plugins {@linkplain #lookupInvocation(ResolvedJavaMethod) searched} + * before searching in this object. + */ + public InvocationPlugins getParent() { + return parent; + } + + @Override + public String toString() { + return registrations.stream().map(MethodKey::toString).collect(Collectors.joining(", ")) + " / parent: " + this.parent; + } + + private static class Checker { + private static final int MAX_ARITY = 5; + /** + * The set of all {@link InvocationPlugin#apply} method signatures. + */ + static final Class[][] SIGS; + + static { + ArrayList[]> sigs = new ArrayList<>(MAX_ARITY); + for (Method method : InvocationPlugin.class.getDeclaredMethods()) { + if (!Modifier.isStatic(method.getModifiers()) && method.getName().equals("apply")) { + Class[] sig = method.getParameterTypes(); + assert sig[0] == GraphBuilderContext.class; + assert sig[1] == ResolvedJavaMethod.class; + assert sig[2] == InvocationPlugin.Receiver.class; + assert Arrays.asList(sig).subList(3, sig.length).stream().allMatch(c -> c == ValueNode.class); + while (sigs.size() < sig.length - 2) { + sigs.add(null); + } + sigs.set(sig.length - 3, sig); + } + } + assert sigs.indexOf(null) == -1 : format("need to add an apply() method to %s that takes %d %s arguments ", InvocationPlugin.class.getName(), sigs.indexOf(null), + ValueNode.class.getSimpleName()); + SIGS = sigs.toArray(new Class[sigs.size()][]); + } + + public static boolean check(InvocationPlugins plugins, MethodKey method, InvocationPlugin plugin) { + InvocationPlugins p = plugins.parent; + while (p != null) { + assert !p.containsKey(method) : "a plugin is already registered for " + method; + p = p.parent; + } + if (plugin instanceof ForeignCallPlugin || plugin instanceof GeneratedInvocationPlugin) { + return true; + } + if (plugin instanceof MethodSubstitutionPlugin) { + MethodSubstitutionPlugin msplugin = (MethodSubstitutionPlugin) plugin; + msplugin.getJavaSubstitute(); + return true; + } + int arguments = method.getDeclaredParameterCount(); + assert arguments < SIGS.length : format("need to extend %s to support method with %d arguments: %s", InvocationPlugin.class.getSimpleName(), arguments, method); + for (Method m : plugin.getClass().getDeclaredMethods()) { + if (m.getName().equals("apply")) { + Class[] parameterTypes = m.getParameterTypes(); + if (Arrays.equals(SIGS[arguments], parameterTypes)) { + return true; + } + } + } + throw new AssertionError(format("graph builder plugin for %s not found", method)); + } + } + + /** + * Checks a set of nodes added to the graph by an {@link InvocationPlugin}. + * + * @param b the graph builder that applied the plugin + * @param plugin a plugin that was just applied + * @param newNodes the nodes added to the graph by {@code plugin} + * @throws AssertionError if any check fail + */ + public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIterable newNodes) { + if (parent != null) { + parent.checkNewNodes(b, plugin, newNodes); + } + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/LoopExplosionPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/LoopExplosionPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public interface LoopExplosionPlugin extends GraphBuilderPlugin { + boolean shouldExplodeLoops(ResolvedJavaMethod method); + + boolean shouldMergeExplosions(ResolvedJavaMethod method); +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/MethodSubstitutionPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/MethodSubstitutionPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.stream.Collectors; + +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import sun.misc.Launcher; + +import com.oracle.graal.nodes.ValueNode; + +/** + * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a + * {@linkplain #getSubstitute(MetaAccessProvider) substitute} method. A substitute method must be + * static even if the substituted method is not. + */ +public final class MethodSubstitutionPlugin implements InvocationPlugin { + + private ResolvedJavaMethod cachedSubstitute; + + /** + * The class in which the substitute method is declared. + */ + private final Class declaringClass; + + /** + * The name of the original and substitute method. + */ + private final String name; + + /** + * The parameter types of the substitute method. + */ + private final Class[] parameters; + + private final boolean originalIsStatic; + + /** + * Creates a method substitution plugin. + * + * @param declaringClass the class in which the substitute method is declared + * @param name the name of the substitute method + * @param parameters the parameter types of the substitute method. If the original method is not + * static, then {@code parameters[0]} must be the {@link Class} value denoting + * {@link InvocationPlugin.Receiver} + */ + public MethodSubstitutionPlugin(Class declaringClass, String name, Class... parameters) { + this.declaringClass = declaringClass; + this.name = name; + this.parameters = parameters; + this.originalIsStatic = parameters.length == 0 || parameters[0] != InvocationPlugin.Receiver.class; + } + + /** + * Creates a method substitution plugin. + * + * @param declaringClass the class in which the substitute method is declared + * @param name the name of the substitute method + * @param parameters the parameter types of the substitute method + */ + public MethodSubstitutionPlugin(boolean originalIsStatic, Class declaringClass, String name, Class... parameters) { + this.declaringClass = declaringClass; + this.name = name; + this.parameters = parameters; + this.originalIsStatic = originalIsStatic; + } + + public boolean inlineOnly() { + // Conservatively assume MacroNodes may be used in a substitution + return true; + } + + /** + * Gets the substitute method, resolving it first if necessary. + */ + public ResolvedJavaMethod getSubstitute(MetaAccessProvider metaAccess) { + if (cachedSubstitute == null) { + cachedSubstitute = metaAccess.lookupJavaMethod(getJavaSubstitute()); + } + return cachedSubstitute; + } + + /** + * Gets the reflection API version of the substitution method. + */ + Method getJavaSubstitute() throws JVMCIError { + Method substituteMethod = lookupSubstitute(); + int modifiers = substituteMethod.getModifiers(); + if (Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + throw new JVMCIError("Substitution method must not be abstract or native: " + substituteMethod); + } + if (!Modifier.isStatic(modifiers)) { + throw new JVMCIError("Substitution method must be static: " + substituteMethod); + } + return substituteMethod; + } + + /** + * Determines if a given method is the substitute method of this plugin. + */ + private boolean isSubstitute(Method m) { + if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) { + if (parameters.length == m.getParameterCount()) { + Class[] mparams = m.getParameterTypes(); + int start = 0; + if (!originalIsStatic) { + start = 1; + if (!mparams[0].isAssignableFrom(parameters[0])) { + return false; + } + } + for (int i = start; i < mparams.length; i++) { + if (mparams[i] != parameters[i]) { + return false; + } + } + } + return true; + } + return false; + } + + /** + * Gets the substitute method of this plugin. + */ + private Method lookupSubstitute() { + for (Method m : declaringClass.getDeclaredMethods()) { + if (isSubstitute(m)) { + return m; + } + } + throw new JVMCIError("No method found specified by %s", this); + } + + /** + * Resolves a name to a class. + * + * @param className the name of the class to resolve + * @param optional if true, resolution failure returns null + * @return the resolved class or null if resolution fails and {@code optional} is true + */ + public static Class resolveClass(String className, boolean optional) { + try { + // Need to use launcher class path to handle classes + // that are not on the boot class path + ClassLoader cl = Launcher.getLauncher().getClassLoader(); + return Class.forName(className, false, cl); + } catch (ClassNotFoundException e) { + if (optional) { + return null; + } + throw new JVMCIError("Could not resolve type " + className); + } + } + + @Override + public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) { + ResolvedJavaMethod subst = getSubstitute(b.getMetaAccess()); + if (receiver != null) { + receiver.get(); + } + b.intrinsify(targetMethod, subst, argsIncludingReceiver); + return true; + } + + public StackTraceElement getApplySourceLocation(MetaAccessProvider metaAccess) { + Class c = getClass(); + for (Method m : c.getDeclaredMethods()) { + if (m.getName().equals("execute")) { + return metaAccess.lookupJavaMethod(m).asStackTraceElement(0); + } + } + throw new JVMCIError("could not find method named \"execute\" in " + c.getName()); + } + + @Override + public String toString() { + return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), name, + Arrays.asList(parameters).stream().map(c -> c.getSimpleName()).collect(Collectors.joining(", "))); + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import com.oracle.graal.compiler.common.type.Stamp; + +public interface NodeIntrinsicPluginFactory { + + public interface InjectionProvider { + + T getInjectedArgument(Class type); + + Stamp getReturnStamp(Class type); + } + + void registerPlugin(InvocationPlugins plugins, InjectionProvider injection); +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodePlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/NodePlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; + +import com.oracle.graal.nodes.ValueNode; + +public interface NodePlugin extends GraphBuilderPlugin { + /** + * Handle the parsing of a method invocation bytecode to a method that can be bound statically. + * If the method returns true, it must {@link GraphBuilderContext#push push} a value as the + * result of the method invocation using the {@link Signature#getReturnKind return kind} of the + * method. + * + * @param b the context + * @param method the statically bound, invoked method + * @param args the arguments of the method invocation + * @return true if the plugin handles the invocation, false otherwise + */ + default boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return false; + } + + /** + * Handle the parsing of a GETFIELD bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value using the + * {@link ResolvedJavaField#getJavaKind() kind} of the field. + * + * @param b the context + * @param object the receiver object for the field access + * @param field the accessed field + * @return true if the plugin handles the field access, false otherwise + */ + default boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { + return false; + } + + /** + * Handle the parsing of a GETSTATIC bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value using the + * {@link ResolvedJavaField#getJavaKind() kind} of the field. + * + * @param b the context + * @param field the accessed field + * @return true if the plugin handles the field access, false otherwise + */ + default boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { + return false; + } + + /** + * Handle the parsing of a PUTFIELD bytecode. + * + * @param b the context + * @param object the receiver object for the field access + * @param field the accessed field + * @param value the value to be stored into the field + * @return true if the plugin handles the field access, false otherwise + */ + default boolean handleStoreField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field, ValueNode value) { + return false; + } + + /** + * Handle the parsing of a PUTSTATIC bytecode. + * + * @param b the context + * @param field the accessed field + * @param value the value to be stored into the field + * @return true if the plugin handles the field access, false otherwise. + */ + default boolean handleStoreStaticField(GraphBuilderContext b, ResolvedJavaField field, ValueNode value) { + return false; + } + + /** + * Handle the parsing of an array load bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value using the provided elementKind. + * + * @param b the context + * @param array the accessed array + * @param index the index for the array access + * @param elementKind the element kind of the accessed array + * @return true if the plugin handles the array access, false otherwise. + */ + default boolean handleLoadIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind) { + return false; + } + + /** + * Handle the parsing of an array store bytecode. + * + * @param b the context + * @param array the accessed array + * @param index the index for the array access + * @param elementKind the element kind of the accessed array + * @param value the value to be stored into the array + * @return true if the plugin handles the array access, false otherwise. + */ + default boolean handleStoreIndexed(GraphBuilderContext b, ValueNode array, ValueNode index, JavaKind elementKind, ValueNode value) { + return false; + } + + /** + * Handle the parsing of a CHECKCAST bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value with the result of the cast using + * {@link JavaKind#Object}. + * + * @param b the context + * @param object the object to be type checked + * @param type the type that the object is checked against + * @param profile the profiling information for the type check, or null if no profiling + * information is available + * @return true if the plugin handles the cast, false otherwise + */ + default boolean handleCheckCast(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) { + return false; + } + + /** + * Handle the parsing of a INSTANCEOF bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value with the result of the instanceof using + * {@link JavaKind#Int}. + * + * @param b the context + * @param object the object to be type checked + * @param type the type that the object is checked against + * @param profile the profiling information for the type check, or null if no profiling + * information is available + * @return true if the plugin handles the instanceof, false otherwise + */ + default boolean handleInstanceOf(GraphBuilderContext b, ValueNode object, ResolvedJavaType type, JavaTypeProfile profile) { + return false; + } + + /** + * Handle the parsing of a NEW bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value with the result of the allocation using + * {@link JavaKind#Object}. + * + * @param b the context + * @param type the type to be instantiated + * @return true if the plugin handles the bytecode, false otherwise + */ + default boolean handleNewInstance(GraphBuilderContext b, ResolvedJavaType type) { + return false; + } + + /** + * Handle the parsing of a NEWARRAY and ANEWARRAY bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value with the result of the allocation using + * {@link JavaKind#Object}. + * + * @param b the context + * @param elementType the element type of the array to be instantiated + * @param length the length of the new array + * @return true if the plugin handles the bytecode, false otherwise + */ + default boolean handleNewArray(GraphBuilderContext b, ResolvedJavaType elementType, ValueNode length) { + return false; + } + + /** + * Handle the parsing of a MULTIANEWARRAY bytecode. If the method returns true, it must + * {@link GraphBuilderContext#push push} a value with the result of the allocation using + * {@link JavaKind#Object}. + * + * @param b the context + * @param type the type of the outermost array to be instantiated + * @param dimensions the array of lengths for all the dimensions to be instantiated + * @return true if the plugin handles the bytecode, false otherwise + */ + default boolean handleNewMultiArray(GraphBuilderContext b, ResolvedJavaType type, ValueNode[] dimensions) { + return false; + } + + /** + * If the plugin {@link GraphBuilderContext#push pushes} a value with a different + * {@link JavaKind} than specified by the bytecode, it must override this method and return + * {@code true}. This disables assertion checking for value kinds. + * + * @param b the context + */ + default boolean canChangeStackKind(GraphBuilderContext b) { + return false; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/ParameterPlugin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/graphbuilderconf/ParameterPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015, 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.graphbuilderconf; + +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.nodes.calc.FloatingNode; + +public interface ParameterPlugin extends GraphBuilderPlugin { + FloatingNode interceptParameter(GraphBuilderContext b, int index, Stamp stamp); +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -49,7 +49,7 @@ public static final NodeClass TYPE = NodeClass.create(WriteNode.class); - private WriteNode(ValueNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) { + protected WriteNode(ValueNode address, LocationIdentity location, ValueNode value, BarrierType barrierType) { this((AddressNode) address, location, value, barrierType); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -568,6 +568,9 @@ private Iterable getInfoElements(ValueNode proxiedValue) { ValueNode value = GraphUtil.unproxify(proxiedValue); + if (value == null) { + return Collections.emptyList(); + } Info info = map.get(value); if (info == null) { return Collections.emptyList(); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/RemoveValueProxyPhase.java Mon Nov 30 16:41:10 2015 -0800 @@ -22,11 +22,11 @@ */ package com.oracle.graal.phases.common; +import com.oracle.graal.nodes.EntryProxyNode; import com.oracle.graal.nodes.FrameState; import com.oracle.graal.nodes.LoopExitNode; import com.oracle.graal.nodes.ProxyNode; import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.nodes.ValueProxyNode; import com.oracle.graal.nodes.util.GraphUtil; import com.oracle.graal.phases.Phase; @@ -35,7 +35,7 @@ @Override protected void run(StructuredGraph graph) { for (ProxyNode vpn : graph.getNodes(ProxyNode.TYPE)) { - if (vpn instanceof ValueProxyNode) { + if (!(vpn instanceof EntryProxyNode)) { graph.replaceFloating(vpn, vpn.value()); } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -32,14 +32,14 @@ import sun.misc.Unsafe; import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; -import com.oracle.graal.graphbuilderconf.ForeignCallPlugin; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.ForeignCallPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.java.AtomicReadAndAddNode; import com.oracle.graal.nodes.java.AtomicReadAndWriteNode; import com.oracle.graal.nodes.memory.address.AddressNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -114,9 +114,9 @@ } } - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ForeignCallNode.class) private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ForeignCallNode.class) private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.sparc/src/com/oracle/graal/replacements/sparc/SPARCGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements.sparc/src/com/oracle/graal/replacements/sparc/SPARCGraphBuilderPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.sparc/src/com/oracle/graal/replacements/sparc/SPARCGraphBuilderPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -33,13 +33,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; -import com.oracle.graal.graphbuilderconf.ForeignCallPlugin; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.ForeignCallPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.replacements.IntegerSubstitutions; import com.oracle.graal.replacements.LongSubstitutions; import com.oracle.graal.replacements.nodes.BitCountNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DerivedOopTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DerivedOopTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DerivedOopTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -31,12 +31,12 @@ import com.oracle.graal.api.directives.GraalDirectives; import com.oracle.graal.compiler.test.GraalCompilerTest; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.replacements.Snippets; import com.oracle.graal.word.Word; import com.oracle.graal.word.nodes.WordCastNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PEGraphDecoderTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PEGraphDecoderTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PEGraphDecoderTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -32,16 +32,16 @@ import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.compiler.test.GraalCompilerTest; import com.oracle.graal.debug.Debug; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.AbstractBeginNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.memory.HeapAccess.BarrierType; import com.oracle.graal.nodes.memory.ReadNode; import com.oracle.graal.nodes.memory.address.AddressNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTrackingTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTrackingTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTrackingTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -31,11 +31,11 @@ import com.oracle.graal.compiler.test.GraalCompilerTest; import com.oracle.graal.debug.Debug; import com.oracle.graal.debug.DebugConfigScope; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.replacements.Snippets; import com.oracle.graal.word.Word; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/ReplacementsParseTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -35,6 +35,7 @@ import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.nodes.PiNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.runtime.RuntimeProvider; @@ -43,6 +44,14 @@ */ public class ReplacementsParseTest extends GraalCompilerTest { + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins ret = super.getDefaultGraphBuilderPlugins(); + // manually register generated factory, jvmci service providers don't work from unit tests + new NodeIntrinsicFactory_ReplacementsParseTest_TestMethodsSubstitutions_asNonNullStringIntrinsic_2bfccb54().registerPlugin(ret.getInvocationPlugins(), null); + return ret; + } + private static final Object THROW_EXCEPTION_MARKER = new Object() { @Override public String toString() { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/SubstitutionsTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -46,12 +46,13 @@ import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; import com.oracle.graal.nodes.extended.GuardingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.memory.MemoryNode; public class SubstitutionsTest extends GraalCompilerTest { @NodeInfo(allowedUsageTypes = {Memory}) - private static class TestMemory extends FixedWithNextNode implements MemoryNode { + static class TestMemory extends FixedWithNextNode implements MemoryNode { private static final NodeClass TYPE = NodeClass.create(TestMemory.class); public TestMemory() { @@ -63,7 +64,7 @@ } @NodeInfo(allowedUsageTypes = {Guard}) - private static class TestGuard extends FloatingNode implements GuardingNode { + static class TestGuard extends FloatingNode implements GuardingNode { private static final NodeClass TYPE = NodeClass.create(TestGuard.class); @Input(Memory) MemoryNode memory; @@ -78,7 +79,7 @@ } @NodeInfo - private static class TestValue extends FloatingNode { + static class TestValue extends FloatingNode { private static final NodeClass TYPE = NodeClass.create(TestValue.class); @Input(Guard) GuardingNode guard; @@ -124,6 +125,16 @@ } @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins ret = super.getDefaultGraphBuilderPlugins(); + // manually register generated factories, jvmci service providers don't work from unit tests + new NodeIntrinsicFactory_SubstitutionsTest_TestGuard_guard_1c2b7e8f().registerPlugin(ret.getInvocationPlugins(), null); + new NodeIntrinsicFactory_SubstitutionsTest_TestMemory_memory().registerPlugin(ret.getInvocationPlugins(), null); + new NodeIntrinsicFactory_SubstitutionsTest_TestValue_value_a22f0f5f().registerPlugin(ret.getInvocationPlugins(), null); + return ret; + } + + @Override protected boolean checkHighTierGraph(StructuredGraph graph) { // Check that the graph contains the expected test nodes. NodeIterable retNodes = graph.getNodes().filter(ReturnNode.class); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/APHotSpotSignature.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -26,9 +26,18 @@ import java.util.List; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; import javax.tools.Diagnostic.Kind; /** @@ -96,6 +105,81 @@ return cur; } + private static void getSignatureName(StringBuilder ret, Element element) { + Element enclosing = element.getEnclosingElement(); + if (enclosing.getKind() == ElementKind.PACKAGE) { + ret.append(((PackageElement) enclosing).getQualifiedName().toString().replace('.', '/')); + ret.append('/'); + } else { + getSignatureName(ret, enclosing); + ret.append('$'); + } + ret.append(element.getSimpleName()); + } + + private static void getSignatureString(StringBuilder ret, TypeMirror type) { + switch (type.getKind()) { + case ARRAY: + ret.append('['); + getSignatureString(ret, ((ArrayType) type).getComponentType()); + break; + case BOOLEAN: + ret.append('Z'); + break; + case BYTE: + ret.append('B'); + break; + case SHORT: + ret.append('S'); + break; + case CHAR: + ret.append('C'); + break; + case INT: + ret.append('I'); + break; + case LONG: + ret.append('J'); + break; + case FLOAT: + ret.append('F'); + break; + case DOUBLE: + ret.append('D'); + break; + case VOID: + ret.append('V'); + break; + case DECLARED: + ret.append('L'); + getSignatureName(ret, ((DeclaredType) type).asElement()); + ret.append(';'); + break; + case TYPEVAR: + getSignatureString(ret, ((TypeVariable) type).getUpperBound()); + break; + case WILDCARD: + getSignatureString(ret, ((WildcardType) type).getExtendsBound()); + break; + case INTERSECTION: + ret.append("Ljava/lang/Object;"); + break; + default: + throw new IllegalArgumentException(type.toString()); + } + } + + public static String toSignature(ExecutableElement intrinsicMethod) { + StringBuilder ret = new StringBuilder(); + ret.append('('); + for (VariableElement param : intrinsicMethod.getParameters()) { + getSignatureString(ret, param.asType()); + } + ret.append(')'); + getSignatureString(ret, intrinsicMethod.getReturnType()); + return ret.toString(); + } + public int getParameterCount(boolean withReceiver) { return arguments.size() + (withReceiver ? 1 : 0); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/FoldPluginGenerator.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015, 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.replacements.verifier; + +import java.io.PrintWriter; +import java.lang.annotation.Annotation; +import java.util.List; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; + +import com.oracle.graal.api.replacements.Fold; +import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency; + +/** + * Create graph builder plugins for {@link Fold} methods. + */ +public class FoldPluginGenerator extends PluginGenerator { + + private class FoldVerifier extends AbstractVerifier { + + public FoldVerifier(ProcessingEnvironment env) { + super(env); + } + + @Override + public void verify(Element element, AnnotationMirror annotation) { + if (element.getKind() != ElementKind.METHOD) { + assert false : "Element is guaranteed to be a method."; + return; + } + + ExecutableElement intrinsicMethod = (ExecutableElement) element; + if (intrinsicMethod.getModifiers().contains(Modifier.PRIVATE)) { + env.getMessager().printMessage(Kind.ERROR, "@Fold method can not be private.", element); + } else { + FoldPluginGenerator.this.createPluginFactory(intrinsicMethod, null, null); + } + } + + @Override + public Class getAnnotationClass() { + return Fold.class; + } + } + + private TypeMirror stringType() { + return env.getElementUtils().getTypeElement("java.lang.String").asType(); + } + + public FoldPluginGenerator(ProcessingEnvironment env) { + super(env); + } + + public AbstractVerifier getVerifier() { + return new FoldVerifier(env); + } + + @Override + protected String getBaseName() { + return "FoldFactory"; + } + + @Override + protected void createImports(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement targetMethod) { + out.printf("import jdk.vm.ci.meta.JavaConstant;\n"); + out.printf("import jdk.vm.ci.meta.JavaKind;\n"); + out.printf("import com.oracle.graal.nodes.ConstantNode;\n"); + super.createImports(out, intrinsicMethod, targetMethod); + } + + @Override + protected InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) { + InjectedDependencies deps = new InjectedDependencies(); + List params = intrinsicMethod.getParameters(); + + int idx = 0; + for (VariableElement param : params) { + constantArgument(out, deps, idx, param.asType(), idx); + idx++; + } + + if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { + out.printf(" @SuppressWarnings(\"deprecation\")\n"); + } + out.printf(" %s result = %s.%s(", intrinsicMethod.getReturnType(), intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName()); + if (idx > 0) { + out.printf("_arg0"); + for (int i = 1; i < idx; i++) { + out.printf(", _arg%d", i); + } + } + out.printf(");\n"); + + TypeMirror returnType = intrinsicMethod.getReturnType(); + switch (returnType.getKind()) { + case BOOLEAN: + out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); + break; + case LONG: + out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); + break; + case FLOAT: + out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); + break; + case DOUBLE: + out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); + break; + case ARRAY: + case TYPEVAR: + case DECLARED: + if (returnType.equals(stringType())) { + out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION)); + } else { + out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION)); + } + break; + default: + throw new IllegalArgumentException(returnType.toString()); + } + + out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH)); + out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod).name()); + out.printf(" return true;\n"); + + return deps; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/InjectedDependencies.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/InjectedDependencies.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015, 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.replacements.verifier; + +import java.util.HashMap; +import java.util.Iterator; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; + +import com.oracle.graal.replacements.verifier.InjectedDependencies.Dependency; + +public class InjectedDependencies implements Iterable { + + public abstract static class Dependency { + + public final String name; + public final String type; + + private Dependency(String name, String type) { + this.name = name; + this.type = type; + } + + public abstract String inject(ExecutableElement inject); + } + + private static final class InjectedDependency extends Dependency { + + private InjectedDependency(String name, String type) { + super(name, type); + } + + @Override + public String inject(ExecutableElement inject) { + return String.format("injection.getInjectedArgument(%s.class)", type); + } + } + + private static final class StampDependency extends Dependency { + + private StampDependency() { + super("returnStamp", "com.oracle.graal.compiler.common.type.Stamp"); + } + + @Override + public String inject(ExecutableElement inject) { + return String.format("injection.getReturnStamp(%s.class)", NodeIntrinsicPluginGenerator.getErasedType(inject.getReturnType())); + } + } + + public enum WellKnownDependency { + CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"), + META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"), + RETURN_STAMP(new StampDependency()), + SNIPPET_REFLECTION(new InjectedDependency("snippetReflection", "com.oracle.graal.api.replacements.SnippetReflectionProvider")), + STAMP_PROVIDER("b.getStampProvider()", "com.oracle.graal.nodes.spi.StampProvider"), + STRUCTURED_GRAPH("b.getGraph()", "com.oracle.graal.nodes.StructuredGraph"); + + private final String expr; + private final String type; + private final Dependency generateMember; + + private WellKnownDependency(String expr, String type) { + this.expr = expr; + this.type = type; + this.generateMember = null; + } + + private WellKnownDependency(Dependency generateMember) { + this.expr = generateMember.name; + this.type = generateMember.type; + this.generateMember = generateMember; + } + + private TypeMirror getType(ProcessingEnvironment env) { + return env.getElementUtils().getTypeElement(type).asType(); + } + } + + private final HashMap deps; + + public InjectedDependencies() { + deps = new HashMap<>(); + } + + public String use(WellKnownDependency wellKnown) { + if (wellKnown.generateMember != null) { + deps.put(wellKnown.type, wellKnown.generateMember); + } + return wellKnown.expr; + } + + public String use(ProcessingEnvironment env, DeclaredType type) { + for (WellKnownDependency wellKnown : WellKnownDependency.values()) { + if (env.getTypeUtils().isAssignable(wellKnown.getType(env), type)) { + return use(wellKnown); + } + } + + String typeName = type.toString(); + Dependency ret = deps.get(typeName); + if (ret == null) { + ret = new InjectedDependency("injected" + type.asElement().getSimpleName(), typeName); + deps.put(typeName, ret); + } + return ret.name; + } + + public Iterator iterator() { + return deps.values().iterator(); + } + + public boolean isEmpty() { + return deps.isEmpty(); + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicPluginGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicPluginGenerator.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 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.replacements.verifier; + +import java.io.PrintWriter; +import java.util.List; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.tools.Diagnostic.Kind; + +import jdk.vm.ci.meta.JavaKind; + +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.InjectedNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency; + +/** + * Create graph builder plugins for {@link NodeIntrinsic} methods. + */ +public class NodeIntrinsicPluginGenerator extends PluginGenerator { + + public NodeIntrinsicPluginGenerator(ProcessingEnvironment env) { + super(env); + } + + private TypeMirror valueNodeType() { + return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.ValueNode").asType(); + } + + @Override + protected String getBaseName() { + return "NodeIntrinsicFactory"; + } + + @Override + protected void createImports(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement targetMethod) { + if (targetMethod.getKind() == ElementKind.CONSTRUCTOR && getReturnKind(intrinsicMethod) != JavaKind.Void) { + out.printf("import jdk.vm.ci.meta.JavaKind;\n"); + } + super.createImports(out, intrinsicMethod, targetMethod); + } + + @Override + protected InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature) { + InjectedDependencies deps = new InjectedDependencies(); + + List params = constructor.getParameters(); + + boolean customFactory = constructor.getKind() != ElementKind.CONSTRUCTOR; + int idx = customFactory ? 1 : 0; + for (; idx < params.size(); idx++) { + VariableElement param = params.get(idx); + if (param.getAnnotation(InjectedNodeParameter.class) == null) { + break; + } + + out.printf(" %s _arg%d = %s;\n", param.asType(), idx, deps.use(env, (DeclaredType) param.asType())); + } + + for (int i = 0; i < signature.length; i++, idx++) { + if (intrinsicMethod.getParameters().get(i).getAnnotation(ConstantNodeParameter.class) != null) { + constantArgument(out, deps, idx, signature[i], i); + } else { + if (signature[i].equals(valueNodeType())) { + out.printf(" ValueNode _arg%d = args[%d];\n", idx, i); + } else { + out.printf(" %s _arg%d = (%s) args[%d];\n", signature[i], idx, signature[i], i); + } + } + } + + if (customFactory) { + out.printf(" return %s.%s(b", constructor.getEnclosingElement(), constructor.getSimpleName()); + for (int i = 1; i < idx; i++) { + out.printf(", _arg%d", i); + } + out.printf(");\n"); + + if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) { + env.getMessager().printMessage(Kind.WARNING, "Ignoring setStampFromReturnType because a custom 'intrinsify' method is used.", intrinsicMethod); + } + } else { + out.printf(" %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement()); + if (idx > 0) { + out.printf("_arg0"); + for (int i = 1; i < idx; i++) { + out.printf(", _arg%d", i); + } + } + out.printf(");\n"); + + if (intrinsicMethod.getAnnotation(NodeIntrinsic.class).setStampFromReturnType()) { + out.printf(" node.setStamp(%s);\n", deps.use(WellKnownDependency.RETURN_STAMP)); + } + + JavaKind returnKind = getReturnKind(intrinsicMethod); + if (returnKind == JavaKind.Void) { + out.printf(" b.add(node);\n"); + } else { + out.printf(" b.addPush(JavaKind.%s, node);\n", returnKind.name()); + } + out.printf(" return true;\n"); + } + + return deps; + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/NodeIntrinsicVerifier.java Mon Nov 30 16:41:10 2015 -0800 @@ -73,8 +73,15 @@ return env.getElementUtils().getTypeElement("com.oracle.graal.nodeinfo.StructuralInput").asType(); } + private TypeMirror graphBuilderContextType() { + return env.getElementUtils().getTypeElement("com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext").asType(); + } + + private final NodeIntrinsicPluginGenerator factoryGen; + public NodeIntrinsicVerifier(ProcessingEnvironment env) { super(env); + factoryGen = new NodeIntrinsicPluginGenerator(env); } @Override @@ -114,20 +121,28 @@ env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic cannot have a generic return type.", element, annotation); } - if (isNodeType(nodeClass)) { - if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { - env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); + TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); + ExecutableElement custom = findCustomIntrinsifyMethod(nodeClass, constructorSignature); + if (custom != null) { + factoryGen.createPluginFactory(intrinsicMethod, custom, constructorSignature); + } else { + if (isNodeType(nodeClass)) { + if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { + env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make @NodeIntrinsic for abstract node class %s.", nodeClass.getSimpleName()), element, annotation); + } else { + TypeMirror ret = intrinsicMethod.getReturnType(); + if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { + checkInputType(nodeClass, ret, element, annotation); + } + + ExecutableElement constructor = findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); + if (constructor != null) { + factoryGen.createPluginFactory(intrinsicMethod, constructor, constructorSignature); + } + } } else { - TypeMirror ret = intrinsicMethod.getReturnType(); - if (env.getTypeUtils().isAssignable(ret, structuralInputType())) { - checkInputType(nodeClass, ret, element, annotation); - } - - TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); - findConstructor(nodeClass, constructorSignature, intrinsicMethod, annotation); + env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation); } - } else { - env.getMessager().printMessage(Kind.ERROR, String.format("The class %s is not a Node subclass.", nodeClass.getSimpleName()), element, annotation); } } @@ -185,47 +200,18 @@ return parameters; } - private void findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { + private ExecutableElement findConstructor(TypeElement nodeClass, TypeMirror[] signature, ExecutableElement intrinsicMethod, AnnotationMirror intrinsicAnnotation) { List constructors = ElementFilter.constructorsIn(nodeClass.getEnclosedElements()); List failureReasons = new ArrayList<>(); - nextConstructor: for (ExecutableElement constructor : constructors) { - int sIdx = 0; - int cIdx = 0; - while (cIdx < constructor.getParameters().size()) { - VariableElement parameter = constructor.getParameters().get(cIdx++); - if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { - // skip injected parameters - continue; - } - - TypeMirror paramType = parameter.asType(); - if (cIdx == constructor.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { - // last argument of constructor is varargs, match remaining intrinsic arguments - TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); - while (sIdx < signature.length) { - if (!isTypeCompatible(varargsType, signature[sIdx++])) { - failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, varargsType, signature[sIdx - 1])); - continue nextConstructor; - } - } - } else if (sIdx >= signature.length) { - // too many arguments in intrinsic method - failureReasons.add(String.format("Too many arguments for %s", constructor)); - continue nextConstructor; - } else if (!isTypeCompatible(paramType, signature[sIdx++])) { - failureReasons.add(String.format("Constructor %s failed because the types of argument %d are incompatible: %s != %s", constructor, sIdx, paramType, signature[sIdx - 1])); - continue nextConstructor; - } + for (ExecutableElement constructor : constructors) { + String failureReason = matchSignature(false, constructor, signature); + if (failureReason == null) { + // found + return constructor; } - if (sIdx == signature.length) { - // found - return; - } - - // too many arguments in constructor - failureReasons.add(String.format("Not enough arguments for %s", constructor)); + failureReasons.add(failureReason); } // not found @@ -236,6 +222,70 @@ env.getMessager().printMessage(Kind.ERROR, reason, intrinsicMethod, intrinsicAnnotation); } } + + return null; + } + + private ExecutableElement findCustomIntrinsifyMethod(TypeElement nodeClass, TypeMirror[] signature) { + List methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); + for (ExecutableElement method : methods) { + if (!method.getSimpleName().toString().equals("intrinsify")) { + continue; + } + + if (method.getParameters().isEmpty()) { + continue; + } + + VariableElement firstArg = method.getParameters().get(0); + if (!isTypeCompatible(firstArg.asType(), graphBuilderContextType())) { + continue; + } + + String failureReason = matchSignature(true, method, signature); + if (failureReason == null) { + // found + return method; + } + } + + return null; + } + + private String matchSignature(boolean skipFirst, ExecutableElement method, TypeMirror[] signature) { + int sIdx = 0; + int cIdx = skipFirst ? 1 : 0; + while (cIdx < method.getParameters().size()) { + VariableElement parameter = method.getParameters().get(cIdx++); + if (parameter.getAnnotation(InjectedNodeParameter.class) != null) { + // skip injected parameters + continue; + } + + TypeMirror paramType = parameter.asType(); + if (cIdx == method.getParameters().size() && paramType.getKind() == TypeKind.ARRAY) { + // last argument of constructor is varargs, match remaining intrinsic arguments + TypeMirror varargsType = ((ArrayType) paramType).getComponentType(); + while (sIdx < signature.length) { + if (!isTypeCompatible(varargsType, signature[sIdx++])) { + return String.format("%s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, varargsType, signature[sIdx - 1]); + } + } + } else if (sIdx >= signature.length) { + // too many arguments in intrinsic method + return String.format("Too many arguments for %s", method); + } else if (!isTypeCompatible(paramType, signature[sIdx++])) { + return String.format("%s failed because the types of argument %d are incompatible: %s != %s", method, sIdx, paramType, signature[sIdx - 1]); + } + } + + if (sIdx == signature.length) { + // found + return null; + } + + // too many arguments in constructor + return String.format("Not enough arguments for %s", method); } private boolean isTypeCompatible(TypeMirror originalType, TypeMirror substitutionType) { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/PluginGenerator.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2015, 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.replacements.verifier; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +import jdk.vm.ci.meta.JavaKind; + +import com.oracle.graal.replacements.verifier.InjectedDependencies.Dependency; +import com.oracle.graal.replacements.verifier.InjectedDependencies.WellKnownDependency; + +public abstract class PluginGenerator { + + protected final ProcessingEnvironment env; + + public PluginGenerator(ProcessingEnvironment env) { + this.env = env; + } + + private TypeMirror resolvedJavaTypeType() { + return env.getElementUtils().getTypeElement("jdk.vm.ci.meta.ResolvedJavaType").asType(); + } + + private static Element getTopLevelClass(Element element) { + Element prev = element; + Element enclosing = element.getEnclosingElement(); + while (enclosing != null && enclosing.getKind() != ElementKind.PACKAGE) { + prev = enclosing; + enclosing = enclosing.getEnclosingElement(); + } + return prev; + } + + private static void mkClassName(StringBuilder ret, Element cls) { + Element enclosingClass = cls.getEnclosingElement(); + if (enclosingClass.getKind() == ElementKind.CLASS || enclosingClass.getKind() == ElementKind.INTERFACE) { + mkClassName(ret, enclosingClass); + ret.append('_'); + } + ret.append(cls.getSimpleName()); + } + + static String getErasedType(TypeMirror type) { + switch (type.getKind()) { + case DECLARED: + DeclaredType declared = (DeclaredType) type; + TypeElement element = (TypeElement) declared.asElement(); + return element.getQualifiedName().toString(); + case TYPEVAR: + return getErasedType(((TypeVariable) type).getUpperBound()); + case WILDCARD: + return getErasedType(((WildcardType) type).getExtendsBound()); + case ARRAY: + return getErasedType(((ArrayType) type).getComponentType()) + "[]"; + default: + return type.toString(); + } + } + + protected abstract String getBaseName(); + + private String mkFactoryClassName(ExecutableElement intrinsicMethod) { + StringBuilder ret = new StringBuilder(); + ret.append(getBaseName()); + ret.append('_'); + mkClassName(ret, intrinsicMethod.getEnclosingElement()); + ret.append('_'); + ret.append(intrinsicMethod.getSimpleName()); + if (!intrinsicMethod.getParameters().isEmpty()) { + ret.append('_'); + ret.append(Integer.toHexString(APHotSpotSignature.toSignature(intrinsicMethod).hashCode())); + } + return ret.toString(); + } + + void createPluginFactory(ExecutableElement intrinsicMethod, ExecutableElement targetMethod, TypeMirror[] constructorSignature) { + Element declaringClass = intrinsicMethod.getEnclosingElement(); + Element topLevelClass = getTopLevelClass(declaringClass); + PackageElement pkg = (PackageElement) topLevelClass.getEnclosingElement(); + + String genClassName = mkFactoryClassName(intrinsicMethod); + + try { + JavaFileObject factory = env.getFiler().createSourceFile(pkg.getQualifiedName() + "." + genClassName, topLevelClass, declaringClass, intrinsicMethod); + try (PrintWriter out = new PrintWriter(factory.openWriter())) { + out.printf("// CheckStyle: stop header check\n"); + out.printf("// CheckStyle: stop line length check\n"); + out.printf("// GENERATED CONTENT - DO NOT EDIT\n"); + out.printf("package %s;\n", pkg.getQualifiedName()); + out.printf("\n"); + createImports(out, intrinsicMethod, targetMethod); + out.printf("\n"); + out.printf("@ServiceProvider(NodeIntrinsicPluginFactory.class)\n"); + out.printf("public class %s implements NodeIntrinsicPluginFactory {\n", genClassName); + out.printf("\n"); + out.printf(" private static final class Plugin extends GeneratedInvocationPlugin {\n"); + out.printf("\n"); + + out.printf(" @Override\n"); + out.printf(" public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n"); + out.printf(" if (!b.parsingIntrinsic()) {\n"); + out.printf(" return false;\n"); + out.printf(" }\n"); + InjectedDependencies deps = createExecute(out, intrinsicMethod, targetMethod, constructorSignature); + out.printf(" }\n"); + + createPrivateMembers(out, intrinsicMethod, deps); + + out.printf(" }\n"); + out.printf("\n"); + createPluginFactoryMethod(out, intrinsicMethod, deps); + out.printf("}\n"); + } + } catch (IOException e) { + env.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); + } + } + + protected abstract InjectedDependencies createExecute(PrintWriter out, ExecutableElement intrinsicMethod, ExecutableElement constructor, TypeMirror[] signature); + + protected void createImports(PrintWriter out, @SuppressWarnings("unused") ExecutableElement intrinsicMethod, @SuppressWarnings("unused") ExecutableElement targetMethod) { + out.printf("import jdk.vm.ci.meta.ResolvedJavaMethod;\n"); + out.printf("import jdk.vm.ci.service.ServiceProvider;\n"); + out.printf("\n"); + out.printf("import com.oracle.graal.nodes.ValueNode;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.GeneratedInvocationPlugin;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins;\n"); + out.printf("import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;\n"); + } + + private static void createPrivateMembers(PrintWriter out, ExecutableElement intrinsicMethod, InjectedDependencies deps) { + if (!deps.isEmpty()) { + out.printf("\n"); + for (Dependency dep : deps) { + out.printf(" private final %s %s;\n", dep.type, dep.name); + } + + out.printf("\n"); + out.printf(" private Plugin(InjectionProvider injection) {\n"); + for (Dependency dep : deps) { + out.printf(" this.%s = %s;\n", dep.name, dep.inject(intrinsicMethod)); + } + out.printf(" }\n"); + } + } + + private static void createPluginFactoryMethod(PrintWriter out, ExecutableElement intrinsicMethod, InjectedDependencies deps) { + out.printf(" public void registerPlugin(InvocationPlugins plugins, InjectionProvider injection) {\n"); + out.printf(" Plugin plugin = new Plugin(%s);\n", deps.isEmpty() ? "" : "injection"); + out.printf(" plugins.register(plugin, %s.class, \"%s\"", intrinsicMethod.getEnclosingElement(), intrinsicMethod.getSimpleName()); + for (VariableElement arg : intrinsicMethod.getParameters()) { + out.printf(", %s.class", getErasedType(arg.asType())); + } + out.printf(");\n"); + out.printf(" }\n"); + } + + protected static JavaKind getReturnKind(ExecutableElement method) { + switch (method.getReturnType().getKind()) { + case BOOLEAN: + case BYTE: + case SHORT: + case CHAR: + case INT: + return JavaKind.Int; + case LONG: + return JavaKind.Long; + case FLOAT: + return JavaKind.Float; + case DOUBLE: + return JavaKind.Double; + case VOID: + return JavaKind.Void; + case ARRAY: + case TYPEVAR: + case DECLARED: + return JavaKind.Object; + default: + throw new IllegalArgumentException(method.getReturnType().toString()); + } + } + + protected void constantArgument(PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) { + out.printf(" %s _arg%d;\n", type, argIdx); + out.printf(" if (args[%d].isConstant()) {\n", nodeIdx); + if (type.equals(resolvedJavaTypeType())) { + out.printf(" _arg%d = %s.asJavaType(args[%d].asConstant());\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION), nodeIdx); + } else { + switch (type.getKind()) { + case BOOLEAN: + out.printf(" _arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx); + break; + case BYTE: + out.printf(" _arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case CHAR: + out.printf(" _arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case SHORT: + out.printf(" _arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case INT: + out.printf(" _arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + break; + case LONG: + out.printf(" _arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx); + break; + case FLOAT: + out.printf(" _arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx); + break; + case DOUBLE: + out.printf(" _arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx); + break; + case DECLARED: + out.printf(" _arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), type, nodeIdx); + break; + default: + throw new IllegalArgumentException(); + } + } + out.printf(" } else {\n"); + out.printf(" return false;\n"); + out.printf(" }\n"); + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java --- a/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements.verifier/src/com/oracle/graal/replacements/verifier/VerifierAnnotationProcessor.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -84,6 +84,7 @@ verifiers.add(new ClassSubstitutionVerifier(this.processingEnv)); verifiers.add(new MethodSubstitutionVerifier(this.processingEnv)); verifiers.add(new NodeIntrinsicVerifier(this.processingEnv)); + verifiers.add(new FoldPluginGenerator(this.processingEnv).getVerifier()); } return verifiers; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CachingPEGraphDecoder.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CachingPEGraphDecoder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/CachingPEGraphDecoder.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.util.HashMap; import java.util.Map; @@ -31,13 +31,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import com.oracle.graal.debug.Debug; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.EncodedGraph; import com.oracle.graal.nodes.GraphEncoder; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.common.CanonicalizerPhase; import com.oracle.graal.phases.tiers.PhaseContext; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ConstantBindingParameterPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ConstantBindingParameterPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ConstantBindingParameterPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -27,10 +27,10 @@ import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.ParameterPlugin; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.ParameterPlugin; /** * A {@link ParameterPlugin} that binds constant values to some parameters. diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -192,7 +192,7 @@ } private void lowerTypeCheckNode(TypeCheckNode n, LoweringTool tool, StructuredGraph graph) { - ValueNode hub = createReadHub(graph, n.getValue(), null, tool); + ValueNode hub = createReadHub(graph, n.getValue(), tool); ValueNode clazz = graph.unique(ConstantNode.forConstant(tool.getStampProvider().createHubStamp((ObjectStamp) n.getValue().stamp()), n.type().getObjectHub(), tool.getMetaAccess())); LogicNode objectEquals = graph.unique(PointerEqualsNode.create(hub, clazz)); n.replaceAndDelete(objectEquals); @@ -344,7 +344,7 @@ */ GuardingNode nullCheck = nullCheckReturn[0]; assert nullCheckReturn[0] != null || createNullCheck(array, storeIndexed, tool) == null; - ValueNode arrayClass = createReadHub(graph, array, nullCheck, tool); + ValueNode arrayClass = createReadHub(graph, graph.unique(new PiNode(array, (ValueNode) nullCheck)), tool); ValueNode componentHub = createReadArrayComponentHub(graph, arrayClass, storeIndexed); checkCastNode = graph.add(new CheckCastDynamicNode(componentHub, value, true)); graph.addBeforeFixed(storeIndexed, checkCastNode); @@ -383,7 +383,7 @@ if (graph.getGuardsStage().allowsFloatingGuards()) { return; } - ValueNode hub = createReadHub(graph, loadHub.getValue(), loadHub.getGuard(), tool); + ValueNode hub = createReadHub(graph, loadHub.getValue(), tool); graph.replaceFloating(loadHub, hub); } @@ -715,40 +715,63 @@ return stamp; } - public ValueNode implicitLoadConvert(StructuredGraph graph, JavaKind kind, ValueNode value) { + public final ValueNode implicitLoadConvert(StructuredGraph graph, JavaKind kind, ValueNode value) { return implicitLoadConvert(graph, kind, value, true); + } + public ValueNode implicitLoadConvert(JavaKind kind, ValueNode value) { + return implicitLoadConvert(kind, value, true); } - protected ValueNode implicitLoadConvert(StructuredGraph graph, JavaKind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { + protected final ValueNode implicitLoadConvert(StructuredGraph graph, JavaKind kind, ValueNode value, boolean compressible) { + ValueNode ret = implicitLoadConvert(kind, value, compressible); + if (!ret.isAlive()) { + ret = graph.addOrUnique(ret); + } + return ret; + } + + protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { switch (kind) { case Byte: case Short: - return graph.unique(new SignExtendNode(value, 32)); + return new SignExtendNode(value, 32); case Boolean: case Char: - return graph.unique(new ZeroExtendNode(value, 32)); + return new ZeroExtendNode(value, 32); } return value; } - public ValueNode implicitStoreConvert(StructuredGraph graph, JavaKind kind, ValueNode value) { + public final ValueNode implicitStoreConvert(StructuredGraph graph, JavaKind kind, ValueNode value) { return implicitStoreConvert(graph, kind, value, true); } - protected ValueNode implicitStoreConvert(StructuredGraph graph, JavaKind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { + public ValueNode implicitStoreConvert(JavaKind kind, ValueNode value) { + return implicitStoreConvert(kind, value, true); + } + + protected final ValueNode implicitStoreConvert(StructuredGraph graph, JavaKind kind, ValueNode value, boolean compressible) { + ValueNode ret = implicitStoreConvert(kind, value, compressible); + if (!ret.isAlive()) { + ret = graph.addOrUnique(ret); + } + return ret; + } + + protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, @SuppressWarnings("unused") boolean compressible) { switch (kind) { case Boolean: case Byte: - return graph.unique(new NarrowNode(value, 8)); + return new NarrowNode(value, 8); case Char: case Short: - return graph.unique(new NarrowNode(value, 16)); + return new NarrowNode(value, 16); } return value; } - protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, GuardingNode guard, LoweringTool tool); + protected abstract ValueNode createReadHub(StructuredGraph graph, ValueNode object, LoweringTool tool); protected abstract ValueNode createReadArrayComponentHub(StructuredGraph graph, ValueNode arrayHub, FixedNode anchor); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraphKit.java Mon Nov 30 16:41:10 2015 -0800 @@ -22,7 +22,7 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -39,9 +39,6 @@ import com.oracle.graal.graph.Graph; import com.oracle.graal.graph.Node; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; import com.oracle.graal.java.FrameStateBuilder; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.AbstractBeginNode; @@ -60,6 +57,9 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.type.StampTool; import com.oracle.graal.phases.OptimisticOptimizations; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InlineDuringParsingPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InlineDuringParsingPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/InlineDuringParsingPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -27,9 +27,9 @@ import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; public final class InlineDuringParsingPlugin implements InlineInvokePlugin { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/IntrinsicGraphBuilder.java Mon Nov 30 16:41:10 2015 -0800 @@ -35,10 +35,6 @@ import com.oracle.graal.compiler.common.type.Stamp; import com.oracle.graal.compiler.common.type.StampFactory; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.FixedNode; import com.oracle.graal.nodes.FixedWithNextNode; @@ -50,6 +46,10 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; import com.oracle.graal.nodes.spi.StampProvider; /** diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MethodHandlePlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MethodHandlePlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MethodHandlePlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -29,10 +29,10 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import com.oracle.graal.graph.NodeInputList; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.NodePlugin; import com.oracle.graal.nodes.CallTargetNode; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.NodePlugin; import com.oracle.graal.nodes.InvokeNode; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.replacements.nodes.MethodHandleNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Mon Nov 30 16:24:57 2015 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,506 +0,0 @@ -/* - * Copyright (c) 2011, 2015, 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.replacements; - -import static jdk.vm.ci.meta.MetaUtil.resolveJavaTypes; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaMethod; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.PrimitiveConstant; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -import com.oracle.graal.api.replacements.Fold; -import com.oracle.graal.api.replacements.SnippetReflectionProvider; -import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.compiler.common.type.StampFactory; -import com.oracle.graal.debug.Debug; -import com.oracle.graal.debug.internal.DebugScope; -import com.oracle.graal.graph.Node; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.InjectedNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.ConstantNode; -import com.oracle.graal.nodes.FrameState; -import com.oracle.graal.nodes.LogicConstantNode; -import com.oracle.graal.nodes.PiNode; -import com.oracle.graal.nodes.ProxyNode; -import com.oracle.graal.nodes.ReturnNode; -import com.oracle.graal.nodes.StructuredGraph; -import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.ValueProxyNode; -import com.oracle.graal.nodes.calc.FloatingNode; -import com.oracle.graal.nodes.calc.IsNullNode; -import com.oracle.graal.nodes.extended.UnboxNode; -import com.oracle.graal.nodes.extended.UnsafeStoreNode; -import com.oracle.graal.nodes.extended.ValueAnchorNode; -import com.oracle.graal.nodes.java.CheckCastNode; -import com.oracle.graal.nodes.java.LoadFieldNode; -import com.oracle.graal.nodes.java.MethodCallTargetNode; -import com.oracle.graal.nodes.spi.StampProvider; -import com.oracle.graal.nodes.util.GraphUtil; -import com.oracle.graal.phases.Phase; - -/** - * Replaces calls to {@link NodeIntrinsic}s with nodes and calls to methods annotated with - * {@link Fold} with the result of invoking the annotated method via reflection. - */ -public class NodeIntrinsificationPhase extends Phase { - - private final MetaAccessProvider metaAccess; - private final ConstantReflectionProvider constantReflection; - private final SnippetReflectionProvider snippetReflection; - private final ForeignCallsProvider foreignCalls; - private final StampProvider stampProvider; - - public NodeIntrinsificationPhase(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, - StampProvider stampProvider) { - this.metaAccess = metaAccess; - this.constantReflection = constantReflection; - this.snippetReflection = snippetReflection; - this.foreignCalls = foreignCalls; - this.stampProvider = stampProvider; - } - - @Override - protected void run(StructuredGraph graph) { - ArrayList cleanUpReturnList = new ArrayList<>(); - for (MethodCallTargetNode node : graph.getNodes(MethodCallTargetNode.TYPE)) { - tryIntrinsify(node, cleanUpReturnList); - } - - for (Node node : cleanUpReturnList) { - cleanUpReturnCheckCast(node); - } - } - - protected boolean tryIntrinsify(MethodCallTargetNode methodCallTargetNode, List cleanUpReturnList) { - ResolvedJavaMethod target = methodCallTargetNode.targetMethod(); - ResolvedJavaType declaringClass = target.getDeclaringClass(); - StructuredGraph graph = methodCallTargetNode.graph(); - - NodeIntrinsic intrinsic = getIntrinsic(target); - if (intrinsic != null) { - Stamp stamp = methodCallTargetNode.invoke().asNode().stamp(); - Node newInstance = createIntrinsicNode(methodCallTargetNode.arguments(), stamp, target, graph, intrinsic); - if (newInstance == null) { - return false; - } - - // Replace the invoke with the new node. - newInstance = graph.addOrUnique(newInstance); - methodCallTargetNode.invoke().intrinsify(newInstance); - - // Clean up checkcast instructions inserted by javac if the return type is generic. - cleanUpReturnList.add(newInstance); - } else if (isFoldable(target)) { - ResolvedJavaType[] parameterTypes = resolveJavaTypes(target.toParameterTypes(), declaringClass); - JavaConstant constant = tryFold(methodCallTargetNode.arguments(), parameterTypes, target); - if (constant != null && constant.equals(COULD_NOT_FOLD)) { - return false; - } - - if (constant != null) { - // Replace the invoke with the result of the call - ConstantNode node = ConstantNode.forConstant(constant, metaAccess, methodCallTargetNode.graph()); - methodCallTargetNode.invoke().intrinsify(node); - - // Clean up checkcast instructions inserted by javac if the return type is generic. - cleanUpReturnList.add(node); - } else { - // Remove the invoke - methodCallTargetNode.invoke().intrinsify(null); - } - } - return true; - } - - public static final JavaConstant COULD_NOT_FOLD = new PrimitiveConstant(JavaKind.Illegal, 100) { - @Override - public boolean equals(Object o) { - return this == o; - } - }; - - public JavaConstant tryFold(List args, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target) { - JavaConstant[] reflectArgs = (JavaConstant[]) prepareArguments(args, parameterTypes, target, true); - if (reflectArgs == null) { - return COULD_NOT_FOLD; - } - JavaConstant receiver = null; - if (!target.isStatic()) { - receiver = reflectArgs[0]; - reflectArgs = Arrays.copyOfRange(reflectArgs, 1, reflectArgs.length); - } - - // Call the method - return target.invoke(receiver, reflectArgs); - } - - /** - * Attempts to create a node to replace a call to a {@link NodeIntrinsic} annotated method. - * - * @param arguments the arguments of the call - * @param stamp the stamp to use for the returned node - * @param method the method annotated with {@link NodeIntrinsic} - * @param graph the graph into which the created node will be added - * @return {@code null} if intrinsification could not (yet) be performed, otherwise the node - * representing the intrinsic - */ - public ValueNode createIntrinsicNode(List arguments, Stamp stamp, ResolvedJavaMethod method, StructuredGraph graph, NodeIntrinsic intrinsic) { - assert method.getAnnotation(Fold.class) == null; - assert method.isStatic() : "node intrinsic must be static: " + method; - - ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); - - // Prepare the arguments for the reflective constructor call on the node class. - Object[] nodeConstructorArguments = prepareArguments(arguments, parameterTypes, method, false); - if (nodeConstructorArguments == null) { - return null; - } - - // Create the new node instance. - ResolvedJavaType c = getNodeClass(method, intrinsic); - return createNodeInstance(graph, c, parameterTypes, stamp, intrinsic.setStampFromReturnType(), nodeConstructorArguments); - } - - /** - * Permits a subclass to override the default definition of "intrinsic". - */ - public NodeIntrinsic getIntrinsic(ResolvedJavaMethod method) { - return method.getAnnotation(Node.NodeIntrinsic.class); - } - - /** - * Permits a subclass to override the default definition of "foldable". - */ - public boolean isFoldable(ResolvedJavaMethod method) { - return method.getAnnotation(Fold.class) != null; - } - - /** - * Converts the arguments of an invoke node to object values suitable for use as the arguments - * to a reflective invocation of a Java constructor or method. - * - * @param folding specifies if the invocation is for handling a {@link Fold} annotation - * @return the arguments for the reflective invocation or null if an argument of {@code invoke} - * that is expected to be constant isn't - */ - private Object[] prepareArguments(List arguments, ResolvedJavaType[] parameterTypes, ResolvedJavaMethod target, boolean folding) { - Object[] reflectionCallArguments = folding ? new JavaConstant[arguments.size()] : new Object[arguments.size()]; - for (int i = 0; i < reflectionCallArguments.length; ++i) { - int parameterIndex = i; - if (!target.isStatic()) { - parameterIndex--; - } - ValueNode argument = arguments.get(i); - if (folding || target.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex) != null) { - if (!(argument instanceof ConstantNode)) { - return null; - } - ConstantNode constantNode = (ConstantNode) argument; - Constant constant = constantNode.asConstant(); - /* - * For intrinsification (but not for folding) if we have a Class object we want - * the corresponding ResolvedJavaType. - */ - ResolvedJavaType type = folding ? null : constantReflection.asJavaType(constant); - Object arg; - if (type != null) { - /* If we found such a type then it's our arg */ - arg = type; - parameterTypes[i] = metaAccess.lookupJavaType(ResolvedJavaType.class); - } else { - JavaConstant javaConstant = (JavaConstant) constant; - if (folding) { - /* For folding we want JavaConstants */ - arg = javaConstant; - } else { - /* For intrinsification we want want corresponding objects */ - if (parameterTypes[i].getJavaKind() == JavaKind.Boolean) { - arg = Boolean.valueOf(javaConstant.asInt() != 0); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Byte) { - arg = Byte.valueOf((byte) javaConstant.asInt()); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Short) { - arg = Short.valueOf((short) javaConstant.asInt()); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Char) { - arg = Character.valueOf((char) javaConstant.asInt()); - } else if (parameterTypes[i].getJavaKind() == JavaKind.Object) { - arg = snippetReflection.asObject(parameterTypes[i], javaConstant); - } else { - arg = javaConstant.asBoxedPrimitive(); - } - } - } - - assert folding || !(arg instanceof JavaConstant); - reflectionCallArguments[i] = arg; - } else { - reflectionCallArguments[i] = argument; - parameterTypes[i] = metaAccess.lookupJavaType(ValueNode.class); - } - } - return reflectionCallArguments; - } - - public ResolvedJavaType getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { - ResolvedJavaType result; - if (intrinsic.value() == NodeIntrinsic.class) { - result = target.getDeclaringClass(); - } else { - result = metaAccess.lookupJavaType(intrinsic.value()); - } - assert metaAccess.lookupJavaType(ValueNode.class).isAssignableFrom(result) : "Node intrinsic class " + result.toJavaName(false) + " derived from @" + NodeIntrinsic.class.getSimpleName() + - " annotation on " + target.format("%H.%n(%p)") + " is not a subclass of " + ValueNode.class; - return result; - } - - protected ValueNode createNodeInstance(StructuredGraph graph, ResolvedJavaType nodeClass, ResolvedJavaType[] parameterTypes, Stamp invokeStamp, boolean setStampFromReturnType, - Object[] nodeConstructorArguments) { - ResolvedJavaMethod constructor = null; - Object[] arguments = null; - - for (ResolvedJavaMethod c : nodeClass.getDeclaredConstructors()) { - Object[] match = match(graph, invokeStamp, c, parameterTypes, nodeConstructorArguments); - - if (match != null) { - if (constructor == null) { - constructor = c; - arguments = match; - if (!Debug.isEnabled()) { - // Don't verify there's a unique match in non-debug mode - break; - } - } else { - throw new JVMCIError("Found multiple constructors in %s compatible with signature %s: %s, %s", nodeClass.toJavaName(), sigString(parameterTypes), constructor, c); - } - } - } - if (constructor == null) { - throw new JVMCIError("Could not find constructor in %s compatible with signature %s", nodeClass.toJavaName(), sigString(parameterTypes)); - } - - try { - ValueNode intrinsicNode = (ValueNode) invokeConstructor(constructor, arguments); - - if (setStampFromReturnType) { - intrinsicNode.setStamp(invokeStamp); - } - return intrinsicNode; - } catch (Exception e) { - throw new RuntimeException(constructor + Arrays.toString(nodeConstructorArguments), e); - } - } - - protected Object invokeConstructor(ResolvedJavaMethod constructor, Object[] arguments) { - return snippetReflection.invoke(constructor, null, arguments); - } - - private static String sigString(ResolvedJavaType[] types) { - StringBuilder sb = new StringBuilder("("); - for (int i = 0; i < types.length; i++) { - if (i != 0) { - sb.append(", "); - } - sb.append(types[i].toJavaName()); - } - return sb.append(")").toString(); - } - - private static boolean checkNoMoreInjected(ResolvedJavaMethod c, int start) { - int count = c.getSignature().getParameterCount(false); - for (int i = start; i < count; i++) { - if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) { - throw new JVMCIError("Injected parameter %d of type %s must precede all non-injected parameters of %s", i, - c.getSignature().getParameterType(i, c.getDeclaringClass()).toJavaName(false), c.format("%H.%n(%p)")); - } - } - return true; - } - - private Object[] match(StructuredGraph graph, Stamp invokeStamp, ResolvedJavaMethod c, ResolvedJavaType[] parameterTypes, Object[] nodeConstructorArguments) { - Object[] arguments = null; - Object[] injected = null; - - ResolvedJavaType[] signature = resolveJavaTypes(c.getSignature().toParameterTypes(null), c.getDeclaringClass()); - for (int i = 0; i < signature.length; i++) { - if (c.getParameterAnnotation(InjectedNodeParameter.class, i) != null) { - injected = injected == null ? new Object[1] : Arrays.copyOf(injected, injected.length + 1); - Object injectedParameter = snippetReflection.getInjectedNodeIntrinsicParameter(signature[i]); - if (injectedParameter != null) { - injected[injected.length - 1] = injectedParameter; - } else if (signature[i].equals(metaAccess.lookupJavaType(MetaAccessProvider.class))) { - injected[injected.length - 1] = metaAccess; - } else if (signature[i].equals(metaAccess.lookupJavaType(StructuredGraph.class))) { - injected[injected.length - 1] = graph; - } else if (signature[i].equals(metaAccess.lookupJavaType(ForeignCallsProvider.class))) { - injected[injected.length - 1] = foreignCalls; - } else if (signature[i].equals(metaAccess.lookupJavaType(SnippetReflectionProvider.class))) { - injected[injected.length - 1] = snippetReflection; - } else if (signature[i].isAssignableFrom(metaAccess.lookupJavaType(Stamp.class))) { - injected[injected.length - 1] = invokeStamp; - } else if (signature[i].isAssignableFrom(metaAccess.lookupJavaType(StampProvider.class))) { - injected[injected.length - 1] = stampProvider; - } else { - throw new JVMCIError("Cannot handle injected argument of type %s in %s", signature[i].toJavaName(), c.format("%H.%n(%p)")); - } - } else { - assert checkNoMoreInjected(c, i); - break; - } - } - if (injected != null) { - // Chop injected arguments from signature - signature = Arrays.copyOfRange(signature, injected.length, signature.length); - } - - if (Arrays.equals(parameterTypes, signature)) { - // Exact match - arguments = nodeConstructorArguments; - - } else if (signature.length > 0 && signature[signature.length - 1].isArray()) { - // Last constructor parameter is an array, so check if we have a vararg match - int fixedArgs = signature.length - 1; - if (parameterTypes.length < fixedArgs) { - return null; - } - for (int i = 0; i < fixedArgs; i++) { - if (!parameterTypes[i].equals(signature[i])) { - return null; - } - } - - ResolvedJavaType componentType = signature[fixedArgs].getComponentType(); - assert componentType != null; - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - if (!parameterTypes[i].equals(componentType)) { - return null; - } - } - arguments = Arrays.copyOf(nodeConstructorArguments, fixedArgs + 1); - arguments[fixedArgs] = snippetReflection.newArray(componentType, nodeConstructorArguments.length - fixedArgs); - - Object varargs = arguments[fixedArgs]; - for (int i = fixedArgs; i < nodeConstructorArguments.length; i++) { - if (componentType.isPrimitive()) { - Array.set(varargs, i - fixedArgs, nodeConstructorArguments[i]); - } else { - ((Object[]) varargs)[i - fixedArgs] = nodeConstructorArguments[i]; - } - } - } else { - return null; - } - - if (injected != null) { - Object[] copy = new Object[injected.length + arguments.length]; - System.arraycopy(injected, 0, copy, 0, injected.length); - System.arraycopy(arguments, 0, copy, injected.length, arguments.length); - arguments = copy; - } - return arguments; - } - - private static String sourceLocation(Node n) { - String loc = GraphUtil.approxSourceLocation(n); - return loc == null ? "" : loc; - } - - public void cleanUpReturnCheckCast(Node newInstance) { - if (newInstance instanceof ValueNode && (((ValueNode) newInstance).getStackKind() != JavaKind.Object || ((ValueNode) newInstance).stamp() == StampFactory.forNodeIntrinsic())) { - StructuredGraph graph = (StructuredGraph) newInstance.graph(); - for (CheckCastNode checkCastNode : newInstance.usages().filter(CheckCastNode.class).snapshot()) { - for (Node checkCastUsage : checkCastNode.usages().snapshot()) { - checkCheckCastUsage(graph, newInstance, checkCastNode, checkCastUsage); - } - GraphUtil.unlinkFixedNode(checkCastNode); - GraphUtil.killCFG(checkCastNode); - } - } - } - - private static void checkCheckCastUsage(StructuredGraph graph, Node intrinsifiedNode, Node input, Node usage) { - if (usage instanceof ValueAnchorNode) { - ValueAnchorNode valueAnchorNode = (ValueAnchorNode) usage; - valueAnchorNode.removeAnchoredNode(); - Debug.log("%s: Removed a ValueAnchor input", Debug.contextSnapshot(JavaMethod.class)); - } else if (usage instanceof UnboxNode) { - UnboxNode unbox = (UnboxNode) usage; - unbox.replaceAtUsages(intrinsifiedNode); - graph.removeFixed(unbox); - Debug.log("%s: Removed an UnboxNode", Debug.contextSnapshot(JavaMethod.class)); - } else if (usage instanceof UnsafeStoreNode) { - UnsafeStoreNode store = (UnsafeStoreNode) usage; - store.replaceFirstInput(input, intrinsifiedNode); - } else if (usage instanceof LoadFieldNode) { - LoadFieldNode load = (LoadFieldNode) usage; - load.replaceAtUsages(intrinsifiedNode); - graph.removeFixed(load); - } else if (usage instanceof MethodCallTargetNode) { - MethodCallTargetNode checkCastCallTarget = (MethodCallTargetNode) usage; - assert checkCastCallTarget.targetMethod().getAnnotation(NodeIntrinsic.class) != null : "checkcast at " + sourceLocation(input) + - " not used by an unboxing method or node intrinsic, but by a call at " + sourceLocation(checkCastCallTarget.usages().first()) + " to " + checkCastCallTarget.targetMethod(); - usage.replaceFirstInput(input, intrinsifiedNode); - Debug.log("%s: Checkcast used in an other node intrinsic", Debug.contextSnapshot(JavaMethod.class)); - } else if (usage instanceof FrameState) { - usage.replaceFirstInput(input, null); - Debug.log("%s: Checkcast used in a FS", Debug.contextSnapshot(JavaMethod.class)); - } else if (usage instanceof ReturnNode && ((ValueNode) intrinsifiedNode).stamp() == StampFactory.forNodeIntrinsic()) { - usage.replaceFirstInput(input, intrinsifiedNode); - Debug.log("%s: Checkcast used in a return with forNodeIntrinsic stamp", Debug.contextSnapshot(JavaMethod.class)); - } else if (usage instanceof IsNullNode) { - if (!usage.hasNoUsages()) { - assert usage.getUsageCount() == 1 && usage.usages().first().predecessor() == input : usage + " " + input; - graph.replaceFloating((FloatingNode) usage, LogicConstantNode.contradiction(graph)); - Debug.log("%s: Replaced IsNull with false", Debug.contextSnapshot(JavaMethod.class)); - } else { - // Removed as usage of a GuardingPiNode - } - } else if (usage instanceof ProxyNode) { - ProxyNode proxy = (ProxyNode) usage; - assert proxy instanceof ValueProxyNode; - ProxyNode newProxy = ProxyNode.forValue((ValueNode) intrinsifiedNode, proxy.proxyPoint(), graph); - for (Node proxyUsage : usage.usages().snapshot()) { - checkCheckCastUsage(graph, newProxy, proxy, proxyUsage); - } - } else if (usage instanceof PiNode) { - for (Node piUsage : usage.usages().snapshot()) { - checkCheckCastUsage(graph, intrinsifiedNode, usage, piUsage); - } - } else { - DebugScope.forceDump(graph, "exception"); - assert false : sourceLocation(usage) + " has unexpected usage " + usage + " of checkcast " + input + " at " + sourceLocation(input); - } - } -} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -22,55 +22,21 @@ */ package com.oracle.graal.replacements; -import static com.oracle.graal.replacements.NodeIntrinsificationPhase.COULD_NOT_FOLD; -import static jdk.vm.ci.meta.MetaUtil.resolveJavaTypes; - -import java.util.Arrays; -import java.util.List; - import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; import com.oracle.graal.api.replacements.Fold; -import com.oracle.graal.compiler.common.type.ObjectStamp; -import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.debug.MethodFilter; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.NodePlugin; -import com.oracle.graal.nodeinfo.InputType; -import com.oracle.graal.nodeinfo.StructuralInput; -import com.oracle.graal.nodeinfo.StructuralInput.MarkerType; -import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.ValueNode; -import com.oracle.graal.nodes.extended.ForeignCallNode; -import com.oracle.graal.nodes.extended.UnsafeCopyNode; -import com.oracle.graal.nodes.extended.UnsafeLoadNode; -import com.oracle.graal.nodes.extended.UnsafeStoreNode; -import com.oracle.graal.word.WordTypes; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.NodePlugin; /** * An {@link NodePlugin} that handles methods annotated by {@link Fold} and {@link NodeIntrinsic}. */ public class NodeIntrinsificationPlugin implements NodePlugin { - protected final NodeIntrinsificationPhase nodeIntrinsification; - private final WordTypes wordTypes; - private final ResolvedJavaType structuralInputType; - private final boolean mustIntrinsify; - - public NodeIntrinsificationPlugin(MetaAccessProvider metaAccess, NodeIntrinsificationPhase nodeIntrinsification, WordTypes wordTypes, boolean mustIntrinsify) { - this.nodeIntrinsification = nodeIntrinsification; - this.wordTypes = wordTypes; - this.mustIntrinsify = mustIntrinsify; - this.structuralInputType = metaAccess.lookupJavaType(StructuralInput.class); - } /** * Calls in replacements to methods matching one of these filters are elided. Only void methods @@ -89,46 +55,7 @@ @Override public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - NodeIntrinsic intrinsic = nodeIntrinsification.getIntrinsic(method); - if (intrinsic != null) { - Signature sig = method.getSignature(); - JavaKind returnKind = sig.getReturnKind(); - Stamp stamp = StampFactory.forKind(returnKind); - if (returnKind == JavaKind.Object) { - JavaType returnType = sig.getReturnType(method.getDeclaringClass()); - if (returnType instanceof ResolvedJavaType) { - ResolvedJavaType resolvedReturnType = (ResolvedJavaType) returnType; - if (wordTypes.isWord(resolvedReturnType)) { - stamp = wordTypes.getWordStamp(resolvedReturnType); - } else { - stamp = StampFactory.declared(resolvedReturnType); - } - } - } - - boolean result = processNodeIntrinsic(b, method, intrinsic, Arrays.asList(args), returnKind, stamp); - if (!result && mustIntrinsify) { - reportIntrinsificationFailure(b, method, args); - } - return result; - - } else if (nodeIntrinsification.isFoldable(method)) { - ResolvedJavaType[] parameterTypes = resolveJavaTypes(method.toParameterTypes(), method.getDeclaringClass()); - JavaConstant constant = nodeIntrinsification.tryFold(Arrays.asList(args), parameterTypes, method); - if (!COULD_NOT_FOLD.equals(constant)) { - if (constant != null) { - // Replace the invoke with the result of the call - b.push(method.getSignature().getReturnKind(), ConstantNode.forConstant(constant, b.getMetaAccess(), b.getGraph())); - } else { - // This must be a void invoke - assert method.getSignature().getReturnKind() == JavaKind.Void; - } - return true; - } else if (mustIntrinsify) { - reportIntrinsificationFailure(b, method, args); - } - - } else if (MethodsElidedInSnippets != null) { + if (MethodsElidedInSnippets != null) { if (MethodFilter.matches(MethodsElidedInSnippets, method)) { if (method.getSignature().getReturnKind() != JavaKind.Void) { throw new JVMCIError("Cannot elide non-void method " + method.format("%H.%n(%p)")); @@ -138,79 +65,4 @@ } return false; } - - private static boolean reportIntrinsificationFailure(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { - StringBuilder msg = new StringBuilder(); - msg.append("Call in ").append(b.getMethod().format("%H.%n(%p)")); - msg.append(" to ").append(method.format("%H.%n(%p)")); - msg.append(" cannot be intrinsified or folded, probably because an argument is not a constant. Arguments: "); - String sep = ""; - for (ValueNode node : args) { - msg.append(sep).append(node.toString()); - sep = ", "; - } - throw new JVMCIError(msg.toString()); - } - - private InputType getInputType(ResolvedJavaType type) { - if (type != null && structuralInputType.isAssignableFrom(type)) { - MarkerType markerType = type.getAnnotation(MarkerType.class); - if (markerType != null) { - return markerType.value(); - } else { - throw JVMCIError.shouldNotReachHere(String.format("%s extends StructuralInput, but is not annotated with @MarkerType", type)); - } - } else { - return InputType.Value; - } - } - - private boolean processNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List args, JavaKind returnKind, Stamp stamp) { - ValueNode res = createNodeIntrinsic(b, method, intrinsic, args, stamp); - if (res == null) { - return false; - } - if (res instanceof UnsafeCopyNode) { - UnsafeCopyNode copy = (UnsafeCopyNode) res; - UnsafeLoadNode value = b.add(new UnsafeLoadNode(copy.sourceObject(), copy.sourceOffset(), copy.accessKind(), copy.getLocationIdentity())); - b.add(new UnsafeStoreNode(copy.destinationObject(), copy.destinationOffset(), value, copy.accessKind(), copy.getLocationIdentity())); - return true; - } else if (res instanceof ForeignCallNode) { - /* - * Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the - * case that the foreign call can deoptimize. As with all deoptimization, we need a - * state in a non-intrinsic method. - */ - GraphBuilderContext nonIntrinsicAncestor = b.getNonIntrinsicAncestor(); - if (nonIntrinsicAncestor != null) { - ForeignCallNode foreign = (ForeignCallNode) res; - foreign.setBci(nonIntrinsicAncestor.bci()); - } - } - - boolean nonValueType = false; - if (returnKind == JavaKind.Object && stamp instanceof ObjectStamp) { - ResolvedJavaType type = ((ObjectStamp) stamp).type(); - if (type != null && structuralInputType.isAssignableFrom(type)) { - assert res.isAllowedUsageType(getInputType(type)); - nonValueType = true; - } - } - - if (returnKind != JavaKind.Void) { - assert nonValueType || res.getStackKind() != JavaKind.Void; - res = b.addPush(returnKind, res); - } else { - assert res.getStackKind() == JavaKind.Void; - res = b.add(res); - } - - return true; - } - - private ValueNode createNodeIntrinsic(GraphBuilderContext b, ResolvedJavaMethod method, NodeIntrinsic intrinsic, List args, Stamp stamp) { - ValueNode res = nodeIntrinsification.createIntrinsicNode(args, stamp, method, b.getGraph(), intrinsic); - assert res != null : String.format("Could not create node intrinsic for call to %s as one of the arguments expected to be constant isn't: arguments=%s", method.format("%H.%n(%p)"), args); - return res; - } } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2011, 2015, 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.replacements; + +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +import com.oracle.graal.api.replacements.SnippetReflectionProvider; +import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; +import com.oracle.graal.compiler.common.type.Stamp; +import com.oracle.graal.compiler.common.type.StampFactory; +import com.oracle.graal.nodes.graphbuilderconf.NodeIntrinsicPluginFactory.InjectionProvider; +import com.oracle.graal.word.WordTypes; + +public class NodeIntrinsificationProvider implements InjectionProvider { + + private final MetaAccessProvider metaAccess; + private final SnippetReflectionProvider snippetReflection; + private final ForeignCallsProvider foreignCalls; + private final WordTypes wordTypes; + + public NodeIntrinsificationProvider(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, WordTypes wordTypes) { + this.metaAccess = metaAccess; + this.snippetReflection = snippetReflection; + this.foreignCalls = foreignCalls; + this.wordTypes = wordTypes; + } + + @Override + public Stamp getReturnStamp(Class type) { + JavaKind kind = JavaKind.fromJavaClass(type); + if (kind == JavaKind.Object) { + ResolvedJavaType returnType = metaAccess.lookupJavaType(type); + if (wordTypes.isWord(returnType)) { + return wordTypes.getWordStamp(returnType); + } else { + return StampFactory.declared(returnType); + } + } else { + return StampFactory.forKind(kind); + } + } + + @Override + public T getInjectedArgument(Class type) { + T injected = snippetReflection.getInjectedNodeIntrinsicParameter(type); + if (injected != null) { + return injected; + } else if (type.equals(ForeignCallsProvider.class)) { + return type.cast(foreignCalls); + } else if (type.equals(SnippetReflectionProvider.class)) { + return type.cast(snippetReflection); + } else { + throw new JVMCIError("Cannot handle injected argument of type %s.", type.getName()); + } + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/PEGraphDecoder.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -53,15 +53,6 @@ import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeClass; import com.oracle.graal.graph.spi.Canonicalizable; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; -import com.oracle.graal.graphbuilderconf.LoopExplosionPlugin; -import com.oracle.graal.graphbuilderconf.ParameterPlugin; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodeinfo.NodeInfo; import com.oracle.graal.nodes.AbstractBeginNode; @@ -87,6 +78,15 @@ import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.extended.ForeignCallNode; import com.oracle.graal.nodes.extended.IntegerSwitchNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.LoopExplosionPlugin; +import com.oracle.graal.nodes.graphbuilderconf.ParameterPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.java.MonitorIdNode; import com.oracle.graal.nodes.spi.StampProvider; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Nov 30 16:41:10 2015 -0800 @@ -24,9 +24,9 @@ import static com.oracle.graal.compiler.common.GraalOptions.DeoptALot; import static com.oracle.graal.compiler.common.GraalOptions.OptCanonicalizer; -import static com.oracle.graal.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static com.oracle.graal.java.BytecodeParserOptions.InlineDuringParsing; import static com.oracle.graal.java.BytecodeParserOptions.InlineIntrinsicsDuringParsing; +import static com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.Required; import static java.lang.String.format; import static jdk.vm.ci.meta.MetaUtil.toInternalName; @@ -73,13 +73,6 @@ import com.oracle.graal.debug.DebugTimer; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.IntrinsicContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.MethodSubstitutionPlugin; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.java.GraphBuilderPhase.Instance; import com.oracle.graal.nodes.CallTargetNode; @@ -88,6 +81,14 @@ import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; +import com.oracle.graal.nodes.graphbuilderconf.GeneratedInvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.IntrinsicContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.MethodSubstitutionPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.spi.Replacements; import com.oracle.graal.nodes.spi.StampProvider; @@ -120,8 +121,12 @@ return graphBuilderPlugins; } + protected boolean hasGeneratedInvocationPluginAnnotation(ResolvedJavaMethod method) { + return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Fold.class) != null; + } + protected boolean hasGenericInvocationPluginAnnotation(ResolvedJavaMethod method) { - return method.getAnnotation(Node.NodeIntrinsic.class) != null || method.getAnnotation(Word.Operation.class) != null || method.getAnnotation(Fold.class) != null; + return method.getAnnotation(Word.Operation.class) != null; } private static final int MAX_GRAPH_INLINING_DEPTH = 100; // more than enough @@ -144,7 +149,8 @@ return null; } if (b.parsingIntrinsic()) { - assert !hasGenericInvocationPluginAnnotation(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), NodeIntrinsificationPlugin.class.getName()); + assert !hasGeneratedInvocationPluginAnnotation(method) : format("%s should have been handled by a %s", method.format("%H.%n(%p)"), GeneratedInvocationPlugin.class.getSimpleName()); + assert !hasGenericInvocationPluginAnnotation(method) : format("%s should have been handled by %s", method.format("%H.%n(%p)"), WordOperationPlugin.class.getSimpleName()); assert b.getDepth() < MAX_GRAPH_INLINING_DEPTH : "inlining limit exceeded"; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounterNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounterNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetCounterNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -127,7 +127,7 @@ static class SnippetCounterSnippets implements Snippets { @Fold - private static int countOffset() { + static int countOffset() { try { return (int) UNSAFE.objectFieldOffset(SnippetCounter.class.getDeclaredField("value")); } catch (Exception e) { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -41,12 +41,6 @@ import com.oracle.graal.graph.Edges; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.NodeList; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; -import com.oracle.graal.graphbuilderconf.MethodSubstitutionPlugin; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.DeoptimizeNode; import com.oracle.graal.nodes.FixedGuardNode; @@ -78,6 +72,12 @@ import com.oracle.graal.nodes.extended.UnboxNode; import com.oracle.graal.nodes.extended.UnsafeLoadNode; import com.oracle.graal.nodes.extended.UnsafeStoreNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.MethodSubstitutionPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.java.ClassIsAssignableFromNode; import com.oracle.graal.nodes.java.CompareAndSwapNode; import com.oracle.graal.nodes.java.DynamicNewArrayNode; @@ -488,10 +488,9 @@ for (Class c : new Class[]{Node.class, NodeList.class}) { r.register2("get" + c.getSimpleName() + "Unsafe", Node.class, long.class, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode node, ValueNode offset) { - ValueNode value = b.add(new UnsafeLoadNode(node, offset, JavaKind.Object, LocationIdentity.any())); - boolean exactType = false; - boolean nonNull = false; - b.addPush(JavaKind.Object, new PiNode(value, metaAccess.lookupJavaType(c), exactType, nonNull)); + UnsafeLoadNode value = b.add(new UnsafeLoadNode(node, offset, JavaKind.Object, LocationIdentity.any())); + value.setStamp(StampFactory.declared(metaAccess.lookupJavaType(c))); + b.addPush(JavaKind.Object, value); return true; } }); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StringSubstitutions.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, 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 @@ -23,7 +23,7 @@ package com.oracle.graal.replacements; import com.oracle.graal.compiler.common.SuppressFBWarnings; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; import com.oracle.graal.nodes.java.LoadFieldNode; import com.oracle.graal.replacements.nodes.ArrayEqualsNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/WordOperationPlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -39,10 +39,6 @@ import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.common.calc.Condition; import com.oracle.graal.compiler.common.type.Stamp; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.NodePlugin; -import com.oracle.graal.graphbuilderconf.ParameterPlugin; import com.oracle.graal.nodes.ConstantNode; import com.oracle.graal.nodes.Invoke; import com.oracle.graal.nodes.ParameterNode; @@ -59,6 +55,10 @@ import com.oracle.graal.nodes.calc.ZeroExtendNode; import com.oracle.graal.nodes.extended.JavaReadNode; import com.oracle.graal.nodes.extended.JavaWriteNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.NodePlugin; +import com.oracle.graal.nodes.graphbuilderconf.ParameterPlugin; import com.oracle.graal.nodes.java.LoadFieldNode; import com.oracle.graal.nodes.java.LoadIndexedNode; import com.oracle.graal.nodes.java.StoreIndexedNode; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/DeferredPiNode.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,12 +36,11 @@ import com.oracle.graal.nodes.PiNode; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; -import com.oracle.graal.replacements.NodeIntrinsificationPhase; /** * A node for use in method substitutions or snippets that changes the type of its input where the - * type is not immediately available at {@link NodeIntrinsificationPhase intrinsification} time. It - * is replaced by a {@link PiNode} once the type becomes constant (which must happen). + * type is not immediately available at intrinsification time. It is replaced by a {@link PiNode} + * once the type becomes constant (which must happen). */ @NodeInfo public final class DeferredPiNode extends FloatingNode implements Canonicalizable { diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java --- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime.java Mon Nov 30 16:41:10 2015 -0800 @@ -64,9 +64,6 @@ import com.oracle.graal.debug.DebugEnvironment; import com.oracle.graal.debug.GraalDebugConfig; import com.oracle.graal.debug.TTY; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; import com.oracle.graal.hotspot.HotSpotBackend; import com.oracle.graal.hotspot.meta.HotSpotProviders; import com.oracle.graal.java.GraphBuilderPhase; @@ -74,6 +71,9 @@ import com.oracle.graal.lir.phases.LIRSuites; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.BasePhase; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; @@ -160,11 +160,20 @@ @Override public TruffleCompiler getTruffleCompiler() { if (truffleCompiler == null) { - truffleCompiler = DefaultTruffleCompiler.create(this); + initializeTruffleCompiler(); } return truffleCompiler; } + private void initializeTruffleCompiler() { + synchronized (this) { + // might occur for multiple compiler threads at the same time. + if (truffleCompiler == null) { + truffleCompiler = DefaultTruffleCompiler.create(this); + } + } + } + @Override public RootCallTarget createCallTarget(RootNode rootNode) { return createCallTargetImpl(null, rootNode); @@ -280,14 +289,6 @@ } @Override - public void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous) { - /* Ensure compiler is created. */ - getTruffleCompiler(); - - super.compile(optimizedCallTarget, mayBeAsynchronous); - } - - @Override public boolean cancelInstalledTask(OptimizedCallTarget optimizedCallTarget, Object source, CharSequence reason) { if (lazy == null) { // if truffle wasn't initialized yet, this is a noop diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ConditionAnchoringTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,6 @@ import com.oracle.graal.compiler.test.GraalCompilerTest; import com.oracle.graal.graph.iterators.NodeIterable; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.BeginNode; import com.oracle.graal.nodes.ConditionAnchorNode; import com.oracle.graal.nodes.IfNode; @@ -47,6 +43,10 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.extended.UnsafeLoadNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.memory.FloatingReadNode; import com.oracle.graal.nodes.memory.ReadNode; import com.oracle.graal.nodes.spi.LoweringTool.StandardLoweringStage; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ import org.junit.Test; import com.oracle.graal.compiler.test.GraalCompilerTest; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; import com.oracle.graal.truffle.substitutions.TruffleGraphBuilderPlugins; import com.oracle.truffle.api.ExactMath; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleCompiler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleCompiler.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/DefaultTruffleCompiler.java Mon Nov 30 16:41:10 2015 -0800 @@ -26,9 +26,9 @@ import com.oracle.graal.api.replacements.SnippetReflectionProvider; import com.oracle.graal.compiler.target.Backend; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.lir.phases.LIRSuites; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.BasePhase; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.tiers.HighTierContext; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/FrameWithoutBoxing.java Mon Nov 30 16:41:10 2015 -0800 @@ -92,8 +92,8 @@ @Override public Object getObject(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, OBJECT_TAG); - return getObjectUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, OBJECT_TAG); + return getObjectUnsafe(slotIndex, slot, condition); } private Object[] getLocals() { @@ -108,8 +108,7 @@ return unsafeCast(tags, byte[].class, true, true); } - private Object getObjectUnsafe(int slotIndex, FrameSlot slot) { - boolean condition = this.getTags()[slotIndex] == OBJECT_TAG; + private Object getObjectUnsafe(int slotIndex, FrameSlot slot, boolean condition) { return unsafeGetObject(getLocals(), Unsafe.ARRAY_OBJECT_BASE_OFFSET + slotIndex * (long) Unsafe.ARRAY_OBJECT_INDEX_SCALE, condition, slot); } @@ -127,13 +126,12 @@ @Override public byte getByte(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, BYTE_TAG); - return getByteUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, BYTE_TAG); + return getByteUnsafe(slotIndex, slot, condition); } - private byte getByteUnsafe(int slotIndex, FrameSlot slot) { + private byte getByteUnsafe(int slotIndex, FrameSlot slot, boolean condition) { long offset = getPrimitiveOffset(slotIndex); - boolean condition = this.getTags()[slotIndex] == BYTE_TAG; return (byte) unsafeGetInt(getPrimitiveLocals(), offset, condition, slot); } @@ -152,13 +150,12 @@ @Override public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, BOOLEAN_TAG); - return getBooleanUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, BOOLEAN_TAG); + return getBooleanUnsafe(slotIndex, slot, condition); } - private boolean getBooleanUnsafe(int slotIndex, FrameSlot slot) { + private boolean getBooleanUnsafe(int slotIndex, FrameSlot slot, boolean condition) { long offset = getPrimitiveOffset(slotIndex); - boolean condition = this.getTags()[slotIndex] == BOOLEAN_TAG; return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot) != 0; } @@ -177,13 +174,12 @@ @Override public float getFloat(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, FLOAT_TAG); - return getFloatUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, FLOAT_TAG); + return getFloatUnsafe(slotIndex, slot, condition); } - private float getFloatUnsafe(int slotIndex, FrameSlot slot) { + private float getFloatUnsafe(int slotIndex, FrameSlot slot, boolean condition) { long offset = getPrimitiveOffset(slotIndex); - boolean condition = this.getTags()[slotIndex] == FLOAT_TAG; return unsafeGetFloat(getPrimitiveLocals(), offset, condition, slot); } @@ -202,13 +198,12 @@ @Override public long getLong(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, LONG_TAG); - return getLongUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, LONG_TAG); + return getLongUnsafe(slotIndex, slot, condition); } - private long getLongUnsafe(int slotIndex, FrameSlot slot) { + private long getLongUnsafe(int slotIndex, FrameSlot slot, boolean condition) { long offset = getPrimitiveOffset(slotIndex); - boolean condition = this.getTags()[slotIndex] == LONG_TAG; return unsafeGetLong(getPrimitiveLocals(), offset, condition, slot); } @@ -227,13 +222,12 @@ @Override public int getInt(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, INT_TAG); - return getIntUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, INT_TAG); + return getIntUnsafe(slotIndex, slot, condition); } - private int getIntUnsafe(int slotIndex, FrameSlot slot) { + private int getIntUnsafe(int slotIndex, FrameSlot slot, boolean condition) { long offset = getPrimitiveOffset(slotIndex); - boolean condition = this.getTags()[slot.getIndex()] == INT_TAG; return unsafeGetInt(getPrimitiveLocals(), offset, condition, slot); } @@ -252,13 +246,12 @@ @Override public double getDouble(FrameSlot slot) throws FrameSlotTypeException { int slotIndex = slot.getIndex(); - verifyGet(slotIndex, DOUBLE_TAG); - return getDoubleUnsafe(slotIndex, slot); + boolean condition = verifyGet(slotIndex, DOUBLE_TAG); + return getDoubleUnsafe(slotIndex, slot, condition); } - private double getDoubleUnsafe(int slotIndex, FrameSlot slot) { + private double getDoubleUnsafe(int slotIndex, FrameSlot slot, boolean condition) { long offset = getPrimitiveOffset(slotIndex); - boolean condition = this.getTags()[slotIndex] == DOUBLE_TAG; return unsafeGetDouble(getPrimitiveLocals(), offset, condition, slot); } @@ -284,12 +277,14 @@ getTags()[slotIndex] = tag; } - private void verifyGet(int slotIndex, byte tag) throws FrameSlotTypeException { + private boolean verifyGet(int slotIndex, byte tag) throws FrameSlotTypeException { checkSlotIndex(slotIndex); - if (getTags()[slotIndex] != tag) { - CompilerDirectives.transferToInterpreter(); + boolean condition = getTags()[slotIndex] == tag; + if (!condition) { + CompilerDirectives.transferToInterpreterAndInvalidate(); throw new FrameSlotTypeException(); } + return condition; } private void checkSlotIndex(int slotIndex) { @@ -308,26 +303,38 @@ public Object getValue(FrameSlot slot) { int slotIndex = slot.getIndex(); if (CompilerDirectives.inInterpreter() && slotIndex >= getTags().length) { - CompilerDirectives.transferToInterpreter(); + CompilerDirectives.transferToInterpreterAndInvalidate(); resize(); } byte tag = getTags()[slotIndex]; - if (tag == BOOLEAN_TAG) { - return getBooleanUnsafe(slotIndex, slot); - } else if (tag == BYTE_TAG) { - return getByteUnsafe(slotIndex, slot); - } else if (tag == INT_TAG) { - return getIntUnsafe(slotIndex, slot); - } else if (tag == DOUBLE_TAG) { - return getDoubleUnsafe(slotIndex, slot); - } else if (tag == LONG_TAG) { - return getLongUnsafe(slotIndex, slot); - } else if (tag == FLOAT_TAG) { - return getFloatUnsafe(slotIndex, slot); - } else { - assert tag == OBJECT_TAG; - return getObjectUnsafe(slotIndex, slot); + boolean condition = (tag == BOOLEAN_TAG); + if (condition) { + return getBooleanUnsafe(slotIndex, slot, condition); + } + condition = (tag == BYTE_TAG); + if (condition) { + return getByteUnsafe(slotIndex, slot, condition); + } + condition = (tag == INT_TAG); + if (condition) { + return getIntUnsafe(slotIndex, slot, condition); } + condition = (tag == DOUBLE_TAG); + if (condition) { + return getDoubleUnsafe(slotIndex, slot, condition); + } + condition = (tag == LONG_TAG); + if (condition) { + return getLongUnsafe(slotIndex, slot, condition); + } + condition = (tag == FLOAT_TAG); + if (condition) { + return getFloatUnsafe(slotIndex, slot, condition); + } + condition = tag == OBJECT_TAG; + assert condition; + return getObjectUnsafe(slotIndex, slot, condition); + } private boolean resize() { @@ -345,10 +352,13 @@ private byte getTag(FrameSlot slot) { int slotIndex = slot.getIndex(); - if (slotIndex >= getTags().length) { - CompilerDirectives.transferToInterpreter(); - resize(); + byte[] cachedTags = getTags(); + if (slotIndex < cachedTags.length) { + return cachedTags[slotIndex]; } + + CompilerDirectives.transferToInterpreterAndInvalidate(); + resize(); return getTags()[slotIndex]; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/GraalTruffleRuntime.java Mon Nov 30 16:41:10 2015 -0800 @@ -340,11 +340,26 @@ getCompilationNotify().notifyShutdown(this); } + protected void doCompile(OptimizedCallTarget optimizedCallTarget) { + int repeats = TruffleCompilerOptions.TruffleCompilationRepeats.getValue(); + if (repeats <= 1) { + /* Normal compilation. */ + doCompile0(optimizedCallTarget); + + } else { + /* Repeated compilation for compilation time benchmarking. */ + for (int i = 0; i < repeats; i++) { + doCompile0(optimizedCallTarget); + } + System.exit(0); + } + } + @SuppressWarnings("try") - protected void doCompile(OptimizedCallTarget optimizedCallTarget) { + private void doCompile0(OptimizedCallTarget optimizedCallTarget) { boolean success = true; try (Scope s = Debug.scope("Truffle", new TruffleDebugJavaMethod(optimizedCallTarget))) { - truffleCompiler.compileMethod(optimizedCallTarget); + getTruffleCompiler().compileMethod(optimizedCallTarget); } catch (Throwable e) { optimizedCallTarget.notifyCompilationFailed(e); success = false; @@ -356,14 +371,13 @@ protected abstract BackgroundCompileQueue getCompileQueue(); public void compile(OptimizedCallTarget optimizedCallTarget, boolean mayBeAsynchronous) { - Runnable r = new Runnable() { + BackgroundCompileQueue l = getCompileQueue(); + Future future = l.compileQueue.submit(new Runnable() { @Override public void run() { doCompile(optimizedCallTarget); } - }; - BackgroundCompileQueue l = getCompileQueue(); - Future future = l.compileQueue.submit(r); + }); l.compilations.put(optimizedCallTarget, future); getCompilationNotify().notifyCompilationQueued(optimizedCallTarget); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Nov 30 16:41:10 2015 -0800 @@ -50,13 +50,6 @@ import com.oracle.graal.debug.Debug; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.debug.Indent; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.LoopExplosionPlugin; -import com.oracle.graal.graphbuilderconf.ParameterPlugin; import com.oracle.graal.java.ComputeLoopFrequenciesClosure; import com.oracle.graal.java.GraphBuilderPhase; import com.oracle.graal.nodes.ConstantNode; @@ -64,6 +57,13 @@ import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; import com.oracle.graal.nodes.ValueNode; import com.oracle.graal.nodes.calc.FloatingNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.LoopExplosionPlugin; +import com.oracle.graal.nodes.graphbuilderconf.ParameterPlugin; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.nodes.java.CheckCastNode; import com.oracle.graal.nodes.java.InstanceOfNode; import com.oracle.graal.nodes.java.MethodCallTargetNode; @@ -159,7 +159,7 @@ @SuppressWarnings("try") public StructuredGraph createGraph(final OptimizedCallTarget callTarget, AllowAssumptions allowAssumptions) { try (Scope c = Debug.scope("TruffleTree")) { - Debug.dump(callTarget, callTarget.toString()); + Debug.dump(callTarget, "%s", callTarget); } catch (Throwable e) { throw Debug.handle(e); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilationResultBuilderFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilationResultBuilderFactory.java Mon Nov 30 16:41:10 2015 -0800 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015, 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.truffle; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import jdk.vm.ci.code.CodeCacheProvider; +import jdk.vm.ci.code.CompilationResult; +import jdk.vm.ci.meta.Assumptions.Assumption; + +import com.oracle.graal.asm.Assembler; +import com.oracle.graal.compiler.common.spi.ForeignCallsProvider; +import com.oracle.graal.lir.asm.CompilationResultBuilder; +import com.oracle.graal.lir.asm.CompilationResultBuilderFactory; +import com.oracle.graal.lir.asm.FrameContext; +import com.oracle.graal.lir.framemap.FrameMap; +import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.truffle.nodes.AssumptionValidAssumption; + +/** + * A mechanism for Truffle to update a {@link CompilationResult} before it is + * {@linkplain CompilationResult#close() closed} by the Graal compiler. + */ +class TruffleCompilationResultBuilderFactory implements CompilationResultBuilderFactory { + + /** + * The graph being compiled. + */ + private final StructuredGraph graph; + + /** + * List into which {@link AssumptionValidAssumption}s are added. + */ + private final List validAssumptions; + + public TruffleCompilationResultBuilderFactory(StructuredGraph graph, List validAssumptions) { + this.graph = graph; + this.validAssumptions = validAssumptions; + } + + public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, FrameContext frameContext, + CompilationResult compilationResult) { + return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, frameContext, compilationResult) { + @Override + protected void closeCompilationResult() { + CompilationResult result = this.compilationResult; + result.setMethods(graph.method(), graph.getInlinedMethods()); + result.setBytecodeSize(graph.getBytecodeSize()); + + Set newAssumptions = new HashSet<>(); + for (Assumption assumption : graph.getAssumptions()) { + TruffleCompilationResultBuilderFactory.processAssumption(newAssumptions, assumption, validAssumptions); + } + + if (result.getAssumptions() != null) { + for (Assumption assumption : result.getAssumptions()) { + TruffleCompilationResultBuilderFactory.processAssumption(newAssumptions, assumption, validAssumptions); + } + } + + result.setAssumptions(newAssumptions.toArray(new Assumption[newAssumptions.size()])); + super.closeCompilationResult(); + } + }; + } + + static void processAssumption(Set newAssumptions, Assumption assumption, List manual) { + if (assumption != null) { + if (assumption instanceof AssumptionValidAssumption) { + AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption; + manual.add(assumptionValidAssumption); + } else { + newAssumptions.add(assumption); + } + } + } +} diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java Mon Nov 30 16:41:10 2015 -0800 @@ -27,16 +27,13 @@ import static jdk.vm.ci.code.CodeUtil.getCallingConvention; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CallingConvention.Type; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.CompilationResult; import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; @@ -50,12 +47,11 @@ import com.oracle.graal.debug.DebugEnvironment; import com.oracle.graal.debug.DebugMemUseTracker; import com.oracle.graal.debug.DebugTimer; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration; -import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import com.oracle.graal.lir.asm.CompilationResultBuilderFactory; import com.oracle.graal.lir.phases.LIRSuites; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import com.oracle.graal.phases.OptimisticOptimizations; import com.oracle.graal.phases.PhaseSuite; import com.oracle.graal.phases.tiers.HighTierContext; @@ -178,6 +174,8 @@ } CompilationResult result = null; + List validAssumptions = new ArrayList<>(); + TruffleCompilationResultBuilderFactory factory = new TruffleCompilationResultBuilderFactory(graph, validAssumptions); try (DebugCloseable a = CompilationTime.start(); Scope s = Debug.scope("TruffleGraal.GraalCompiler", graph, providers.getCodeCache()); DebugCloseable c = CompilationMemUse.start()) { SpeculationLog speculationLog = graph.getSpeculationLog(); if (speculationLog != null) { @@ -187,31 +185,13 @@ CodeCacheProvider codeCache = providers.getCodeCache(); CallingConvention cc = getCallingConvention(codeCache, Type.JavaCallee, graph.method(), false); CompilationResult compilationResult = new CompilationResult(name); - result = compileGraph(graph, cc, graph.method(), providers, backend, graphBuilderSuite, Optimizations, getProfilingInfo(graph), suites, lirSuites, compilationResult, - CompilationResultBuilderFactory.Default); + result = compileGraph(graph, cc, graph.method(), providers, backend, graphBuilderSuite, Optimizations, getProfilingInfo(graph), suites, lirSuites, compilationResult, factory); } catch (Throwable e) { throw Debug.handle(e); } compilationNotify.notifyCompilationGraalTierFinished((OptimizedCallTarget) predefinedInstalledCode, graph); - result.setMethods(graph.method(), graph.getInlinedMethods()); - result.setBytecodeSize(graph.getBytecodeSize()); - - List validAssumptions = new ArrayList<>(); - Set newAssumptions = new HashSet<>(); - for (Assumption assumption : graph.getAssumptions()) { - processAssumption(newAssumptions, assumption, validAssumptions); - } - - if (result.getAssumptions() != null) { - for (Assumption assumption : result.getAssumptions()) { - processAssumption(newAssumptions, assumption, validAssumptions); - } - } - - result.setAssumptions(newAssumptions.toArray(new Assumption[newAssumptions.size()])); - InstalledCode installedCode; try (Scope s = Debug.scope("CodeInstall", providers.getCodeCache()); DebugCloseable a = CodeInstallationTime.start(); DebugCloseable c = CodeInstallationMemUse.start()) { installedCode = providers.getCodeCache().addCode(graph.method(), result, graph.getSpeculationLog(), predefinedInstalledCode); @@ -228,17 +208,6 @@ protected abstract PhaseSuite createGraphBuilderSuite(); - public void processAssumption(Set newAssumptions, Assumption assumption, List manual) { - if (assumption != null) { - if (assumption instanceof AssumptionValidAssumption) { - AssumptionValidAssumption assumptionValidAssumption = (AssumptionValidAssumption) assumption; - manual.add(assumptionValidAssumption); - } else { - newAssumptions.add(assumption); - } - } - } - public PartialEvaluator getPartialEvaluator() { return partialEvaluator; } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Nov 30 16:41:10 2015 -0800 @@ -126,6 +126,9 @@ @Option(help = "Print information for compilation results", type = OptionType.Debug) public static final OptionValue TraceTruffleCompilation = new OptionValue<>(false); + @Option(help = "Compile time benchmarking: repeat Truffle compilation n times and then exit the VM", type = OptionType.Debug) + public static final OptionValue TruffleCompilationRepeats = new OptionValue<>(0); + @Option(help = "Print information for compilation queuing", type = OptionType.Debug) public static final OptionValue TraceTruffleCompilationDetails = new OptionValue<>(false); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/debug/HistogramInlineInvokePlugin.java Mon Nov 30 16:41:10 2015 -0800 @@ -31,11 +31,11 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import com.oracle.graal.graph.Node; -import com.oracle.graal.graphbuilderconf.InlineInvokePlugin; import com.oracle.graal.nodes.BeginNode; import com.oracle.graal.nodes.DeoptimizeNode; import com.oracle.graal.nodes.StructuredGraph; import com.oracle.graal.nodes.VirtualState; +import com.oracle.graal.nodes.graphbuilderconf.InlineInvokePlugin; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.virtual.VirtualObjectNode; import com.oracle.graal.truffle.OptimizedCallTarget; diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Mon Nov 30 16:41:10 2015 -0800 @@ -43,11 +43,6 @@ import com.oracle.graal.compiler.common.type.StampFactory; import com.oracle.graal.debug.Debug; import com.oracle.graal.graph.Node; -import com.oracle.graal.graphbuilderconf.GraphBuilderContext; -import com.oracle.graal.graphbuilderconf.InvocationPlugin; -import com.oracle.graal.graphbuilderconf.InvocationPlugin.Receiver; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; -import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.CallTargetNode; import com.oracle.graal.nodes.CallTargetNode.InvokeKind; import com.oracle.graal.nodes.ConditionAnchorNode; @@ -65,6 +60,11 @@ import com.oracle.graal.nodes.extended.BranchProbabilityNode; import com.oracle.graal.nodes.extended.UnsafeLoadNode; import com.oracle.graal.nodes.extended.UnsafeStoreNode; +import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderContext; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins.Registration; import com.oracle.graal.nodes.java.MethodCallTargetNode; import com.oracle.graal.nodes.virtual.EnsureVirtualizedNode; import com.oracle.graal.replacements.nodes.arithmetic.IntegerAddExactNode; @@ -228,7 +228,7 @@ * and constant folding could still eliminate the call to bailout(). However, we * also want to stop parsing, since we are sure that we will never need the * graph beyond the bailout point. - * + * * Therefore, we manually emit the call to bailout, which will be intrinsified * later when intrinsifications can no longer be delayed. The call is followed * by a NeverPartOfCompilationNode, which is a control sink and therefore stops @@ -398,17 +398,24 @@ } else { piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); } - LogicNode compareNode = CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), constantReflection); - boolean skipAnchor = false; - if (compareNode instanceof LogicConstantNode) { - LogicConstantNode logicConstantNode = (LogicConstantNode) compareNode; - if (logicConstantNode.getValue()) { - skipAnchor = true; + + ConditionAnchorNode valueAnchorNode = null; + if (condition.isConstant() && condition.asJavaConstant().asInt() == 1) { + // Nothing to do. + } else { + boolean skipAnchor = false; + LogicNode compareNode = CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()), constantReflection); + + if (compareNode instanceof LogicConstantNode) { + LogicConstantNode logicConstantNode = (LogicConstantNode) compareNode; + if (logicConstantNode.getValue()) { + skipAnchor = true; + } } - } - ConditionAnchorNode valueAnchorNode = null; - if (!skipAnchor) { - valueAnchorNode = b.add(new ConditionAnchorNode(compareNode)); + + if (!skipAnchor) { + valueAnchorNode = b.add(new ConditionAnchorNode(compareNode)); + } } b.addPush(JavaKind.Object, new PiNode(object, piStamp, valueAnchorNode)); } diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleInvocationPluginProvider.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleInvocationPluginProvider.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleInvocationPluginProvider.java Mon Nov 30 16:41:10 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import com.oracle.graal.api.replacements.SnippetReflectionProvider; -import com.oracle.graal.graphbuilderconf.InvocationPlugins; +import com.oracle.graal.nodes.graphbuilderconf.InvocationPlugins; public interface TruffleInvocationPluginProvider { void registerInvocationPlugins(MetaAccessProvider metaAccess, InvocationPlugins plugins, boolean canDelayIntrinsification, SnippetReflectionProvider snippetReflection); diff -r 99b21d7f7ed6 -r 02b6e8f05130 graal/com.oracle.graal.virtual.bench/src/com/oracle/graal/virtual/bench/PartialEscapeBench.java --- a/graal/com.oracle.graal.virtual.bench/src/com/oracle/graal/virtual/bench/PartialEscapeBench.java Mon Nov 30 16:24:57 2015 -0800 +++ b/graal/com.oracle.graal.virtual.bench/src/com/oracle/graal/virtual/bench/PartialEscapeBench.java Mon Nov 30 16:41:10 2015 -0800 @@ -27,7 +27,9 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; -public class PartialEscapeBench { +import com.oracle.graal.microbenchmarks.graal.GraalBenchmark; + +public class PartialEscapeBench extends GraalBenchmark { private static class Thing { final int id; diff -r 99b21d7f7ed6 -r 02b6e8f05130 mx.graal/mx_graal_8.py --- a/mx.graal/mx_graal_8.py Mon Nov 30 16:24:57 2015 -0800 +++ b/mx.graal/mx_graal_8.py Mon Nov 30 16:41:10 2015 -0800 @@ -113,12 +113,10 @@ vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs # look for -f in JMH arguments - containsF = False forking = True for i in range(len(jmhArgs)): arg = jmhArgs[i] if arg.startswith('-f'): - containsF = True if arg == '-f' and (i+1) < len(jmhArgs): arg += jmhArgs[i+1] try: @@ -133,10 +131,6 @@ if not forking: args += vmArgs else: - # default to -f1 if not specified otherwise - if not containsF: - jmhArgs += ['-f1'] - # find all projects with a direct JMH dependency jmhProjects = [] for p in mx.projects_opt_limit_to_suites(): @@ -237,6 +231,15 @@ out = None run_vm(self.args + _noneAsEmptyList(extraVMarguments) + ['-XX:-TieredCompilation', '-XX:+BootstrapJVMCI', '-version'], out=out) +class MicrobenchRun: + def __init__(self, name, args): + self.name = name + self.args = args + + def run(self, tasks, extraVMarguments=None): + with Task(self.name + ': hosted-product ', tasks) as t: + if t: microbench(_noneAsEmptyList(extraVMarguments) + ['--'] + self.args) + def compiler_gate_runner(suites, unit_test_runs, bootstrap_tests, tasks, extraVMarguments=None): # Build server-hosted-jvmci now so we can run the unit tests @@ -248,6 +251,11 @@ for r in unit_test_runs: r.run(suites, tasks, extraVMarguments) + # Run microbench on server-hosted-jvmci (only for testing the JMH setup) + with VM('server', 'product'): + for r in [MicrobenchRun('Microbench', ['TestJMH'])]: + r.run(tasks, extraVMarguments) + # Run ctw against rt.jar on server-hosted-jvmci with VM('server', 'product'): with Task('CTW:hosted-product', tasks) as t: @@ -289,8 +297,8 @@ graal_bootstrap_tests = [ BootstrapTest('BootstrapWithSystemAssertions', 'fastdebug', ['-esa']), BootstrapTest('BootstrapWithSystemAssertionsNoCoop', 'fastdebug', ['-esa', '-XX:-UseCompressedOops', '-G:+ExitVMOnException']), - BootstrapTest('BootstrapWithGCVecification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), - BootstrapTest('BootstrapWithG1GCVecification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), + BootstrapTest('BootstrapWithGCVerification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), + BootstrapTest('BootstrapWithG1GCVerification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), BootstrapTest('BootstrapEconomyWithSystemAssertions', 'fastdebug', ['-esa', '-Djvmci.compiler=graal-economy', '-G:+ExitVMOnException']), BootstrapTest('BootstrapWithExceptionEdges', 'fastdebug', ['-esa', '-G:+StressInvokeWithExceptionNode', '-G:+ExitVMOnException']), BootstrapTest('BootstrapWithRegisterPressure', 'product', ['-esa', '-G:RegisterPressure=' + _registers, '-G:+ExitVMOnException']), diff -r 99b21d7f7ed6 -r 02b6e8f05130 mx.graal/mx_graal_9.py --- a/mx.graal/mx_graal_9.py Mon Nov 30 16:24:57 2015 -0800 +++ b/mx.graal/mx_graal_9.py Mon Nov 30 16:41:10 2015 -0800 @@ -127,12 +127,10 @@ vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True) # look for -f in JMH arguments - containsF = False forking = True for i in range(len(jmhArgs)): arg = jmhArgs[i] if arg.startswith('-f'): - containsF = True if arg == '-f' and (i+1) < len(jmhArgs): arg += jmhArgs[i+1] try: @@ -147,10 +145,6 @@ if not forking: args += vmArgs else: - # default to -f1 if not specified otherwise - if not containsF: - jmhArgs += ['-f1'] - # find all projects with a direct JMH dependency jmhProjects = [] for p in mx.projects_opt_limit_to_suites(): @@ -235,6 +229,15 @@ out = None run_vm(self.args + _noneAsEmptyList(extraVMarguments) + ['-XX:-TieredCompilation', '-XX:+BootstrapJVMCI', '-version'], out=out) +class MicrobenchRun: + def __init__(self, name, args): + self.name = name + self.args = args + + def run(self, tasks, extraVMarguments=None): + with Task(self.name + ': hosted-product ', tasks) as t: + if t: microbench(_noneAsEmptyList(extraVMarguments) + ['--'] + self.args) + def compiler_gate_runner(suites, unit_test_runs, bootstrap_tests, tasks, extraVMarguments=None): # Run unit tests in hosted mode @@ -242,6 +245,11 @@ for r in unit_test_runs: r.run(suites, tasks, extraVMarguments) + # Run microbench in hosted mode (only for testing the JMH setup) + with JVMCIMode('hosted'): + for r in [MicrobenchRun('Microbench', ['TestJMH'])]: + r.run(tasks, extraVMarguments) + # Run ctw against rt.jar on server-hosted-jvmci with JVMCIMode('hosted'): with Task('CTW:hosted', tasks) as t: @@ -278,8 +286,8 @@ graal_bootstrap_tests = [ BootstrapTest('BootstrapWithSystemAssertions', 'fastdebug', ['-esa']), BootstrapTest('BootstrapWithSystemAssertionsNoCoop', 'fastdebug', ['-esa', '-XX:-UseCompressedOops', '-G:+ExitVMOnException']), - BootstrapTest('BootstrapWithGCVecification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), - BootstrapTest('BootstrapWithG1GCVecification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), + BootstrapTest('BootstrapWithGCVerification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), + BootstrapTest('BootstrapWithG1GCVerification', 'product', ['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-G:+ExitVMOnException'], suppress=['VerifyAfterGC:', 'VerifyBeforeGC:']), BootstrapTest('BootstrapEconomyWithSystemAssertions', 'fastdebug', ['-esa', '-Djvmci.compiler=graal-economy', '-G:+ExitVMOnException']), BootstrapTest('BootstrapWithExceptionEdges', 'fastdebug', ['-esa', '-G:+StressInvokeWithExceptionNode', '-G:+ExitVMOnException']), BootstrapTest('BootstrapWithRegisterPressure', 'product', ['-esa', '-G:RegisterPressure=' + _registers, '-G:+ExitVMOnException']), diff -r 99b21d7f7ed6 -r 02b6e8f05130 mx.graal/suite.py --- a/mx.graal/suite.py Mon Nov 30 16:24:57 2015 -0800 +++ b/mx.graal/suite.py Mon Nov 30 16:41:10 2015 -0800 @@ -39,7 +39,7 @@ { "name" : "jvmci", "optional" : "true", - "version" : "2dea101cdfe9aacf55083cf5bd6f84cb23106f4e", + "version" : "e9424bc1e288a646e1c38a398014fb91b2f3bc18", "urls" : [ {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/graal-jvmci-8", "kind" : "hg"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, @@ -47,7 +47,7 @@ }, { "name" : "truffle", - "version" : "fd53ccebb10b21af953de2da4340a7d17b85e5ed", + "version" : "bc1e026ef5b1ab8a1f68a3e78437e48f2d91fd91", "urls" : [ {"url" : "http://lafo.ssw.uni-linz.ac.at/hg/truffle", "kind" : "hg"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, @@ -85,18 +85,18 @@ }, "JMH" : { - "sha1" : "be2e08e6776191e9c559a65b7d34e92e86b4fa5c", - "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/jmh/jmh-runner-1.10.4.jar"], + "sha1" : "0fe92ac8718909c632345d4ecb4e596d1fa40071", + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/jmh/jmh-runner-1.11.2.jar"], }, # Library that allows Graal to compile against JVMCI without the jvmci suite. # This library is not added to the boot class path at run time and so code # compiled against this library must be run on (JVMCI enabled) JDK9. "JVMCI" : { - "sha1" : "9482b9ba7760c09cd95d78f08ce28171b4081268", - "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jvmci-1648ffb0158e.jar"], - "sourceSha1" : "b34c184cb1d383aec07bcadefadff01543f10222", - "sourceUrls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jvmci-1648ffb0158e.src.zip"], + "sha1" : "31c6bb33db89e7863d716641518bb6997fe2d340", + "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jvmci-7a570929c5e5.jar"], + "sourceSha1" : "8020f243ce1d5453c7a3b9f2bba52ad69ce689b4", + "sourceUrls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/jvmci-7a570929c5e5.src.zip"], "license": "GPLv2-CPE", }, }), @@ -518,6 +518,7 @@ "javaCompliance" : "1.8", "annotationProcessors" : [ "GRAAL_NODEINFO_PROCESSOR", + "GRAAL_REPLACEMENTS_VERIFIER", ], "workingSets" : "Graal,Replacements,AMD64", }, @@ -541,7 +542,10 @@ "com.oracle.graal.compiler.test", "com.oracle.graal.replacements", ], - "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"], + "annotationProcessors" : [ + "GRAAL_NODEINFO_PROCESSOR", + "GRAAL_REPLACEMENTS_VERIFIER" + ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal,Replacements,Test", @@ -639,7 +643,7 @@ "com.oracle.graal.virtual.bench" : { "subDir" : "graal", "sourceDirs" : ["src"], - "dependencies" : ["JMH"], + "dependencies" : ["JMH", "com.oracle.graal.microbenchmarks"], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "annotationProcessors" : ["JMH"], @@ -784,7 +788,6 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.graal.phases", - "com.oracle.graal.graphbuilderconf", ], "annotationProcessors" : deps(["jvmci:JVMCI_OPTIONS_PROCESSOR"]), "checkstyle" : "com.oracle.graal.graph", @@ -792,17 +795,6 @@ "workingSets" : "Graal,Java", }, - "com.oracle.graal.graphbuilderconf" : { - "subDir" : "graal", - "sourceDirs" : ["src"], - "dependencies" : [ - "com.oracle.graal.nodes", - ], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "Graal,Java", - }, - "com.oracle.graal.compiler.common" : { "subDir" : "graal", "sourceDirs" : ["src"], @@ -1123,9 +1115,10 @@ "GRAAL_REPLACEMENTS_VERIFIER" : { "subDir" : "graal", "dependencies" : ["com.oracle.graal.replacements.verifier"], - "distDependencies" : [ + "distDependencies" : deps([ "GRAAL_API", - ], + "jvmci:JVMCI_SERVICE_PROCESSOR", + ]) }, "GRAAL_COMPILER_MATCH_PROCESSOR" : {