# HG changeset patch # User Thomas Wuerthinger # Date 1423577456 -3600 # Node ID afe5d805c88a6675931d23d8822f295a91dd6965 # Parent 637ca4d37bca01f0dcbf2e42f0e0e66ad451157e# Parent 5b75ec42c975bee797579c5703f38b6af6a335c9 Merge. diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Tue Feb 10 15:10:56 2015 +0100 @@ -684,10 +684,38 @@ * @param handlerPos the position of the handler */ public void recordExceptionHandler(int codePos, int handlerPos) { + assert validateExceptionHandlerAdd(codePos, handlerPos) : String.format("Duplicate exception handler for pc 0x%x handlerPos 0x%x", codePos, handlerPos); exceptionHandlers.add(new ExceptionHandler(codePos, handlerPos)); } /** + * Validate if the exception handler for codePos already exists and handlerPos is different. + * + * @param codePos + * @param handlerPos + * @return true if the validation is successful + */ + private boolean validateExceptionHandlerAdd(int codePos, int handlerPos) { + ExceptionHandler exHandler = getExceptionHandlerForCodePos(codePos); + return exHandler == null || exHandler.handlerPos == handlerPos; + } + + /** + * Returns the first ExceptionHandler which matches codePos. + * + * @param codePos position to search for + * @return first matching ExceptionHandler + */ + private ExceptionHandler getExceptionHandlerForCodePos(int codePos) { + for (ExceptionHandler h : exceptionHandlers) { + if (h.pcOffset == codePos) { + return h; + } + } + return null; + } + + /** * Records an infopoint in the code array. * * @param codePos the position of the infopoint in the code array diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DataSection.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DataSection.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DataSection.java Tue Feb 10 15:10:56 2015 +0100 @@ -47,27 +47,8 @@ return (buffer, patch) -> buffer.put(data); } - static DataBuilder primitive(PrimitiveConstant c) { - switch (c.getKind()) { - case Boolean: - return (buffer, patch) -> buffer.put(c.asBoolean() ? (byte) 1 : (byte) 0); - case Byte: - return (buffer, patch) -> buffer.put((byte) c.asInt()); - case Char: - return (buffer, patch) -> buffer.putChar((char) c.asInt()); - case Short: - return (buffer, patch) -> buffer.putShort((short) c.asInt()); - case Int: - return (buffer, patch) -> buffer.putInt(c.asInt()); - case Long: - return (buffer, patch) -> buffer.putLong(c.asLong()); - case Float: - return (buffer, patch) -> buffer.putFloat(c.asFloat()); - case Double: - return (buffer, patch) -> buffer.putDouble(c.asDouble()); - default: - throw new IllegalArgumentException(); - } + static DataBuilder serializable(SerializableConstant c) { + return (buffer, patch) -> c.serialize(buffer); } static DataBuilder zero(int size) { diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java --- a/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Tue Feb 10 15:10:56 2015 +0100 @@ -68,7 +68,7 @@ public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); Register ret = registerConfig.getReturnRegister(Kind.Double); - Data data = new Data(8, 8, DataBuilder.primitive(JavaConstant.forDouble(84.72))); + Data data = new Data(8, 8, DataBuilder.serializable(JavaConstant.forDouble(84.72))); DataSectionReference ref = compResult.getDataSection().insertData(data); compResult.recordDataPatch(asm.position(), ref); asm.movdbl(ret, asm.getPlaceholder()); diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue Feb 10 15:10:56 2015 +0100 @@ -123,7 +123,7 @@ long finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { - baseRegister = SPARC.g0.asValue(); + baseRegister = SPARC.g0.asValue(base.getLIRKind()); } else if (asConstant(base).getKind() != Kind.Object) { finalDisp += asConstant(base).asLong(); baseRegister = Value.ILLEGAL; diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Feb 10 15:10:56 2015 +0100 @@ -55,6 +55,7 @@ import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.schedule.*; @@ -87,7 +88,7 @@ private final Providers providers; private final Backend backend; - private final Suites suites; + private final DerivedOptionValue suites; /** * Can be overridden by unit tests to verify properties of the graph. @@ -166,7 +167,7 @@ public GraalCompilerTest() { this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = getBackend().getProviders(); - this.suites = createSuites(); + this.suites = new DerivedOptionValue<>(this::createSuites); installSubstitutions(); } @@ -186,7 +187,7 @@ this.backend = runtime.getHostBackend(); } this.providers = backend.getProviders(); - this.suites = createSuites(); + this.suites = new DerivedOptionValue<>(this::createSuites); installSubstitutions(); } @@ -351,7 +352,7 @@ } protected Suites getSuites() { - return suites; + return suites.getValue(); } protected Providers getProviders() { diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Feb 10 15:10:56 2015 +0100 @@ -276,7 +276,7 @@ try (TimerCloseable a = BackEnd.start()) { LIRGenerationResult lirGen = null; lirGen = emitLIR(backend, target, schedule, graph, stub, cc, registerConfig); - try (Scope s = Debug.scope("CodeGen", lirGen)) { + try (Scope s = Debug.scope("CodeGen", new Object[]{lirGen, lirGen.getLIR()})) { emitCode(backend, assumptions, lirGen, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { throw Debug.handle(e); diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Tue Feb 10 15:10:56 2015 +0100 @@ -327,10 +327,10 @@ boolean compressed = COMPRESSED_NULL.equals(constant); size = target.getSizeInBytes(compressed ? Kind.Int : target.wordKind); builder = DataBuilder.zero(size); - } else if (constant instanceof PrimitiveConstant) { - PrimitiveConstant prim = (PrimitiveConstant) constant; - size = target.getSizeInBytes(prim.getKind()); - builder = DataBuilder.primitive(prim); + } else if (constant instanceof SerializableConstant) { + SerializableConstant s = (SerializableConstant) constant; + size = s.getSerializedSize(); + builder = DataBuilder.serializable(s); } else { throw GraalInternalError.shouldNotReachHere(); } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPluginsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphBuilderPluginsProvider.java Tue Feb 10 15:10:56 2015 +0100 @@ -0,0 +1,93 @@ +/* + * 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.meta; + +import static com.oracle.graal.java.GraphBuilderContext.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.options.*; + +/** + * Provider of HotSpot specific {@link GraphBuilderPlugin}s. + */ +@ServiceProvider(GraphBuilderPluginsProvider.class) +public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { + public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + // Object.class + Registration r = new Registration(plugins, metaAccess, Object.class); + r.register1("getClass", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { + ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); + ValueNode mirror; + if (objectStamp.isExactType() && objectStamp.nonNull()) { + mirror = builder.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), builder.getMetaAccess())); + } else { + StampProvider stampProvider = builder.getStampProvider(); + LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, nullCheckedValue(builder, rcvr))); + mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub)); + } + builder.push(Kind.Object, mirror); + return true; + } + }); + + // Class.class + r = new Registration(plugins, metaAccess, Class.class); + r.register2("cast", Receiver.class, Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode rcvr, ValueNode object) { + if (rcvr.isConstant() && !rcvr.isNullConstant() && object.isConstant()) { + ResolvedJavaType type = builder.getConstantReflection().asJavaType(rcvr.asConstant()); + if (type != null && !type.isPrimitive() && type.isInstance(object.asJavaConstant())) { + builder.push(Kind.Object, object); + return true; + } + } + return false; + } + }); + // StableOptionValue.class + r = new Registration(plugins, metaAccess, StableOptionValue.class); + r.register1("getValue", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { + if (rcvr.isConstant() && !rcvr.isNullConstant()) { + Object object = ((HotSpotObjectConstantImpl) rcvr.asConstant()).object(); + StableOptionValue option = (StableOptionValue) object; + ConstantNode value = builder.append(ConstantNode.forConstant(HotSpotObjectConstantImpl.forObject(option.getValue()), builder.getMetaAccess())); + builder.push(Kind.Object, value); + return true; + } + return false; + } + }); + } +} diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotSuitesProvider.java Tue Feb 10 15:10:56 2015 +0100 @@ -24,8 +24,6 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; -import java.util.function.*; - import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; @@ -35,13 +33,16 @@ import com.oracle.graal.java.GraphBuilderConfiguration.DebugInfoMode; import com.oracle.graal.java.GraphBuilderPlugins.InlineInvokePlugin; import com.oracle.graal.options.*; +import com.oracle.graal.options.DerivedOptionValue.OptionSupplier; import com.oracle.graal.phases.*; import com.oracle.graal.phases.tiers.*; /** * HotSpot implementation of {@link SuitesProvider}. */ -public class HotSpotSuitesProvider implements SuitesProvider, Supplier { +public class HotSpotSuitesProvider implements SuitesProvider, OptionSupplier { + + private static final long serialVersionUID = -5755004498526945687L; protected final DerivedOptionValue defaultSuites; protected final PhaseSuite defaultGraphBuilderSuite; diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotGraphBuilderPluginsProvider.java Tue Feb 10 15:10:46 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +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.replacements; - -import static com.oracle.graal.java.GraphBuilderContext.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Provider of HotSpot specific {@link GraphBuilderPlugin}s. - */ -@ServiceProvider(GraphBuilderPluginsProvider.class) -public class HotSpotGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { - public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - Registration r = new Registration(plugins, metaAccess, Object.class); - r.register1("getClass", Receiver.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode rcvr) { - ObjectStamp objectStamp = (ObjectStamp) rcvr.stamp(); - ValueNode mirror; - if (objectStamp.isExactType() && objectStamp.nonNull()) { - mirror = builder.append(ConstantNode.forConstant(objectStamp.type().getJavaClass(), metaAccess)); - } else { - StampProvider stampProvider = builder.getStampProvider(); - LoadHubNode hub = builder.append(new LoadHubNode(stampProvider, nullCheckedValue(builder, rcvr))); - mirror = builder.append(new HubGetClassNode(builder.getMetaAccess(), hub)); - } - builder.push(Kind.Object, mirror); - return true; - } - }); - } -} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HubGetClassNode.java Tue Feb 10 15:10:56 2015 +0100 @@ -41,7 +41,7 @@ public class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { @Input protected ValueNode hub; - protected HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { + public HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { super(StampFactory.declaredNonNull(metaAccess.lookupJavaType(Class.class)), null); this.hub = hub; } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderContext.java Tue Feb 10 15:10:56 2015 +0100 @@ -47,6 +47,8 @@ Assumptions getAssumptions(); + ConstantReflectionProvider getConstantReflection(); + void push(Kind kind, ValueNode value); /** diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Feb 10 15:10:56 2015 +0100 @@ -37,8 +37,8 @@ import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.java.BciBlockMapping.BciBlock; @@ -102,7 +102,7 @@ private final OptimisticOptimizations optimisticOpts; private final StampProvider stampProvider; private final Assumptions assumptions; - private final ConstantReflectionProvider constantReflectionProvider; + private final ConstantReflectionProvider constantReflection; /** * Gets the graph being processed by this builder. @@ -111,7 +111,7 @@ return currentGraph; } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflectionProvider, + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, GraphBuilderPlugins graphBuilderPlugins, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; @@ -119,13 +119,13 @@ this.stampProvider = stampProvider; this.assumptions = assumptions; this.graphBuilderPlugins = graphBuilderPlugins; - this.constantReflectionProvider = constantReflectionProvider; + this.constantReflection = constantReflection; assert metaAccess != null; } - public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflectionProvider, + public Instance(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - this(metaAccess, stampProvider, assumptions, constantReflectionProvider, graphBuilderConfig, null, optimisticOpts); + this(metaAccess, stampProvider, assumptions, constantReflection, graphBuilderConfig, null, optimisticOpts); } @Override @@ -508,7 +508,7 @@ @Override protected ValueNode genLoadIndexed(ValueNode array, ValueNode index, Kind kind) { - return LoadIndexedNode.create(array, index, kind, metaAccess, constantReflectionProvider); + return LoadIndexedNode.create(array, index, kind, metaAccess, constantReflection); } @Override @@ -634,17 +634,17 @@ @Override protected ValueNode genObjectEquals(ValueNode x, ValueNode y) { - return ObjectEqualsNode.create(x, y, constantReflectionProvider); + return ObjectEqualsNode.create(x, y, constantReflection); } @Override protected ValueNode genIntegerEquals(ValueNode x, ValueNode y) { - return IntegerEqualsNode.create(x, y, constantReflectionProvider); + return IntegerEqualsNode.create(x, y, constantReflection); } @Override protected ValueNode genIntegerLessThan(ValueNode x, ValueNode y) { - return IntegerLessThanNode.create(x, y, constantReflectionProvider); + return IntegerLessThanNode.create(x, y, constantReflection); } @Override @@ -716,7 +716,7 @@ protected void emitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = currentGraph.add(new BeginNode()); BytecodeExceptionNode exception = currentGraph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); - append(new IfNode(currentGraph.unique(IntegerBelowNode.create(index, length, constantReflectionProvider)), trueSucc, exception, 0.99)); + append(new IfNode(currentGraph.unique(IntegerBelowNode.create(index, length, constantReflection)), trueSucc, exception, 0.99)); lastInstr = trueSucc; exception.setStateAfter(frameState.create(bci())); @@ -725,7 +725,7 @@ @Override protected ValueNode genArrayLength(ValueNode x) { - return ArrayLengthNode.create(x, constantReflectionProvider); + return ArrayLengthNode.create(x, constantReflection); } @Override @@ -1060,7 +1060,7 @@ JsrScope scope = currentBlock.getJsrScope(); int retAddress = scope.nextReturnAddress(); ConstantNode returnBciNode = getJsrConstant(retAddress); - LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflectionProvider); + LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflection); guard = currentGraph.unique(guard); append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.getJsrScope().equals(scope.pop())) { @@ -1691,6 +1691,7 @@ } public void push(Kind kind, ValueNode value) { + assert kind == kind.getStackKind(); frameState.push(kind, value); } @@ -1701,6 +1702,11 @@ return this.explodeLoopsContext.peek().peelIteration; } } + + public ConstantReflectionProvider getConstantReflection() { + return constantReflection; + } + } } } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPlugins.java Tue Feb 10 15:10:56 2015 +0100 @@ -94,6 +94,13 @@ } /** + * @see #execute(GraphBuilderContext, InvocationPlugin, ValueNode[]) + */ + default boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4) { + throw invalidHandler(builder, arg1, arg2, arg3, arg4); + } + + /** * Executes a given plugin against a set of invocation arguments by dispatching to the * plugin's {@code apply(...)} method that matches the number of arguments. * @@ -111,6 +118,8 @@ return plugin.apply(builder, args[0], args[1]); } else if (args.length == 3) { return plugin.apply(builder, args[0], args[1], args[2]); + } else if (args.length == 4) { + return plugin.apply(builder, args[0], args[1], args[2], args[3]); } else { throw plugin.invalidHandler(builder, args); } @@ -200,6 +209,17 @@ } /** + * 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) { + ResolvedJavaMethod method = arg1 == Receiver.class ? resolve(metaAccess, declaringClass, name, arg2, arg3, arg4) : resolve(metaAccess, declaringClass, name, arg1, arg2, arg3, arg4); + plugins.register(method, plugin); + } + + /** * Resolves a method given a declaring class, name and parameter types. */ public static ResolvedJavaMethod resolve(MetaAccessProvider metaAccess, Class declaringClass, String name, Class... parameterTypes) { @@ -212,11 +232,27 @@ } public static class InvocationPluginChecker { - static final Class[] APPLY0 = {GraphBuilderContext.class}; - static final Class[] APPLY1 = {GraphBuilderContext.class, ValueNode.class}; - static final Class[] APPLY2 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class}; - static final Class[] APPLY3 = {GraphBuilderContext.class, ValueNode.class, ValueNode.class, ValueNode.class}; - static final Class[][] SIGS = {APPLY0, APPLY1, APPLY2, APPLY3}; + /** + * The set of all {@link InvocationPlugin#apply} method signatures. + */ + static final Class[][] SIGS; + static { + ArrayList[]> sigs = new ArrayList<>(5); + 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 Arrays.asList(Arrays.copyOfRange(sig, 1, sig.length)).stream().allMatch(c -> c == ValueNode.class); + while (sigs.size() < sig.length) { + sigs.add(null); + } + sigs.set(sig.length - 1, 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(ResolvedJavaMethod method, InvocationPlugin plugin) { int arguments = method.getSignature().getParameterCount(!method.isStatic()); diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Tue Feb 10 15:10:56 2015 +0100 @@ -383,5 +383,11 @@ public void reset() { asm.reset(); compilationResult.reset(); + if (exceptionInfoList != null) { + exceptionInfoList.clear(); + } + if (dataCache != null) { + dataCache.clear(); + } } } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Tue Feb 10 15:10:56 2015 +0100 @@ -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 @@ -22,6 +22,8 @@ */ package com.oracle.graal.loop; +import static com.oracle.graal.loop.MathUtil.*; + import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; @@ -29,10 +31,10 @@ public class BasicInductionVariable extends InductionVariable { - private ValuePhiNode phi; - private ValueNode init; - private ValueNode rawStride; - private BinaryArithmeticNode op; + private final ValuePhiNode phi; + private final ValueNode init; + private final ValueNode rawStride; + private final BinaryArithmeticNode op; public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, BinaryArithmeticNode op) { super(loop); @@ -135,7 +137,7 @@ if (!maxTripCount.stamp().isCompatible(stamp)) { maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); } - return BinaryArithmeticNode.add(graph, BinaryArithmeticNode.mul(graph, stride, BinaryArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); + return add(graph, mul(graph, stride, sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); } @Override @@ -145,7 +147,7 @@ if (!maxTripCount.stamp().isCompatible(stamp)) { maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); } - return BinaryArithmeticNode.add(graph(), BinaryArithmeticNode.mul(graph(), strideNode(), maxTripCount), initNode()); + return add(graph(), mul(graph(), strideNode(), maxTripCount), initNode()); } @Override diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Tue Feb 10 15:10:56 2015 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.loop; -import static com.oracle.graal.nodes.calc.BinaryArithmeticNode.*; +import static com.oracle.graal.loop.MathUtil.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -55,20 +55,19 @@ public ValueNode maxTripCountNode(boolean assumePositive) { StructuredGraph graph = iv.valueNode().graph(); Stamp stamp = iv.valueNode().stamp(); - BinaryArithmeticNode range = BinaryArithmeticNode.sub(graph, end, iv.initNode()); + ValueNode range = sub(graph, end, iv.initNode()); if (oneOff) { if (iv.direction() == Direction.Up) { - range = BinaryArithmeticNode.add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); + range = add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } else { - range = BinaryArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); + range = sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } } - IntegerDivNode div = graph.add(new IntegerDivNode(range, iv.strideNode())); - graph.addBeforeFixed(loop.entryPoint(), div); - ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph); + ValueNode div = divBefore(graph, loop.entryPoint(), range, iv.strideNode()); if (assumePositive) { return div; } + ConstantNode zero = ConstantNode.forIntegerStamp(stamp, 0, graph); return graph.unique(new ConditionalNode(graph.unique(new IntegerLessThanNode(zero, div)), div, zero)); } @@ -144,14 +143,14 @@ CompareNode cond; // we use a negated guard with a < condition to achieve a >= ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph); if (iv.direction() == Direction.Up) { - BinaryArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one)); + ValueNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one)); if (oneOff) { v1 = sub(graph, v1, one); } cond = graph.unique(new IntegerLessThanNode(v1, end)); } else { assert iv.direction() == Direction.Down; - BinaryArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode())); + ValueNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode())); if (oneOff) { v1 = add(graph, v1, one); } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedInductionVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedInductionVariable.java Tue Feb 10 15:10:56 2015 +0100 @@ -0,0 +1,47 @@ +/* + * 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.loop; + +import com.oracle.graal.nodes.*; + +/** + * Base class of the derived induction variables. + */ +public abstract class DerivedInductionVariable extends InductionVariable { + + protected final InductionVariable base; + + public DerivedInductionVariable(LoopEx loop, InductionVariable base) { + super(loop); + this.base = base; + } + + @Override + public StructuredGraph graph() { + return base.graph(); + } + + public InductionVariable getBase() { + return base; + } +} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Tue Feb 10 15:10:56 2015 +0100 @@ -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 @@ -22,38 +22,29 @@ */ package com.oracle.graal.loop; +import static com.oracle.graal.loop.MathUtil.*; + import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; -public class DerivedOffsetInductionVariable extends InductionVariable { +public class DerivedOffsetInductionVariable extends DerivedInductionVariable { - private InductionVariable base; - private ValueNode offset; - private BinaryArithmeticNode value; + private final ValueNode offset; + private final BinaryArithmeticNode value; public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, BinaryArithmeticNode value) { - super(loop); - this.base = base; + super(loop, base); this.offset = offset; this.value = value; } - public InductionVariable getBase() { - return base; - } - public ValueNode getOffset() { return offset; } @Override - public StructuredGraph graph() { - return base.graph(); - } - - @Override public Direction direction() { return base.direction(); } @@ -136,14 +127,14 @@ private ValueNode op(ValueNode b, ValueNode o) { if (value instanceof AddNode) { - return BinaryArithmeticNode.add(graph(), b, o); + return add(graph(), b, o); } if (value instanceof SubNode) { if (base.valueNode() == value.getX()) { - return BinaryArithmeticNode.sub(graph(), b, o); + return sub(graph(), b, o); } else { assert base.valueNode() == value.getY(); - return BinaryArithmeticNode.sub(graph(), o, b); + return sub(graph(), o, b); } } throw GraalInternalError.shouldNotReachHere(); diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Tue Feb 10 15:10:56 2015 +0100 @@ -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 @@ -22,34 +22,37 @@ */ package com.oracle.graal.loop; +import static com.oracle.graal.loop.MathUtil.*; + import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.util.*; -public class DerivedScaledInductionVariable extends InductionVariable { +public class DerivedScaledInductionVariable extends DerivedInductionVariable { - private InductionVariable base; - private ValueNode scale; - private ValueNode value; + private final ValueNode scale; + private final ValueNode value; public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, ValueNode scale, ValueNode value) { - super(loop); - this.base = base; + super(loop, base); this.scale = scale; this.value = value; } public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, NegateNode value) { - super(loop); - this.base = base; + super(loop, base); this.scale = ConstantNode.forInt(-1, value.graph()); this.value = value; } + public ValueNode getScale() { + return scale; + } + @Override - public StructuredGraph graph() { - return base.graph(); + public ValueNode valueNode() { + return value; } @Override @@ -67,18 +70,13 @@ } @Override - public ValueNode valueNode() { - return value; - } - - @Override public ValueNode initNode() { - return BinaryArithmeticNode.mul(graph(), base.initNode(), scale); + return mul(graph(), base.initNode(), scale); } @Override public ValueNode strideNode() { - return BinaryArithmeticNode.mul(graph(), base.strideNode(), scale); + return mul(graph(), base.strideNode(), scale); } @Override @@ -103,12 +101,12 @@ @Override public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { - return BinaryArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph())); + return mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph())); } @Override public ValueNode exitValueNode() { - return BinaryArithmeticNode.mul(graph(), base.exitValueNode(), scale); + return mul(graph(), base.exitValueNode(), scale); } @Override diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariable.java Tue Feb 10 15:10:56 2015 +0100 @@ -87,7 +87,9 @@ /** * Returns the extremum value of the induction variable. The extremum value is the value of the - * induction variable in the loop body of the last iteration. + * induction variable in the loop body of the last iteration, only taking into account the main + * loop limit test. It's possible for the loop to exit before this value if + * {@link CountedLoopInfo#isExactTripCount()} returns false for the containing loop. */ public ValueNode extremumNode() { return extremumNode(false, valueNode().stamp()); diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Tue Feb 10 15:10:46 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.loop; - -import static com.oracle.graal.graph.Node.*; - -import java.util.*; - -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; - -public class InductionVariables { - - private final LoopEx loop; - private Map ivs; - - public InductionVariables(LoopEx loop) { - this.loop = loop; - ivs = newIdentityMap(); - findDerived(findBasic()); - } - - public InductionVariable get(ValueNode v) { - return ivs.get(v); - } - - private Collection findBasic() { - List bivs = new LinkedList<>(); - LoopBeginNode loopBegin = loop.loopBegin(); - AbstractEndNode forwardEnd = loopBegin.forwardEnd(); - for (PhiNode phi : loopBegin.phis().filter(ValuePhiNode.class)) { - ValueNode backValue = phi.singleBackValue(); - if (backValue == PhiNode.MULTIPLE_VALUES) { - continue; - } - ValueNode stride = addSub(backValue, phi); - if (stride != null) { - BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode) backValue); - ivs.put(phi, biv); - bivs.add(biv); - } - } - return bivs; - } - - private void findDerived(Collection bivs) { - Queue scanQueue = new LinkedList<>(bivs); - while (!scanQueue.isEmpty()) { - InductionVariable baseIv = scanQueue.remove(); - ValueNode baseIvNode = baseIv.valueNode(); - for (ValueNode op : baseIvNode.usages().filter(ValueNode.class)) { - if (loop.isOutsideLoop(op)) { - continue; - } - if (op.usages().count() == 1 && op.usages().first() == baseIvNode) { - /* - * This is just the base induction variable increment with no other uses so - * don't bother reporting it. - */ - continue; - } - InductionVariable iv = null; - ValueNode offset = addSub(op, baseIvNode); - ValueNode scale; - if (offset != null) { - iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode) op); - } else if (op instanceof NegateNode) { - iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op); - } else if ((scale = mul(op, baseIvNode)) != null) { - iv = new DerivedScaledInductionVariable(loop, baseIv, scale, op); - } - - if (iv != null) { - ivs.put(op, iv); - scanQueue.offer(iv); - } - } - } - } - - private ValueNode addSub(ValueNode op, ValueNode base) { - if (op.stamp() instanceof IntegerStamp && (op instanceof AddNode || op instanceof SubNode)) { - BinaryArithmeticNode aritOp = (BinaryArithmeticNode) op; - if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) { - return aritOp.getY(); - } else if (aritOp.getY() == base && loop.isOutsideLoop(aritOp.getX())) { - return aritOp.getX(); - } - } - return null; - } - - private ValueNode mul(ValueNode op, ValueNode base) { - if (op instanceof MulNode) { - MulNode mul = (MulNode) op; - if (mul.getX() == base && loop.isOutsideLoop(mul.getY())) { - return mul.getY(); - } else if (mul.getY() == base && loop.isOutsideLoop(mul.getX())) { - return mul.getX(); - } - } - if (op instanceof LeftShiftNode) { - LeftShiftNode shift = (LeftShiftNode) op; - if (shift.getX() == base && shift.getY().isConstant()) { - return ConstantNode.forInt(1 << shift.getY().asJavaConstant().asInt(), base.graph()); - } - } - return null; - } - - /** - * Deletes any nodes created within the scope of this object that have no usages. - */ - public void deleteUnusedNodes() { - for (InductionVariable iv : ivs.values()) { - iv.deleteUnusedNodes(); - } - } -} diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Tue Feb 10 15:10:56 2015 +0100 @@ -22,11 +22,14 @@ */ package com.oracle.graal.loop; +import static com.oracle.graal.graph.Node.*; + import java.util.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; @@ -44,7 +47,7 @@ private LoopFragmentWhole whole; private CountedLoopInfo counted; // TODO (gd) detect private LoopsData data; - private InductionVariables ivs; + private Map ivs; LoopEx(Loop loop, LoopsData data) { this.loop = loop; @@ -252,19 +255,111 @@ return LoopFragment.computeNodes(point.graph(), blocks, exits); } - public InductionVariables getInductionVariables() { + public Map getInductionVariables() { if (ivs == null) { - ivs = new InductionVariables(this); + ivs = findInductionVariables(this); } return ivs; } /** + * Collect all the basic induction variables for the loop and the find any induction variables + * which are derived from the basic ones. + * + * @param loop + * @return a map from node to induction variable + */ + private static Map findInductionVariables(LoopEx loop) { + Map ivs = newIdentityMap(); + + Queue scanQueue = new LinkedList<>(); + LoopBeginNode loopBegin = loop.loopBegin(); + AbstractEndNode forwardEnd = loopBegin.forwardEnd(); + for (PhiNode phi : loopBegin.phis().filter(ValuePhiNode.class)) { + ValueNode backValue = phi.singleBackValue(); + if (backValue == PhiNode.MULTIPLE_VALUES) { + continue; + } + ValueNode stride = addSub(loop, backValue, phi); + if (stride != null) { + BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode) backValue); + ivs.put(phi, biv); + scanQueue.add(biv); + } + } + + while (!scanQueue.isEmpty()) { + InductionVariable baseIv = scanQueue.remove(); + ValueNode baseIvNode = baseIv.valueNode(); + for (ValueNode op : baseIvNode.usages().filter(ValueNode.class)) { + if (loop.isOutsideLoop(op)) { + continue; + } + if (op.usages().count() == 1 && op.usages().first() == baseIvNode) { + /* + * This is just the base induction variable increment with no other uses so + * don't bother reporting it. + */ + continue; + } + InductionVariable iv = null; + ValueNode offset = addSub(loop, op, baseIvNode); + ValueNode scale; + if (offset != null) { + iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode) op); + } else if (op instanceof NegateNode) { + iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op); + } else if ((scale = mul(loop, op, baseIvNode)) != null) { + iv = new DerivedScaledInductionVariable(loop, baseIv, scale, op); + } + + if (iv != null) { + ivs.put(op, iv); + scanQueue.offer(iv); + } + } + } + return Collections.unmodifiableMap(ivs); + } + + private static ValueNode addSub(LoopEx loop, ValueNode op, ValueNode base) { + if (op.stamp() instanceof IntegerStamp && (op instanceof AddNode || op instanceof SubNode)) { + BinaryArithmeticNode aritOp = (BinaryArithmeticNode) op; + if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) { + return aritOp.getY(); + } else if (aritOp.getY() == base && loop.isOutsideLoop(aritOp.getX())) { + return aritOp.getX(); + } + } + return null; + } + + private static ValueNode mul(LoopEx loop, ValueNode op, ValueNode base) { + if (op instanceof MulNode) { + MulNode mul = (MulNode) op; + if (mul.getX() == base && loop.isOutsideLoop(mul.getY())) { + return mul.getY(); + } else if (mul.getY() == base && loop.isOutsideLoop(mul.getX())) { + return mul.getX(); + } + } + if (op instanceof LeftShiftNode) { + LeftShiftNode shift = (LeftShiftNode) op; + if (shift.getX() == base && shift.getY().isConstant()) { + return ConstantNode.forInt(1 << shift.getY().asJavaConstant().asInt(), base.graph()); + } + } + return null; + } + + /** * Deletes any nodes created within the scope of this object that have no usages. */ public void deleteUnusedNodes() { if (ivs != null) { - ivs.deleteUnusedNodes(); + for (InductionVariable iv : ivs.values()) { + iv.deleteUnusedNodes(); + } } } } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.loop/src/com/oracle/graal/loop/MathUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/MathUtil.java Tue Feb 10 15:10:56 2015 +0100 @@ -0,0 +1,76 @@ +/* + * 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.loop; + +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +/** + * Utility methods to perform integer math with some obvious constant folding first. + */ +public class MathUtil { + private static boolean isConstantOne(ValueNode v1) { + return v1.isConstant() && v1.stamp() instanceof IntegerStamp && v1.asJavaConstant().asLong() == 1; + } + + private static boolean isConstantZero(ValueNode v1) { + return v1.isConstant() && v1.stamp() instanceof IntegerStamp && v1.asJavaConstant().asLong() == 0; + } + + public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { + if (isConstantZero(v1)) { + return v2; + } + if (isConstantZero(v2)) { + return v1; + } + return BinaryArithmeticNode.add(graph, v1, v2); + } + + public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { + if (isConstantOne(v1)) { + return v2; + } + if (isConstantOne(v2)) { + return v1; + } + return BinaryArithmeticNode.mul(graph, v1, v2); + } + + public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { + if (isConstantZero(v2)) { + return v1; + } + return BinaryArithmeticNode.sub(graph, v1, v2); + } + + public static ValueNode divBefore(StructuredGraph graph, FixedNode before, ValueNode dividend, ValueNode divisor) { + if (isConstantOne(divisor)) { + return dividend; + } + IntegerDivNode div = graph.add(new IntegerDivNode(dividend, divisor)); + graph.addBeforeFixed(before, div); + return div; + } +} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Tue Feb 10 15:10:56 2015 +0100 @@ -51,7 +51,7 @@ protected final BinaryOp getOp(ValueNode forX, ValueNode forY) { ArithmeticOpTable table = ArithmeticOpTable.forStamp(forX.stamp()); - assert table.toString().equals(ArithmeticOpTable.forStamp(forY.stamp()).toString()); + assert table.equals(ArithmeticOpTable.forStamp(forY.stamp())); return getOp.apply(table); } diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/DerivedOptionValue.java Tue Feb 10 15:10:56 2015 +0100 @@ -22,6 +22,7 @@ */ package com.oracle.graal.options; +import java.io.*; import java.util.function.*; import com.oracle.graal.options.OptionValue.OverrideScope; @@ -31,10 +32,13 @@ */ public class DerivedOptionValue { + public interface OptionSupplier extends Supplier, Serializable { + } + private final T initialValue; - private final Supplier supplier; + private final OptionSupplier supplier; - public DerivedOptionValue(Supplier supplier) { + public DerivedOptionValue(OptionSupplier supplier) { this.supplier = supplier; assert OptionValue.getOverrideScope() == null : "derived option value should be initialized outside any override scope"; this.initialValue = createValue(); diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Tue Feb 10 15:10:56 2015 +0100 @@ -633,9 +633,9 @@ return graph; } - protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflectionProvider, + protected Instance createGraphBuilder(MetaAccessProvider metaAccess, StampProvider stampProvider, Assumptions assumptions, ConstantReflectionProvider constantReflection, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { - return new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, constantReflectionProvider, graphBuilderConfig, optimisticOpts); + return new GraphBuilderPhase.Instance(metaAccess, stampProvider, assumptions, constantReflection, graphBuilderConfig, optimisticOpts); } protected void afterParsing(StructuredGraph graph) { diff -r 637ca4d37bca -r afe5d805c88a 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 Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Tue Feb 10 15:10:56 2015 +0100 @@ -218,7 +218,7 @@ for (GraphBuilderPluginsProvider p : sl) { p.registerPlugins(providers.getMetaAccess(), plugins); } - new TruffleGraphBuilderPluginsProvider().registerPlugins(providers.getMetaAccess(), plugins); + TruffleGraphBuilderPlugins.registerPlugins(providers.getMetaAccess(), plugins); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), new Assumptions(false), providers.getConstantReflection(), newConfig, plugins, TruffleCompilerImpl.Optimizations).apply(graph); Debug.dump(graph, "After FastPE"); diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPlugins.java Tue Feb 10 15:10:56 2015 +0100 @@ -0,0 +1,215 @@ +/* + * 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.substitutions; + +import static java.lang.Character.*; + +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.calc.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.java.*; +import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; +import com.oracle.graal.java.GraphBuilderPlugins.Registration; +import com.oracle.graal.java.GraphBuilderPlugins.Registration.Receiver; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.truffle.*; +import com.oracle.graal.truffle.nodes.*; +import com.oracle.graal.truffle.nodes.frame.*; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * Provider of {@link GraphBuilderPlugin}s for Truffle classes. + */ +public class TruffleGraphBuilderPlugins { + public static void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { + + // CompilerDirectives.class + Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); + r.register0("inInterpreter", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(false))); + return true; + } + }); + r.register0("inCompiledCode", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); + return true; + } + }); + r.register0("transferToInterpreter", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); + return true; + } + }); + r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder) { + builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); + return true; + } + }); + r.register1("interpreterOnly", Runnable.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg) { + return true; + } + }); + r.register1("interpreterOnly", Callable.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg) { + return true; + } + }); + r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { + builder.push(Kind.Boolean.getStackKind(), builder.append(new BranchProbabilityNode(probability, condition))); + return true; + } + }); + r.register1("bailout", String.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode message) { + if (message.isConstant()) { + throw new BailoutException(message.asConstant().toValueString()); + } + throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)"); + } + }); + r.register1("isCompilationConstant", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) { + builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); + return true; + } + return false; + } + }); + r.register1("materialize", Object.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode value) { + builder.append(new ForceMaterializeNode(value)); + return true; + } + }); + + // OptimizedCallTarget.class + r = new Registration(plugins, metaAccess, OptimizedCallTarget.class); + r.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { + builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2))); + return true; + } + }); + + // FrameWithoutBoxing.class + r = new Registration(plugins, metaAccess, FrameWithoutBoxing.class); + r.register1("materialize", Receiver.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode frame) { + builder.append(new MaterializeFrameNode(frame)); + return true; + } + }); + r.register4("unsafeCast", Object.class, Class.class, boolean.class, boolean.class, new InvocationPlugin() { + public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode clazz, ValueNode condition, ValueNode nonNull) { + if (clazz.isConstant() && nonNull.isConstant()) { + ConstantReflectionProvider constantReflection = builder.getConstantReflection(); + ResolvedJavaType javaType = constantReflection.asJavaType(clazz.asConstant()); + if (javaType == null) { + builder.push(Kind.Object, object); + } else { + Stamp piStamp = StampFactory.declaredTrusted(javaType, nonNull.asJavaConstant().asInt() != 0); + ConditionAnchorNode valueAnchorNode = builder.append(new ConditionAnchorNode(CompareNode.createCompareNode(object.graph(), Condition.EQ, condition, + ConstantNode.forBoolean(true, object.graph())))); + PiNode piCast = builder.append(new PiNode(object, piStamp, valueAnchorNode)); + builder.push(Kind.Object, piCast); + } + return true; + } + // TODO: should we throw GraalInternalError.shouldNotReachHere() here? + return false; + } + }); + for (Kind kind : new Kind[]{Kind.Boolean, Kind.Byte, Kind.Int, Kind.Long, Kind.Float, Kind.Double, Kind.Object}) { + String kindName = kind.getJavaName(); + kindName = toUpperCase(kindName.charAt(0)) + kindName.substring(1); + String getName = "unsafeGet" + kindName; + String putName = "unsafePut" + kindName; + r.register4(getName, Object.class, long.class, boolean.class, Object.class, new CustomizedUnsafeLoadPlugin(kind)); + r.register4(putName, Object.class, long.class, kind == Kind.Object ? Object.class : kind.toJavaClass(), Object.class, new CustomizedUnsafeStorePlugin(kind)); + } + } + + static class CustomizedUnsafeLoadPlugin implements InvocationPlugin { + + private final Kind returnKind; + + public CustomizedUnsafeLoadPlugin(Kind returnKind) { + this.returnKind = returnKind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode condition, ValueNode location) { + if (location.isConstant()) { + LocationIdentity locationIdentity; + if (location.isNullConstant()) { + locationIdentity = LocationIdentity.ANY_LOCATION; + } else { + locationIdentity = ObjectLocationIdentity.create(location.asJavaConstant()); + } + CompareNode compare = builder.append(CompareNode.createCompareNode(Condition.EQ, condition, ConstantNode.forBoolean(true, object.graph()))); + builder.push(returnKind.getStackKind(), builder.append(new UnsafeLoadNode(object, offset, returnKind, locationIdentity, compare))); + return true; + } + // TODO: should we throw GraalInternalError.shouldNotReachHere() here? + return false; + } + } + + static class CustomizedUnsafeStorePlugin implements InvocationPlugin { + + private final Kind kind; + + public CustomizedUnsafeStorePlugin(Kind kind) { + this.kind = kind; + } + + public boolean apply(GraphBuilderContext builder, ValueNode object, ValueNode offset, ValueNode value, ValueNode location) { + ValueNode locationArgument = location; + if (locationArgument.isConstant()) { + LocationIdentity locationIdentity; + if (locationArgument.isNullConstant()) { + locationIdentity = LocationIdentity.ANY_LOCATION; + } else { + locationIdentity = ObjectLocationIdentity.create(locationArgument.asJavaConstant()); + } + + builder.append(new UnsafeStoreNode(object, offset, value, kind, locationIdentity, null)); + return true; + } + // TODO: should we throw GraalInternalError.shouldNotReachHere() here? + return false; + } + } +} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/TruffleGraphBuilderPluginsProvider.java Tue Feb 10 15:10:46 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +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.truffle.substitutions; - -import java.util.concurrent.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.java.*; -import com.oracle.graal.java.GraphBuilderPlugins.InvocationPlugin; -import com.oracle.graal.java.GraphBuilderPlugins.Registration; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.truffle.*; -import com.oracle.graal.truffle.nodes.frame.*; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.frame.*; - -/** - * Provider of {@link GraphBuilderPlugin}s for Truffle classes. - */ -public class TruffleGraphBuilderPluginsProvider implements GraphBuilderPluginsProvider { - public void registerPlugins(MetaAccessProvider metaAccess, GraphBuilderPlugins plugins) { - - Registration r2 = new Registration(plugins, metaAccess, OptimizedCallTarget.class); - r2.register2("createFrame", FrameDescriptor.class, Object[].class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg1, ValueNode arg2) { - builder.push(Kind.Object, builder.append(new NewFrameNode(StampFactory.exactNonNull(metaAccess.lookupJavaType(FrameWithoutBoxing.class)), arg1, arg2))); - return true; - } - }); - - Registration r = new Registration(plugins, metaAccess, CompilerDirectives.class); - r.register0("inInterpreter", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(false))); - return true; - } - }); - r.register0("inCompiledCode", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); - return true; - } - }); - r.register0("transferToInterpreter", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter)); - return true; - } - }); - r.register0("transferToInterpreterAndInvalidate", new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder) { - builder.append(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter)); - return true; - } - }); - r.register1("interpreterOnly", Runnable.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg) { - return true; - } - }); - r.register1("interpreterOnly", Callable.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode arg) { - return true; - } - }); - r.register2("injectBranchProbability", double.class, boolean.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode probability, ValueNode condition) { - builder.push(Kind.Boolean.getStackKind(), builder.append(new BranchProbabilityNode(probability, condition))); - return true; - } - }); - r.register1("bailout", String.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode message) { - if (message.isConstant()) { - throw new BailoutException(message.asConstant().toValueString()); - } - throw new BailoutException("bailout (message is not compile-time constant, so no additional information is available)"); - } - }); - r.register1("isCompilationConstant", Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - if ((value instanceof BoxNode ? ((BoxNode) value).getValue() : value).isConstant()) { - builder.push(Kind.Boolean.getStackKind(), builder.append(ConstantNode.forBoolean(true))); - return true; - } - return false; - } - }); - r.register1("materialize", Object.class, new InvocationPlugin() { - public boolean apply(GraphBuilderContext builder, ValueNode value) { - builder.append(new ForceMaterializeNode(value)); - return true; - } - }); - } -} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/tools/TruffleToolTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/tools/TruffleToolTest.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/tools/TruffleToolTest.java Tue Feb 10 15:10:56 2015 +0100 @@ -29,7 +29,7 @@ import com.oracle.truffle.api.instrument.*; /** - * Test the basic life cycle properties shared by all instances of {@link TruffleTool}. + * Test the basic life cycle properties shared by all instances of {@link InstrumentationTool}. */ public class TruffleToolTest { @@ -110,7 +110,7 @@ tool.dispose(); } - private static final class DummyTruffleTool extends TruffleTool { + private static final class DummyTruffleTool extends InstrumentationTool { @Override protected boolean internalInstall() { diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/InstrumentationTool.java Tue Feb 10 15:10:56 2015 +0100 @@ -0,0 +1,185 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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.truffle.api.instrument; + +/** + * {@linkplain Instrument Instrumentation}-based tools that gather data during Guest Language + * program execution. + *

+ * Tools share a common life cycle: + *

    + *
  • A newly created tool is inert until {@linkplain #install() installed}.
  • + *
  • An installed tool becomes enabled and immediately begins installing + * {@linkplain Instrument instrumentation} on subsequently created ASTs and collecting data from + * those instruments
  • + *
  • A tool may only be installed once.
  • + *
  • It should be possible to install multiple instances of a tool, possibly (but not necessarily) + * configured differently with respect to what data is being collected.
  • + *
  • Once installed, a tool can be {@linkplain #setEnabled(boolean) enabled and disabled} + * arbitrarily.
  • + *
  • A disabled tool: + *
      + *
    • Collects no data;
    • + *
    • Retains existing AST instrumentation;
    • + *
    • Continues to instrument newly created ASTs; and
    • + *
    • Retains previously collected data.
    • + *
    + *
  • + *
  • An installed tool may be {@linkplain #reset() reset} at any time, which leaves the tool + * installed but with all previously collected data removed.
  • + *
  • A {@linkplain #dispose() disposed} tool removes all instrumentation (but not + * {@linkplain Probe probes}) and becomes permanently disabled; previously collected data persists.
  • + *
+ *

+ * Tool-specific methods that access data collected by the tool should: + *

    + *
  • Return modification-safe representations of the data; and
  • + *
  • Not change the state of the data.
  • + *
+ * Note:
+ * Tool installation is currently global to the Truffle Execution environment. When + * language-agnostic management of individual execution environments is added to the platform, + * installation will be (optionally) specific to a single execution environment. + */ +public abstract class InstrumentationTool { + // TODO (mlvdv) still thinking about the most appropriate name for this class of tools + + private enum ToolState { + + /** Not yet installed, inert. */ + UNINSTALLED, + + /** Installed, collecting data. */ + ENABLED, + + /** Installed, not collecting data. */ + DISABLED, + + /** Was installed, but now removed, inactive, and no longer usable. */ + DISPOSED; + } + + private ToolState toolState = ToolState.UNINSTALLED; + + protected InstrumentationTool() { + } + + /** + * Connect the tool to some part of the Truffle runtime, and enable data collection to start. + * Instrumentation will only be added to subsequently created ASTs. + * + * @throws IllegalStateException if the tool has previously been installed. + */ + public final void install() { + checkUninstalled(); + if (internalInstall()) { + toolState = ToolState.ENABLED; + } + } + + /** + * @return whether the tool is currently collecting data. + */ + public final boolean isEnabled() { + return toolState == ToolState.ENABLED; + } + + /** + * Switches tool state between enabled (collecting data) and disabled (not + * collecting data, but keeping data already collected). + * + * @throws IllegalStateException if not yet installed or disposed. + */ + public final void setEnabled(boolean isEnabled) { + checkInstalled(); + internalSetEnabled(isEnabled); + toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED; + } + + /** + * Clears any data already collected, but otherwise does not change the state of the tool. + * + * @throws IllegalStateException if not yet installed or disposed. + */ + public final void reset() { + checkInstalled(); + internalReset(); + } + + /** + * Makes the tool permanently disabled, removes instrumentation, but keeps data already + * collected. + * + * @throws IllegalStateException if not yet installed or disposed. + */ + public final void dispose() { + checkInstalled(); + internalDispose(); + toolState = ToolState.DISPOSED; + } + + /** + * @return whether the installation succeeded. + */ + protected abstract boolean internalInstall(); + + /** + * No subclass action required. + * + * @param isEnabled + */ + protected void internalSetEnabled(boolean isEnabled) { + } + + protected abstract void internalReset(); + + protected abstract void internalDispose(); + + /** + * Ensure that the tool is currently installed. + * + * @throws IllegalStateException + */ + private void checkInstalled() throws IllegalStateException { + if (toolState == ToolState.UNINSTALLED) { + throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed"); + } + if (toolState == ToolState.DISPOSED) { + throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed"); + } + } + + /** + * Ensure that the tool has not yet been installed. + * + * @throws IllegalStateException + */ + private void checkUninstalled() { + if (toolState != ToolState.UNINSTALLED) { + throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed"); + } + } + +} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleTool.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/TruffleTool.java Tue Feb 10 15:10:46 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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.truffle.api.instrument; - -/** - * {@linkplain Instrument Instrumentation}-based tools that gather data during Guest Language - * program execution. - *

- * Tools share a common life cycle: - *

    - *
  • A newly created tool is inert until {@linkplain #install() installed}.
  • - *
  • An installed tool becomes enabled and immediately begins installing - * {@linkplain Instrument instrumentation} on subsequently created ASTs and collecting data from - * those instruments
  • - *
  • A tool may only be installed once.
  • - *
  • It should be possible to install multiple instances of a tool, possibly (but not necessarily) - * configured differently with respect to what data is being collected.
  • - *
  • Once installed, a tool can be {@linkplain #setEnabled(boolean) enabled and disabled} - * arbitrarily.
  • - *
  • A disabled tool: - *
      - *
    • Collects no data;
    • - *
    • Retains existing AST instrumentation;
    • - *
    • Continues to instrument newly created ASTs; and
    • - *
    • Retains previously collected data.
    • - *
    - *
  • - *
  • An installed tool may be {@linkplain #reset() reset} at any time, which leaves the tool - * installed but with all previously collected data removed.
  • - *
  • A {@linkplain #dispose() disposed} tool removes all instrumentation (but not - * {@linkplain Probe probes}) and becomes permanently disabled; previously collected data persists.
  • - *
- *

- * Tool-specific methods that access data collected by the tool should: - *

    - *
  • Return modification-safe representations of the data; and
  • - *
  • Not change the state of the data.
  • - *
- * Note:
- * Tool installation is currently global to the Truffle Execution environment. When - * language-agnostic management of individual execution environments is added to the platform, - * installation will be (optionally) specific to a single execution environment. - */ -public abstract class TruffleTool { - - private enum ToolState { - - /** Not yet installed, inert. */ - UNINSTALLED, - - /** Installed, collecting data. */ - ENABLED, - - /** Installed, not collecting data. */ - DISABLED, - - /** Was installed, but now removed, inactive, and no longer usable. */ - DISPOSED; - } - - private ToolState toolState = ToolState.UNINSTALLED; - - protected TruffleTool() { - } - - /** - * Connect the tool to some part of the Truffle runtime, and enable data collection to start. - * Instrumentation will only be added to subsequently created ASTs. - * - * @throws IllegalStateException if the tool has previously been installed. - */ - public final void install() { - checkUninstalled(); - if (internalInstall()) { - toolState = ToolState.ENABLED; - } - } - - /** - * @return whether the tool is currently collecting data. - */ - public final boolean isEnabled() { - return toolState == ToolState.ENABLED; - } - - /** - * Switches tool state between enabled (collecting data) and disabled (not - * collecting data, but keeping data already collected). - * - * @throws IllegalStateException if not yet installed or disposed. - */ - public final void setEnabled(boolean isEnabled) { - checkInstalled(); - internalSetEnabled(isEnabled); - toolState = isEnabled ? ToolState.ENABLED : ToolState.DISABLED; - } - - /** - * Clears any data already collected, but otherwise does not change the state of the tool. - * - * @throws IllegalStateException if not yet installed or disposed. - */ - public final void reset() { - checkInstalled(); - internalReset(); - } - - /** - * Makes the tool permanently disabled, removes instrumentation, but keeps data already - * collected. - * - * @throws IllegalStateException if not yet installed or disposed. - */ - public final void dispose() { - checkInstalled(); - internalDispose(); - toolState = ToolState.DISPOSED; - } - - /** - * @return whether the installation succeeded. - */ - protected abstract boolean internalInstall(); - - /** - * No subclass action required. - * - * @param isEnabled - */ - protected void internalSetEnabled(boolean isEnabled) { - } - - protected abstract void internalReset(); - - protected abstract void internalDispose(); - - /** - * Ensure that the tool is currently installed. - * - * @throws IllegalStateException - */ - private void checkInstalled() throws IllegalStateException { - if (toolState == ToolState.UNINSTALLED) { - throw new IllegalStateException("Tool " + getClass().getSimpleName() + " not yet installed"); - } - if (toolState == ToolState.DISPOSED) { - throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has been disposed"); - } - } - - /** - * Ensure that the tool has not yet been installed. - * - * @throws IllegalStateException - */ - private void checkUninstalled() { - if (toolState != ToolState.UNINSTALLED) { - throw new IllegalStateException("Tool " + getClass().getSimpleName() + " has already been installed"); - } - } - -} diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/CoverageTracker.java Tue Feb 10 15:10:56 2015 +0100 @@ -38,15 +38,15 @@ import com.oracle.truffle.api.source.*; /** - * A {@link TruffleTool} that counts interpreter execution calls to AST nodes that hold a - * specified {@linkplain SyntaxTag tag}, tabulated by source and line number associated with each - * node. Tags are presumed to be applied external to the tool. If no tag is specified, + * An {@link InstrumentationTool} that counts interpreter execution calls to AST nodes that + * hold a specified {@linkplain SyntaxTag tag}, tabulated by source and line number associated with + * each node. Tags are presumed to be applied external to the tool. If no tag is specified, * {@linkplain StandardSyntaxTag#STATEMENT STATEMENT} is used, corresponding to conventional * behavior for code coverage tools. *

* Tool Life Cycle *

- * See {@link TruffleTool} for the life cycle common to all such tools. + * See {@link InstrumentationTool} for the life cycle common to all such tools. *

* Execution Counts *

@@ -72,7 +72,7 @@ * @see Instrument * @see SyntaxTag */ -public final class CoverageTracker extends TruffleTool { +public final class CoverageTracker extends InstrumentationTool { /** Counting data. */ private final Map counters = new HashMap<>(); diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/LineToProbesMap.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/LineToProbesMap.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/LineToProbesMap.java Tue Feb 10 15:10:56 2015 +0100 @@ -32,10 +32,10 @@ import com.oracle.truffle.api.source.*; /** - * A {@link TruffleTool} that builds a map of every {@Probe} attached to some AST, indexed - * by {@link Source} and line number. + * An {@link InstrumentationTool} that builds a map of every {@Probe} attached to some AST, + * indexed by {@link Source} and line number. */ -public final class LineToProbesMap extends TruffleTool { +public final class LineToProbesMap extends InstrumentationTool { private static final boolean TRACE = false; private static final PrintStream OUT = System.out; diff -r 637ca4d37bca -r afe5d805c88a graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java Tue Feb 10 15:10:46 2015 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/tools/NodeExecCounter.java Tue Feb 10 15:10:56 2015 +0100 @@ -36,13 +36,14 @@ import com.oracle.truffle.api.nodes.Node.Child; /** - * A {@link TruffleTool} that counts interpreter execution calls to AST nodes, tabulated by - * the type of called nodes; counting can be enabled all nodes or restricted to nodes with - * a specified {@linkplain SyntaxTag tag} that is presumed to be applied external to the tool. + * An {@link InstrumentationTool} that counts interpreter execution calls to AST nodes, + * tabulated by the type of called nodes; counting can be enabled all nodes or restricted + * to nodes with a specified {@linkplain SyntaxTag tag} that is presumed to be applied external to + * the tool. *

* Tool Life Cycle *

- * See {@link TruffleTool} for the life cycle common to all such tools. + * See {@link InstrumentationTool} for the life cycle common to all such tools. *

* Execution Counts *

@@ -79,7 +80,7 @@ * @see SyntaxTag * @see ProbeFailure */ -public final class NodeExecCounter extends TruffleTool { +public final class NodeExecCounter extends InstrumentationTool { /** * Execution count for AST nodes of a particular type. diff -r 637ca4d37bca -r afe5d805c88a mx/mx_graal.py --- a/mx/mx_graal.py Tue Feb 10 15:10:46 2015 +0100 +++ b/mx/mx_graal.py Tue Feb 10 15:10:56 2015 +0100 @@ -2280,7 +2280,7 @@ complt += '\t(args)\n' # TODO: improve matcher: if mx args are given, this doesn't work complt += '\t\tcase $line[1] in\n' - complt += '\t\t\t(vm)\n' + complt += '\t\t\t(vm | vmg | vmfg | unittest | jmh | dacapo | scaladacapo | specjvm2008 | specjbb2013 | specjbb2005)\n' complt += '\t\t\t\tnoglob \\\n' complt += '\t\t\t\t\t_arguments -s -S \\\n' complt += _appendOptions("graal", r"G\:") @@ -2347,7 +2347,7 @@ # gather graal options output = StringIO.StringIO() - vm(['-XX:-BootstrapGraal', '-G:+PrintFlags' if optionType == "graal" else '-XX:+PrintFlagsWithComments'], + vm(['-XX:-BootstrapGraal', '-XX:+UnlockDiagnosticVMOptions', '-G:+PrintFlags' if optionType == "graal" else '-XX:+PrintFlagsWithComments'], vm="graal", vmbuild="optimized", nonZeroIsFatal=False, diff -r 637ca4d37bca -r afe5d805c88a src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Tue Feb 10 15:10:46 2015 +0100 +++ b/src/share/vm/runtime/arguments.cpp Tue Feb 10 15:10:56 2015 +0100 @@ -3585,6 +3585,12 @@ if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) { IgnoreUnrecognizedVMOptions = false; } + if (match_option(option, "-XX:+UnlockDiagnosticVMOptions", &tail)) { + UnlockDiagnosticVMOptions = true; + } + if (match_option(option, "-XX:-UnlockDiagnosticVMOptions", &tail)) { + UnlockDiagnosticVMOptions = false; + } if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) { CommandLineFlags::printFlags(tty, false); vm_exit(0); diff -r 637ca4d37bca -r afe5d805c88a test/blacklist_sparc.txt --- a/test/blacklist_sparc.txt Tue Feb 10 15:10:46 2015 +0100 +++ b/test/blacklist_sparc.txt Tue Feb 10 15:10:56 2015 +0100 @@ -1,4 +1,2 @@ com.oracle.graal.replacements.test.StandardMethodSubstitutionsTest com.oracle.graal.hotspot.amd64.test.CompressedNullCheckTest -com.oracle.graal.hotspot.test.HotSpotCryptoSubstitutionTest -