# HG changeset patch # User Christian Humer # Date 1382346467 -7200 # Node ID e47f373499ec00e4efa4673c687aefde51c42744 # Parent 935dcd8ad8eb2242bbccccc744b6abe426fe66d1# Parent b7c8b843dc7b44ada5ea80bbe873190c0dcbb464 Merge. diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/NameAndSignature.java Mon Oct 21 11:07:47 2013 +0200 @@ -27,10 +27,11 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.runtime.*; class NameAndSignature { - public static final MetaAccessProvider runtime = Graal.getRequiredCapability(MetaAccessProvider.class); + public static final MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); final String name; final Class returnType; @@ -71,14 +72,14 @@ public boolean signatureEquals(ResolvedJavaMethod m) { Signature s = m.getSignature(); ResolvedJavaType declaringClass = m.getDeclaringClass(); - if (!s.getReturnType(declaringClass).resolve(declaringClass).equals(runtime.lookupJavaType(returnType))) { + if (!s.getReturnType(declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(returnType))) { return false; } if (s.getParameterCount(false) != parameterTypes.length) { return false; } for (int i = 0; i < parameterTypes.length; i++) { - if (!s.getParameterType(i, declaringClass).resolve(declaringClass).equals(runtime.lookupJavaType(parameterTypes[i]))) { + if (!s.getParameterType(i, declaringClass).resolve(declaringClass).equals(metaAccess.lookupJavaType(parameterTypes[i]))) { return false; } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -25,7 +25,7 @@ import org.junit.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; +import com.oracle.graal.java.*; /** * Tests for {@link BytecodeDisassemblerProvider}. @@ -40,7 +40,7 @@ */ @Test public void disassembleTest() { - BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class); + BytecodeDisassemblerProvider dis = new BytecodeDisassembler(); if (dis != null) { int count = 0; for (ResolvedJavaMethod m : methods.values()) { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java --- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TypeUniverse.java Mon Oct 21 11:07:47 2013 +0200 @@ -33,6 +33,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; /** * Context for type related api.meta tests. @@ -40,13 +42,17 @@ public class TypeUniverse { public final Unsafe unsafe; - public final MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); - public final ConstantReflectionProvider constantReflection = Graal.getRequiredCapability(ConstantReflectionProvider.class); + + public final MetaAccessProvider metaAccess; + public final ConstantReflectionProvider constantReflection; public final Collection> classes = new HashSet<>(); public final Map, Class> arrayClasses = new HashMap<>(); public final List constants = new ArrayList<>(); public TypeUniverse() { + Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); + metaAccess = providers.getMetaAccess(); + constantReflection = providers.getConstantReflection(); Unsafe theUnsafe = null; try { theUnsafe = Unsafe.getUnsafe(); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -73,4 +73,8 @@ * @return the encoded value as an integer */ Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason); + + DeoptimizationReason decodeDeoptReason(Constant constant); + + DeoptimizationAction decodeDeoptAction(Constant constant); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/Graal.java diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.api.runtime/src/com/oracle/graal/api/runtime/GraalRuntime.java diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,12 +22,12 @@ */ package com.oracle.graal.asm.sparc; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.sparc.SPARC.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.sparc.*; /** @@ -1269,7 +1269,7 @@ Icc(0b00, "icc"), Xcc(0b10, "xcc"), - Ptrcc(HotSpotGraalRuntime.wordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"), + Ptrcc(getHostWordKind() == Kind.Long ? Xcc.getValue() : Icc.getValue(), "ptrcc"), Fcc0(0b00, "fcc0"), Fcc1(0b01, "fcc1"), Fcc2(0b10, "fcc2"), diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -30,6 +30,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.asm.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.test.*; public abstract class AssemblerTest extends GraalTest { @@ -43,8 +45,9 @@ } public AssemblerTest() { - this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); - this.codeCache = Graal.getRequiredCapability(CodeCacheProvider.class); + Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); + this.metaAccess = providers.getMetaAccess(); + this.codeCache = providers.getCodeCache(); } public MetaAccessProvider getMetaAccess() { @@ -62,7 +65,7 @@ InstalledCode code = codeCache.addMethod(method, compResult); - DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class); + DisassemblerProvider dis = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getDisassembler(); if (dis != null) { String disasm = dis.disassemble(code); Assert.assertTrue(code.toString(), disasm == null || disasm.length() > 0); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java --- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/Buffer.java Mon Oct 21 11:07:47 2013 +0200 @@ -60,6 +60,9 @@ } public byte[] copyData(int start, int end) { + if (data == null) { + return null; + } return Arrays.copyOfRange(data, start, end); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/BasicHSAILTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -24,15 +24,20 @@ import org.junit.*; -import com.oracle.graal.compiler.test.GraalCompilerTest; +import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.hsail.*; -import com.oracle.graal.nodes.StructuredGraph; +import com.oracle.graal.hsail.*; +import com.oracle.graal.nodes.*; /** * Test class for small Java methods compiled to HSAIL kernels. */ public class BasicHSAILTest extends GraalCompilerTest { + public BasicHSAILTest() { + super(HSAIL.class); + } + public void testAdd() { test("testAddSnippet"); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -24,8 +24,12 @@ package com.oracle.graal.compiler.hsail.test; import java.util.*; + import org.junit.*; -import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +import com.oracle.graal.compiler.hsail.*; +import com.oracle.graal.compiler.hsail.test.infra.*; +import com.oracle.graal.graph.*; /** * Tests floating point square root. @@ -54,7 +58,10 @@ dispatchMethodKernel(64, input, output); } - @Test + /** + * Requires {@link HSAILLIRGenerator#emitDirectCall} to be implemented. + */ + @Test(expected = GraalInternalError.class) public void test() { testGeneratedHsail(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodySpillTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodySpillTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodySpillTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -27,7 +27,9 @@ import org.junit.*; -import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.compiler.hsail.*; +import com.oracle.graal.compiler.hsail.test.infra.*; +import com.oracle.graal.graph.*; /** * This version of NBody causes Graal to generate register spilling code. @@ -96,9 +98,11 @@ } // Marked to only run on hardware until simulator spill bug is fixed. - @Test + /** + * Requires {@link HSAILLIRGenerator#emitDirectCall} to be implemented. + */ + @Test(expected = GraalInternalError.class) public void test() { testGeneratedHsail(); } - } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticNBodyTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -26,7 +26,10 @@ import java.util.*; import org.junit.*; -import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; + +import com.oracle.graal.compiler.hsail.*; +import com.oracle.graal.compiler.hsail.test.infra.*; +import com.oracle.graal.graph.*; /** * Unit test of NBody demo app. @@ -94,7 +97,10 @@ dispatchMethodKernel(bodies, inxyz, outxyz, invxyz, outvxyz); } - @Test + /** + * Requires {@link HSAILLIRGenerator#emitDirectCall} to be implemented. + */ + @Test(expected = GraalInternalError.class) public void test() { testGeneratedHsail(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringContainsTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -24,6 +24,9 @@ package com.oracle.graal.compiler.hsail.test; import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.hsail.*; + import org.junit.Test; /** @@ -56,7 +59,10 @@ dispatchMethodKernel(NUM, base); } - @Test + /** + * Requires {@link HSAILHotSpotForeignCallsProvider#lookupForeignCall} to be implemented. + */ + @Test(expected = GraalInternalError.class) public void test() { testGeneratedHsail(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringIndexOfTest.java --- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringIndexOfTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StringIndexOfTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -24,6 +24,9 @@ package com.oracle.graal.compiler.hsail.test; import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.hsail.*; + import org.junit.Test; /** @@ -56,7 +59,10 @@ dispatchMethodKernel(NUM, base); } - @Test + /** + * Requires {@link HSAILHotSpotForeignCallsProvider#lookupForeignCall} to be implemented. + */ + @Test(expected = GraalInternalError.class) public void test() { testGeneratedHsail(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java Mon Oct 21 11:07:47 2013 +0200 @@ -164,7 +164,7 @@ @Override public Variable emitAddress(StackSlot address) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -212,12 +212,12 @@ @Override public void emitOverflowCheckBranch(LabelRef label, boolean negated) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -243,7 +243,7 @@ @Override public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -435,12 +435,12 @@ @Override public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -461,12 +461,12 @@ @Override public Variable emitOr(Value a, Value b) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public Variable emitXor(Value a, Value b) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -487,7 +487,7 @@ @Override public Variable emitShr(Value a, Value b) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -545,17 +545,17 @@ @Override public void emitMembar(int barriers) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -571,11 +571,11 @@ append(new ForeignCall1ArgOp(callName, result, arguments[0])); break; default: - throw new InternalError("NYI emitForeignCall"); + throw GraalInternalError.unimplemented(); } } else { - throw new InternalError("NYI emitForeignCall"); + throw GraalInternalError.unimplemented(); } } @@ -590,17 +590,17 @@ @Override public void emitBitScanForward(Variable result, Value value) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public void emitBitScanReverse(Variable result, Value value) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public Value emitMathAbs(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -612,27 +612,27 @@ @Override public Value emitMathLog(Value input, boolean base10) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public Value emitMathCos(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public Value emitMathSin(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public Value emitMathTan(Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public void emitByteSwap(Variable result, Value input) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -642,27 +642,27 @@ @Override protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override public void visitBreakpointNode(BreakpointNode node) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -672,7 +672,7 @@ @Override public void emitUnwind(Value operand) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } @Override @@ -685,6 +685,6 @@ @Override public void visitInfopointNode(InfopointNode i) { - throw new InternalError("NYI"); + throw GraalInternalError.unimplemented(); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java --- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java Mon Oct 21 11:07:47 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.ptx.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.hotspot.meta.*; @@ -54,13 +55,17 @@ } + public PTXTestBase() { + super(PTX.class); + } + protected CompilationResult compile(String test) { - if (getCodeCache() instanceof PTXHotSpotCodeCacheProvider) { + if (getBackend() instanceof PTXHotSpotBackend) { StructuredGraph graph = parse(test); sg = graph; Debug.dump(graph, "Graph"); - TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true); - PTXBackend ptxBackend = new PTXBackend(getProviders()); + Backend ptxBackend = getBackend(); + TargetDescription target = ptxBackend.getTarget(); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); @@ -76,8 +81,9 @@ * Ultimately we might want to have both the kernel and the code natively compiled for * GPU fallback to CPU in cases of ECC failure on kernel invocation. */ + Suites suites = Suites.createDefaultSuites(); CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), ptxBackend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), - Suites.createDefaultSuites(), new ExternalCompilationResult()); + suites, new ExternalCompilationResult()); return result; } else { return null; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.compiler.ptx; - -import static com.oracle.graal.lir.LIRValueUtil.*; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.ptx.*; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.OperandFlag; -import com.oracle.graal.lir.LIRInstruction.OperandMode; -import com.oracle.graal.lir.LIRInstruction.ValueProcedure; -import com.oracle.graal.lir.StandardOp.LabelOp; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.lir.ptx.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.cfg.*; -import com.oracle.graal.phases.util.*; - -/** - * PTX specific backend. - */ -public class PTXBackend extends Backend { - - public PTXBackend(Providers providers) { - super(providers); - } - - @Override - public boolean shouldAllocateRegisters() { - return false; - } - - @Override - public FrameMap newFrameMap() { - return new PTXFrameMap(getCodeCache()); - } - - @Override - public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) { - return new PTXLIRGenerator(graph, getProviders(), frameMap, cc, lir); - } - - class PTXFrameContext implements FrameContext { - - @Override - public void enter(TargetMethodAssembler tasm) { - // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3 - } - - @Override - public void leave(TargetMethodAssembler tasm) { - } - } - - @Override - protected AbstractAssembler createAssembler(FrameMap frameMap) { - return new PTXAssembler(getTarget(), frameMap.registerConfig); - } - - @Override - public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { - // Omit the frame of the method: - // - has no spill slots or other slots allocated during register allocation - // - has no callee-saved registers - // - has no incoming arguments passed on the stack - // - has no instructions with debug info - FrameMap frameMap = lirGen.frameMap; - AbstractAssembler masm = createAssembler(frameMap); - PTXFrameContext frameContext = new PTXFrameContext(); - TargetMethodAssembler tasm = new PTXTargetMethodAssembler(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); - tasm.setFrameSize(0); - return tasm; - } - - private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { - // Emit PTX kernel entry text based on PTXParameterOp - // instructions in the start block. Remove the instructions - // once kernel entry text and directives are emitted to - // facilitate seemless PTX code generation subsequently. - assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; - final String name = codeCacheOwner.getName(); - Buffer codeBuffer = tasm.asm.codeBuffer; - - // Emit initial boiler-plate directives. - codeBuffer.emitString(".version 3.0"); - codeBuffer.emitString(".target sm_30"); - codeBuffer.emitString0(".entry " + name + " ("); - codeBuffer.emitString(""); - - // Get the start block - Block startBlock = lirGen.lir.cfg.getStartBlock(); - // Keep a list of ParameterOp instructions to delete from the - // list of instructions in the block. - ArrayList deleteOps = new ArrayList<>(); - - // Emit .param arguments to kernel entry based on ParameterOp - // instruction. - for (LIRInstruction op : lirGen.lir.lir(startBlock)) { - if (op instanceof PTXParameterOp) { - op.emitCode(tasm); - deleteOps.add(op); - } - } - - // Delete ParameterOp instructions. - for (LIRInstruction op : deleteOps) { - lirGen.lir.lir(startBlock).remove(op); - } - - // Start emiting body of the PTX kernel. - codeBuffer.emitString0(") {"); - codeBuffer.emitString(""); - } - - // Emit .reg space declarations - private static void emitRegisterDecl(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { - - assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; - - Buffer codeBuffer = tasm.asm.codeBuffer; - - final SortedSet signed32 = new TreeSet<>(); - final SortedSet signed64 = new TreeSet<>(); - final SortedSet unsigned64 = new TreeSet<>(); - final SortedSet float32 = new TreeSet<>(); - final SortedSet float64 = new TreeSet<>(); - - ValueProcedure trackRegisterKind = new ValueProcedure() { - - @Override - public Value doValue(Value value, OperandMode mode, EnumSet flags) { - if (isVariable(value)) { - Variable regVal = (Variable) value; - Kind regKind = regVal.getKind(); - switch (regKind) { - case Int: - // If the register was used as a wider signed type - // do not add it here - if (!signed64.contains(regVal.index)) { - signed32.add(regVal.index); - } - break; - case Long: - // If the register was used as a narrower signed type - // remove it from there and add it to wider type. - if (signed32.contains(regVal.index)) { - signed32.remove(regVal.index); - } - signed64.add(regVal.index); - break; - case Float: - // If the register was used as a wider signed type - // do not add it here - if (!float64.contains(regVal.index)) { - float32.add(regVal.index); - } - break; - case Double: - // If the register was used as a narrower signed type - // remove it from there and add it to wider type. - if (float32.contains(regVal.index)) { - float32.remove(regVal.index); - } - float64.add(regVal.index); - break; - case Object: - unsigned64.add(regVal.index); - break; - default: - throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString()); - } - } - return value; - } - }; - - for (Block b : lirGen.lir.codeEmittingOrder()) { - for (LIRInstruction op : lirGen.lir.lir(b)) { - if (op instanceof LabelOp) { - // Don't consider this as a definition - } else { - op.forEachTemp(trackRegisterKind); - op.forEachOutput(trackRegisterKind); - } - } - } - - for (Integer i : signed32) { - codeBuffer.emitString(".reg .s32 %r" + i.intValue() + ";"); - } - for (Integer i : signed64) { - codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";"); - } - for (Integer i : unsigned64) { - codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";"); - } - for (Integer i : float32) { - codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";"); - } - for (Integer i : float64) { - codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";"); - } - // emit predicate register declaration - int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber(); - if (maxPredRegNum > 0) { - codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); - } - codeBuffer.emitString(".reg .pred %r;"); // used for setp bool - } - - @Override - public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { - assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; - Buffer codeBuffer = tasm.asm.codeBuffer; - // Emit the prologue - emitKernelEntry(tasm, lirGen, codeCacheOwner); - - // Emit register declarations - try { - emitRegisterDecl(tasm, lirGen, codeCacheOwner); - } catch (GraalInternalError e) { - e.printStackTrace(); - // TODO : Better error handling needs to be done once - // all types of parameters are handled. - codeBuffer.setPosition(0); - codeBuffer.close(false); - return; - } - // Emit code for the LIR - try { - lirGen.lir.emitCode(tasm); - } catch (GraalInternalError e) { - e.printStackTrace(); - // TODO : Better error handling needs to be done once - // all types of parameters are handled. - codeBuffer.setPosition(0); - codeBuffer.close(false); - return; - } - - // Emit the epilogue - codeBuffer.emitString0("}"); - codeBuffer.emitString(""); - } -} diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -54,6 +54,7 @@ import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.printer.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.test.*; /** @@ -78,13 +79,32 @@ public abstract class GraalCompilerTest extends GraalTest { private final Providers providers; - protected final Backend backend; - protected final Suites suites; + private final Backend backend; + private final Suites suites; public GraalCompilerTest() { - this.providers = GraalCompiler.getGraalProviders(); - this.backend = Graal.getRequiredCapability(Backend.class); - this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); + this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); + this.providers = getBackend().getProviders(); + this.suites = backend.getSuites().createSuites(); + } + + /** + * Set up a test for a non-default backend. The test should check (via {@link #getBackend()} ) + * whether the desired backend is available. + * + * @param arch the name of the desired backend architecture + */ + public GraalCompilerTest(Class arch) { + RuntimeProvider runtime = Graal.getRequiredCapability(RuntimeProvider.class); + Backend b = runtime.getBackend(arch); + if (b != null) { + this.backend = b; + } else { + // Fall back to the default/host backend + this.backend = runtime.getHostBackend(); + } + this.providers = backend.getProviders(); + this.suites = backend.getSuites().createSuites(); } @BeforeClass @@ -157,6 +177,14 @@ return result.toString(); } + protected Backend getBackend() { + return backend; + } + + protected Suites getSuites() { + return suites; + } + protected Providers getProviders() { return providers; } @@ -487,8 +515,8 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), backend, getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, - new SpeculationLog(), suites, new CompilationResult()); + final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, phasePlan, + OptimisticOptimizations.ALL, new SpeculationLog(), getSuites(), new CompilationResult()); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } @@ -504,7 +532,7 @@ Debug.dump(new Object[]{compResult, code}, "After code installation"); } if (Debug.isLogEnabled()) { - DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class); + DisassemblerProvider dis = backend.getDisassembler(); if (dis != null) { String text = dis.disassemble(code); if (text != null) { diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -59,8 +59,8 @@ final Method method = getMethod("testMethod"); final StructuredGraph graph = parse(method); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), backend, getCodeCache().getTarget(), null, getDefaultPhasePlan(), - OptimisticOptimizations.ALL, new SpeculationLog(), suites, new CompilationResult()); + final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultPhasePlan(), + OptimisticOptimizations.ALL, new SpeculationLog(), getSuites(), new CompilationResult()); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -81,8 +81,8 @@ } assertTrue(graphLineSPs > 0); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), backend, getCodeCache().getTarget(), null, getDefaultPhasePlan(true), - OptimisticOptimizations.ALL, new SpeculationLog(), suites, new CompilationResult()); + final CompilationResult cr = GraalCompiler.compileGraph(graph, cc, graph.method(), getProviders(), getBackend(), getCodeCache().getTarget(), null, getDefaultPhasePlan(true), + OptimisticOptimizations.ALL, new SpeculationLog(), getSuites(), new CompilationResult()); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -86,7 +86,7 @@ PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); new FloatingReadPhase().apply(graph); - new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph); + new OptimizeGuardAnchors().apply(graph); new ReadEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -119,7 +119,7 @@ @Override public LIR call() { - return GraalCompiler.emitHIR(getProviders(), backend.getTarget(), graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), suites); + return GraalCompiler.emitHIR(getProviders(), getBackend().getTarget(), graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), getSuites()); } }); @@ -128,7 +128,7 @@ @Override public RegisterStats call() { CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - GraalCompiler.emitLIR(backend, backend.getTarget(), lir, graph, cc); + GraalCompiler.emitLIR(getBackend(), getBackend().getTarget(), lir, graph, cc); return new RegisterStats(lir); } }); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.test.ea; -import java.util.concurrent.*; - import org.junit.*; import com.oracle.graal.api.code.*; @@ -32,12 +30,14 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.java.*; +import com.oracle.graal.loop.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; +import com.oracle.graal.phases.schedule.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.virtual.phases.ea.*; @@ -223,31 +223,97 @@ testEscapeAnalysis("testNewNodeSnippet", null, false); } - private ReturnNode testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) { - ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet)); - final StructuredGraph graph = new StructuredGraph(method); + private static final TestObject2 staticObj = new TestObject2(null); + + public static Object testFullyUnrolledLoopSnippet() { + /* + * This tests a case that can appear if PEA is performed both before and after loop + * unrolling/peeling: If the VirtualInstanceNode is not anchored correctly to stay within + * the loop, it will not be duplicated, and therefore the resulting object will reference + * itself, and not a second (different) object. + */ + TestObject2 obj = staticObj; + for (int i = 0; i < 2; i++) { + obj = new TestObject2(obj); + } + return obj.o; + } - return Debug.scope("GraalCompiler", new Object[]{graph, method, getCodeCache()}, new Callable() { + @Test + public void testFullyUnrolledLoop() { + testEscapeAnalysisUnrolled("testFullyUnrolledLoopSnippet"); + } + + private static Object staticField; + + private static TestObject2 inlinedPart(TestObject2 obj) { + TestObject2 ret = new TestObject2(obj); + staticField = null; + return ret; + } + + public static Object testPeeledLoopSnippet() { + TestObject2 obj = staticObj; + int i = 0; + do { + obj = inlinedPart(obj); + } while (i++ < 10); + staticField = obj; + return obj.o; + } - public ReturnNode call() { - new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); + @Test + public void testPeeledLoop() { + testEscapeAnalysisPeeled("testPeeledLoopSnippet"); + } + + private StructuredGraph graph; + private HighTierContext context; + private ReturnNode returnNode; + + private void testEscapeAnalysis(String snippet, final Constant expectedConstantResult, final boolean iterativeEscapeAnalysis) { + prepareGraph(snippet, iterativeEscapeAnalysis); + if (expectedConstantResult != null) { + Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); + Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); + } + int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() + + graph.getNodes().filter(CommitAllocationNode.class).count(); + Assert.assertEquals(0, newInstanceCount); + } + private void testEscapeAnalysisUnrolled(String snippet) { + prepareGraph(snippet, false); + new LoopFullUnrollPhase(new CanonicalizerPhase(true)).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context); + Assert.assertTrue(returnNode.result() instanceof AllocatedObjectNode); + CommitAllocationNode commit = ((AllocatedObjectNode) returnNode.result()).getCommit(); + Assert.assertEquals(1, commit.getValues().size()); + Assert.assertEquals(1, commit.getVirtualObjects().size()); + Assert.assertTrue("non-cyclic data structure expected", commit.getVirtualObjects().get(0) != commit.getValues().get(0)); + } + + private void testEscapeAnalysisPeeled(String snippet) { + prepareGraph(snippet, false); + new LoopTransformHighPhase().apply(graph); + new LoopTransformLowPhase().apply(graph); + new SchedulePhase().apply(graph); + } + + private void prepareGraph(String snippet, final boolean iterativeEscapeAnalysis) { + graph = new StructuredGraph(getMetaAccess().lookupJavaMethod(getMethod(snippet))); + Debug.scope("GraalCompiler", new Object[]{graph, getMetaAccess().lookupJavaMethod(getMethod(snippet)), getCodeCache()}, new Runnable() { + + public void run() { + new GraphBuilderPhase(getMetaAccess(), getForeignCalls(), GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); Assumptions assumptions = new Assumptions(false); - HighTierContext context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); + context = new HighTierContext(getProviders(), assumptions, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase(true).apply(graph, context); new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context); Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count()); - ReturnNode returnNode = graph.getNodes().filter(ReturnNode.class).first(); - if (expectedConstantResult != null) { - Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); - Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); - } - int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() + - graph.getNodes().filter(CommitAllocationNode.class).count(); - Assert.assertEquals(0, newInstanceCount); - return returnNode; + returnNode = graph.getNodes().filter(ReturnNode.class).first(); } }); } diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Oct 21 11:07:47 2013 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.alloc.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.alloc.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -133,9 +132,9 @@ * argument can be null. * @return the result of the compilation */ - public static CompilationResult compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final Providers providers, + public static T compileGraph(final StructuredGraph graph, final CallingConvention cc, final ResolvedJavaMethod installedCodeOwner, final Providers providers, final Backend backend, final TargetDescription target, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts, - final SpeculationLog speculationLog, final Suites suites, final CompilationResult compilationResult) { + final SpeculationLog speculationLog, final Suites suites, final T compilationResult) { Debug.scope("GraalCompiler", new Object[]{graph, providers.getCodeCache()}, new Runnable() { public void run() { @@ -284,19 +283,10 @@ } result.setLeafGraphIds(leafGraphIds); + if (Debug.isLogEnabled()) { + Debug.log("%s", backend.getProviders().getCodeCache().disassemble(result, null)); + } + Debug.dump(result, "After code generation"); } - - /** - * Creates a set of providers via {@link Graal#getRequiredCapability(Class)}. - */ - public static Providers getGraalProviders() { - MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); - CodeCacheProvider codeCache = Graal.getRequiredCapability(CodeCacheProvider.class); - ConstantReflectionProvider constantReflection = Graal.getRequiredCapability(ConstantReflectionProvider.class); - ForeignCallsProvider foreignCalls = Graal.getRequiredCapability(ForeignCallsProvider.class); - LoweringProvider lowerer = Graal.getRequiredCapability(LoweringProvider.class); - Replacements replacements = Graal.getRequiredCapability(Replacements.class); - return new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements); - } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Mon Oct 21 11:07:47 2013 +0200 @@ -64,7 +64,7 @@ } if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new EliminatePartiallyRedundantGuardsPhase(false, true)); + appendPhase(new OptimizeGuardAnchors()); } if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) { @@ -72,7 +72,7 @@ } if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new EliminatePartiallyRedundantGuardsPhase(true, true)); + appendPhase(new OptimizeGuardAnchors()); } if (OptCanonicalizer.getValue()) { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Oct 21 11:07:47 2013 +0200 @@ -29,10 +29,11 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; /** - * The {@code Backend} class represents a compiler backend for Graal. + * Represents a compiler backend for Graal. */ public abstract class Backend { @@ -54,6 +55,10 @@ return providers.getForeignCalls(); } + public abstract SuitesProvider getSuites(); + + public abstract DisassemblerProvider getDisassembler(); + public TargetDescription getTarget() { return providers.getCodeCache().getTarget(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Mon Oct 21 11:07:47 2013 +0200 @@ -125,7 +125,8 @@ return registry.make(key); } - static final int NOT_ITERABLE = -1; + public static final int NOT_ITERABLE = -1; + public static final int NODE_LIST = -2; private static final Class NODE_CLASS = Node.class; private static final Class INPUT_LIST_CLASS = NodeInputList.class; @@ -817,6 +818,12 @@ } } + public NodeList getNodeList(Node node, Position pos) { + long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]; + assert pos.subIndex == NODE_LIST; + return getNodeList(node, offset); + } + public String getName(Position pos) { return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]); } @@ -1175,20 +1182,64 @@ return false; } - public List getFirstLevelInputPositions() { - List positions = new ArrayList<>(inputOffsets.length); - for (int i = 0; i < inputOffsets.length; i++) { - positions.add(new Position(true, i, NOT_ITERABLE)); - } - return positions; + public Collection getFirstLevelInputPositions() { + return new AbstractCollection() { + @Override + public Iterator iterator() { + return new Iterator() { + int i = 0; + + public void remove() { + throw new UnsupportedOperationException(); + } + + public Position next() { + Position pos = new Position(true, i, i >= directInputCount ? 0 : NOT_ITERABLE); + i++; + return pos; + } + + public boolean hasNext() { + return i < inputOffsets.length; + } + }; + } + + @Override + public int size() { + return inputOffsets.length; + } + }; } - public List getFirstLevelSuccessorPositions() { - List positions = new ArrayList<>(successorOffsets.length); - for (int i = 0; i < successorOffsets.length; i++) { - positions.add(new Position(false, i, NOT_ITERABLE)); - } - return positions; + public Collection getFirstLevelSuccessorPositions() { + return new AbstractCollection() { + @Override + public Iterator iterator() { + return new Iterator() { + int i = 0; + + public void remove() { + throw new UnsupportedOperationException(); + } + + public Position next() { + Position pos = new Position(false, i, i >= directSuccessorCount ? 0 : NOT_ITERABLE); + i++; + return pos; + } + + public boolean hasNext() { + return i < successorOffsets.length; + } + }; + } + + @Override + public int size() { + return successorOffsets.length; + } + }; } public Class getJavaClass() { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import java.util.*; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.util.*; + +@ServiceProvider(HotSpotBackendFactory.class) +public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { + + protected Architecture createArchitecture(HotSpotVMConfig config) { + return new AMD64(config.useSSE, config.useAVX); + } + + protected TargetDescription createTarget(HotSpotVMConfig config) { + final int stackFrameAlignment = 16; + final int implicitNullCheckLimit = 4096; + final boolean inlineObjects = true; + return new TargetDescription(createArchitecture(config), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + } + + @Override + public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) { + assert host == null; + TargetDescription target = createTarget(runtime.getConfig()); + + HotSpotMetaAccessProvider metaAccess = createMetaAccess(runtime); + HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target); + HotSpotConstantReflectionProvider constantReflection = createConstantReflection(runtime); + Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); + HotSpotForeignCallsProvider foreignCalls = createForeignCalls(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); + HotSpotLoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls); + // Replacements cannot have speculative optimizations since they have + // to be valid for the entire run of the VM. + Assumptions assumptions = new Assumptions(false); + Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); + Replacements replacements = createReplacements(runtime, assumptions, p); + HotSpotDisassemblerProvider disassembler = createDisassembler(runtime); + HotSpotSuitesProvider suites = createSuites(runtime); + HotSpotRegisters registers = createRegisters(); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); + + return createBackend(runtime, providers); + } + + protected AMD64HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) { + return new AMD64HotSpotBackend(runtime, providers); + } + + protected HotSpotRegisters createRegisters() { + return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp); + } + + protected HotSpotDisassemblerProvider createDisassembler(HotSpotGraalRuntime runtime) { + return new HotSpotDisassemblerProvider(runtime); + } + + protected Replacements createReplacements(HotSpotGraalRuntime runtime, Assumptions assumptions, Providers p) { + return new HotSpotReplacementsImpl(p, runtime.getConfig(), assumptions); + } + + protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, + Value[] nativeABICallerSaveRegisters) { + return new AMD64HotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); + } + + protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotGraalRuntime runtime) { + return new HotSpotConstantReflectionProvider(runtime); + } + + protected AMD64HotSpotCodeCacheProvider createCodeCache(HotSpotGraalRuntime runtime, TargetDescription target) { + return new AMD64HotSpotCodeCacheProvider(runtime, target); + } + + protected HotSpotMetaAccessProvider createMetaAccess(HotSpotGraalRuntime runtime) { + return new HotSpotMetaAccessProvider(runtime); + } + + protected HotSpotSuitesProvider createSuites(HotSpotGraalRuntime runtime) { + return new HotSpotSuitesProvider(runtime); + } + + protected AMD64HotSpotLoweringProvider createLowerer(HotSpotGraalRuntime runtime, HotSpotMetaAccessProvider metaAccess, HotSpotForeignCallsProvider foreignCalls) { + return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls); + } + + protected Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) { + List callerSave = new ArrayList<>(Arrays.asList(regConfig.getAllocatableRegisters())); + if (config.windowsOs) { + // http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx + callerSave.remove(AMD64.rdi); + callerSave.remove(AMD64.rsi); + callerSave.remove(AMD64.rbx); + callerSave.remove(AMD64.rbp); + callerSave.remove(AMD64.rsp); + callerSave.remove(AMD64.r12); + callerSave.remove(AMD64.r13); + callerSave.remove(AMD64.r14); + callerSave.remove(AMD64.r15); + callerSave.remove(AMD64.xmm6); + callerSave.remove(AMD64.xmm7); + callerSave.remove(AMD64.xmm8); + callerSave.remove(AMD64.xmm9); + callerSave.remove(AMD64.xmm10); + callerSave.remove(AMD64.xmm11); + callerSave.remove(AMD64.xmm12); + callerSave.remove(AMD64.xmm13); + callerSave.remove(AMD64.xmm14); + callerSave.remove(AMD64.xmm15); + } else { + /* + * System V Application Binary Interface, AMD64 Architecture Processor Supplement + * + * Draft Version 0.96 + * + * http://www.uclibc.org/docs/psABI-x86_64.pdf + * + * 3.2.1 + * + * ... + * + * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 + * through %r15 "belong" to the calling function and the called function is required to + * preserve their values. In other words, a called function must preserve these + * registers' values for its caller. Remaining registers "belong" to the called + * function. If a calling function wants to preserve such a register value across a + * function call, it must save the value in its local stack frame. + */ + callerSave.remove(AMD64.rbp); + callerSave.remove(AMD64.rbx); + callerSave.remove(AMD64.r12); + callerSave.remove(AMD64.r13); + callerSave.remove(AMD64.r14); + callerSave.remove(AMD64.r15); + } + Value[] nativeABICallerSaveRegisters = new Value[callerSave.size()]; + for (int i = 0; i < callerSave.size(); i++) { + nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue(); + } + return nativeABICallerSaveRegisters; + } + + public String getArchitecture() { + return "AMD64"; + } + + public String getGraalRuntimeName() { + return "basic"; + } + + @Override + public String toString() { + return getGraalRuntimeName() + ":" + getArchitecture(); + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,11 +22,8 @@ */ package com.oracle.graal.hotspot.amd64; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -34,13 +31,20 @@ @Opcode("CRUNTIME_CALL_EPILOGUE") final class AMD64HotSpotCRuntimeCallEpilogueOp extends AMD64LIRInstruction { + private final int threadLastJavaSpOffset; + private final int threadLastJavaFpOffset; + private final Register thread; + + public AMD64HotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaFpOffset, Register thread) { + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaFpOffset = threadLastJavaFpOffset; + this.thread = thread; + } + @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { // reset last Java frame: - HotSpotVMConfig config = runtime().getConfig(); - Register thread = runtime().getProviders().getRegisters().getThreadRegister(); - - masm.movslq(new AMD64Address(thread, config.threadLastJavaSpOffset), 0); - masm.movslq(new AMD64Address(thread, config.threadLastJavaFpOffset), 0); + masm.movslq(new AMD64Address(thread, threadLastJavaSpOffset), 0); + masm.movslq(new AMD64Address(thread, threadLastJavaFpOffset), 0); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.amd64.AMD64.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; @@ -34,11 +33,17 @@ @Opcode final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction { + private final int threadLastJavaSpOffset; + private final Register thread; + + public AMD64HotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread) { + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.thread = thread; + } + @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - // save last Java frame - Register thread = runtime().getProviders().getRegisters().getThreadRegister(); - masm.movq(new AMD64Address(thread, runtime().getConfig().threadLastJavaSpOffset), rsp); + masm.movq(new AMD64Address(thread, threadLastJavaSpOffset), rsp); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCodeCacheProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCodeCacheProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -28,13 +28,12 @@ public class AMD64HotSpotCodeCacheProvider extends HotSpotCodeCacheProvider { - public AMD64HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) { - super(runtime); - + public AMD64HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) { + super(runtime, target); } @Override protected RegisterConfig createRegisterConfig() { - return new AMD64HotSpotRegisterConfig(runtime.getTarget().arch, runtime.getConfig()); + return new AMD64HotSpotRegisterConfig(getTarget().arch, runtime.getConfig()); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -39,16 +39,18 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -public class AMD64HotSpotForeignCallsProvider extends HotSpotForeignCallsProvider { +public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider { + + private final Value[] nativeABICallerSaveRegisters; - public AMD64HotSpotForeignCallsProvider(HotSpotGraalRuntime runtime) { - super(runtime); + public AMD64HotSpotForeignCallsProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, Value[] nativeABICallerSaveRegisters) { + super(runtime, metaAccess, codeCache); + this.nativeABICallerSaveRegisters = nativeABICallerSaveRegisters; } @Override - public void initialize(HotSpotProviders providers) { - Kind word = runtime.getTarget().wordKind; - HotSpotVMConfig config = runtime.getConfig(); + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + Kind word = providers.getCodeCache().getTarget().wordKind; // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() @@ -66,6 +68,12 @@ registerForeignCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - super.initialize(providers); + super.initialize(providers, config); } + + @Override + public Value[] getNativeABICallerSaveRegisters() { + return nativeABICallerSaveRegisters; + } + } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.amd64; - -import java.util.*; - -import com.oracle.graal.amd64.*; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.phases.util.*; - -/** - * AMD64 specific implementation of {@link HotSpotGraalRuntime}. - */ -public class AMD64HotSpotGraalRuntime extends HotSpotGraalRuntime { - - private Value[] nativeABICallerSaveRegisters; - - protected AMD64HotSpotGraalRuntime() { - } - - /** - * Called from C++ code to retrieve the singleton instance, creating it first if necessary. - */ - public static HotSpotGraalRuntime makeInstance() { - HotSpotGraalRuntime runtime = runtime(); - if (runtime == null) { - HotSpotGraalRuntimeFactory factory = findFactory("AMD64"); - if (factory != null) { - runtime = factory.createRuntime(); - } else { - runtime = new AMD64HotSpotGraalRuntime(); - } - runtime.completeInitialization(); - } - return runtime; - } - - protected Architecture createArchitecture() { - return new AMD64(config.useSSE, config.useAVX); - } - - @Override - protected HotSpotProviders createProviders() { - HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(this); - HotSpotCodeCacheProvider codeCache = new AMD64HotSpotCodeCacheProvider(this); - HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(this); - HotSpotForeignCallsProvider foreignCalls = new AMD64HotSpotForeignCallsProvider(this); - HotSpotLoweringProvider lowerer = new AMD64HotSpotLoweringProvider(this, metaAccess, foreignCalls); - // Replacements cannot have speculative optimizations since they have - // to be valid for the entire run of the VM. - Assumptions assumptions = new Assumptions(false); - Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, getConfig(), assumptions); - HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(this); - HotSpotSuitesProvider suites = new HotSpotSuitesProvider(this); - HotSpotRegisters registers = new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp); - return new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); - } - - @Override - protected TargetDescription createTarget() { - final int stackFrameAlignment = 16; - final int implicitNullCheckLimit = 4096; - final boolean inlineObjects = true; - return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); - } - - @Override - protected HotSpotBackend createBackend() { - return new AMD64HotSpotBackend(this, getProviders()); - } - - @Override - protected Value[] getNativeABICallerSaveRegisters() { - if (nativeABICallerSaveRegisters == null) { - List callerSave = new ArrayList<>(Arrays.asList(getProviders().getCodeCache().getRegisterConfig().getAllocatableRegisters())); - if (getConfig().windowsOs) { - // http://msdn.microsoft.com/en-us/library/9z1stfyw.aspx - callerSave.remove(AMD64.rdi); - callerSave.remove(AMD64.rsi); - callerSave.remove(AMD64.rbx); - callerSave.remove(AMD64.rbp); - callerSave.remove(AMD64.rsp); - callerSave.remove(AMD64.r12); - callerSave.remove(AMD64.r13); - callerSave.remove(AMD64.r14); - callerSave.remove(AMD64.r15); - callerSave.remove(AMD64.xmm6); - callerSave.remove(AMD64.xmm7); - callerSave.remove(AMD64.xmm8); - callerSave.remove(AMD64.xmm9); - callerSave.remove(AMD64.xmm10); - callerSave.remove(AMD64.xmm11); - callerSave.remove(AMD64.xmm12); - callerSave.remove(AMD64.xmm13); - callerSave.remove(AMD64.xmm14); - callerSave.remove(AMD64.xmm15); - } else { - /* - * System V Application Binary Interface, AMD64 Architecture Processor Supplement - * - * Draft Version 0.96 - * - * http://www.uclibc.org/docs/psABI-x86_64.pdf - * - * 3.2.1 - * - * ... - * - * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 - * through %r15 "belong" to the calling function and the called function is required - * to preserve their values. In other words, a called function must preserve these - * registers' values for its caller. Remaining registers "belong" to the called - * function. If a calling function wants to preserve such a register value across a - * function call, it must save the value in its local stack frame. - */ - callerSave.remove(AMD64.rbp); - callerSave.remove(AMD64.rbx); - callerSave.remove(AMD64.r12); - callerSave.remove(AMD64.r13); - callerSave.remove(AMD64.r14); - callerSave.remove(AMD64.r15); - } - nativeABICallerSaveRegisters = new Value[callerSave.size()]; - for (int i = 0; i < callerSave.size(); i++) { - nativeABICallerSaveRegisters[i] = callerSave.get(i).asValue(); - } - } - - return nativeABICallerSaveRegisters; - } -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntimeFactory.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntimeFactory.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.amd64; - -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.hotspot.*; - -@ServiceProvider(HotSpotGraalRuntimeFactory.class) -public class AMD64HotSpotGraalRuntimeFactory implements HotSpotGraalRuntimeFactory { - - @Override - public HotSpotGraalRuntime createRuntime() { - return new AMD64HotSpotGraalRuntime(); - } - - @Override - public String getArchitecture() { - return "AMD64"; - } - - @Override - public String getName() { - return "basic"; - } -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -24,7 +24,6 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.code.*; @@ -44,11 +43,15 @@ @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; @Use(REG) AllocatableValue exceptionPc; + private final Register thread; + private final int isMethodHandleReturnOffset; - AMD64HotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc) { + AMD64HotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) { this.handlerInCallerPc = handlerInCallerPc; this.exception = exception; this.exceptionPc = exceptionPc; + this.isMethodHandleReturnOffset = isMethodHandleReturnOffset; + this.thread = thread; } @Override @@ -59,8 +62,6 @@ masm.incrementq(rsp, 8); // Restore rsp from rbp if the exception PC is a method handle call site. - Register thread = runtime().getProviders().getRegisters().getThreadRegister(); - int isMethodHandleReturnOffset = runtime().getConfig().threadIsMethodHandleReturnOffset; AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset); masm.cmpl(dst, 0); masm.cmovq(ConditionFlag.NotEqual, rsp, rbp); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Mon Oct 21 11:07:47 2013 +0200 @@ -180,9 +180,24 @@ } } + private Register findPollOnReturnScratchRegister() { + RegisterConfig regConfig = getProviders().getCodeCache().getRegisterConfig(); + for (Register r : regConfig.getAllocatableRegisters(Kind.Long)) { + if (r != regConfig.getReturnRegister(Kind.Long) && r != AMD64.rbp) { + return r; + } + } + throw GraalInternalError.shouldNotReachHere(); + } + + private Register pollOnReturnScratchRegister; + @Override protected void emitReturn(Value input) { - append(new AMD64HotSpotReturnOp(input, getStub() != null)); + if (pollOnReturnScratchRegister == null) { + pollOnReturnScratchRegister = findPollOnReturnScratchRegister(); + } + append(new AMD64HotSpotReturnOp(input, getStub() != null, pollOnReturnScratchRegister)); } @Override @@ -249,9 +264,10 @@ if (linkage.canDeoptimize()) { assert info != null || stub != null; - append(new AMD64HotSpotCRuntimeCallPrologueOp()); + Register thread = getProviders().getRegisters().getThreadRegister(); + append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread)); result = super.emitForeignCall(linkage, info, args); - append(new AMD64HotSpotCRuntimeCallEpilogueOp()); + append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaFpOffset, thread)); } else { result = super.emitForeignCall(linkage, null, args); } @@ -408,7 +424,8 @@ RegisterValue exceptionPcFixed = (RegisterValue) outgoingCc.getArgument(1); emitMove(exceptionFixed, operand(exception)); emitMove(exceptionPcFixed, operand(exceptionPc)); - AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed); + Register thread = getProviders().getRegisters().getThreadRegister(); + AMD64HotSpotJumpToExceptionHandlerInCallerOp op = new AMD64HotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread); append(op); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLoweringProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -31,7 +31,7 @@ import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.amd64.*; -public class AMD64HotSpotLoweringProvider extends HotSpotLoweringProvider { +public class AMD64HotSpotLoweringProvider extends HotSpotHostLoweringProvider { private AMD64ConvertSnippets.Templates convertSnippets; @@ -40,10 +40,9 @@ } @Override - public void initialize() { - HotSpotProviders providers = runtime.getProviders(); - convertSnippets = new AMD64ConvertSnippets.Templates(providers, runtime.getTarget()); - super.initialize(); + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getCodeCache().getTarget()); + super.initialize(providers, config); } @Override diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -26,12 +26,9 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static com.oracle.graal.phases.GraalOptions.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -43,24 +40,14 @@ @Use({REG, ILLEGAL}) protected Value value; private final boolean isStub; + private final Register scratchForSafepointOnReturn; - AMD64HotSpotReturnOp(Value value, boolean isStub) { + AMD64HotSpotReturnOp(Value value, boolean isStub, Register scratchForSafepointOnReturn) { this.value = value; this.isStub = isStub; + this.scratchForSafepointOnReturn = scratchForSafepointOnReturn; } - private static Register findPollOnReturnScratchRegister() { - RegisterConfig config = HotSpotGraalRuntime.runtime().getProviders().getCodeCache().getRegisterConfig(); - for (Register r : config.getAllocatableRegisters(Kind.Long)) { - if (r != config.getReturnRegister(Kind.Long) && r != AMD64.rbp) { - return r; - } - } - throw GraalInternalError.shouldNotReachHere(); - } - - private static final Register scratchForSafepointOnReturn = findPollOnReturnScratchRegister(); - @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { leaveFrameAndRestoreRbp(tasm, masm); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/ForEachToGraal.java Mon Oct 21 11:07:47 2013 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; @@ -57,8 +56,7 @@ acceptMethod = m; } } - HotSpotGraalRuntime runtime = HotSpotGraalRuntime.runtime(); - HotSpotProviders providers = runtime.getProviders(); + HotSpotProviders providers = HSAILCompilationResult.backend.getProviders(); MetaAccessProvider metaAccess = providers.getMetaAccess(); ResolvedJavaMethod method = metaAccess.lookupJavaMethod(acceptMethod); StructuredGraph graph = new StructuredGraph(method); @@ -83,7 +81,7 @@ if (hsailCompResult != null) { hsailCompResult.dumpCompilationResult(); } - return hsailCompResult.getCompilationResult(); + return hsailCompResult; } // Implementations of the CompileAndDispatch interface. diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILCompilationResult.java Mon Oct 21 11:07:47 2013 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.hotspot.hsail; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + import java.lang.reflect.*; import java.util.logging.*; @@ -33,8 +35,8 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hsail.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -42,13 +44,15 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; /** * Class that represents a HSAIL compilation result. Includes the compiled HSAIL code. */ -public class HSAILCompilationResult { +public class HSAILCompilationResult extends CompilationResult { - private CompilationResult compResult; + private static final long serialVersionUID = -4178700465275724625L; + private static final String propPkgName = HSAILCompilationResult.class.getPackage().getName(); private static Level logLevel; private static ConsoleHandler consoleHandler; @@ -73,17 +77,27 @@ consoleHandler.setLevel(logLevel); } - private static final HotSpotGraalRuntime runtime = new HSAILHotSpotGraalRuntime(); + static final HSAILHotSpotBackend backend; + static { + // Look for installed HSAIL backend + RuntimeProvider runtime = Graal.getRequiredCapability(RuntimeProvider.class); + HSAILHotSpotBackend b = (HSAILHotSpotBackend) runtime.getBackend(HSAIL.class); + if (b == null) { + // Fall back to a new instance + b = new HSAILHotSpotBackendFactory().createBackend(runtime(), runtime().getHostBackend()); + } + backend = b; + } public static HSAILCompilationResult getHSAILCompilationResult(Method meth) { - HotSpotMetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess(); + HotSpotMetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(meth); return getHSAILCompilationResult(javaMethod); } public static HSAILCompilationResult getHSAILCompilationResult(ResolvedJavaMethod javaMethod) { - HotSpotMetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess(); - ForeignCallsProvider foreignCalls = runtime.getProviders().getForeignCalls(); + HotSpotMetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); + ForeignCallsProvider foreignCalls = backend.getProviders().getForeignCalls(); StructuredGraph graph = new StructuredGraph(javaMethod); new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getEagerDefault(), OptimisticOptimizations.ALL).apply(graph); return getHSAILCompilationResult(graph); @@ -112,28 +126,27 @@ argTypes[argIndex++] = sig.getParameterType(i, null); } - RegisterConfig registerConfig = runtime.getProviders().getCodeCache().getRegisterConfig(); + RegisterConfig registerConfig = backend.getProviders().getCodeCache().getRegisterConfig(); return registerConfig.getCallingConvention(type, retType, argTypes, target, stackOnly); } public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) { Debug.dump(graph, "Graph"); - Providers providers = runtime.getProviders(); + Providers providers = backend.getProviders(); TargetDescription target = providers.getCodeCache().getTarget(); - HSAILHotSpotBackend hsailBackend = (HSAILHotSpotBackend) runtime.getBackend(); PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(providers.getMetaAccess(), providers.getForeignCalls(), GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase()); new HSAILPhase().apply(graph); CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false); - SuitesProvider suitesProvider = Graal.getRequiredCapability(SuitesProvider.class); + SuitesProvider suitesProvider = backend.getSuites(); try { - CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), providers, hsailBackend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), - suitesProvider.getDefaultSuites(), new CompilationResult()); - return new HSAILCompilationResult(compResult); + HSAILCompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), providers, backend, target, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog(), + suitesProvider.getDefaultSuites(), new HSAILCompilationResult()); + return compResult; } catch (GraalInternalError e) { - String partialCode = hsailBackend.getPartialCodeString(); + String partialCode = backend.getPartialCodeString(); if (partialCode != null && !partialCode.equals("")) { logger.fine("-------------------\nPartial Code Generation:\n--------------------"); logger.fine(partialCode); @@ -155,20 +168,15 @@ } } - protected HSAILCompilationResult(CompilationResult compResultInput) { - compResult = compResultInput; - } - - public CompilationResult getCompilationResult() { - return compResult; + protected HSAILCompilationResult() { } public String getHSAILCode() { - return new String(compResult.getTargetCode(), 0, compResult.getTargetCodeSize()); + return new String(getTargetCode(), 0, getTargetCodeSize()); } public void dumpCompilationResult() { - logger.fine("targetCodeSize=" + compResult.getTargetCodeSize()); + logger.fine("targetCodeSize=" + getTargetCodeSize()); logger.fine(getHSAILCode()); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Oct 21 11:07:47 2013 +0200 @@ -78,7 +78,11 @@ } public String getPartialCodeString() { - return (codeBuffer == null ? "" : new String(codeBuffer.copyData(0, codeBuffer.position()))); + if (codeBuffer == null) { + return ""; + } + byte[] data = codeBuffer.copyData(0, codeBuffer.position()); + return (data == null ? "" : new String(data)); } class HotSpotFrameContext implements FrameContext { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.hsail; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hsail.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.util.*; + +@ServiceProvider(HotSpotBackendFactory.class) +public class HSAILHotSpotBackendFactory implements HotSpotBackendFactory { + + @Override + public HSAILHotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) { + HotSpotProviders host = hostBackend.getProviders(); + + HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); + HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(runtime, createTarget()); + ConstantReflectionProvider constantReflection = host.getConstantReflection(); + HotSpotForeignCallsProvider foreignCalls = new HSAILHotSpotForeignCallsProvider(host.getForeignCalls()); + LoweringProvider lowerer = new HSAILHotSpotLoweringProvider(host.getLowerer()); + // Replacements cannot have speculative optimizations since they have + // to be valid for the entire run of the VM. + Assumptions assumptions = new Assumptions(false); + Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); + Replacements replacements = new HSAILHotSpotReplacementsImpl(p, assumptions); + HotSpotDisassemblerProvider disassembler = host.getDisassembler(); + HotSpotSuitesProvider suites = host.getSuites(); + HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); + + return new HSAILHotSpotBackend(runtime, providers); + } + + protected TargetDescription createTarget() { + final int stackFrameAlignment = 8; + final int implicitNullCheckLimit = 0; + final boolean inlineObjects = true; + return new TargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + } + + public String getArchitecture() { + return "HSAIL"; + } + + public String getGraalRuntimeName() { + return "basic"; + } + + @Override + public String toString() { + return getGraalRuntimeName() + ":" + getArchitecture(); + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotCodeCacheProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot.hsail; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -29,9 +31,15 @@ public class HSAILHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider { - public HSAILHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) { - super(runtime); + public HSAILHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) { + super(runtime, target); + + } + @Override + public String disassemble(CompilationResult compResult, InstalledCode installedCode) { + byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode(); + return new String(code); } @Override diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotForeignCallsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotForeignCallsProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.hsail; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; + +public class HSAILHotSpotForeignCallsProvider implements HotSpotForeignCallsProvider { + + private final ForeignCallsProvider host; + + public HSAILHotSpotForeignCallsProvider(ForeignCallsProvider host) { + this.host = host; + } + + public boolean isReexecutable(ForeignCallDescriptor descriptor) { + return host.isReexecutable(descriptor); + } + + public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { + return host.getKilledLocations(descriptor); + } + + public boolean canDeoptimize(ForeignCallDescriptor descriptor) { + return host.canDeoptimize(descriptor); + } + + public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { + throw GraalInternalError.unimplemented(); + } + + public Value[] getNativeABICallerSaveRegisters() { + throw GraalInternalError.unimplemented(); + } + + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotGraalRuntime.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.hsail; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.hsail.*; -import com.oracle.graal.nodes.spi.*; - -/** - * HSAIL specific implementation of {@link HotSpotGraalRuntime}. - */ -public class HSAILHotSpotGraalRuntime extends HotSpotGraalRuntime { - - @Override - protected HotSpotProviders createProviders() { - HotSpotProviders host = HotSpotGraalRuntime.runtime().getProviders(); - - HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); - HSAILHotSpotCodeCacheProvider codeCache = new HSAILHotSpotCodeCacheProvider(this); - ConstantReflectionProvider constantReflection = host.getConstantReflection(); - HotSpotForeignCallsProvider foreignCalls = host.getForeignCalls(); - LoweringProvider lowerer = new HSAILHotSpotLoweringProvider(host.getLowerer()); - Replacements replacements = host.getReplacements(); - HotSpotDisassemblerProvider disassembler = host.getDisassembler(); - HotSpotSuitesProvider suites = host.getSuites(); - HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None); - return new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); - } - - @Override - protected TargetDescription createTarget() { - final int stackFrameAlignment = 8; - final int implicitNullCheckLimit = 0; - final boolean inlineObjects = true; - return new TargetDescription(new HSAIL(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); - } - - @Override - protected HotSpotBackend createBackend() { - return new HSAILHotSpotBackend(this, getProviders()); - } - - @Override - protected Value[] getNativeABICallerSaveRegisters() { - throw new InternalError("NYI"); - } -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLoweringProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,18 +22,21 @@ */ package com.oracle.graal.hotspot.hsail; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -public class HSAILHotSpotLoweringProvider implements LoweringProvider { +public class HSAILHotSpotLoweringProvider implements HotSpotLoweringProvider { - private LoweringProvider hostLowerer; + private LoweringProvider host; - public HSAILHotSpotLoweringProvider(LoweringProvider hostLowerer) { - this.hostLowerer = hostLowerer; + public HSAILHotSpotLoweringProvider(LoweringProvider host) { + this.host = host; } public void lower(Node n, LoweringTool tool) { @@ -41,11 +44,18 @@ // TODO return; } else { - hostLowerer.lower(n, tool); + host.lower(n, tool); } } public ValueNode reconstructArrayIndex(LocationNode location) { - return hostLowerer.reconstructArrayIndex(location); + throw GraalInternalError.unimplemented(); + } + + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + } + + public int getScalingFactor(Kind elementKind) { + throw GraalInternalError.unimplemented(); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotReplacementsImpl.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.hsail; + +import java.lang.reflect.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.replacements.*; + +/** + * Filters the substitutions and snippets supported by HSAIL. + */ +public class HSAILHotSpotReplacementsImpl extends ReplacementsImpl { + + public HSAILHotSpotReplacementsImpl(Providers providers, Assumptions assumptions) { + super(providers, assumptions); + } + + @Override + protected ResolvedJavaMethod registerMethodSubstitution(Member originalMethod, Method substituteMethod) { + // TODO decide here what methods substitutions are supported + return null; + } + + @Override + public Class getMacroSubstitution(ResolvedJavaMethod method) { + // TODO decide here what macro substitutions are supported + return null; + } + + @Override + public StructuredGraph getSnippet(ResolvedJavaMethod method) { + // TODO must work in cooperation with HSAILHotSpotLoweringProvider + return null; + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,15 +22,28 @@ */ package com.oracle.graal.hotspot.ptx; +import static com.oracle.graal.lir.LIRValueUtil.*; + +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.ptx.*; import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.ptx.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; +import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.ptx.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; /** * HotSpot PTX specific backend. @@ -43,31 +56,219 @@ @Override public boolean shouldAllocateRegisters() { - throw new InternalError("NYI"); + return false; } @Override public FrameMap newFrameMap() { - throw new InternalError("NYI"); + return new PTXFrameMap(getCodeCache()); + } + + class PTXFrameContext implements FrameContext { + + @Override + public void enter(TargetMethodAssembler tasm) { + // codeBuffer.emitString(".address_size 32"); // PTX ISA version 2.3 + } + + @Override + public void leave(TargetMethodAssembler tasm) { + } } @Override public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) { - throw new InternalError("NYI"); - } - - @Override - public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod installedCodeOwner) { - throw new InternalError("NYI"); + // Omit the frame of the method: + // - has no spill slots or other slots allocated during register allocation + // - has no callee-saved registers + // - has no incoming arguments passed on the stack + // - has no instructions with debug info + FrameMap frameMap = lirGen.frameMap; + AbstractAssembler masm = createAssembler(frameMap); + PTXFrameContext frameContext = new PTXFrameContext(); + TargetMethodAssembler tasm = new PTXTargetMethodAssembler(getCodeCache(), getForeignCalls(), frameMap, masm, frameContext, compilationResult); + tasm.setFrameSize(0); + return tasm; } @Override protected AbstractAssembler createAssembler(FrameMap frameMap) { - throw new InternalError("NYI"); + return new PTXAssembler(getTarget(), frameMap.registerConfig); } @Override public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, CallingConvention cc, LIR lir) { - throw new InternalError("NYI"); + return new PTXLIRGenerator(graph, getProviders(), frameMap, cc, lir); + } + + private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { + // Emit PTX kernel entry text based on PTXParameterOp + // instructions in the start block. Remove the instructions + // once kernel entry text and directives are emitted to + // facilitate seemless PTX code generation subsequently. + assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; + final String name = codeCacheOwner.getName(); + Buffer codeBuffer = tasm.asm.codeBuffer; + + // Emit initial boiler-plate directives. + codeBuffer.emitString(".version 3.0"); + codeBuffer.emitString(".target sm_30"); + codeBuffer.emitString0(".entry " + name + " ("); + codeBuffer.emitString(""); + + // Get the start block + Block startBlock = lirGen.lir.cfg.getStartBlock(); + // Keep a list of ParameterOp instructions to delete from the + // list of instructions in the block. + ArrayList deleteOps = new ArrayList<>(); + + // Emit .param arguments to kernel entry based on ParameterOp + // instruction. + for (LIRInstruction op : lirGen.lir.lir(startBlock)) { + if (op instanceof PTXParameterOp) { + op.emitCode(tasm); + deleteOps.add(op); + } + } + + // Delete ParameterOp instructions. + for (LIRInstruction op : deleteOps) { + lirGen.lir.lir(startBlock).remove(op); + } + + // Start emiting body of the PTX kernel. + codeBuffer.emitString0(") {"); + codeBuffer.emitString(""); + } + + // Emit .reg space declarations + private static void emitRegisterDecl(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { + + assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; + + Buffer codeBuffer = tasm.asm.codeBuffer; + + final SortedSet signed32 = new TreeSet<>(); + final SortedSet signed64 = new TreeSet<>(); + final SortedSet unsigned64 = new TreeSet<>(); + final SortedSet float32 = new TreeSet<>(); + final SortedSet float64 = new TreeSet<>(); + + ValueProcedure trackRegisterKind = new ValueProcedure() { + + @Override + public Value doValue(Value value, OperandMode mode, EnumSet flags) { + if (isVariable(value)) { + Variable regVal = (Variable) value; + Kind regKind = regVal.getKind(); + switch (regKind) { + case Int: + // If the register was used as a wider signed type + // do not add it here + if (!signed64.contains(regVal.index)) { + signed32.add(regVal.index); + } + break; + case Long: + // If the register was used as a narrower signed type + // remove it from there and add it to wider type. + if (signed32.contains(regVal.index)) { + signed32.remove(regVal.index); + } + signed64.add(regVal.index); + break; + case Float: + // If the register was used as a wider signed type + // do not add it here + if (!float64.contains(regVal.index)) { + float32.add(regVal.index); + } + break; + case Double: + // If the register was used as a narrower signed type + // remove it from there and add it to wider type. + if (float32.contains(regVal.index)) { + float32.remove(regVal.index); + } + float64.add(regVal.index); + break; + case Object: + unsigned64.add(regVal.index); + break; + default: + throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString()); + } + } + return value; + } + }; + + for (Block b : lirGen.lir.codeEmittingOrder()) { + for (LIRInstruction op : lirGen.lir.lir(b)) { + if (op instanceof LabelOp) { + // Don't consider this as a definition + } else { + op.forEachTemp(trackRegisterKind); + op.forEachOutput(trackRegisterKind); + } + } + } + + for (Integer i : signed32) { + codeBuffer.emitString(".reg .s32 %r" + i.intValue() + ";"); + } + for (Integer i : signed64) { + codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";"); + } + for (Integer i : unsigned64) { + codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";"); + } + for (Integer i : float32) { + codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";"); + } + for (Integer i : float64) { + codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";"); + } + // emit predicate register declaration + int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber(); + if (maxPredRegNum > 0) { + codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;"); + } + codeBuffer.emitString(".reg .pred %r;"); // used for setp bool + } + + @Override + public void emitCode(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) { + assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method"; + Buffer codeBuffer = tasm.asm.codeBuffer; + // Emit the prologue + emitKernelEntry(tasm, lirGen, codeCacheOwner); + + // Emit register declarations + try { + emitRegisterDecl(tasm, lirGen, codeCacheOwner); + } catch (GraalInternalError e) { + e.printStackTrace(); + // TODO : Better error handling needs to be done once + // all types of parameters are handled. + codeBuffer.setPosition(0); + codeBuffer.close(false); + return; + } + // Emit code for the LIR + try { + lirGen.lir.emitCode(tasm); + } catch (GraalInternalError e) { + e.printStackTrace(); + // TODO : Better error handling needs to be done once + // all types of parameters are handled. + codeBuffer.setPosition(0); + codeBuffer.close(false); + return; + } + + // Emit the epilogue + codeBuffer.emitString0("}"); + codeBuffer.emitString(""); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.ptx.*; + +@ServiceProvider(HotSpotBackendFactory.class) +public class PTXHotSpotBackendFactory implements HotSpotBackendFactory { + + public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend hostBackend) { + HotSpotProviders host = hostBackend.getProviders(); + + HotSpotMetaAccessProvider metaAccess = host.getMetaAccess(); + PTXHotSpotCodeCacheProvider codeCache = new PTXHotSpotCodeCacheProvider(runtime, createTarget()); + ConstantReflectionProvider constantReflection = host.getConstantReflection(); + HotSpotForeignCallsProvider foreignCalls = new PTXHotSpotForeignCallsProvider(); + HotSpotLoweringProvider lowerer = new PTXHotSpotLoweringProvider(host.getLowerer()); + Replacements replacements = host.getReplacements(); + HotSpotDisassemblerProvider disassembler = host.getDisassembler(); + HotSpotSuitesProvider suites = host.getSuites(); + HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None); + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); + return new PTXHotSpotBackend(runtime, providers); + } + + protected Architecture createArchitecture() { + return new PTX(); + } + + protected TargetDescription createTarget() { + final int stackFrameAlignment = 1; + final int implicitNullCheckLimit = 0; + final boolean inlineObjects = true; + return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + } + + public String getArchitecture() { + return "PTX"; + } + + public String getGraalRuntimeName() { + return "basic"; + } + + @Override + public String toString() { + return getGraalRuntimeName() + ":" + getArchitecture(); + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotCodeCacheProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -28,8 +28,8 @@ public class PTXHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider { - public PTXHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) { - super(runtime); + public PTXHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) { + super(runtime, target); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotForeignCallsProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; + +public class PTXHotSpotForeignCallsProvider implements HotSpotForeignCallsProvider { + + public boolean isReexecutable(ForeignCallDescriptor descriptor) { + throw GraalInternalError.unimplemented(); + } + + public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { + throw GraalInternalError.unimplemented(); + } + + public boolean canDeoptimize(ForeignCallDescriptor descriptor) { + throw GraalInternalError.unimplemented(); + } + + public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { + throw GraalInternalError.unimplemented(); + } + + public Value[] getNativeABICallerSaveRegisters() { + throw GraalInternalError.unimplemented(); + } + + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.ptx; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.phases.util.*; -import com.oracle.graal.ptx.*; - -/** - * PTX specific implementation of {@link HotSpotGraalRuntime}. - */ -public class PTXHotSpotGraalRuntime extends HotSpotGraalRuntime { - - protected PTXHotSpotGraalRuntime() { - } - - /** - * Called from C++ code to retrieve the singleton instance, creating it first if necessary. - */ - public static HotSpotGraalRuntime makeInstance() { - HotSpotGraalRuntime runtime = runtime(); - if (runtime == null) { - HotSpotGraalRuntimeFactory factory = findFactory("PTX"); - if (factory != null) { - runtime = factory.createRuntime(); - } else { - runtime = new PTXHotSpotGraalRuntime(); - } - runtime.completeInitialization(); - } - return runtime; - } - - @Override - protected HotSpotProviders createProviders() { - HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(this); - PTXHotSpotCodeCacheProvider codeCache = new PTXHotSpotCodeCacheProvider(this); - HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(this); - HotSpotForeignCallsProvider foreignCalls = new HotSpotForeignCallsProvider(this); - HotSpotLoweringProvider lowerer = new PTXHotSpotLoweringProvider(this, metaAccess, foreignCalls); - // Replacements cannot have speculative optimizations since they have - // to be valid for the entire run of the VM. - Assumptions assumptions = new Assumptions(false); - Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, getConfig(), assumptions); - HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(this); - HotSpotSuitesProvider suites = new HotSpotSuitesProvider(this); - HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None); - return new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); - } - - protected Architecture createArchitecture() { - return new PTX(); - } - - @Override - protected TargetDescription createTarget() { - final int stackFrameAlignment = 16; - final int implicitNullCheckLimit = 4096; - final boolean inlineObjects = true; - return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); - } - - @Override - protected HotSpotBackend createBackend() { - return new PTXHotSpotBackend(this, getProviders()); - } - - @Override - protected Value[] getNativeABICallerSaveRegisters() { - throw new InternalError("NYI"); - } -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotLoweringProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,18 +22,21 @@ */ package com.oracle.graal.hotspot.ptx; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -public class PTXHotSpotLoweringProvider extends HotSpotLoweringProvider { +public class PTXHotSpotLoweringProvider implements HotSpotLoweringProvider { - public PTXHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) { - super(runtime, metaAccess, foreignCalls); + private final LoweringProvider host; + + public PTXHotSpotLoweringProvider(LoweringProvider host) { + this.host = host; } @Override @@ -46,7 +49,18 @@ // So, there is no need to lower the operation. return; } else { - super.lower(n, tool); + host.lower(n, tool); } } + + public ValueNode reconstructArrayIndex(LocationNode location) { + throw GraalInternalError.unimplemented(); + } + + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + } + + public int getScalingFactor(Kind elementKind) { + throw GraalInternalError.unimplemented(); + } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackendFactory.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.phases.util.*; +import com.oracle.graal.sparc.*; + +@ServiceProvider(HotSpotBackendFactory.class) +public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { + + protected static Architecture createArchitecture() { + return new SPARC(); + } + + protected TargetDescription createTarget() { + final int stackFrameAlignment = 16; + final int implicitNullCheckLimit = 4096; + final boolean inlineObjects = true; + return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); + } + + public HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host) { + assert host == null; + TargetDescription target = createTarget(); + + HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime); + HotSpotCodeCacheProvider codeCache = new SPARCHotSpotCodeCacheProvider(runtime, target); + HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime); + Value[] nativeABICallerSaveRegisters = createNativeABICallerSaveRegisters(runtime.getConfig(), codeCache.getRegisterConfig()); + HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(runtime, metaAccess, codeCache, nativeABICallerSaveRegisters); + HotSpotLoweringProvider lowerer = new SPARCHotSpotLoweringProvider(runtime, metaAccess, foreignCalls); + // Replacements cannot have speculative optimizations since they have + // to be valid for the entire run of the VM. + Assumptions assumptions = new Assumptions(false); + Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); + HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, runtime.getConfig(), assumptions); + HotSpotDisassemblerProvider disassembler = new HotSpotDisassemblerProvider(runtime); + HotSpotSuitesProvider suites = new HotSpotSuitesProvider(runtime); + HotSpotRegisters registers = new HotSpotRegisters(Register.None, Register.None, Register.None); // FIXME + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); + + return new SPARCHotSpotBackend(runtime, providers); + } + + @SuppressWarnings("unused") + private static Value[] createNativeABICallerSaveRegisters(HotSpotVMConfig config, RegisterConfig regConfig) { + throw GraalInternalError.unimplemented(); + } + + public String getArchitecture() { + return "SPARC"; + } + + public String getGraalRuntimeName() { + return "basic"; + } + + @Override + public String toString() { + return getGraalRuntimeName() + ":" + getArchitecture(); + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallEpilogueOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -23,30 +23,40 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.hotspot.*; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stw; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.asm.*; @Opcode("CRUNTIME_CALL_EPILOGUE") final class SPARCHotSpotCRuntimeCallEpilogueOp extends SPARCLIRInstruction { + private final int threadLastJavaSpOffset; + private final int threadLastJavaPcOffset; + private final int threadJavaFrameAnchorFlagsOffset; + private final Register thread; + + public SPARCHotSpotCRuntimeCallEpilogueOp(int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset, Register thread) { + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.threadLastJavaPcOffset = threadLastJavaPcOffset; + this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; + this.thread = thread; + } + @Override public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { - Register thread = runtime().getProviders().getRegisters().getThreadRegister(); - HotSpotVMConfig config = runtime().getConfig(); // Restore the thread register when coming back from the runtime. new Mov(l7, thread).emit(masm); // Reset last Java frame, last Java PC and flags. - new Stx(g0, new SPARCAddress(thread, config.threadLastJavaSpOffset)).emit(masm); - new Stx(g0, new SPARCAddress(thread, config.threadLastJavaPcOffset)).emit(masm); - new Stw(g0, new SPARCAddress(thread, config.threadJavaFrameAnchorFlagsOffset)).emit(masm); + new Stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); + new Stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)).emit(masm); + new Stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)).emit(masm); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCRuntimeCallPrologueOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -23,30 +23,35 @@ package com.oracle.graal.hotspot.sparc; import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.sparc.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.asm.sparc.SPARCAssembler.Add; +import com.oracle.graal.asm.sparc.SPARCAssembler.Stx; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Mov; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.sparc.*; -import com.oracle.graal.lir.asm.*; @Opcode("CRUNTIME_CALL_PROLOGUE") final class SPARCHotSpotCRuntimeCallPrologueOp extends SPARCLIRInstruction { + private final int threadLastJavaSpOffset; + private final Register thread; + private final Register stackPointer; + + public SPARCHotSpotCRuntimeCallPrologueOp(int threadLastJavaSpOffset, Register thread, Register stackPointer) { + this.threadLastJavaSpOffset = threadLastJavaSpOffset; + this.thread = thread; + this.stackPointer = stackPointer; + } + @Override public void emitCode(TargetMethodAssembler tasm, SPARCMacroAssembler masm) { - HotSpotRegistersProvider registers = runtime().getProviders().getRegisters(); - HotSpotVMConfig config = runtime().getConfig(); - Register thread = registers.getThreadRegister(); - Register stackPointer = registers.getStackPointerRegister(); // Save last Java frame. new Add(stackPointer, new SPARCAddress(stackPointer, 0).getDisplacement(), g4).emit(masm); - new Stx(g4, new SPARCAddress(thread, config.threadLastJavaSpOffset)).emit(masm); + new Stx(g4, new SPARCAddress(thread, threadLastJavaSpOffset)).emit(masm); // Save the thread register when calling out to the runtime. new Mov(thread, l7).emit(masm); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotCodeCacheProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; + +public class SPARCHotSpotCodeCacheProvider extends HotSpotCodeCacheProvider { + + public SPARCHotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) { + super(runtime, target); + } + + @Override + protected RegisterConfig createRegisterConfig() { + throw GraalInternalError.unimplemented(); + } + +} diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -35,15 +35,18 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -public class SPARCHotSpotForeignCallsProvider extends HotSpotForeignCallsProvider { +public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsProvider { + + private final Value[] nativeABICallerSaveRegisters; - public SPARCHotSpotForeignCallsProvider(HotSpotGraalRuntime runtime) { - super(runtime); + public SPARCHotSpotForeignCallsProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache, Value[] nativeABICallerSaveRegisters) { + super(runtime, metaAccess, codeCache); + this.nativeABICallerSaveRegisters = nativeABICallerSaveRegisters; } @Override - public void initialize(HotSpotProviders providers) { - Kind word = runtime.getTarget().wordKind; + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + Kind word = providers.getCodeCache().getTarget().wordKind; // The calling convention for the exception handler stub is (only?) defined in // TemplateInterpreterGenerator::generate_throw_exception() @@ -56,5 +59,12 @@ CallingConvention incomingExceptionCc = new CallingConvention(0, ILLEGAL, incomingException, incomingExceptionPc); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); register(new HotSpotForeignCallLinkage(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, ANY_LOCATION)); + + super.initialize(providers, config); + } + + @Override + public Value[] getNativeABICallerSaveRegisters() { + return nativeABICallerSaveRegisters; } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.sparc; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.sparc.*; - -/** - * SPARC specific implementation of {@link HotSpotGraalRuntime}. - */ -final class SPARCHotSpotGraalRuntime extends HotSpotGraalRuntime { - - private SPARCHotSpotGraalRuntime() { - } - - /** - * Called from C++ code to retrieve the singleton instance, creating it first if necessary. - */ - public static HotSpotGraalRuntime makeInstance() { - HotSpotGraalRuntime runtime = runtime(); - if (runtime == null) { - runtime = new SPARCHotSpotGraalRuntime(); - runtime.completeInitialization(); - } - return runtime; - } - - @Override - protected HotSpotProviders createProviders() { - // TODO Auto-generated method stub - return null; - } - - protected static Architecture createArchitecture() { - return new SPARC(); - } - - @Override - protected TargetDescription createTarget() { - final int stackFrameAlignment = 16; - final int implicitNullCheckLimit = 4096; - final boolean inlineObjects = true; - return new TargetDescription(createArchitecture(), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects); - } - - @Override - protected HotSpotBackend createBackend() { - return new SPARCHotSpotBackend(this, getProviders()); - } - - @Override - protected Value[] getNativeABICallerSaveRegisters() { - throw GraalInternalError.unimplemented(); - } -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotJumpToExceptionHandlerInCallerOp.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,15 +22,19 @@ */ package com.oracle.graal.hotspot.sparc; -import static com.oracle.graal.asm.sparc.SPARCMacroAssembler.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import static com.oracle.graal.sparc.SPARC.*; -import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.asm.sparc.SPARCAssembler.CC; +import com.oracle.graal.asm.sparc.SPARCAssembler.ConditionFlag; +import com.oracle.graal.asm.sparc.SPARCAssembler.Jmpl; +import com.oracle.graal.asm.sparc.SPARCAssembler.Lduw; +import com.oracle.graal.asm.sparc.SPARCAssembler.Movcc; +import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Cmp; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -44,11 +48,15 @@ @Use(REG) AllocatableValue handlerInCallerPc; @Use(REG) AllocatableValue exception; @Use(REG) AllocatableValue exceptionPc; + private final Register thread; + private final int isMethodHandleReturnOffset; - SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc) { + SPARCHotSpotJumpToExceptionHandlerInCallerOp(AllocatableValue handlerInCallerPc, AllocatableValue exception, AllocatableValue exceptionPc, int isMethodHandleReturnOffset, Register thread) { this.handlerInCallerPc = handlerInCallerPc; this.exception = exception; this.exceptionPc = exceptionPc; + this.isMethodHandleReturnOffset = isMethodHandleReturnOffset; + this.thread = thread; } @Override @@ -56,8 +64,6 @@ leaveFrame(tasm); // Restore SP from L7 if the exception PC is a method handle call site. - Register thread = runtime().getProviders().getRegisters().getThreadRegister(); - int isMethodHandleReturnOffset = runtime().getConfig().threadIsMethodHandleReturnOffset; SPARCAddress dst = new SPARCAddress(thread, isMethodHandleReturnOffset); new Lduw(dst, o7).emit(masm); new Cmp(o7, o7).emit(masm); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerator.java Mon Oct 21 11:07:47 2013 +0200 @@ -100,9 +100,12 @@ if (linkage.canDeoptimize()) { assert info != null; - append(new SPARCHotSpotCRuntimeCallPrologueOp()); + HotSpotRegistersProvider registers = getProviders().getRegisters(); + Register thread = registers.getThreadRegister(); + Register stackPointer = registers.getStackPointerRegister(); + append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset, thread, stackPointer)); result = super.emitForeignCall(linkage, info, args); - append(new SPARCHotSpotCRuntimeCallEpilogueOp()); + append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset, config.threadLastJavaPcOffset, config.threadJavaFrameAnchorFlagsOffset, thread)); } else { result = super.emitForeignCall(linkage, null, args); } @@ -223,7 +226,8 @@ RegisterValue exceptionPcFixed = (RegisterValue) linkageCc.getArgument(1); emitMove(exceptionFixed, operand(exception)); emitMove(exceptionPcFixed, operand(exceptionPc)); - SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed); + Register thread = getProviders().getRegisters().getThreadRegister(); + SPARCHotSpotJumpToExceptionHandlerInCallerOp op = new SPARCHotSpotJumpToExceptionHandlerInCallerOp(handler, exceptionFixed, exceptionPcFixed, config.threadIsMethodHandleReturnOffset, thread); append(op); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLoweringProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -public class SPARCHotSpotLoweringProvider extends HotSpotLoweringProvider { +public class SPARCHotSpotLoweringProvider extends HotSpotHostLoweringProvider { public SPARCHotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) { super(runtime, metaAccess, foreignCalls); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -41,6 +41,7 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.runtime.*; /** * use @@ -204,8 +205,8 @@ phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); // create suites everytime, as we modify options for the compiler - final Suites suitesLocal = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); - final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), backend, getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, + final Suites suitesLocal = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites().createSuites(); + final CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, method, getProviders(), getBackend(), getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog(), suitesLocal, new CompilationResult()); addMethod(method, compResult); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/CompressedOopTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -33,6 +33,7 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.runtime.*; /** * The following tests perform object/array equality and assignments in various ways. The selected @@ -43,7 +44,7 @@ private final MetaAccessProvider metaAccess; public CompressedOopTest() { - this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); + this.metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); } private HotSpotInstalledCode getInstalledCode(String name) throws Exception { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/InstalledCodeExecuteHelperTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -35,6 +35,7 @@ import com.oracle.graal.compiler.test.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.runtime.*; public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { @@ -43,7 +44,7 @@ Object[] argsToBind; public InstalledCodeExecuteHelperTest() { - this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); + this.metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); } @Test diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -43,6 +43,7 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.runtime.*; /** * The following unit tests assert the presence of write barriers for both Serial and G1 GCs. @@ -58,7 +59,7 @@ private final MetaAccessProvider metaAccess; public WriteBarrierAdditionTest() { - this.metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); + this.metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); } public static class Container { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Mon Oct 21 11:07:47 2013 +0200 @@ -42,7 +42,6 @@ import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -import com.oracle.graal.phases.util.*; public final class CompilationTask implements Runnable { @@ -58,9 +57,8 @@ Queued, Running } - private final HotSpotGraalRuntime runtime; + private final HotSpotBackend backend; private final PhasePlan plan; - private final SuitesProvider suitesProvider; private final OptimisticOptimizations optimisticOpts; private final HotSpotResolvedJavaMethod method; private final int entryBCI; @@ -69,15 +67,14 @@ private StructuredGraph graph; - public static CompilationTask create(HotSpotGraalRuntime runtime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) { - return new CompilationTask(runtime, plan, optimisticOpts, method, entryBCI, id); + public static CompilationTask create(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) { + return new CompilationTask(backend, plan, optimisticOpts, method, entryBCI, id); } - private CompilationTask(HotSpotGraalRuntime runtime, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) { + private CompilationTask(HotSpotBackend backend, PhasePlan plan, OptimisticOptimizations optimisticOpts, HotSpotResolvedJavaMethod method, int entryBCI, int id) { assert id >= 0; - this.runtime = runtime; + this.backend = backend; this.plan = plan; - this.suitesProvider = runtime.getCapability(SuitesProvider.class); this.method = method; this.optimisticOpts = optimisticOpts; this.entryBCI = entryBCI; @@ -143,8 +140,12 @@ @Override public CompilationResult call() throws Exception { - runtime.evictDeoptedGraphs(); - Providers providers = runtime.getProviders(); + GraphCache graphCache = backend.getRuntime().getGraphCache(); + if (graphCache != null) { + graphCache.removeStaleGraphs(); + } + + HotSpotProviders providers = backend.getProviders(); Replacements replacements = providers.getReplacements(); graph = replacements.getMethodSubstitution(method); if (graph == null || entryBCI != INVOCATION_ENTRY_BCI) { @@ -155,8 +156,9 @@ } InliningUtil.InlinedBytecodes.add(method.getCodeSize()); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); - return GraalCompiler.compileGraph(graph, cc, method, providers, runtime.getBackend(), runtime.getTarget(), runtime.getCache(), plan, optimisticOpts, - method.getSpeculationLog(), suitesProvider.getDefaultSuites(), new CompilationResult()); + Suites suites = providers.getSuites().getDefaultSuites(); + return GraalCompiler.compileGraph(graph, cc, method, providers, backend, backend.getTarget(), graphCache, plan, optimisticOpts, method.getSpeculationLog(), suites, + new CompilationResult()); } }); } finally { @@ -212,7 +214,7 @@ } private void installMethod(final CompilationResult compResult) { - final HotSpotCodeCacheProvider codeCache = runtime.getProviders().getCodeCache(); + final HotSpotCodeCacheProvider codeCache = backend.getProviders().getCodeCache(); Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), codeCache, method}, new Runnable() { @Override @@ -222,7 +224,7 @@ Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); } if (Debug.isLogEnabled()) { - Debug.log("%s", runtime.getProviders().getDisassembler().disassemble(installedCode)); + Debug.log("%s", backend.getProviders().getDisassembler().disassemble(installedCode)); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Mon Oct 21 11:07:47 2013 +0200 @@ -182,7 +182,7 @@ } // Are we compiling this class? - HotSpotMetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess(); + HotSpotMetaAccessProvider metaAccess = runtime.getHostProviders().getMetaAccess(); if (classFileCounter >= startAt) { TTY.println("CompileTheWorld (%d) : %s", classFileCounter, className); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,12 +22,14 @@ */ package com.oracle.graal.hotspot; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.word.*; /** @@ -82,4 +84,14 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } + + @Override + public SuitesProvider getSuites() { + return getProviders().getSuites(); + } + + @Override + public DisassemblerProvider getDisassembler() { + return getProviders().getDisassembler(); + } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackendFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackendFactory.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot; + +import com.oracle.graal.hotspot.HotSpotGraalRuntime.Options; + +public interface HotSpotBackendFactory { + + HotSpotBackend createBackend(HotSpotGraalRuntime runtime, HotSpotBackend host); + + /** + * Gets the CPU architecture of this backend. + */ + String getArchitecture(); + + /** + * Gets the name of the {@link Options#GraalRuntime GraalRuntime} in which the backend created + * by this factory should be used. + */ + String getGraalRuntimeName(); + +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotForeignCallLinkage.java Mon Oct 21 11:07:47 2013 +0200 @@ -31,6 +31,7 @@ import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.word.*; @@ -119,13 +120,13 @@ * re-executed. * @param killedLocations the memory locations killed by the call */ - public static HotSpotForeignCallLinkage create(ForeignCallDescriptor descriptor, long address, RegisterEffect effect, Type outgoingCcType, Type incomingCcType, Transition transition, - boolean reexecutable, LocationIdentity... killedLocations) { - CallingConvention outgoingCc = createCallingConvention(descriptor, outgoingCcType); - CallingConvention incomingCc = incomingCcType == null ? null : createCallingConvention(descriptor, incomingCcType); + public static HotSpotForeignCallLinkage create(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, HotSpotForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, + long address, RegisterEffect effect, Type outgoingCcType, Type incomingCcType, Transition transition, boolean reexecutable, LocationIdentity... killedLocations) { + CallingConvention outgoingCc = createCallingConvention(metaAccess, codeCache, descriptor, outgoingCcType); + CallingConvention incomingCc = incomingCcType == null ? null : createCallingConvention(metaAccess, codeCache, descriptor, incomingCcType); HotSpotForeignCallLinkage linkage = new HotSpotForeignCallLinkage(descriptor, address, effect, transition, outgoingCc, incomingCc, reexecutable, killedLocations); if (outgoingCcType == Type.NativeCall) { - linkage.temporaries = runtime().getNativeABICallerSaveRegisters(); + linkage.temporaries = foreignCalls.getNativeABICallerSaveRegisters(); } return linkage; } @@ -133,23 +134,22 @@ /** * Gets a calling convention for a given descriptor and call type. */ - public static CallingConvention createCallingConvention(ForeignCallDescriptor descriptor, Type ccType) { + public static CallingConvention createCallingConvention(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ForeignCallDescriptor descriptor, Type ccType) { assert ccType != null; - MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess(); Class[] argumentTypes = descriptor.getArgumentTypes(); JavaType[] parameterTypes = new JavaType[argumentTypes.length]; for (int i = 0; i < parameterTypes.length; ++i) { parameterTypes[i] = asJavaType(argumentTypes[i], metaAccess); } - TargetDescription target = runtime().getTarget(); + TargetDescription target = codeCache.getTarget(); JavaType returnType = asJavaType(descriptor.getResultType(), metaAccess); - RegisterConfig regConfig = runtime().getProviders().getCodeCache().getRegisterConfig(); + RegisterConfig regConfig = codeCache.getRegisterConfig(); return regConfig.getCallingConvention(ccType, returnType, parameterTypes, target, false); } private static JavaType asJavaType(Class type, MetaAccessProvider metaAccess) { if (WordBase.class.isAssignableFrom(type)) { - return metaAccess.lookupJavaType(wordKind().toJavaClass()); + return metaAccess.lookupJavaType(getHostWordKind().toJavaClass()); } else { return metaAccess.lookupJavaType(type); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Oct 21 11:07:47 2013 +0200 @@ -38,24 +38,25 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.logging.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.tiers.*; +import com.oracle.graal.runtime.*; /** * Singleton class holding the instance of the {@link GraalRuntime}. - * - * The platform specific subclass is created by a call from the C++ HotSpot code. */ -public abstract class HotSpotGraalRuntime implements GraalRuntime { +public final class HotSpotGraalRuntime implements GraalRuntime, RuntimeProvider { - private static final HotSpotGraalRuntime instance = (HotSpotGraalRuntime) Graal.getRuntime(); + private static final HotSpotGraalRuntime instance = new HotSpotGraalRuntime(); + static { + instance.completeInitialization(); + } /** * Gets the singleton {@link HotSpotGraalRuntime} object. */ public static HotSpotGraalRuntime runtime() { + assert instance != null; return instance; } @@ -86,7 +87,7 @@ this.compilerToVm = toVM; } - // Options must not be directly declared in HotSpotGraalRuntime - see VerifyHotSpotOptionsPhase + // Options must not be directly declared in HotSpotGraalRuntime - see VerifyOptionsPhase static class Options { // @formatter:off @@ -95,19 +96,19 @@ // @formatter:on } - protected static HotSpotGraalRuntimeFactory findFactory(String architecture) { - HotSpotGraalRuntimeFactory basic = null; - HotSpotGraalRuntimeFactory selected = null; - HotSpotGraalRuntimeFactory nonBasic = null; + private static HotSpotBackendFactory findFactory(String architecture) { + HotSpotBackendFactory basic = null; + HotSpotBackendFactory selected = null; + HotSpotBackendFactory nonBasic = null; int nonBasicCount = 0; - for (HotSpotGraalRuntimeFactory factory : ServiceLoader.loadInstalled(HotSpotGraalRuntimeFactory.class)) { - if (factory.getArchitecture().equals(architecture)) { - if (factory.getName().equals(GraalRuntime.getValue())) { + for (HotSpotBackendFactory factory : ServiceLoader.loadInstalled(HotSpotBackendFactory.class)) { + if (factory.getArchitecture().equalsIgnoreCase(architecture)) { + if (factory.getGraalRuntimeName().equals(GraalRuntime.getValue())) { assert selected == null; selected = factory; } - if (factory.getName().equals("basic")) { + if (factory.getGraalRuntimeName().equals("basic")) { assert basic == null; basic = factory; } else { @@ -133,21 +134,18 @@ } } - private static Kind wordKind; - /** - * Gets the kind of a word value. + * Gets the kind of a word value on the {@linkplain #getHostBackend() host} backend. */ - public static Kind wordKind() { - assert wordKind != null; - return wordKind; + public static Kind getHostWordKind() { + return instance.getHostBackend().getTarget().wordKind; } /** * Reads a word value from a given address. */ public static long unsafeReadWord(long address) { - if (wordKind == Kind.Long) { + if (getHostWordKind() == Kind.Long) { return unsafe.getLong(address); } return unsafe.getInt(address); @@ -164,7 +162,7 @@ * Reads a word value from a given object. */ public static long unsafeReadWord(Object object, long offset) { - if (wordKind == Kind.Long) { + if (getHostWordKind() == Kind.Long) { return unsafe.getLong(object, offset); } return unsafe.getInt(object, offset); @@ -174,21 +172,17 @@ protected/* final */CompilerToGPU compilerToGpu; protected/* final */VMToCompiler vmToCompiler; - protected final HotSpotProviders providers; - - protected final TargetDescription target; - private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface; private volatile HotSpotGraphCache cache; protected final HotSpotVMConfig config; - private final HotSpotBackend backend; + private final HotSpotBackend hostBackend; - protected HotSpotGraalRuntime() { + private final Map, HotSpotBackend> backends = new HashMap<>(); + + private HotSpotGraalRuntime() { CompilerToVM toVM = new CompilerToVMImpl(); CompilerToGPU toGPU = new CompilerToGPUImpl(); - - // initialize VmToCompiler VMToCompiler toCompiler = new VMToCompilerImpl(this); compilerToVm = toVM; @@ -213,18 +207,64 @@ printConfig(config); } - target = createTarget(); - providers = createProviders(); - assert wordKind == null || wordKind.equals(target.wordKind); - wordKind = target.wordKind; + String hostArchitecture = getHostArchitectureName(); + hostBackend = registerBackend(findFactory(hostArchitecture).createBackend(this, null)); - backend = createBackend(); + String[] gpuArchitectures = getGPUArchitectureNames(); + for (String arch : gpuArchitectures) { + HotSpotBackendFactory factory = findFactory(arch); + if (factory == null) { + throw new GraalInternalError("No backend available for specified GPU architecture \"%s\"", arch); + } + registerBackend(factory.createBackend(this, hostBackend)); + } + GraalOptions.StackShadowPages.setValue(config.stackShadowPages); if (GraalOptions.CacheGraphs.getValue()) { - cache = new HotSpotGraphCache(); + cache = new HotSpotGraphCache(compilerToVm); } } + private HotSpotBackend registerBackend(HotSpotBackend backend) { + Class arch = backend.getTarget().arch.getClass(); + HotSpotBackend oldValue = backends.put(arch, backend); + assert oldValue == null : "cannot overwrite existing backend for architecture " + arch.getSimpleName(); + return backend; + } + + /** + * Gets the host architecture name for the purpose of finding the corresponding + * {@linkplain HotSpotBackendFactory backend}. + */ + private static String getHostArchitectureName() { + String arch = System.getProperty("os.arch"); + switch (arch) { + case "x86_64": + // This is what Mac OS X reports; + arch = "amd64"; + break; + } + return arch; + } + + public static final String GRAAL_GPU_ISALIST_PROPERTY_NAME = "graal.gpu.isalist"; + + /** + * Gets the names of the supported GPU architectures for the purpose of finding the + * corresponding {@linkplain HotSpotBackendFactory backend} objects. This method first looks for + * a comma or {@link java.io.File#pathSeparatorChar} separated list of names in the + * {@value #GRAAL_GPU_ISALIST_PROPERTY_NAME} system property. If this property is not set, then + * the GPU native support code is queried. + */ + private static String[] getGPUArchitectureNames() { + String gpuList = System.getProperty(GRAAL_GPU_ISALIST_PROPERTY_NAME); + if (gpuList != null && !gpuList.isEmpty()) { + String[] gpus = gpuList.split("[,:]"); + return gpus; + } + return new String[0]; + } + private static void printConfig(HotSpotVMConfig config) { Field[] fields = config.getClass().getDeclaredFields(); Map sortedFields = new TreeMap<>(); @@ -240,26 +280,15 @@ } } - protected abstract HotSpotProviders createProviders(); - - protected abstract TargetDescription createTarget(); - - protected abstract HotSpotBackend createBackend(); - - /** - * Gets the registers that must be saved across a foreign call into the runtime. - */ - protected abstract Value[] getNativeABICallerSaveRegisters(); - public HotSpotVMConfig getConfig() { return config; } public TargetDescription getTarget() { - return target; + return hostBackend.getTarget(); } - public HotSpotGraphCache getCache() { + public HotSpotGraphCache getGraphCache() { return cache; } @@ -309,26 +338,13 @@ public HotSpotRuntimeInterpreterInterface getRuntimeInterpreterInterface() { if (runtimeInterpreterInterface == null) { - runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(providers.getMetaAccess()); + runtimeInterpreterInterface = new HotSpotRuntimeInterpreterInterface(getHostProviders().getMetaAccess()); } return runtimeInterpreterInterface; } - public HotSpotProviders getProviders() { - return providers; - } - - public void evictDeoptedGraphs() { - if (cache != null) { - long[] deoptedGraphs = getCompilerToVM().getDeoptedLeafGraphIds(); - if (deoptedGraphs != null) { - if (deoptedGraphs.length == 0) { - cache.clear(); - } else { - cache.removeGraphs(deoptedGraphs); - } - } - } + public HotSpotProviders getHostProviders() { + return getHostBackend().getProviders(); } @Override @@ -339,44 +355,23 @@ @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { - if (clazz == LoweringProvider.class) { - return (T) providers.getLowerer(); - } - if (clazz == CodeCacheProvider.class) { - return (T) providers.getCodeCache(); - } - if (clazz == MetaAccessProvider.class) { - return (T) providers.getMetaAccess(); - } - if (clazz == ConstantReflectionProvider.class) { - return (T) providers.getConstantReflection(); - } - if (clazz == ForeignCallsProvider.class) { - return (T) providers.getForeignCalls(); - } - if (clazz == DisassemblerProvider.class) { - return (T) providers.getDisassembler(); - } - if (clazz == BytecodeDisassemblerProvider.class) { - return (T) providers.getBytecodeDisassembler(); - } - if (clazz == SuitesProvider.class) { - return (T) providers.getSuites(); - } - if (clazz == Replacements.class) { - return (T) providers.getReplacements(); - } - if (clazz == HotSpotRegistersProvider.class) { - return (T) providers.getRegisters(); - } - if (clazz == Backend.class) { - return (T) getBackend(); + if (clazz == RuntimeProvider.class) { + return (T) this; } return null; } - public HotSpotBackend getBackend() { - return backend; + public HotSpotBackend getHostBackend() { + return hostBackend; + } + + public Backend getBackend(Class arch) { + assert arch != Architecture.class; + return backends.get(arch); + } + + public Map, HotSpotBackend> getBackends() { + return Collections.unmodifiableMap(backends); } /** diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntimeFactory.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntimeFactory.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot; - -public interface HotSpotGraalRuntimeFactory { - - HotSpotGraalRuntime createRuntime(); - - String getArchitecture(); - - String getName(); -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPU.java Mon Oct 21 11:07:47 2013 +0200 @@ -48,8 +48,7 @@ int availableProcessors(); /** - * Attempts to generate and return a bound function to the - * loaded method kernel on the GPU. + * Attempts to generate and return a bound function to the loaded method kernel on the GPU. * * @param code the text or binary values for a method kernel * @return the value of the bound kernel in GPU space. @@ -58,7 +57,5 @@ Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; - - Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, - Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToGPUImpl.java Mon Oct 21 11:07:47 2013 +0200 @@ -26,7 +26,6 @@ import com.oracle.graal.api.code.InvalidInstalledCodeException; import com.oracle.graal.hotspot.meta.HotSpotInstalledCode; - /** * Entries into the HotSpot GPU interface from Java code. */ @@ -40,10 +39,7 @@ public native int availableProcessors(); - public native Object executeExternalMethodVarargs(Object[] args, - HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + public native Object executeExternalMethodVarargs(Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; - public native Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, - Object[] args, - HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; + public native Object executeParallelMethodVarargs(int dimX, int dimY, int dimZ, Object[] args, HotSpotInstalledCode hotspotInstalledCode) throws InvalidInstalledCodeException; } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Mon Oct 21 11:07:47 2013 +0200 @@ -128,7 +128,7 @@ bootstrapRunning = bootstrapEnabled; - HotSpotVMConfig config = runtime.getConfig(); + final HotSpotVMConfig config = runtime.getConfig(); long offset = config.graalMirrorInClassOffset; initMirror(typeBoolean, offset); initMirror(typeChar, offset); @@ -180,9 +180,8 @@ } } - final HotSpotProviders providers = runtime.getProviders(); - final MetaAccessProvider metaAccess = providers.getMetaAccess(); - assert VerifyOptionsPhase.checkOptions(metaAccess, providers.getForeignCalls()); + final HotSpotProviders hostProviders = runtime.getHostProviders(); + assert VerifyOptionsPhase.checkOptions(hostProviders.getMetaAccess(), hostProviders.getForeignCalls()); // Install intrinsics. if (Intrinsify.getValue()) { @@ -190,15 +189,35 @@ @Override public void run() { + + List initializedLowerers = new ArrayList<>(); + List initializedForeignCalls = new ArrayList<>(); + + for (Map.Entry e : runtime.getBackends().entrySet()) { + HotSpotBackend backend = e.getValue(); + HotSpotProviders providers = backend.getProviders(); + + HotSpotForeignCallsProvider foreignCalls = providers.getForeignCalls(); + if (!initializedForeignCalls.contains(foreignCalls)) { + initializedForeignCalls.add(foreignCalls); + foreignCalls.initialize(providers, config); + } + HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); + if (!initializedLowerers.contains(lowerer)) { + initializedLowerers.add(lowerer); + initializeLowerer(providers, lowerer); + } + } + } + + private void initializeLowerer(HotSpotProviders providers, HotSpotLoweringProvider lowerer) { final Replacements replacements = providers.getReplacements(); - ServiceLoader serviceLoader = ServiceLoader.loadInstalled(ReplacementsProvider.class); + ServiceLoader sl = ServiceLoader.loadInstalled(ReplacementsProvider.class); TargetDescription target = providers.getCodeCache().getTarget(); - HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - for (ReplacementsProvider provider : serviceLoader) { - provider.registerReplacements(metaAccess, lowerer, replacements, target); + for (ReplacementsProvider replacementsProvider : sl) { + replacementsProvider.registerReplacements(providers.getMetaAccess(), lowerer, replacements, target); } - providers.getForeignCalls().initialize(providers); - lowerer.initialize(); + lowerer.initialize(providers, config); if (BootstrapReplacements.getValue()) { for (ResolvedJavaMethod method : replacements.getAllReplacements()) { replacements.getMacroSubstitution(method); @@ -326,6 +345,14 @@ TTY.print("."); TTY.flush(); } + + // Are we out of time? + final int timedBootstrap = TimedBootstrap.getValue(); + if (timedBootstrap != -1) { + if ((System.currentTimeMillis() - startTime) > timedBootstrap) { + break; + } + } } } while ((System.currentTimeMillis() - startTime) <= TimedBootstrap.getValue()); @@ -334,8 +361,8 @@ bootstrapRunning = false; TTY.println(" in %d ms (compiled %d methods)", System.currentTimeMillis() - startTime, compileQueue.getCompletedTaskCount()); - if (runtime.getCache() != null) { - runtime.getCache().clear(); + if (runtime.getGraphCache() != null) { + runtime.getGraphCache().clear(); } System.gc(); phaseTransition("bootstrap2"); @@ -350,7 +377,7 @@ private MetricRateInPhase inlinedBytecodesPerSecond; private void enqueue(Method m) throws Throwable { - JavaMethod javaMethod = runtime.getProviders().getMetaAccess().lookupJavaMethod(m); + JavaMethod javaMethod = runtime.getHostProviders().getMetaAccess().lookupJavaMethod(m); assert !Modifier.isAbstract(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) && !Modifier.isNative(((HotSpotResolvedJavaMethod) javaMethod).getModifiers()) : javaMethod; compileMethod((HotSpotResolvedJavaMethod) javaMethod, StructuredGraph.INVOCATION_ENTRY_BCI, false); } @@ -557,7 +584,8 @@ final OptimisticOptimizations optimisticOpts = new OptimisticOptimizations(method); int id = compileTaskIds.incrementAndGet(); - CompilationTask task = CompilationTask.create(runtime, createPhasePlan(optimisticOpts, osrCompilation), optimisticOpts, method, entryBCI, id); + HotSpotBackend backend = runtime.getHostBackend(); + CompilationTask task = CompilationTask.create(backend, createPhasePlan(backend.getProviders(), optimisticOpts, osrCompilation), optimisticOpts, method, entryBCI, id); if (blocking) { task.runCompilation(); @@ -690,10 +718,10 @@ return new LocalImpl(name, type, holder, bciStart, bciEnd, slot); } - public PhasePlan createPhasePlan(OptimisticOptimizations optimisticOpts, boolean onStackReplacement) { + public PhasePlan createPhasePlan(HotSpotProviders providers, OptimisticOptimizations optimisticOpts, boolean onStackReplacement) { PhasePlan phasePlan = new PhasePlan(); - MetaAccessProvider metaAccess = runtime.getProviders().getMetaAccess(); - ForeignCallsProvider foreignCalls = runtime.getProviders().getForeignCalls(); + MetaAccessProvider metaAccess = providers.getMetaAccess(); + ForeignCallsProvider foreignCalls = providers.getForeignCalls(); phasePlan.addPhase(PhasePosition.AFTER_PARSING, new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getDefault(), optimisticOpts)); if (onStackReplacement) { phasePlan.addPhase(PhasePosition.AFTER_PARSING, new OnStackReplacementPhase()); diff -r 935dcd8ad8eb -r e47f373499ec 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 Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotCodeCacheProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -44,10 +44,12 @@ public abstract class HotSpotCodeCacheProvider implements CodeCacheProvider { protected final HotSpotGraalRuntime runtime; + protected final TargetDescription target; protected final RegisterConfig regConfig; - public HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime) { + public HotSpotCodeCacheProvider(HotSpotGraalRuntime runtime, TargetDescription target) { this.runtime = runtime; + this.target = target; regConfig = createRegisterConfig(); } @@ -57,7 +59,6 @@ public String disassemble(CompilationResult compResult, InstalledCode installedCode) { byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode(); long start = installedCode == null ? 0L : installedCode.getStart(); - TargetDescription target = runtime.getTarget(); HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8); if (compResult != null) { HexCodeFile.addAnnotations(hcf, compResult.getAnnotations()); @@ -191,7 +192,7 @@ @Override public TargetDescription getTarget() { - return runtime.getTarget(); + return target; } public String disassemble(InstalledCode code) { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotForeignCallsProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,202 +22,19 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.api.code.CallingConvention.Type.*; -import static com.oracle.graal.api.meta.LocationIdentity.*; -import static com.oracle.graal.hotspot.HotSpotBackend.*; -import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; -import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; -import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; -import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; -import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; -import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; -import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*; -import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; -import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*; -import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*; -import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*; -import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*; -import static com.oracle.graal.hotspot.stubs.NewArrayStub.*; -import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; -import static com.oracle.graal.hotspot.stubs.StubUtil.*; -import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*; -import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; -import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; -import static com.oracle.graal.replacements.Log.*; -import static com.oracle.graal.replacements.MathSubstitutionsX86.*; - -import java.util.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect; -import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition; -import com.oracle.graal.hotspot.stubs.*; -import com.oracle.graal.word.*; /** - * HotSpot implementation of {@link ForeignCallsProvider}. + * HotSpot extension of {@link ForeignCallsProvider}. */ -public class HotSpotForeignCallsProvider implements ForeignCallsProvider { - - public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class); - public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class); - public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class); - public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class); - - protected final HotSpotGraalRuntime runtime; - - private final Map foreignCalls = new HashMap<>(); - - public HotSpotForeignCallsProvider(HotSpotGraalRuntime runtime) { - this.runtime = runtime; - } - - /** - * Registers the linkage for a foreign call. - */ - protected HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) { - assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor(); - foreignCalls.put(linkage.getDescriptor(), linkage); - return linkage; - } +public interface HotSpotForeignCallsProvider extends ForeignCallsProvider { - /** - * Creates and registers the details for linking a foreign call to a {@link Stub}. - * - * @param descriptor the signature of the call to the stub - * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side - * effects. Deoptimization will not return to a point before a stub call that cannot - * be re-executed. - * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call - * @param killedLocations the memory locations killed by the stub call - */ - protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) { - return register(HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); - } - - /** - * Creates and registers the linkage for a foreign call. - * - * @param descriptor the signature of the foreign call - * @param address the address of the code to call - * @param outgoingCcType outgoing (caller) calling convention type - * @param effect specifies if the call destroys or preserves all registers (apart from - * temporaries which are always destroyed) - * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call - * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) - * side effects. Deoptimization will not return to a point before a foreign call that - * cannot be re-executed. - * @param killedLocations the memory locations killed by the foreign call - */ - protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type outgoingCcType, RegisterEffect effect, Transition transition, - boolean reexecutable, LocationIdentity... killedLocations) { - Class resultType = descriptor.getResultType(); - assert transition == LEAF || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor; - return register(HotSpotForeignCallLinkage.create(descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations)); - } - - private static void link(Stub stub) { - stub.getLinkage().setCompiledStub(stub); - } + void initialize(HotSpotProviders providers, HotSpotVMConfig config); /** - * Creates a {@linkplain ForeignCallStub stub} for a foreign call. - * - * @param descriptor the signature of the call to the stub - * @param address the address of the foreign code to call - * @param prependThread true if the JavaThread value for the current thread is to be prepended - * to the arguments for the call to {@code address} - * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call - * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) - * side effects. Deoptimization will not return to a point before a foreign call that - * cannot be re-executed. - * @param killedLocations the memory locations killed by the foreign call + * Gets the registers that must be saved across a foreign call into the runtime. */ - private void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, - LocationIdentity... killedLocations) { - ForeignCallStub stub = new ForeignCallStub(providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); - HotSpotForeignCallLinkage linkage = stub.getLinkage(); - HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); - linkage.setCompiledStub(stub); - register(linkage); - register(targetLinkage); - } - - public static final boolean PREPEND_THREAD = true; - public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; - - public static final boolean REEXECUTABLE = true; - public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE; - - public static final LocationIdentity[] NO_LOCATIONS = {}; - - public void initialize(HotSpotProviders providers) { - HotSpotVMConfig c = runtime.getConfig(); - TargetDescription target = providers.getCodeCache().getTarget(); - - registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - - registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - - registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); - - link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); - link(new NewArrayStub(providers, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION))); - link(new ExceptionHandlerStub(providers, target, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(providers, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); - link(new VerifyOopStub(providers, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS))); - - linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION); - linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(providers, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(providers, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); - linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); - linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF, NOT_REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - } - - public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { - HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor); - assert foreignCalls != null : descriptor; - callTarget.finalizeAddress(runtime.getBackend()); - return callTarget; - } - - @Override - public boolean isReexecutable(ForeignCallDescriptor descriptor) { - return foreignCalls.get(descriptor).isReexecutable(); - } - - public boolean canDeoptimize(ForeignCallDescriptor descriptor) { - return foreignCalls.get(descriptor).canDeoptimize(); - } - - public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { - return foreignCalls.get(descriptor).getKilledLocations(); - } + Value[] getNativeABICallerSaveRegisters(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotGraphCache.java Mon Oct 21 11:07:47 2013 +0200 @@ -30,6 +30,7 @@ import java.util.Map.Entry; import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -96,7 +97,8 @@ private final Map> cachedGraphIds = Collections.synchronizedMap(new LRUCache()); - public HotSpotGraphCache() { + public HotSpotGraphCache(CompilerToVM compilerToVM) { + this.compilerToVM = compilerToVM; if (PrintGraphCache.getValue()) { Runtime.getRuntime().addShutdownHook(new Thread() { @@ -127,7 +129,7 @@ } @Override - public void put(StructuredGraph graph, boolean hasMatureProfilingInfo) { + public boolean put(StructuredGraph graph, boolean hasMatureProfilingInfo) { assert graph.method() != null; if (hasMatureProfilingInfo) { cachedGraphIds.put(graph.graphId(), new WeakReference<>(graph.method())); @@ -136,7 +138,9 @@ if (PrintGraphCache.getValue()) { putCounter++; } + return true; } + return false; } public void clear() { @@ -174,4 +178,17 @@ } } } + + private final CompilerToVM compilerToVM; + + public void removeStaleGraphs() { + long[] deoptedGraphs = compilerToVM.getDeoptedLeafGraphIds(); + if (deoptedGraphs != null) { + if (deoptedGraphs.length == 0) { + clear(); + } else { + removeGraphs(deoptedGraphs); + } + } + } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.meta; + +import static com.oracle.graal.api.code.CallingConvention.Type.*; +import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.hotspot.HotSpotBackend.*; +import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect.*; +import static com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition.*; +import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; +import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; +import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; +import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; +import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.replacements.MonitorSnippets.*; +import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; +import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*; +import static com.oracle.graal.hotspot.replacements.ThreadSubstitutions.*; +import static com.oracle.graal.hotspot.replacements.WriteBarrierSnippets.*; +import static com.oracle.graal.hotspot.stubs.ExceptionHandlerStub.*; +import static com.oracle.graal.hotspot.stubs.NewArrayStub.*; +import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; +import static com.oracle.graal.hotspot.stubs.StubUtil.*; +import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*; +import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; +import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; +import static com.oracle.graal.replacements.Log.*; +import static com.oracle.graal.replacements.MathSubstitutionsX86.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.RegisterEffect; +import com.oracle.graal.hotspot.HotSpotForeignCallLinkage.Transition; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.word.*; + +/** + * HotSpot implementation of {@link ForeignCallsProvider}. + */ +public abstract class HotSpotHostForeignCallsProvider implements HotSpotForeignCallsProvider { + + public static final ForeignCallDescriptor OSR_MIGRATION_END = new ForeignCallDescriptor("OSR_migration_end", void.class, long.class); + public static final ForeignCallDescriptor IDENTITY_HASHCODE = new ForeignCallDescriptor("identity_hashcode", int.class, Object.class); + public static final ForeignCallDescriptor VERIFY_OOP = new ForeignCallDescriptor("verify_oop", Object.class, Object.class); + public static final ForeignCallDescriptor LOAD_AND_CLEAR_EXCEPTION = new ForeignCallDescriptor("load_and_clear_exception", Object.class, Word.class); + + protected final HotSpotGraalRuntime runtime; + + private final Map foreignCalls = new HashMap<>(); + private final MetaAccessProvider metaAccess; + private final CodeCacheProvider codeCache; + + public HotSpotHostForeignCallsProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache) { + this.runtime = runtime; + this.metaAccess = metaAccess; + this.codeCache = codeCache; + } + + /** + * Registers the linkage for a foreign call. + */ + protected HotSpotForeignCallLinkage register(HotSpotForeignCallLinkage linkage) { + assert !foreignCalls.containsKey(linkage.getDescriptor()) : "already registered linkage for " + linkage.getDescriptor(); + foreignCalls.put(linkage.getDescriptor(), linkage); + return linkage; + } + + /** + * Creates and registers the details for linking a foreign call to a {@link Stub}. + * + * @param descriptor the signature of the call to the stub + * @param reexecutable specifies if the stub call can be re-executed without (meaningful) side + * effects. Deoptimization will not return to a point before a stub call that cannot + * be re-executed. + * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call + * @param killedLocations the memory locations killed by the stub call + */ + protected HotSpotForeignCallLinkage registerStubCall(ForeignCallDescriptor descriptor, boolean reexecutable, Transition transition, LocationIdentity... killedLocations) { + return register(HotSpotForeignCallLinkage.create(metaAccess, codeCache, this, descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); + } + + /** + * Creates and registers the linkage for a foreign call. + * + * @param descriptor the signature of the foreign call + * @param address the address of the code to call + * @param outgoingCcType outgoing (caller) calling convention type + * @param effect specifies if the call destroys or preserves all registers (apart from + * temporaries which are always destroyed) + * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call + * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) + * side effects. Deoptimization will not return to a point before a foreign call that + * cannot be re-executed. + * @param killedLocations the memory locations killed by the foreign call + */ + protected HotSpotForeignCallLinkage registerForeignCall(ForeignCallDescriptor descriptor, long address, CallingConvention.Type outgoingCcType, RegisterEffect effect, Transition transition, + boolean reexecutable, LocationIdentity... killedLocations) { + Class resultType = descriptor.getResultType(); + assert transition == LEAF || resultType.isPrimitive() || Word.class.isAssignableFrom(resultType) : "non-leaf foreign calls must return objects in thread local storage: " + descriptor; + return register(HotSpotForeignCallLinkage.create(metaAccess, codeCache, this, descriptor, address, effect, outgoingCcType, null, transition, reexecutable, killedLocations)); + } + + private static void link(Stub stub) { + stub.getLinkage().setCompiledStub(stub); + } + + /** + * Creates a {@linkplain ForeignCallStub stub} for a foreign call. + * + * @param descriptor the signature of the call to the stub + * @param address the address of the foreign code to call + * @param prependThread true if the JavaThread value for the current thread is to be prepended + * to the arguments for the call to {@code address} + * @param transition specifies if this is a {@linkplain Transition#LEAF leaf} call + * @param reexecutable specifies if the foreign call can be re-executed without (meaningful) + * side effects. Deoptimization will not return to a point before a foreign call that + * cannot be re-executed. + * @param killedLocations the memory locations killed by the foreign call + */ + private void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, + LocationIdentity... killedLocations) { + ForeignCallStub stub = new ForeignCallStub(providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); + HotSpotForeignCallLinkage linkage = stub.getLinkage(); + HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); + linkage.setCompiledStub(stub); + register(linkage); + register(targetLinkage); + } + + public static final boolean PREPEND_THREAD = true; + public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; + + public static final boolean REEXECUTABLE = true; + public static final boolean NOT_REEXECUTABLE = !REEXECUTABLE; + + public static final LocationIdentity[] NO_LOCATIONS = {}; + + public void initialize(HotSpotProviders providers, HotSpotVMConfig c) { + TargetDescription target = providers.getCodeCache().getTarget(); + + registerForeignCall(UNCOMMON_TRAP, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(DEOPT_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + + registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(JAVA_TIME_NANOS, c.javaTimeNanosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_SIN, c.arithmeticSinAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_COS, c.arithmeticCosAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(ARITHMETIC_TAN, c.arithmeticTanAddress, NativeCall, DESTROYS_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(LOAD_AND_CLEAR_EXCEPTION, c.loadAndClearExceptionAddress, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + + registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + + link(new NewInstanceStub(providers, target, registerStubCall(NEW_INSTANCE, REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new NewArrayStub(providers, target, registerStubCall(NEW_ARRAY, REEXECUTABLE, NOT_LEAF, INIT_LOCATION))); + link(new ExceptionHandlerStub(providers, target, foreignCalls.get(EXCEPTION_HANDLER))); + link(new UnwindExceptionToCallerStub(providers, target, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, NOT_LEAF, ANY_LOCATION))); + link(new VerifyOopStub(providers, target, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF, NO_LOCATIONS))); + + linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, MARK_WORD_LOCATION); + linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(providers, CREATE_NULL_POINTER_EXCEPTION, c.createNullPointerExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(providers, CREATE_OUT_OF_BOUNDS_EXCEPTION, c.createOutOfBoundsExceptionAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, ANY_LOCATION); + linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); + linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, INIT_LOCATION); + linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, NOT_LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF, NOT_REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + } + + public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) { + HotSpotForeignCallLinkage callTarget = foreignCalls.get(descriptor); + assert foreignCalls != null : descriptor; + callTarget.finalizeAddress(runtime.getHostBackend()); + return callTarget; + } + + @Override + public boolean isReexecutable(ForeignCallDescriptor descriptor) { + return foreignCalls.get(descriptor).isReexecutable(); + } + + public boolean canDeoptimize(ForeignCallDescriptor descriptor) { + return foreignCalls.get(descriptor).canDeoptimize(); + } + + public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) { + return foreignCalls.get(descriptor).getKilledLocations(); + } + + /** + * Gets the registers that must be saved across a foreign call into the runtime. + */ + public abstract Value[] getNativeABICallerSaveRegisters(); +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostLoweringProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostLoweringProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.meta; + +import static com.oracle.graal.api.code.MemoryBarriers.*; +import static com.oracle.graal.api.meta.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.api.meta.LocationIdentity.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; +import static com.oracle.graal.nodes.java.ArrayLengthNode.*; +import static com.oracle.graal.phases.GraalOptions.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.debug.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.replacements.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.HeapAccess.BarrierType; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.debug.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.replacements.*; + +/** + * HotSpot implementation of {@link LoweringProvider}. + */ +public class HotSpotHostLoweringProvider implements HotSpotLoweringProvider { + + protected final HotSpotGraalRuntime runtime; + protected final MetaAccessProvider metaAccess; + protected final ForeignCallsProvider foreignCalls; + + private CheckCastDynamicSnippets.Templates checkcastDynamicSnippets; + private InstanceOfSnippets.Templates instanceofSnippets; + private NewObjectSnippets.Templates newObjectSnippets; + private MonitorSnippets.Templates monitorSnippets; + protected WriteBarrierSnippets.Templates writeBarrierSnippets; + private BoxingSnippets.Templates boxingSnippets; + private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; + private UnsafeLoadSnippets.Templates unsafeLoadSnippets; + + public HotSpotHostLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) { + this.runtime = runtime; + this.metaAccess = metaAccess; + this.foreignCalls = foreignCalls; + } + + public void initialize(HotSpotProviders providers, HotSpotVMConfig config) { + Replacements r = providers.getReplacements(); + + r.registerSubstitutions(ObjectSubstitutions.class); + r.registerSubstitutions(SystemSubstitutions.class); + r.registerSubstitutions(ThreadSubstitutions.class); + r.registerSubstitutions(UnsafeSubstitutions.class); + r.registerSubstitutions(ClassSubstitutions.class); + r.registerSubstitutions(AESCryptSubstitutions.class); + r.registerSubstitutions(CipherBlockChainingSubstitutions.class); + r.registerSubstitutions(CRC32Substitutions.class); + r.registerSubstitutions(ReflectionSubstitutions.class); + + TargetDescription target = providers.getCodeCache().getTarget(); + checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, target); + instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); + newObjectSnippets = new NewObjectSnippets.Templates(providers, target); + monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target); + boxingSnippets = new BoxingSnippets.Templates(providers, target); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); + unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); + + r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); + } + + @Override + public void lower(Node n, LoweringTool tool) { + HotSpotVMConfig config = runtime.getConfig(); + StructuredGraph graph = (StructuredGraph) n.graph(); + + Kind wordKind = runtime.getTarget().wordKind; + if (n instanceof ArrayLengthNode) { + ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; + ValueNode array = arrayLengthNode.array(); + ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(), + BarrierType.NONE, false)); + tool.createNullCheckGuard(arrayLengthRead, array); + graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); + } else if (n instanceof Invoke) { + Invoke invoke = (Invoke) n; + if (invoke.callTarget() instanceof MethodCallTargetNode) { + + 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 && !ObjectStamp.isObjectNonNull(receiver)) { + receiverNullCheck = tool.createNullCheckGuard(invoke, receiver); + } + JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); + + LoweredCallTargetNode loweredCallTarget = null; + if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { + + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); + if (!hsMethod.getDeclaringClass().isInterface()) { + if (hsMethod.isInVirtualMethodTable()) { + int vtableEntryOffset = hsMethod.vtableEntryOffset(); + assert vtableEntryOffset > 0; + FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck); + + ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod); + // We use LocationNode.ANY_LOCATION for the reads that access the + // compiled code entry as HotSpot does not guarantee they are final + // values. + ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), + StampFactory.forKind(wordKind), BarrierType.NONE, false)); + + loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), + CallingConvention.Type.JavaCall)); + + graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); + graph.addAfterFixed(metaspaceMethod, compiledEntry); + } + } + } + + if (loweredCallTarget == null) { + loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, + callTarget.invokeKind())); + } + callTarget.replaceAndDelete(loweredCallTarget); + } + } else if (n instanceof LoadFieldNode) { + LoadFieldNode loadField = (LoadFieldNode) n; + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); + ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object(); + assert loadField.kind() != Kind.Illegal; + BarrierType barrierType = getFieldLoadBarrierType(field); + ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object))); + graph.replaceFixedWithFixed(loadField, memoryRead); + tool.createNullCheckGuard(memoryRead, object); + + if (loadField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); + graph.addBeforeFixed(memoryRead, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); + graph.addAfterFixed(memoryRead, postMembar); + } + } else if (n instanceof StoreFieldNode) { + StoreFieldNode storeField = (StoreFieldNode) n; + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); + ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object(); + BarrierType barrierType = getFieldStoreBarrierType(storeField); + WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object)); + tool.createNullCheckGuard(memoryWrite, object); + memoryWrite.setStateAfter(storeField.stateAfter()); + graph.replaceFixedWithFixed(storeField, memoryWrite); + FixedWithNextNode last = memoryWrite; + FixedWithNextNode first = memoryWrite; + + if (storeField.isVolatile()) { + MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); + graph.addBeforeFixed(first, preMembar); + MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); + graph.addAfterFixed(last, postMembar); + } + } else if (n instanceof CompareAndSwapNode) { + // Separate out GC barrier semantics + CompareAndSwapNode cas = (CompareAndSwapNode) n; + LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); + LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas), + cas.expected().kind() == Kind.Object)); + atomicNode.setStateAfter(cas.stateAfter()); + graph.replaceFixedWithFixed(cas, atomicNode); + } else if (n instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexed = (LoadIndexedNode) n; + GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool); + Kind elementKind = loadIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); + ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object)); + memoryRead.setGuard(boundsCheck); + graph.replaceFixedWithFixed(loadIndexed, memoryRead); + } else if (n instanceof StoreIndexedNode) { + StoreIndexedNode storeIndexed = (StoreIndexedNode) n; + GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); + Kind elementKind = storeIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); + ValueNode value = storeIndexed.value(); + ValueNode array = storeIndexed.array(); + + CheckCastNode checkcastNode = null; + CheckCastDynamicNode checkcastDynamicNode = null; + if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) { + // Store check! + ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); + if (arrayType != null && ObjectStamp.isExactType(array)) { + ResolvedJavaType elementType = arrayType.getComponentType(); + if (!MetaUtil.isJavaLangObject(elementType)) { + checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); + graph.addBeforeFixed(storeIndexed, checkcastNode); + value = checkcastNode; + } + } else { + FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); + /* + * Anchor the read of the element klass to the cfg, because it is only valid + * when arrayClass is an object class, which might not be the case in other + * parts of the compiled method. + */ + FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed))); + checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); + graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); + value = checkcastDynamicNode; + } + } + BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); + WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object)); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + graph.replaceFixedWithFixed(storeIndexed, memoryWrite); + + // Lower the associated checkcast node. + if (checkcastNode != null) { + checkcastNode.lower(tool); + } else if (checkcastDynamicNode != null) { + checkcastDynamicSnippets.lower(checkcastDynamicNode); + } + } else if (n instanceof UnsafeLoadNode) { + UnsafeLoadNode load = (UnsafeLoadNode) n; + if (load.getGuardingCondition() != null) { + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); + LocationNode location = createLocation(load); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible)); + load.replaceAtUsages(memoryRead); + graph.replaceFixedWithFixed(load, valueAnchorNode); + graph.addAfterFixed(valueAnchorNode, memoryRead); + } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { + assert load.kind() != Kind.Illegal; + boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); + if (addReadBarrier(load)) { + unsafeLoadSnippets.lower(load, tool); + } else { + LocationNode location = createLocation(load); + ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible)); + // An unsafe read must not float outside its block otherwise + // it may float above an explicit null check on its object. + memoryRead.setGuard(AbstractBeginNode.prevBegin(load)); + graph.replaceFixedWithFixed(load, memoryRead); + } + } + } else if (n instanceof UnsafeStoreNode) { + UnsafeStoreNode store = (UnsafeStoreNode) n; + LocationNode location = createLocation(store); + ValueNode object = store.object(); + BarrierType barrierType = getUnsafeStoreBarrierType(store); + WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object)); + write.setStateAfter(store.stateAfter()); + graph.replaceFixedWithFixed(store, write); + } else if (n instanceof LoadHubNode) { + LoadHubNode loadHub = (LoadHubNode) n; + assert loadHub.kind() == wordKind; + ValueNode object = loadHub.object(); + GuardingNode guard = loadHub.getGuard(); + FloatingReadNode hub = createReadHub(graph, wordKind, object, guard); + graph.replaceFloating(loadHub, hub); + } else if (n instanceof LoadMethodNode) { + LoadMethodNode loadMethodNode = (LoadMethodNode) n; + ResolvedJavaMethod method = loadMethodNode.getMethod(); + ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method); + graph.replaceFixed(loadMethodNode, metaspaceMethod); + } else if (n instanceof StoreHubNode) { + StoreHubNode storeHub = (StoreHubNode) n; + WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue()); + graph.replaceFixed(storeHub, hub); + } else if (n instanceof CommitAllocationNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + CommitAllocationNode commit = (CommitAllocationNode) n; + + ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + + FixedWithNextNode newObject; + if (virtual instanceof VirtualInstanceNode) { + newObject = graph.add(new NewInstanceNode(virtual.type(), true)); + } else { + ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType(); + newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true)); + } + graph.addBeforeFixed(commit, newObject); + allocations[objIndex] = newObject; + } + int valuePos = 0; + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); + int entryCount = virtual.entryCount(); + + ValueNode newObject = allocations[objIndex]; + if (virtual instanceof VirtualInstanceNode) { + VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos++); + if (value instanceof VirtualObjectNode) { + value = allocations[commit.getVirtualObjects().indexOf(value)]; + } + if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true), + (virtualInstance.field(i).getKind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.IMPRECISE : BarrierType.NONE, + virtualInstance.field(i).getKind() == Kind.Object); + graph.addBeforeFixed(commit, graph.add(write)); + } + } + + } else { + VirtualArrayNode array = (VirtualArrayNode) virtual; + ResolvedJavaType element = array.componentType(); + for (int i = 0; i < entryCount; i++) { + ValueNode value = commit.getValues().get(valuePos++); + if (value instanceof VirtualObjectNode) { + int indexOf = commit.getVirtualObjects().indexOf(value); + assert indexOf != -1 : commit + " " + value; + value = allocations[indexOf]; + } + if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { + WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph), true), + (value.kind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.PRECISE : BarrierType.NONE, value.kind() == Kind.Object); + graph.addBeforeFixed(commit, graph.add(write)); + } + } + } + } + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); + allocations[objIndex] = anchor; + graph.addBeforeFixed(commit, anchor); + } + for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { + for (int lockDepth : commit.getLocks().get(objIndex)) { + MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth)); + graph.addBeforeFixed(commit, enter); + enter.lower(tool); + } + } + for (Node usage : commit.usages().snapshot()) { + AllocatedObjectNode addObject = (AllocatedObjectNode) usage; + int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); + graph.replaceFloating(addObject, allocations[index]); + } + graph.removeFixed(commit); + } + } else if (n instanceof OSRStartNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + OSRStartNode osrStart = (OSRStartNode) n; + StartNode newStart = graph.add(new StartNode()); + LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind))); + ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); + migrationEnd.setStateAfter(osrStart.stateAfter()); + + newStart.setNext(migrationEnd); + FixedNode next = osrStart.next(); + osrStart.setNext(null); + migrationEnd.setNext(next); + graph.setStart(newStart); + + // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) + int localsOffset = (graph.method().getMaxLocals() - 1) * 8; + for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) { + int size = FrameStateBuilder.stackSlots(osrLocal.kind()); + int offset = localsOffset - (osrLocal.index() + size - 1) * 8; + IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1); + ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false)); + osrLocal.replaceAndDelete(load); + graph.addBeforeFixed(migrationEnd, load); + } + osrStart.replaceAtUsages(newStart); + osrStart.safeDelete(); + } + } else if (n instanceof DynamicCounterNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + BenchmarkCounters.lower((DynamicCounterNode) n, runtime.getHostProviders().getRegisters(), runtime.getConfig(), wordKind); + } + } else if (n instanceof CheckCastDynamicNode) { + checkcastDynamicSnippets.lower((CheckCastDynamicNode) n); + } else if (n instanceof InstanceOfNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + instanceofSnippets.lower((InstanceOfNode) n, tool); + } + } else if (n instanceof InstanceOfDynamicNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); + } + } else if (n instanceof NewInstanceNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + newObjectSnippets.lower((NewInstanceNode) n); + } + } else if (n instanceof NewArrayNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + newObjectSnippets.lower((NewArrayNode) n); + } + } else if (n instanceof DynamicNewArrayNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + newObjectSnippets.lower((DynamicNewArrayNode) n); + } + } else if (n instanceof MonitorEnterNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + monitorSnippets.lower((MonitorEnterNode) n, tool); + } + } else if (n instanceof MonitorExitNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { + monitorSnippets.lower((MonitorExitNode) n, tool); + } + } else if (n instanceof G1PreWriteBarrier) { + writeBarrierSnippets.lower((G1PreWriteBarrier) n, tool); + } else if (n instanceof G1PostWriteBarrier) { + writeBarrierSnippets.lower((G1PostWriteBarrier) n, tool); + } else if (n instanceof G1ReferentFieldReadBarrier) { + writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool); + } else if (n instanceof SerialWriteBarrier) { + writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); + } else if (n instanceof SerialArrayRangeWriteBarrier) { + writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); + } else if (n instanceof G1ArrayRangePreWriteBarrier) { + writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, tool); + } else if (n instanceof G1ArrayRangePostWriteBarrier) { + writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool); + } else if (n instanceof NewMultiArrayNode) { + if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { + newObjectSnippets.lower((NewMultiArrayNode) n); + } + } else if (n instanceof LoadExceptionObjectNode) { + exceptionObjectSnippets.lower((LoadExceptionObjectNode) n); + } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { + // Nothing to do for division nodes. The HotSpot signal handler catches divisions by + // zero and the MIN_VALUE / -1 cases. + } else if (n instanceof BoxNode) { + boxingSnippets.lower((BoxNode) n, tool); + } else if (n instanceof UnboxNode) { + boxingSnippets.lower((UnboxNode) n, tool); + } else { + assert false : "Node implementing Lowerable not handled: " + n; + throw GraalInternalError.shouldNotReachHere(); + } + } + + private static LocationNode createLocation(UnsafeAccessNode access) { + ValueNode offset = access.offset(); + if (offset.isConstant()) { + long offsetValue = offset.asConstant().asLong(); + return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph()); + } + + long displacement = 0; + int indexScaling = 1; + if (offset instanceof IntegerAddNode) { + IntegerAddNode integerAddNode = (IntegerAddNode) offset; + if (integerAddNode.y() instanceof ConstantNode) { + displacement = integerAddNode.y().asConstant().asLong(); + offset = integerAddNode.x(); + } + } + + if (offset instanceof LeftShiftNode) { + LeftShiftNode leftShiftNode = (LeftShiftNode) offset; + if (leftShiftNode.y() instanceof ConstantNode) { + long shift = leftShiftNode.y().asConstant().asLong(); + if (shift >= 1 && shift <= 3) { + if (shift == 1) { + indexScaling = 2; + } else if (shift == 2) { + indexScaling = 4; + } else { + indexScaling = 8; + } + offset = leftShiftNode.x(); + } + } + } + + return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling); + } + + private static boolean addReadBarrier(UnsafeLoadNode load) { + if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && + !ObjectStamp.isObjectAlwaysNull(load.object())) { + ResolvedJavaType type = ObjectStamp.typeOrNull(load.object()); + if (type != null && !type.isArray()) { + return true; + } + } + return false; + } + + private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, ResolvedJavaMethod method) { + HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; + assert !hsMethod.getDeclaringClass().isInterface(); + assert hsMethod.isInVirtualMethodTable(); + + int vtableEntryOffset = hsMethod.vtableEntryOffset(); + assert vtableEntryOffset > 0; + // We use LocationNode.ANY_LOCATION for the reads that access the vtable + // entry as HotSpot does not guarantee that this is a final value. + ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE, false)); + return metaspaceMethod; + } + + private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) { + HotSpotVMConfig config = runtime.getConfig(); + LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); + assert !object.isConstant() || object.asConstant().isNull(); + return graph.unique(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind), guard, BarrierType.NONE, config.useCompressedClassPointers)); + } + + private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) { + HotSpotVMConfig config = runtime.getConfig(); + LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph); + assert !object.isConstant() || object.asConstant().isNull(); + return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedClassPointers)); + } + + private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) { + BarrierType barrierType = BarrierType.NONE; + if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) { + barrierType = BarrierType.PRECISE; + } + return barrierType; + } + + private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { + BarrierType barrierType = BarrierType.NONE; + if (storeField.field().getKind() == Kind.Object && !deferInitBarrier(storeField.object())) { + barrierType = BarrierType.IMPRECISE; + } + return barrierType; + } + + private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) { + BarrierType barrierType = BarrierType.NONE; + if (store.elementKind() == Kind.Object && !deferInitBarrier(store.array())) { + barrierType = BarrierType.PRECISE; + } + return barrierType; + } + + private static boolean deferInitBarrier(ValueNode object) { + return useDeferredInitBarriers() && (object instanceof NewInstanceNode || object instanceof NewArrayNode); + } + + private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { + BarrierType barrierType = BarrierType.NONE; + if (store.value().kind() == Kind.Object) { + ResolvedJavaType type = ObjectStamp.typeOrNull(store.object()); + if (type != null && !type.isArray()) { + barrierType = BarrierType.IMPRECISE; + } else { + barrierType = BarrierType.PRECISE; + } + } + return barrierType; + } + + private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) { + BarrierType barrierType = BarrierType.NONE; + if (cas.expected().kind() == Kind.Object) { + ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object()); + if (type != null && !type.isArray()) { + barrierType = BarrierType.IMPRECISE; + } else { + barrierType = BarrierType.PRECISE; + } + } + return barrierType; + } + + protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) { + LocationIdentity loc = initialization ? INIT_LOCATION : field; + return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph); + } + + public int getScalingFactor(Kind kind) { + if (useCompressedOops() && kind == Kind.Object) { + return this.runtime.getTarget().arch.getSizeInBytes(Kind.Int); + } else { + return this.runtime.getTarget().arch.getSizeInBytes(kind); + } + } + + protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) { + LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind); + int scale = getScalingFactor(elementKind); + return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale); + } + + @Override + public ValueNode reconstructArrayIndex(LocationNode location) { + Kind elementKind = location.getValueKind(); + assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); + + long base; + ValueNode index; + int scale = getScalingFactor(elementKind); + + if (location instanceof ConstantLocationNode) { + base = ((ConstantLocationNode) location).getDisplacement(); + index = null; + } else if (location instanceof IndexedLocationNode) { + IndexedLocationNode indexedLocation = (IndexedLocationNode) location; + assert indexedLocation.getIndexScaling() == scale; + base = indexedLocation.getDisplacement(); + index = indexedLocation.getIndex(); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + + base -= getArrayBaseOffset(elementKind); + assert base >= 0 && base % scale == 0; + + base /= scale; + assert NumUtil.isInt(base); + + if (index == null) { + return ConstantNode.forInt((int) base, location.graph()); + } else { + if (base == 0) { + return index; + } else { + return IntegerArithmeticNode.add(ConstantNode.forInt((int) base, location.graph()), index); + } + } + } + + private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { + StructuredGraph g = n.graph(); + ValueNode array = n.array(); + ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection()); + if (arrayLength == null) { + Stamp stamp = StampFactory.positiveInt(); + ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false)); + g.addBeforeFixed(n, readArrayLength); + tool.createNullCheckGuard(readArrayLength, array); + arrayLength = readArrayLength; + } + + return tool.createGuard(g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); + } + +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,661 +22,16 @@ */ package com.oracle.graal.hotspot.meta; -import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.meta.DeoptimizationAction.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; -import static com.oracle.graal.api.meta.LocationIdentity.*; -import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProvider.*; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; -import static com.oracle.graal.nodes.java.ArrayLengthNode.*; -import static com.oracle.graal.phases.GraalOptions.*; - -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.debug.*; -import com.oracle.graal.hotspot.nodes.*; -import com.oracle.graal.hotspot.replacements.*; -import com.oracle.graal.java.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.HeapAccess.BarrierType; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.debug.*; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.virtual.*; -import com.oracle.graal.replacements.*; /** - * HotSpot implementation of {@link LoweringProvider}. + * HotSpot extension of {@link LoweringProvider}. */ -public class HotSpotLoweringProvider implements LoweringProvider { - - protected final HotSpotGraalRuntime runtime; - protected final MetaAccessProvider metaAccess; - protected final ForeignCallsProvider foreignCalls; - - private CheckCastDynamicSnippets.Templates checkcastDynamicSnippets; - private InstanceOfSnippets.Templates instanceofSnippets; - private NewObjectSnippets.Templates newObjectSnippets; - private MonitorSnippets.Templates monitorSnippets; - protected WriteBarrierSnippets.Templates writeBarrierSnippets; - private BoxingSnippets.Templates boxingSnippets; - private LoadExceptionObjectSnippets.Templates exceptionObjectSnippets; - private UnsafeLoadSnippets.Templates unsafeLoadSnippets; - - public HotSpotLoweringProvider(HotSpotGraalRuntime runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls) { - this.runtime = runtime; - this.metaAccess = metaAccess; - this.foreignCalls = foreignCalls; - } - - public void initialize() { - HotSpotVMConfig c = runtime.getConfig(); - HotSpotProviders providers = runtime.getProviders(); - Replacements r = providers.getReplacements(); - - r.registerSubstitutions(ObjectSubstitutions.class); - r.registerSubstitutions(SystemSubstitutions.class); - r.registerSubstitutions(ThreadSubstitutions.class); - r.registerSubstitutions(UnsafeSubstitutions.class); - r.registerSubstitutions(ClassSubstitutions.class); - r.registerSubstitutions(AESCryptSubstitutions.class); - r.registerSubstitutions(CipherBlockChainingSubstitutions.class); - r.registerSubstitutions(CRC32Substitutions.class); - r.registerSubstitutions(ReflectionSubstitutions.class); - - checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(providers, runtime.getTarget()); - instanceofSnippets = new InstanceOfSnippets.Templates(providers, runtime.getTarget()); - newObjectSnippets = new NewObjectSnippets.Templates(providers, runtime.getTarget()); - monitorSnippets = new MonitorSnippets.Templates(providers, runtime.getTarget(), c.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, runtime.getTarget()); - boxingSnippets = new BoxingSnippets.Templates(providers, runtime.getTarget()); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, runtime.getTarget()); - unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, runtime.getTarget()); - - r.registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, runtime.getTarget())); - } - - @Override - public void lower(Node n, LoweringTool tool) { - HotSpotVMConfig config = runtime.getConfig(); - StructuredGraph graph = (StructuredGraph) n.graph(); - - Kind wordKind = runtime.getTarget().wordKind; - if (n instanceof ArrayLengthNode) { - ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; - ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt(), - BarrierType.NONE, false)); - tool.createNullCheckGuard(arrayLengthRead, array); - graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); - } else if (n instanceof Invoke) { - Invoke invoke = (Invoke) n; - if (invoke.callTarget() instanceof MethodCallTargetNode) { - - 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 && !ObjectStamp.isObjectNonNull(receiver)) { - receiverNullCheck = tool.createNullCheckGuard(invoke, receiver); - } - JavaType[] signature = MetaUtil.signatureToTypes(callTarget.targetMethod().getSignature(), callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); - - LoweredCallTargetNode loweredCallTarget = null; - if (callTarget.invokeKind() == InvokeKind.Virtual && InlineVTableStubs.getValue() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { - - HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); - if (!hsMethod.getDeclaringClass().isInterface()) { - if (hsMethod.isInVirtualMethodTable()) { - int vtableEntryOffset = hsMethod.vtableEntryOffset(); - assert vtableEntryOffset > 0; - FloatingReadNode hub = createReadHub(graph, wordKind, receiver, receiverNullCheck); - - ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, hub, hsMethod); - // We use LocationNode.ANY_LOCATION for the reads that access the - // compiled code entry as HotSpot does not guarantee they are final - // values. - ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), - StampFactory.forKind(wordKind), BarrierType.NONE, false)); - - loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), - CallingConvention.Type.JavaCall)); - - graph.addBeforeFixed(invoke.asNode(), metaspaceMethod); - graph.addAfterFixed(metaspaceMethod, compiledEntry); - } - } - } - - if (loweredCallTarget == null) { - loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, - callTarget.invokeKind())); - } - callTarget.replaceAndDelete(loweredCallTarget); - } - } else if (n instanceof LoadFieldNode) { - LoadFieldNode loadField = (LoadFieldNode) n; - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); - ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : loadField.object(); - assert loadField.kind() != Kind.Illegal; - BarrierType barrierType = getFieldLoadBarrierType(field); - ReadNode memoryRead = graph.add(new ReadNode(object, createFieldLocation(graph, field, false), loadField.stamp(), barrierType, (loadField.kind() == Kind.Object))); - graph.replaceFixedWithFixed(loadField, memoryRead); - tool.createNullCheckGuard(memoryRead, object); - - if (loadField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_READ)); - graph.addBeforeFixed(memoryRead, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_READ)); - graph.addAfterFixed(memoryRead, postMembar); - } - } else if (n instanceof StoreFieldNode) { - StoreFieldNode storeField = (StoreFieldNode) n; - HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); - ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), metaAccess, graph) : storeField.object(); - BarrierType barrierType = getFieldStoreBarrierType(storeField); - WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), createFieldLocation(graph, field, false), barrierType, storeField.field().getKind() == Kind.Object)); - tool.createNullCheckGuard(memoryWrite, object); - memoryWrite.setStateAfter(storeField.stateAfter()); - graph.replaceFixedWithFixed(storeField, memoryWrite); - FixedWithNextNode last = memoryWrite; - FixedWithNextNode first = memoryWrite; - - if (storeField.isVolatile()) { - MembarNode preMembar = graph.add(new MembarNode(JMM_PRE_VOLATILE_WRITE)); - graph.addBeforeFixed(first, preMembar); - MembarNode postMembar = graph.add(new MembarNode(JMM_POST_VOLATILE_WRITE)); - graph.addAfterFixed(last, postMembar); - } - } else if (n instanceof CompareAndSwapNode) { - // Separate out GC barrier semantics - CompareAndSwapNode cas = (CompareAndSwapNode) n; - LocationNode location = IndexedLocationNode.create(ANY_LOCATION, cas.expected().kind(), cas.displacement(), cas.offset(), graph, 1); - LoweredCompareAndSwapNode atomicNode = graph.add(new LoweredCompareAndSwapNode(cas.object(), location, cas.expected(), cas.newValue(), getCompareAndSwapBarrier(cas), - cas.expected().kind() == Kind.Object)); - atomicNode.setStateAfter(cas.stateAfter()); - graph.replaceFixedWithFixed(cas, atomicNode); - } else if (n instanceof LoadIndexedNode) { - LoadIndexedNode loadIndexed = (LoadIndexedNode) n; - GuardingNode boundsCheck = createBoundsCheck(loadIndexed, tool); - Kind elementKind = loadIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index(), false); - ReadNode memoryRead = graph.add(new ReadNode(loadIndexed.array(), arrayLocation, loadIndexed.stamp(), BarrierType.NONE, elementKind == Kind.Object)); - memoryRead.setGuard(boundsCheck); - graph.replaceFixedWithFixed(loadIndexed, memoryRead); - } else if (n instanceof StoreIndexedNode) { - StoreIndexedNode storeIndexed = (StoreIndexedNode) n; - GuardingNode boundsCheck = createBoundsCheck(storeIndexed, tool); - Kind elementKind = storeIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index(), false); - ValueNode value = storeIndexed.value(); - ValueNode array = storeIndexed.array(); - - CheckCastNode checkcastNode = null; - CheckCastDynamicNode checkcastDynamicNode = null; - if (elementKind == Kind.Object && !ObjectStamp.isObjectAlwaysNull(value)) { - // Store check! - ResolvedJavaType arrayType = ObjectStamp.typeOrNull(array); - if (arrayType != null && ObjectStamp.isExactType(array)) { - ResolvedJavaType elementType = arrayType.getComponentType(); - if (!MetaUtil.isJavaLangObject(elementType)) { - checkcastNode = graph.add(new CheckCastNode(elementType, value, null, true)); - graph.addBeforeFixed(storeIndexed, checkcastNode); - value = checkcastNode; - } - } else { - FloatingReadNode arrayClass = createReadHub(graph, wordKind, array, boundsCheck); - LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); - /* - * Anchor the read of the element klass to the cfg, because it is only valid - * when arrayClass is an object class, which might not be the case in other - * parts of the compiled method. - */ - FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind), BeginNode.prevBegin(storeIndexed))); - checkcastDynamicNode = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); - graph.addBeforeFixed(storeIndexed, checkcastDynamicNode); - value = checkcastDynamicNode; - } - } - BarrierType barrierType = getArrayStoreBarrierType(storeIndexed); - WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation, barrierType, elementKind == Kind.Object)); - memoryWrite.setGuard(boundsCheck); - memoryWrite.setStateAfter(storeIndexed.stateAfter()); - graph.replaceFixedWithFixed(storeIndexed, memoryWrite); - - // Lower the associated checkcast node. - if (checkcastNode != null) { - checkcastNode.lower(tool); - } else if (checkcastDynamicNode != null) { - checkcastDynamicSnippets.lower(checkcastDynamicNode); - } - } else if (n instanceof UnsafeLoadNode) { - UnsafeLoadNode load = (UnsafeLoadNode) n; - if (load.getGuardingCondition() != null) { - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - ConditionAnchorNode valueAnchorNode = graph.add(new ConditionAnchorNode(load.getGuardingCondition())); - LocationNode location = createLocation(load); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), valueAnchorNode, BarrierType.NONE, compressible)); - load.replaceAtUsages(memoryRead); - graph.replaceFixedWithFixed(load, valueAnchorNode); - graph.addAfterFixed(valueAnchorNode, memoryRead); - } else if (graph.getGuardsStage().ordinal() > StructuredGraph.GuardsStage.FLOATING_GUARDS.ordinal()) { - assert load.kind() != Kind.Illegal; - boolean compressible = (!load.object().isNullConstant() && load.accessKind() == Kind.Object); - if (addReadBarrier(load)) { - unsafeLoadSnippets.lower(load, tool); - } else { - LocationNode location = createLocation(load); - ReadNode memoryRead = graph.add(new ReadNode(load.object(), location, load.stamp(), BarrierType.NONE, compressible)); - // An unsafe read must not float outside its block otherwise - // it may float above an explicit null check on its object. - memoryRead.setGuard(AbstractBeginNode.prevBegin(load)); - graph.replaceFixedWithFixed(load, memoryRead); - } - } - } else if (n instanceof UnsafeStoreNode) { - UnsafeStoreNode store = (UnsafeStoreNode) n; - LocationNode location = createLocation(store); - ValueNode object = store.object(); - BarrierType barrierType = getUnsafeStoreBarrierType(store); - WriteNode write = graph.add(new WriteNode(object, store.value(), location, barrierType, store.value().kind() == Kind.Object)); - write.setStateAfter(store.stateAfter()); - graph.replaceFixedWithFixed(store, write); - } else if (n instanceof LoadHubNode) { - LoadHubNode loadHub = (LoadHubNode) n; - assert loadHub.kind() == wordKind; - ValueNode object = loadHub.object(); - GuardingNode guard = loadHub.getGuard(); - FloatingReadNode hub = createReadHub(graph, wordKind, object, guard); - graph.replaceFloating(loadHub, hub); - } else if (n instanceof LoadMethodNode) { - LoadMethodNode loadMethodNode = (LoadMethodNode) n; - ResolvedJavaMethod method = loadMethodNode.getMethod(); - ReadNode metaspaceMethod = createReadVirtualMethod(graph, wordKind, loadMethodNode.getHub(), method); - graph.replaceFixed(loadMethodNode, metaspaceMethod); - } else if (n instanceof StoreHubNode) { - StoreHubNode storeHub = (StoreHubNode) n; - WriteNode hub = createWriteHub(graph, wordKind, storeHub.getObject(), storeHub.getValue()); - graph.replaceFixed(storeHub, hub); - } else if (n instanceof CommitAllocationNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - CommitAllocationNode commit = (CommitAllocationNode) n; - - ValueNode[] allocations = new ValueNode[commit.getVirtualObjects().size()]; - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - - FixedWithNextNode newObject; - if (virtual instanceof VirtualInstanceNode) { - newObject = graph.add(new NewInstanceNode(virtual.type(), true)); - } else { - ResolvedJavaType element = ((VirtualArrayNode) virtual).componentType(); - newObject = graph.add(new NewArrayNode(element, ConstantNode.forInt(entryCount, graph), true)); - } - graph.addBeforeFixed(commit, newObject); - allocations[objIndex] = newObject; - } - int valuePos = 0; - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex); - int entryCount = virtual.entryCount(); - - ValueNode newObject = allocations[objIndex]; - if (virtual instanceof VirtualInstanceNode) { - VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual; - for (int i = 0; i < entryCount; i++) { - ValueNode value = commit.getValues().get(valuePos++); - if (value instanceof VirtualObjectNode) { - value = allocations[commit.getVirtualObjects().indexOf(value)]; - } - if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - WriteNode write = new WriteNode(newObject, value, createFieldLocation(graph, (HotSpotResolvedJavaField) virtualInstance.field(i), true), - (virtualInstance.field(i).getKind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.IMPRECISE : BarrierType.NONE, - virtualInstance.field(i).getKind() == Kind.Object); - graph.addBeforeFixed(commit, graph.add(write)); - } - } +public interface HotSpotLoweringProvider extends LoweringProvider { - } else { - VirtualArrayNode array = (VirtualArrayNode) virtual; - ResolvedJavaType element = array.componentType(); - for (int i = 0; i < entryCount; i++) { - ValueNode value = commit.getValues().get(valuePos++); - if (value instanceof VirtualObjectNode) { - int indexOf = commit.getVirtualObjects().indexOf(value); - assert indexOf != -1 : commit + " " + value; - value = allocations[indexOf]; - } - if (!(value.isConstant() && value.asConstant().isDefaultForKind())) { - WriteNode write = new WriteNode(newObject, value, createArrayLocation(graph, element.getKind(), ConstantNode.forInt(i, graph), true), - (value.kind() == Kind.Object && !deferInitBarrier(newObject)) ? BarrierType.PRECISE : BarrierType.NONE, value.kind() == Kind.Object); - graph.addBeforeFixed(commit, graph.add(write)); - } - } - } - } - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex])); - allocations[objIndex] = anchor; - graph.addBeforeFixed(commit, anchor); - } - for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) { - for (int lockDepth : commit.getLocks().get(objIndex)) { - MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], lockDepth)); - graph.addBeforeFixed(commit, enter); - enter.lower(tool); - } - } - for (Node usage : commit.usages().snapshot()) { - AllocatedObjectNode addObject = (AllocatedObjectNode) usage; - int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject()); - graph.replaceFloating(addObject, allocations[index]); - } - graph.removeFixed(commit); - } - } else if (n instanceof OSRStartNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - OSRStartNode osrStart = (OSRStartNode) n; - StartNode newStart = graph.add(new StartNode()); - LocalNode buffer = graph.unique(new LocalNode(0, StampFactory.forKind(wordKind))); - ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); - migrationEnd.setStateAfter(osrStart.stateAfter()); - - newStart.setNext(migrationEnd); - FixedNode next = osrStart.next(); - osrStart.setNext(null); - migrationEnd.setNext(next); - graph.setStart(newStart); - - // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) - int localsOffset = (graph.method().getMaxLocals() - 1) * 8; - for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.class)) { - int size = FrameStateBuilder.stackSlots(osrLocal.kind()); - int offset = localsOffset - (osrLocal.index() + size - 1) * 8; - IndexedLocationNode location = IndexedLocationNode.create(ANY_LOCATION, osrLocal.kind(), offset, ConstantNode.forLong(0, graph), graph, 1); - ReadNode load = graph.add(new ReadNode(buffer, location, osrLocal.stamp(), BarrierType.NONE, false)); - osrLocal.replaceAndDelete(load); - graph.addBeforeFixed(migrationEnd, load); - } - osrStart.replaceAtUsages(newStart); - osrStart.safeDelete(); - } - } else if (n instanceof DynamicCounterNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - BenchmarkCounters.lower((DynamicCounterNode) n, runtime.getProviders().getRegisters(), runtime.getConfig(), wordKind); - } - } else if (n instanceof CheckCastDynamicNode) { - checkcastDynamicSnippets.lower((CheckCastDynamicNode) n); - } else if (n instanceof InstanceOfNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - instanceofSnippets.lower((InstanceOfNode) n, tool); - } - } else if (n instanceof InstanceOfDynamicNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - instanceofSnippets.lower((InstanceOfDynamicNode) n, tool); - } - } else if (n instanceof NewInstanceNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((NewInstanceNode) n); - } - } else if (n instanceof NewArrayNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((NewArrayNode) n); - } - } else if (n instanceof DynamicNewArrayNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((DynamicNewArrayNode) n); - } - } else if (n instanceof MonitorEnterNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - monitorSnippets.lower((MonitorEnterNode) n, tool); - } - } else if (n instanceof MonitorExitNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - monitorSnippets.lower((MonitorExitNode) n, tool); - } - } else if (n instanceof G1PreWriteBarrier) { - writeBarrierSnippets.lower((G1PreWriteBarrier) n, tool); - } else if (n instanceof G1PostWriteBarrier) { - writeBarrierSnippets.lower((G1PostWriteBarrier) n, tool); - } else if (n instanceof G1ReferentFieldReadBarrier) { - writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, tool); - } else if (n instanceof SerialWriteBarrier) { - writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); - } else if (n instanceof SerialArrayRangeWriteBarrier) { - writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); - } else if (n instanceof G1ArrayRangePreWriteBarrier) { - writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, tool); - } else if (n instanceof G1ArrayRangePostWriteBarrier) { - writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, tool); - } else if (n instanceof NewMultiArrayNode) { - if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((NewMultiArrayNode) n); - } - } else if (n instanceof LoadExceptionObjectNode) { - exceptionObjectSnippets.lower((LoadExceptionObjectNode) n); - } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { - // Nothing to do for division nodes. The HotSpot signal handler catches divisions by - // zero and the MIN_VALUE / -1 cases. - } else if (n instanceof BoxNode) { - boxingSnippets.lower((BoxNode) n, tool); - } else if (n instanceof UnboxNode) { - boxingSnippets.lower((UnboxNode) n, tool); - } else { - assert false : "Node implementing Lowerable not handled: " + n; - throw GraalInternalError.shouldNotReachHere(); - } - } - - private static LocationNode createLocation(UnsafeAccessNode access) { - ValueNode offset = access.offset(); - if (offset.isConstant()) { - long offsetValue = offset.asConstant().asLong(); - return ConstantLocationNode.create(access.getLocationIdentity(), access.accessKind(), offsetValue, access.graph()); - } - - long displacement = 0; - int indexScaling = 1; - if (offset instanceof IntegerAddNode) { - IntegerAddNode integerAddNode = (IntegerAddNode) offset; - if (integerAddNode.y() instanceof ConstantNode) { - displacement = integerAddNode.y().asConstant().asLong(); - offset = integerAddNode.x(); - } - } - - if (offset instanceof LeftShiftNode) { - LeftShiftNode leftShiftNode = (LeftShiftNode) offset; - if (leftShiftNode.y() instanceof ConstantNode) { - long shift = leftShiftNode.y().asConstant().asLong(); - if (shift >= 1 && shift <= 3) { - if (shift == 1) { - indexScaling = 2; - } else if (shift == 2) { - indexScaling = 4; - } else { - indexScaling = 8; - } - offset = leftShiftNode.x(); - } - } - } + void initialize(HotSpotProviders providers, HotSpotVMConfig config); - return IndexedLocationNode.create(access.getLocationIdentity(), access.accessKind(), displacement, offset, access.graph(), indexScaling); - } - - private static boolean addReadBarrier(UnsafeLoadNode load) { - if (useG1GC() && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().kind() == Kind.Object && load.accessKind() == Kind.Object && - !ObjectStamp.isObjectAlwaysNull(load.object())) { - ResolvedJavaType type = ObjectStamp.typeOrNull(load.object()); - if (type != null && !type.isArray()) { - return true; - } - } - return false; - } - - private static ReadNode createReadVirtualMethod(StructuredGraph graph, Kind wordKind, ValueNode hub, ResolvedJavaMethod method) { - HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) method; - assert !hsMethod.getDeclaringClass().isInterface(); - assert hsMethod.isInVirtualMethodTable(); - - int vtableEntryOffset = hsMethod.vtableEntryOffset(); - assert vtableEntryOffset > 0; - // We use LocationNode.ANY_LOCATION for the reads that access the vtable - // entry as HotSpot does not guarantee that this is a final value. - ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind), BarrierType.NONE, false)); - return metaspaceMethod; - } - - private FloatingReadNode createReadHub(StructuredGraph graph, Kind wordKind, ValueNode object, GuardingNode guard) { - HotSpotVMConfig config = runtime.getConfig(); - LocationNode location = ConstantLocationNode.create(FINAL_LOCATION, wordKind, config.hubOffset, graph); - assert !object.isConstant() || object.asConstant().isNull(); - return graph.unique(new FloatingReadNode(object, location, null, StampFactory.forKind(wordKind), guard, BarrierType.NONE, config.useCompressedClassPointers)); - } - - private WriteNode createWriteHub(StructuredGraph graph, Kind wordKind, ValueNode object, ValueNode value) { - HotSpotVMConfig config = runtime.getConfig(); - LocationNode location = ConstantLocationNode.create(HUB_LOCATION, wordKind, config.hubOffset, graph); - assert !object.isConstant() || object.asConstant().isNull(); - return graph.add(new WriteNode(object, value, location, BarrierType.NONE, config.useCompressedClassPointers)); - } - - private static BarrierType getFieldLoadBarrierType(HotSpotResolvedJavaField loadField) { - BarrierType barrierType = BarrierType.NONE; - if (config().useG1GC && loadField.getKind() == Kind.Object && loadField.getDeclaringClass().mirror() == java.lang.ref.Reference.class && loadField.getName().equals("referent")) { - barrierType = BarrierType.PRECISE; - } - return barrierType; - } - - private static BarrierType getFieldStoreBarrierType(StoreFieldNode storeField) { - BarrierType barrierType = BarrierType.NONE; - if (storeField.field().getKind() == Kind.Object && !deferInitBarrier(storeField.object())) { - barrierType = BarrierType.IMPRECISE; - } - return barrierType; - } - - private static BarrierType getArrayStoreBarrierType(StoreIndexedNode store) { - BarrierType barrierType = BarrierType.NONE; - if (store.elementKind() == Kind.Object && !deferInitBarrier(store.array())) { - barrierType = BarrierType.PRECISE; - } - return barrierType; - } - - private static boolean deferInitBarrier(ValueNode object) { - return useDeferredInitBarriers() && (object instanceof NewInstanceNode || object instanceof NewArrayNode); - } - - private static BarrierType getUnsafeStoreBarrierType(UnsafeStoreNode store) { - BarrierType barrierType = BarrierType.NONE; - if (store.value().kind() == Kind.Object) { - ResolvedJavaType type = ObjectStamp.typeOrNull(store.object()); - if (type != null && !type.isArray()) { - barrierType = BarrierType.IMPRECISE; - } else { - barrierType = BarrierType.PRECISE; - } - } - return barrierType; - } - - private static BarrierType getCompareAndSwapBarrier(CompareAndSwapNode cas) { - BarrierType barrierType = BarrierType.NONE; - if (cas.expected().kind() == Kind.Object) { - ResolvedJavaType type = ObjectStamp.typeOrNull(cas.object()); - if (type != null && !type.isArray()) { - barrierType = BarrierType.IMPRECISE; - } else { - barrierType = BarrierType.PRECISE; - } - } - return barrierType; - } - - protected static ConstantLocationNode createFieldLocation(StructuredGraph graph, HotSpotResolvedJavaField field, boolean initialization) { - LocationIdentity loc = initialization ? INIT_LOCATION : field; - return ConstantLocationNode.create(loc, field.getKind(), field.offset(), graph); - } - - public int getScalingFactor(Kind kind) { - if (useCompressedOops() && kind == Kind.Object) { - return this.runtime.getTarget().arch.getSizeInBytes(Kind.Int); - } else { - return this.runtime.getTarget().arch.getSizeInBytes(kind); - } - } - - protected IndexedLocationNode createArrayLocation(Graph graph, Kind elementKind, ValueNode index, boolean initialization) { - LocationIdentity loc = initialization ? INIT_LOCATION : NamedLocationIdentity.getArrayLocation(elementKind); - int scale = getScalingFactor(elementKind); - return IndexedLocationNode.create(loc, elementKind, getArrayBaseOffset(elementKind), index, graph, scale); - } - - @Override - public ValueNode reconstructArrayIndex(LocationNode location) { - Kind elementKind = location.getValueKind(); - assert location.getLocationIdentity().equals(NamedLocationIdentity.getArrayLocation(elementKind)); - - long base; - ValueNode index; - int scale = getScalingFactor(elementKind); - - if (location instanceof ConstantLocationNode) { - base = ((ConstantLocationNode) location).getDisplacement(); - index = null; - } else if (location instanceof IndexedLocationNode) { - IndexedLocationNode indexedLocation = (IndexedLocationNode) location; - assert indexedLocation.getIndexScaling() == scale; - base = indexedLocation.getDisplacement(); - index = indexedLocation.getIndex(); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - - base -= getArrayBaseOffset(elementKind); - assert base >= 0 && base % scale == 0; - - base /= scale; - assert NumUtil.isInt(base); - - if (index == null) { - return ConstantNode.forInt((int) base, location.graph()); - } else { - if (base == 0) { - return index; - } else { - return IntegerArithmeticNode.add(ConstantNode.forInt((int) base, location.graph()), index); - } - } - } - - private GuardingNode createBoundsCheck(AccessIndexedNode n, LoweringTool tool) { - StructuredGraph g = n.graph(); - ValueNode array = n.array(); - ValueNode arrayLength = readArrayLength(array, tool.getConstantReflection()); - if (arrayLength == null) { - Stamp stamp = StampFactory.positiveInt(); - ReadNode readArrayLength = g.add(new ReadNode(array, ConstantLocationNode.create(FINAL_LOCATION, Kind.Int, runtime.getConfig().arrayLengthOffset, g), stamp, BarrierType.NONE, false)); - g.addBeforeFixed(n, readArrayLength); - tool.createNullCheckGuard(readArrayLength, array); - arrayLength = readArrayLength; - } - - return tool.createGuard(g.unique(new IntegerBelowThanNode(n.index(), arrayLength)), BoundsCheckException, InvalidateReprofile); - } - + int getScalingFactor(Kind elementKind); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -79,14 +79,29 @@ return runtime.getCompilerToVM().getJavaField(reflectionField); } + private static final int ACTION_SHIFT = 0; + private static final int ACTION_MASK = 0x07; + private static final int REASON_SHIFT = 3; + private static final int REASON_MASK = 0x1f; + @Override public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) { - final int actionShift = 0; - final int reasonShift = 3; - int actionValue = convertDeoptAction(action); int reasonValue = convertDeoptReason(reason); - return Constant.forInt(~(((reasonValue) << reasonShift) + ((actionValue) << actionShift))); + Constant c = Constant.forInt(~(((reasonValue) << REASON_SHIFT) + ((actionValue) << ACTION_SHIFT))); + return c; + } + + public DeoptimizationReason decodeDeoptReason(Constant constant) { + int reasonValue = ((~constant.asInt()) >> REASON_SHIFT) & REASON_MASK; + DeoptimizationReason reason = convertDeoptReason(reasonValue); + return reason; + } + + public DeoptimizationAction decodeDeoptAction(Constant constant) { + int actionValue = ((~constant.asInt()) >> ACTION_SHIFT) & ACTION_MASK; + DeoptimizationAction action = convertDeoptAction(actionValue); + return action; } public int convertDeoptAction(DeoptimizationAction action) { @@ -106,6 +121,22 @@ } } + public DeoptimizationAction convertDeoptAction(int action) { + if (action == runtime.getConfig().deoptActionNone) { + return DeoptimizationAction.None; + } else if (action == runtime.getConfig().deoptActionMaybeRecompile) { + return DeoptimizationAction.RecompileIfTooManyDeopts; + } else if (action == runtime.getConfig().deoptActionReinterpret) { + return DeoptimizationAction.InvalidateReprofile; + } else if (action == runtime.getConfig().deoptActionMakeNotEntrant) { + return DeoptimizationAction.InvalidateRecompile; + } else if (action == runtime.getConfig().deoptActionMakeNotCompilable) { + return DeoptimizationAction.InvalidateStopCompiling; + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } + public int convertDeoptReason(DeoptimizationReason reason) { switch (reason) { case None: @@ -140,4 +171,38 @@ throw GraalInternalError.shouldNotReachHere(); } } + + public DeoptimizationReason convertDeoptReason(int reason) { + if (reason == runtime.getConfig().deoptReasonNone) { + return DeoptimizationReason.None; + } else if (reason == runtime.getConfig().deoptReasonNullCheck) { + return DeoptimizationReason.NullCheckException; + } else if (reason == runtime.getConfig().deoptReasonRangeCheck) { + return DeoptimizationReason.BoundsCheckException; + } else if (reason == runtime.getConfig().deoptReasonClassCheck) { + return DeoptimizationReason.ClassCastException; + } else if (reason == runtime.getConfig().deoptReasonArrayCheck) { + return DeoptimizationReason.ArrayStoreException; + } else if (reason == runtime.getConfig().deoptReasonUnreached0) { + return DeoptimizationReason.UnreachedCode; + } else if (reason == runtime.getConfig().deoptReasonTypeCheckInlining) { + return DeoptimizationReason.TypeCheckedInliningViolated; + } else if (reason == runtime.getConfig().deoptReasonOptimizedTypeCheck) { + return DeoptimizationReason.OptimizedTypeCheckViolated; + } else if (reason == runtime.getConfig().deoptReasonNotCompiledExceptionHandler) { + return DeoptimizationReason.NotCompiledExceptionHandler; + } else if (reason == runtime.getConfig().deoptReasonUnresolved) { + return DeoptimizationReason.Unresolved; + } else if (reason == runtime.getConfig().deoptReasonJsrMismatch) { + return DeoptimizationReason.JavaSubroutineMismatch; + } else if (reason == runtime.getConfig().deoptReasonDiv0Check) { + return DeoptimizationReason.ArithmeticException; + } else if (reason == runtime.getConfig().deoptReasonConstraint) { + return DeoptimizationReason.RuntimeConstraint; + } else if (reason == runtime.getConfig().deoptReasonLoopLimitCheck) { + return DeoptimizationReason.LoopLimitCheck; + } else { + throw GraalInternalError.shouldNotReachHere(Integer.toHexString(reason)); + } + } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java Mon Oct 21 11:07:47 2013 +0200 @@ -78,7 +78,7 @@ } public int getDeoptimizationCount(DeoptimizationReason reason) { - int reasonIndex = runtime().getProviders().getMetaAccess().convertDeoptReason(reason); + int reasonIndex = runtime().getHostProviders().getMetaAccess().convertDeoptReason(reason); return unsafe.getByte(metaspaceMethodData + config.methodDataOopTrapHistoryOffset + reasonIndex) & 0xFF; } diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Mon Oct 21 11:07:47 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.hotspot.meta; import com.oracle.graal.api.meta.*; -import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; @@ -59,10 +58,6 @@ return disassembler; } - public BytecodeDisassemblerProvider getBytecodeDisassembler() { - return new BytecodeDisassembler(); - } - @Override public HotSpotForeignCallsProvider getForeignCalls() { return (HotSpotForeignCallsProvider) super.getForeignCalls(); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Oct 21 11:07:47 2013 +0200 @@ -92,7 +92,7 @@ * only called for snippets or replacements. */ private static boolean isCalledForSnippets() { - MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess(); + MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess(); ResolvedJavaMethod makeGraphMethod = null; ResolvedJavaMethod initMethod = null; try { @@ -119,7 +119,7 @@ private static final Set notEmbeddable = new HashSet<>(); private static void addResolvedToSet(Field field) { - MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess(); + MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess(); notEmbeddable.add(metaAccess.lookupJavaField(field)); } @@ -216,12 +216,12 @@ if (receiver == null) { assert Modifier.isStatic(flags); if (holder.isInitialized()) { - return runtime().getProviders().getConstantReflection().readUnsafeConstant(getKind(), holder.mirror(), offset, getKind() == Kind.Object); + return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), holder.mirror(), offset, getKind() == Kind.Object); } return null; } else { assert !Modifier.isStatic(flags); - return runtime().getProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver.asObject(), offset, getKind() == Kind.Object); + return runtime().getHostProviders().getConstantReflection().readUnsafeConstant(getKind(), receiver.asObject(), offset, getKind() == Kind.Object); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Mon Oct 21 11:07:47 2013 +0200 @@ -113,7 +113,7 @@ * Gets the address of the C++ Method object for this method. */ public Constant getMetaspaceMethodConstant() { - return Constant.forIntegerKind(runtime().getTarget().wordKind, metaspaceMethod, this); + return Constant.forIntegerKind(getHostWordKind(), metaspaceMethod, this); } @Override @@ -343,7 +343,7 @@ // Cannot use toJava() as it ignores the return type HotSpotSignature sig = getSignature(); JavaType[] sigTypes = MetaUtil.signatureToTypes(sig, null); - MetaAccessProvider metaAccess = runtime().getProviders().getMetaAccess(); + MetaAccessProvider metaAccess = runtime().getHostProviders().getMetaAccess(); for (Method method : holder.mirror().getDeclaredMethods()) { if (method.getName().equals(name)) { if (metaAccess.lookupJavaType(method.getReturnType()).equals(sig.getReturnType(holder))) { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Oct 21 11:07:47 2013 +0200 @@ -544,7 +544,7 @@ Constructor[] constructors = javaMirror.getDeclaredConstructors(); ResolvedJavaMethod[] result = new ResolvedJavaMethod[constructors.length]; for (int i = 0; i < constructors.length; i++) { - result[i] = runtime().getProviders().getMetaAccess().lookupJavaConstructor(constructors[i]); + result[i] = runtime().getHostProviders().getMetaAccess().lookupJavaConstructor(constructors[i]); assert result[i].isConstructor(); } return result; @@ -555,7 +555,7 @@ Method[] methods = javaMirror.getDeclaredMethods(); ResolvedJavaMethod[] result = new ResolvedJavaMethod[methods.length]; for (int i = 0; i < methods.length; i++) { - result[i] = runtime().getProviders().getMetaAccess().lookupJavaMethod(methods[i]); + result[i] = runtime().getHostProviders().getMetaAccess().lookupJavaMethod(methods[i]); assert !result[i].isConstructor(); } return result; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/CurrentJavaThreadNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -41,7 +41,7 @@ @Override public void generate(LIRGeneratorTool gen) { - Register rawThread = runtime().getProviders().getRegisters().getThreadRegister(); + Register rawThread = runtime().getHostProviders().getRegisters().getThreadRegister(); gen.setResult(this, rawThread.asValue(this.kind())); } diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotReplacementsUtil.java Mon Oct 21 11:07:47 2013 +0200 @@ -24,7 +24,7 @@ import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProvider.*; +import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; import sun.misc.*; @@ -203,12 +203,12 @@ @Fold public static Register threadRegister() { - return runtime().getProviders().getRegisters().getThreadRegister(); + return runtime().getHostProviders().getRegisters().getThreadRegister(); } @Fold public static Register stackPointerRegister() { - return runtime().getProviders().getRegisters().getStackPointerRegister(); + return runtime().getHostProviders().getRegisters().getStackPointerRegister(); } @Fold diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProvider.*; +import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/ForeignCallStub.java Mon Oct 21 11:07:47 2013 +0200 @@ -84,11 +84,13 @@ */ public ForeignCallStub(HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, boolean reexecutable, LocationIdentity... killedLocations) { - super(providers, HotSpotForeignCallLinkage.create(descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); + super(providers, HotSpotForeignCallLinkage.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, + transition, reexecutable, killedLocations)); this.prependThread = prependThread; Class[] targetParameterTypes = createTargetParameters(descriptor); ForeignCallDescriptor targetSig = new ForeignCallDescriptor(descriptor.getName() + ":C", descriptor.getResultType(), targetParameterTypes); - target = HotSpotForeignCallLinkage.create(targetSig, address, DESTROYS_REGISTERS, NativeCall, NativeCall, transition, reexecutable, killedLocations); + target = HotSpotForeignCallLinkage.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getForeignCalls(), targetSig, address, DESTROYS_REGISTERS, NativeCall, NativeCall, + transition, reexecutable, killedLocations); } /** diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/VerifyOopStub.java Mon Oct 21 11:07:47 2013 +0200 @@ -30,7 +30,7 @@ import com.oracle.graal.replacements.*; /** - * Stub called via {@link HotSpotForeignCallsProvider#VERIFY_OOP}. + * Stub called via {@link HotSpotHostForeignCallsProvider#VERIFY_OOP}. */ public class VerifyOopStub extends SnippetStub { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java --- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/Test.java Mon Oct 21 11:07:47 2013 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.java.decompiler.test.example.*; import com.oracle.graal.printer.*; +import com.oracle.graal.runtime.*; public class Test { @@ -38,7 +39,7 @@ */ public static void main(String[] args) throws NoSuchMethodException, SecurityException { DebugEnvironment.initialize(System.out); - MetaAccessProvider metaAccess = Graal.getRequiredCapability(MetaAccessProvider.class); + MetaAccessProvider metaAccess = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess(); Method method = Example.class.getDeclaredMethod("loop7", new Class[]{int.class, int.class}); final ResolvedJavaMethod javaMethod = metaAccess.lookupJavaMethod(method); TestUtil.compileMethod(javaMethod); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java --- a/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.java.decompiler.test/src/com/oracle/graal/java/decompiler/test/TestUtil.java Mon Oct 21 11:07:47 2013 +0200 @@ -36,12 +36,15 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; public class TestUtil { public static void compileMethod(ResolvedJavaMethod method) { - Providers providers = GraalCompiler.getGraalProviders(); - Suites suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); + Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); + Providers providers = backend.getProviders(); + SuitesProvider suitesProvider = backend.getSuites(); + Suites suites = suitesProvider.createSuites(); StructuredGraph graph = new StructuredGraph(method); MetaAccessProvider metaAccess = providers.getMetaAccess(); ForeignCallsProvider foreignCalls = providers.getForeignCalls(); @@ -50,7 +53,6 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, graph.method(), false); - Backend backend = Graal.getRequiredCapability(Backend.class); GraalCompiler.compileGraph(graph, cc, method, providers, backend, providers.getCodeCache().getTarget(), null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog(), suites, new CompilationResult()); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Mon Oct 21 11:07:47 2013 +0200 @@ -32,6 +32,7 @@ import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.VirtualState.VirtualClosure; import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.virtual.*; public abstract class LoopFragment { @@ -181,10 +182,16 @@ final NodeBitMap notloopNodes = graph.createNodeBitMap(true); for (AbstractBeginNode b : blocks) { for (Node n : b.getBlockNodes()) { + if (n instanceof CommitAllocationNode) { + for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) { + markFloating(obj, nodes, notloopNodes); + } + } for (Node usage : n.usages()) { markFloating(usage, nodes, notloopNodes); } } + } return nodes; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/NegateNodeCanonicalizationTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +/** + * This class tests that the canonicalization for constant negate nodes cover all cases. + */ +public class NegateNodeCanonicalizationTest { + + private StructuredGraph graph; + + @Before + public void before() { + graph = new StructuredGraph(); + } + + @Test + public void testByte() { + byte[] a = new byte[]{Byte.MIN_VALUE, Byte.MIN_VALUE + 1, -1, 0, 1, Byte.MAX_VALUE - 1, Byte.MAX_VALUE}; + for (byte i : a) { + ConstantNode node = ConstantNode.forByte(i, graph); + Constant expected = Constant.forInt(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + + @Test + public void testChar() { + char[] a = new char[]{Character.MIN_VALUE, Character.MIN_VALUE + 1, 0, 1, Character.MAX_VALUE - 1, Character.MAX_VALUE}; + for (char i : a) { + ConstantNode node = ConstantNode.forChar(i, graph); + Constant expected = Constant.forInt(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + + @Test + public void testShort() { + short[] a = new short[]{Short.MIN_VALUE, Short.MIN_VALUE + 1, -1, 0, 1, Short.MAX_VALUE - 1, Short.MAX_VALUE}; + for (short i : a) { + ConstantNode node = ConstantNode.forShort(i, graph); + Constant expected = Constant.forInt(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + + @Test + public void testInt() { + int[] a = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -1, 0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE}; + for (int i : a) { + ConstantNode node = ConstantNode.forInt(i, graph); + Constant expected = Constant.forInt(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + + @Test + public void testLong() { + long[] a = new long[]{Long.MIN_VALUE, Long.MIN_VALUE + 1, -1, 0, 1, Long.MAX_VALUE - 1, Long.MAX_VALUE}; + for (long i : a) { + ConstantNode node = ConstantNode.forLong(i, graph); + Constant expected = Constant.forLong(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + + @Test + public void testFloat() { + float[] a = new float[]{Float.MIN_VALUE, Float.MIN_VALUE + 1, -1, 0, 1, Float.MAX_VALUE - 1, Float.MAX_VALUE}; + for (float i : a) { + ConstantNode node = ConstantNode.forFloat(i, graph); + Constant expected = Constant.forFloat(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + + @Test + public void testDouble() { + double[] a = new double[]{Double.MIN_VALUE, Double.MIN_VALUE + 1, -1, 0, 1, Double.MAX_VALUE - 1, Double.MAX_VALUE}; + for (double i : a) { + ConstantNode node = ConstantNode.forDouble(i, graph); + Constant expected = Constant.forDouble(-i); + assertEquals(expected, new NegateNode(node).evalConst(node.asConstant())); + } + } + +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ControlSplitNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,13 +22,14 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.type.*; /** * The {@code ControlSplitNode} is a base class for all instructions that split the control flow * (ie. have more than one successor). */ -public abstract class ControlSplitNode extends FixedNode { +public abstract class ControlSplitNode extends FixedNode implements IterableNodeType { public ControlSplitNode(Stamp stamp) { super(stamp); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -33,6 +33,8 @@ private final DeoptimizationReason reason; public DeoptimizeNode(DeoptimizationAction action, DeoptimizationReason reason) { + assert action != null; + assert reason != null; this.action = action; this.reason = reason; } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DynamicDeoptimizeNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -23,9 +23,11 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.spi.*; -public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable { +public class DynamicDeoptimizeNode extends AbstractDeoptimizeNode implements LIRLowerable, Canonicalizable { @Input private ValueNode actionAndReason; public DynamicDeoptimizeNode(ValueNode actionAndReason) { @@ -44,4 +46,15 @@ public void generate(LIRGeneratorTool generator) { generator.emitDeoptimize(generator.operand(actionAndReason), this); } + + @Override + public Node canonical(CanonicalizerTool tool) { + if (actionAndReason.isConstant()) { + Constant constant = actionAndReason.asConstant(); + DeoptimizeNode newDeopt = graph().add(new DeoptimizeNode(tool.getMetaAccess().decodeDeoptAction(constant), tool.getMetaAccess().decodeDeoptReason(constant))); + newDeopt.setDeoptimizationState(getDeoptimizationState()); + return newDeopt; + } + return this; + } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -358,9 +358,9 @@ if (trueValue.kind() != Kind.Int && trueValue.kind() != Kind.Long) { return false; } - if (trueValue.isConstant() && falseValue.isConstant()) { - ConditionalNode materialize = graph().unique(new ConditionalNode(condition(), trueValue, falseValue)); - graph().replaceFloating(singlePhi, materialize); + ConditionalNode conditional = canonicalizeConditionalCascade(trueValue, falseValue); + if (conditional != null) { + graph().replaceFloating(singlePhi, conditional); removeEmptyIf(tool); return true; } @@ -371,6 +371,44 @@ return false; } + private ConditionalNode canonicalizeConditionalCascade(ValueNode trueValue, ValueNode falseValue) { + if (trueValue.isConstant() && falseValue.isConstant()) { + return graph().unique(new ConditionalNode(condition(), trueValue, falseValue)); + } else { + ConditionalNode conditional = null; + ValueNode constant = null; + boolean negateCondition; + if (trueValue instanceof ConditionalNode && falseValue.isConstant()) { + conditional = (ConditionalNode) trueValue; + constant = falseValue; + negateCondition = true; + } else if (falseValue instanceof ConditionalNode && trueValue.isConstant()) { + conditional = (ConditionalNode) falseValue; + constant = trueValue; + negateCondition = false; + } else { + return null; + } + boolean negateConditionalCondition; + ValueNode otherValue; + if (constant == conditional.x()) { + otherValue = conditional.y(); + negateConditionalCondition = false; + } else if (constant == conditional.y()) { + otherValue = conditional.x(); + negateConditionalCondition = true; + } else { + return null; + } + if (otherValue.isConstant()) { + double shortCutProbability = probability(trueSuccessor()); + LogicNode newCondition = LogicNode.or(condition(), negateCondition, conditional.condition(), negateConditionalCondition, shortCutProbability); + return graph().unique(new ConditionalNode(newCondition, constant, otherValue)); + } + } + return null; + } + /** * Tries to connect code that initializes a variable directly with the successors of an if * construct that switches on the variable. For example, the pseudo code below: diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -32,7 +32,7 @@ import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "Invoke!#{p#targetMethod/s}") -public class InvokeWithExceptionNode extends ControlSplitNode implements IterableNodeType, Invoke, MemoryCheckpoint.Single, LIRLowerable { +public class InvokeWithExceptionNode extends ControlSplitNode implements Invoke, MemoryCheckpoint.Single, LIRLowerable { private static final double EXCEPTION_PROBA = 1e-5; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -57,17 +57,18 @@ public Constant evalConst(Constant... inputs) { assert inputs.length == 1; - switch (inputs[0].getKind()) { + Constant constant = inputs[0]; + switch (constant.getKind()) { case Int: - return Constant.forInt(-inputs[0].asInt()); + return Constant.forInt(-(constant.asInt())); case Long: - return Constant.forLong(-inputs[0].asLong()); + return Constant.forLong(-(constant.asLong())); case Float: - return Constant.forFloat(-inputs[0].asFloat()); + return Constant.forFloat(-(constant.asFloat())); case Double: - return Constant.forDouble(-inputs[0].asDouble()); + return Constant.forDouble(-(constant.asDouble())); default: - throw GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere("unknown kind " + constant.getKind()); } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/GraphCache.java Mon Oct 21 11:07:47 2013 +0200 @@ -25,10 +25,32 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +/** + * A cache for graphs associated with {@linkplain StructuredGraph#method() methods}. + */ public interface GraphCache { - void put(StructuredGraph graph, boolean hasMatureProfilingInfo); + /** + * Requests that a graph be added to this cache. + * + * @param hasMatureProfilingInfo indicates that the caller has + * {@linkplain ProfilingInfo#isMature() mature} profiling info for the method + * associated with the graph + * @return true if {@code graph} was added to this cache, false otherwise + */ + boolean put(StructuredGraph graph, boolean hasMatureProfilingInfo); + /** + * Gets the graph from this cache associated with a given method. + * + * @param method a method for which a cached graph is requested + * @return the graph cached for {@code method} or null if it does not exist + */ StructuredGraph get(ResolvedJavaMethod method); + /** + * The cache will remove graphs it considers stale. For example, graphs associated with + * installed code that has subsequently be deoptimized might be considered stale. + */ + void removeStaleGraphs(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/EscapeObjectState.java Mon Oct 21 11:07:47 2013 +0200 @@ -22,9 +22,10 @@ */ package com.oracle.graal.nodes.virtual; +import com.oracle.graal.graph.Node.*; import com.oracle.graal.nodes.*; -public abstract class EscapeObjectState extends VirtualState { +public abstract class EscapeObjectState extends VirtualState implements ValueNumberable { @Input private VirtualObjectNode object; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java Mon Oct 21 11:07:47 2013 +0200 @@ -296,39 +296,39 @@ graph.replaceFloating((FloatingNode) node, canonical); } } else { - assert node instanceof FixedWithNextNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; - FixedWithNextNode fixedWithNext = (FixedWithNextNode) node; - + assert node instanceof FixedNode && node.predecessor() != null : node + " -> " + canonical + " : node should be fixed & connected (" + node.predecessor() + ")"; + FixedNode fixed = (FixedNode) node; if (canonical instanceof ControlSinkNode) { // case 7 FixedWithNextNode pred = (FixedWithNextNode) node.predecessor(); - GraphUtil.killCFG(fixedWithNext); + GraphUtil.killCFG(fixed); pred.setNext((FixedNode) canonical); return true; - } - - // When removing a fixed node, new canonicalization - // opportunities for its successor may arise - assert fixedWithNext.next() != null; - tool.addToWorkList(fixedWithNext.next()); - - if (canonical == null) { - // case 3 - graph.removeFixed(fixedWithNext); - } else if (canonical instanceof FloatingNode) { - // case 4 - graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); } else { - assert canonical instanceof FixedNode; - if (canonical.predecessor() == null) { - assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; - // case 5 - graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + assert fixed instanceof FixedWithNextNode; + FixedWithNextNode fixedWithNext = (FixedWithNextNode) fixed; + // When removing a fixed node, new canonicalization + // opportunities for its successor may arise + assert fixedWithNext.next() != null; + tool.addToWorkList(fixedWithNext.next()); + if (canonical == null) { + // case 3 + graph.removeFixed(fixedWithNext); + } else if (canonical instanceof FloatingNode) { + // case 4 + graph.replaceFixedWithFloating(fixedWithNext, (FloatingNode) canonical); } else { - assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; - // case 6 - node.replaceAtUsages(canonical); - graph.removeFixed(fixedWithNext); + assert canonical instanceof FixedNode; + if (canonical.predecessor() == null) { + assert !canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " shouldn't have successors"; + // case 5 + graph.replaceFixedWithFixed(fixedWithNext, (FixedWithNextNode) canonical); + } else { + assert canonical.cfgSuccessors().iterator().hasNext() : "replacement " + canonical + " should have successors"; + // case 6 + node.replaceAtUsages(canonical); + graph.removeFixed(fixedWithNext); + } } } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Oct 21 11:07:47 2013 +0200 @@ -318,44 +318,43 @@ ShortCircuitOrNode disjunction = (ShortCircuitOrNode) condition; registerCondition(disjunction.isXNegated(), disjunction.getX(), anchor); registerCondition(disjunction.isYNegated(), disjunction.getY(), anchor); - } else { - state.addCondition(isTrue, condition, anchor); + } + state.addCondition(isTrue, condition, anchor); - if (isTrue && condition instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) condition; - ValueNode object = instanceOf.object(); - state.addNullness(false, object); - state.addType(instanceOf.type(), object); - } else if (condition instanceof IsNullNode) { - IsNullNode nullCheck = (IsNullNode) condition; - state.addNullness(isTrue, nullCheck.object()); - } else if (condition instanceof ObjectEqualsNode) { - ObjectEqualsNode equals = (ObjectEqualsNode) condition; - ValueNode x = equals.x(); - ValueNode y = equals.y(); - if (isTrue) { - if (state.isNull(x) && !state.isNull(y)) { - metricObjectEqualsRegistered.increment(); - state.addNullness(true, y); - } else if (!state.isNull(x) && state.isNull(y)) { - metricObjectEqualsRegistered.increment(); - state.addNullness(true, x); - } - if (state.isNonNull(x) && !state.isNonNull(y)) { - metricObjectEqualsRegistered.increment(); - state.addNullness(false, y); - } else if (!state.isNonNull(x) && state.isNonNull(y)) { - metricObjectEqualsRegistered.increment(); - state.addNullness(false, x); - } - } else { - if (state.isNull(x) && !state.isNonNull(y)) { - metricObjectEqualsRegistered.increment(); - state.addNullness(false, y); - } else if (!state.isNonNull(x) && state.isNull(y)) { - metricObjectEqualsRegistered.increment(); - state.addNullness(false, x); - } + if (isTrue && condition instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) condition; + ValueNode object = instanceOf.object(); + state.addNullness(false, object); + state.addType(instanceOf.type(), object); + } else if (condition instanceof IsNullNode) { + IsNullNode nullCheck = (IsNullNode) condition; + state.addNullness(isTrue, nullCheck.object()); + } else if (condition instanceof ObjectEqualsNode) { + ObjectEqualsNode equals = (ObjectEqualsNode) condition; + ValueNode x = equals.x(); + ValueNode y = equals.y(); + if (isTrue) { + if (state.isNull(x) && !state.isNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(true, y); + } else if (!state.isNull(x) && state.isNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(true, x); + } + if (state.isNonNull(x) && !state.isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(false, y); + } else if (!state.isNonNull(x) && state.isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(false, x); + } + } else { + if (state.isNull(x) && !state.isNonNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(false, y); + } else if (!state.isNonNull(x) && state.isNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(false, x); } } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/EliminatePartiallyRedundantGuardsPhase.java Mon Oct 21 11:07:32 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import java.util.*; -import java.util.Map.*; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; -import com.oracle.graal.phases.*; - -public class EliminatePartiallyRedundantGuardsPhase extends Phase { - - private static final DebugMetric metricPRGuardsEliminatedAtMerge = Debug.metric("PRGuardsEliminatedAtMerge"); - private static final DebugMetric metricPRGuardsEliminatedAtSplit = Debug.metric("PRGuardsEliminatedAtSplit"); - - private final boolean eliminateAtSplit; - private final boolean eliminateAtMerge; - - public EliminatePartiallyRedundantGuardsPhase(boolean eliminateAtSplit, boolean eliminateAtMerge) { - assert eliminateAtMerge || eliminateAtSplit; - this.eliminateAtSplit = eliminateAtSplit; - this.eliminateAtMerge = eliminateAtMerge; - } - - private static class Condition { - - final LogicNode conditionNode; - final boolean negated; - - public Condition(LogicNode conditionNode, boolean negated) { - this.conditionNode = conditionNode; - this.negated = negated; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((conditionNode == null) ? 0 : conditionNode.hashCode()); - result = prime * result + (negated ? 1231 : 1237); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Condition other = (Condition) obj; - if (conditionNode == null) { - if (other.conditionNode != null) { - return false; - } - } else if (!conditionNode.equals(other.conditionNode)) { - return false; - } - if (negated != other.negated) { - return false; - } - return true; - } - } - - @Override - protected void run(StructuredGraph graph) { - boolean hits; - do { - hits = false; - if (eliminateAtMerge) { - for (MergeNode merge : graph.getNodes(MergeNode.class)) { - hits |= eliminateAtMerge(merge); - } - } - if (eliminateAtSplit) { - for (ControlSplitNode controlSplit : graph.getNodes().filter(ControlSplitNode.class)) { - hits |= eliminateAtControlSplit(controlSplit); - } - } - } while (hits); - } - - private static boolean eliminateAtMerge(MergeNode merge) { - if (merge.forwardEndCount() < 2) { - return false; - } - Collection hits = new LinkedList<>(); - for (GuardNode guard : merge.guards()) { - for (AbstractEndNode end : merge.forwardEnds()) { - AbstractBeginNode begin = AbstractBeginNode.prevBegin(end); - boolean found = false; - for (GuardNode predecessorGuard : begin.guards()) { - if (guard.condition() == predecessorGuard.condition() && guard.negated() == predecessorGuard.negated()) { - hits.add(guard); - found = true; - break; - } - } - if (found) { - break; - } - } - } - Graph graph = merge.graph(); - for (GuardNode guard : hits) { - PhiNode phi = graph.addWithoutUnique(new PhiNode(PhiType.Guard, merge, null)); - for (AbstractEndNode otherEnd : merge.forwardEnds()) { - phi.addInput(graph.unique(new GuardNode(guard.condition(), AbstractBeginNode.prevBegin(otherEnd), guard.reason(), guard.action(), guard.negated()))); - } - guard.replaceAndDelete(phi); - metricPRGuardsEliminatedAtMerge.increment(); - } - return !hits.isEmpty(); - } - - private static boolean eliminateAtControlSplit(ControlSplitNode controlSplit) { - Map> conditionToGuard = new HashMap<>(); - for (Node successor : controlSplit.successors()) { - AbstractBeginNode begin = (AbstractBeginNode) successor; - for (GuardNode guard : begin.guards()) { - Condition condition = new Condition(guard.condition(), guard.negated()); - Collection guards = conditionToGuard.get(condition); - if (guards == null) { - guards = new LinkedList<>(); - conditionToGuard.put(condition, guards); - } - guards.add(guard); - } - } - - boolean hits = false; - for (Entry> entry : conditionToGuard.entrySet()) { - Collection guards = entry.getValue(); - if (guards.size() < 2) { - continue; - } - DeoptimizationReason reason = null; - DeoptimizationAction action = DeoptimizationAction.None; - Set begins = new HashSet<>(3); - for (GuardNode guard : guards) { - AbstractBeginNode begin = (AbstractBeginNode) guard.getGuard(); - begins.add(begin); - if (guard.action().ordinal() > action.ordinal()) { - action = guard.action(); - } - if (reason == null) { - reason = guard.reason(); - } else if (reason != guard.reason()) { - reason = DeoptimizationReason.None; - } - } - if (begins.size() == controlSplit.successors().count()) { - hits = true; - Condition condition = entry.getKey(); - GuardNode newGuard = controlSplit.graph().unique(new GuardNode(condition.conditionNode, AbstractBeginNode.prevBegin(controlSplit), reason, action, condition.negated)); - for (GuardNode guard : guards) { - guard.replaceAndDelete(newGuard); - metricPRGuardsEliminatedAtSplit.increment(); - } - } - } - return hits; - } -} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2013, 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.phases.common; + +import java.util.*; + +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.NodeClass.NodeClassIterator; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.phases.*; + +public class OptimizeGuardAnchors extends Phase { + private static final DebugMetric metricGuardsAnchorOptimized = Debug.metric("GuardsAnchorOptimized"); + private static final DebugMetric metricGuardsOptimizedAtSplit = Debug.metric("GuardsOptimizedAtSplit"); + + private static class LazyCFG { + private ControlFlowGraph cfg; + private StructuredGraph graph; + + public LazyCFG(StructuredGraph graph) { + this.graph = graph; + } + + public ControlFlowGraph get() { + if (cfg == null) { + cfg = ControlFlowGraph.compute(graph, true, false, true, true); + } + return cfg; + } + } + + @Override + protected void run(StructuredGraph graph) { + LazyCFG cfg = new LazyCFG(graph); + for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.class)) { + if (!(begin instanceof StartNode || begin.predecessor() instanceof ControlSplitNode)) { + NodeIterable guards = begin.guards(); + if (guards.isNotEmpty()) { + AbstractBeginNode newAnchor = computeOptimalAnchor(cfg.get(), begin); + // newAnchor == begin is possible because postdominator computation assumes that + // loops never end + if (newAnchor != begin) { + for (GuardNode guard : guards.snapshot()) { + guard.setGuard(newAnchor); + } + metricGuardsAnchorOptimized.increment(); + } + } + } + } + for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) { + otpimizeAtControlSplit(controlSplit, cfg); + } + } + + private static AbstractBeginNode computeOptimalAnchor(ControlFlowGraph cfg, AbstractBeginNode begin) { + Block anchor = cfg.blockFor(begin); + while (anchor.getDominator() != null && anchor.getDominator().getPostdominator() == anchor) { + anchor = anchor.getDominator(); + } + return anchor.getBeginNode(); + } + + private static void otpimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) { + AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit); + int successorCount = controlSplit.successors().count(); + List otherGuards = new ArrayList<>(successorCount - 1); + for (GuardNode guard : successor.guards().snapshot()) { + if (guard.condition().usages().count() < successorCount) { + continue; + } + + for (GuardNode conditonGuard : guard.condition().usages().filter(GuardNode.class)) { + if (conditonGuard != guard) { + GuardingNode conditonGuardAnchor = conditonGuard.getGuard(); + if (conditonGuardAnchor.asNode().predecessor() == controlSplit && compatibleGuards(guard, conditonGuard)) { + otherGuards.add(conditonGuard); + } + } + } + + if (otherGuards.size() == successorCount - 1) { + AbstractBeginNode anchor = computeOptimalAnchor(cfg.get(), AbstractBeginNode.prevBegin(controlSplit)); + GuardNode newGuard = controlSplit.graph().unique(new GuardNode(guard.condition(), anchor, guard.reason(), guard.action(), guard.negated())); + for (GuardNode otherGuard : otherGuards) { + otherGuard.replaceAndDelete(newGuard); + } + guard.replaceAndDelete(newGuard); + metricGuardsOptimizedAtSplit.increment(); + } + otherGuards.clear(); + } + } + + private static boolean compatibleGuards(GuardNode guard, GuardNode conditonGuard) { + return conditonGuard.negated() == guard.negated() && conditonGuard.action() == guard.action() && conditonGuard.reason() == guard.reason(); + } + + private static AbstractBeginNode findMinimumUsagesSuccessor(ControlSplitNode controlSplit) { + NodeClassIterator successors = controlSplit.successors().iterator(); + AbstractBeginNode min = (AbstractBeginNode) successors.next(); + int minUsages = min.usages().count(); + while (successors.hasNext()) { + AbstractBeginNode successor = (AbstractBeginNode) successors.next(); + int count = successor.usages().count(); + if (count < minUsages) { + minUsages = count; + min = successor; + } + } + return min; + } +} diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java Mon Oct 21 11:07:47 2013 +0200 @@ -32,7 +32,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.NodeClass.Position; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; @@ -42,7 +41,7 @@ public class BinaryGraphPrinter implements GraphPrinter { - private static final int CONSTANT_POOL_MAX_SIZE = 2000; + private static final int CONSTANT_POOL_MAX_SIZE = 8000; private static final int BEGIN_GROUP = 0x00; private static final int BEGIN_GRAPH = 0x01; @@ -71,10 +70,10 @@ private static final int KLASS = 0x00; private static final int ENUM_KLASS = 0x01; - private static final class ConstantPool extends LinkedHashMap { + private static final class ConstantPool extends LinkedHashMap { - private final LinkedList availableIds; - private int nextId; + private final LinkedList availableIds; + private char nextId; private static final long serialVersionUID = -2676889957907285681L; public ConstantPool() { @@ -83,7 +82,7 @@ } @Override - protected boolean removeEldestEntry(java.util.Map.Entry eldest) { + protected boolean removeEldestEntry(java.util.Map.Entry eldest) { if (size() > CONSTANT_POOL_MAX_SIZE) { availableIds.addFirst(eldest.getValue()); return true; @@ -91,15 +90,15 @@ return false; } - private Integer nextAvailableId() { + private Character nextAvailableId() { if (!availableIds.isEmpty()) { return availableIds.removeFirst(); } return nextId++; } - public int add(Object obj) { - Integer id = nextAvailableId(); + public char add(Object obj) { + Character id = nextAvailableId(); put(obj, id); return id; } @@ -149,6 +148,7 @@ } private void ensureAvailable(int i) throws IOException { + assert buffer.capacity() >= i : "Can not make " + i + " bytes available, buffer is too small"; while (buffer.remaining() < i) { flush(); } @@ -186,10 +186,10 @@ private void writeString(String str) throws IOException { writeInt(str.length()); - ensureAvailable(str.length() * 2); - for (int i = 0; i < str.length(); i++) { - buffer.putChar(str.charAt(i)); - } + int sizeInBytes = str.length() * 2; + ensureAvailable(sizeInBytes); + buffer.asCharBuffer().put(str); + buffer.position(buffer.position() + sizeInBytes); } private void writeBytes(byte[] b) throws IOException { @@ -207,10 +207,10 @@ writeInt(-1); } else { writeInt(b.length); - ensureAvailable(b.length * 4); - for (int i = 0; i < b.length; i++) { - buffer.putInt(b[i]); - } + int sizeInBytes = b.length * 4; + ensureAvailable(sizeInBytes); + buffer.asIntBuffer().put(b); + buffer.position(buffer.position() + sizeInBytes); } } @@ -219,10 +219,10 @@ writeInt(-1); } else { writeInt(b.length); - ensureAvailable(b.length * 8); - for (int i = 0; i < b.length; i++) { - buffer.putDouble(b[i]); - } + int sizeInBytes = b.length * 8; + ensureAvailable(sizeInBytes); + buffer.asDoubleBuffer().put(b); + buffer.position(buffer.position() + sizeInBytes); } } @@ -231,7 +231,7 @@ writeByte(POOL_NULL); return; } - Integer id = constantPool.get(object); + Character id = constantPool.get(object); if (id == null) { addPoolEntry(object); } else { @@ -250,7 +250,7 @@ } else { writeByte(POOL_STRING); } - writeInt(id.intValue()); + writeShort(id.charValue()); } } @@ -262,9 +262,9 @@ } private void addPoolEntry(Object object) throws IOException { - int index = constantPool.add(object); + char index = constantPool.add(object); writeByte(POOL_NEW); - writeInt(index); + writeShort(index); if (object instanceof Class) { Class klass = (Class) object; writeByte(POOL_CLASS); @@ -293,14 +293,16 @@ writeByte(POOL_NODE_CLASS); writeString(nodeClass.getJavaClass().getSimpleName()); writeString(nodeClass.getNameTemplate()); - List directInputPositions = nodeClass.getFirstLevelInputPositions(); + Collection directInputPositions = nodeClass.getFirstLevelInputPositions(); writeShort((char) directInputPositions.size()); for (Position pos : directInputPositions) { + writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } - List directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); + Collection directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); writeShort((char) directSuccessorPositions.size()); for (Position pos : directSuccessorPositions) { + writeByte(pos.subIndex == NodeClass.NOT_ITERABLE ? 0 : 1); writePoolObject(nodeClass.getName(pos)); } } else if (object instanceof ResolvedJavaMethod) { @@ -411,25 +413,53 @@ writePoolObject(key); writePropertyObject(entry.getValue()); } - // successors - NodeClassIterable successors = node.successors(); - writeShort((char) successors.count()); - NodeClassIterator suxIt = successors.iterator(); - while (suxIt.hasNext()) { - Position pos = suxIt.nextPosition(); - Node sux = nodeClass.get(node, pos); - writeInt(sux.getId()); - writeShort((char) pos.index); + // inputs + Collection directInputPositions = nodeClass.getFirstLevelInputPositions(); + for (Position pos : directInputPositions) { + if (pos.subIndex == NodeClass.NOT_ITERABLE) { + Node in = nodeClass.get(node, pos); + if (in != null) { + writeInt(in.getId()); + } else { + writeInt(-1); + } + } else { + NodeList list = nodeClass.getNodeList(node, pos); + int listSize = list.count(); + assert listSize == ((char) listSize); + writeShort((char) listSize); + for (Node in : list) { + if (in != null) { + writeInt(in.getId()); + } else { + writeInt(-1); + } + } + } } - // inputs - NodeClassIterable inputs = node.inputs(); - writeShort((char) inputs.count()); - NodeClassIterator inIt = inputs.iterator(); - while (inIt.hasNext()) { - Position pos = inIt.nextPosition(); - Node in = nodeClass.get(node, pos); - writeInt(in.getId()); - writeShort((char) pos.index); + // successors + Collection directSuccessorPositions = nodeClass.getFirstLevelSuccessorPositions(); + for (Position pos : directSuccessorPositions) { + if (pos.subIndex == NodeClass.NOT_ITERABLE) { + Node sux = nodeClass.get(node, pos); + if (sux != null) { + writeInt(sux.getId()); + } else { + writeInt(-1); + } + } else { + NodeList list = nodeClass.getNodeList(node, pos); + int listSize = list.count(); + assert listSize == ((char) listSize); + writeShort((char) listSize); + for (Node sux : list) { + if (sux != null) { + writeInt(sux.getId()); + } else { + writeInt(-1); + } + } + } } props.clear(); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CompiledExceptionHandlerTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -37,7 +37,7 @@ public class CompiledExceptionHandlerTest extends GraalCompilerTest { public CompiledExceptionHandlerTest() { - suites.getHighTier().findPhase(AbstractInliningPhase.class).remove(); + getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); } @Override diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DeoptimizeOnExceptionTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DeoptimizeOnExceptionTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/DeoptimizeOnExceptionTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -33,7 +33,7 @@ public class DeoptimizeOnExceptionTest extends GraalCompilerTest { public DeoptimizeOnExceptionTest() { - suites.getHighTier().findPhase(AbstractInliningPhase.class).remove(); + getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); } private static void raiseException(String m1, String m2, String m3, String m4, String m5) { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -42,7 +42,7 @@ public class InstanceOfTest extends TypeCheckTest { public InstanceOfTest() { - suites.getHighTier().findPhase(AbstractInliningPhase.class).remove(); + getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); } @Override diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InvokeTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -33,7 +33,7 @@ public class InvokeTest extends GraalCompilerTest { public InvokeTest() { - suites.getHighTier().findPhase(AbstractInliningPhase.class).remove(); + getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); } public interface I { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.runtime/src/com/oracle/graal/runtime/RuntimeProvider.java Mon Oct 21 11:07:47 2013 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.runtime; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.nodes.spi.*; + +/** + * A runtime supporting a host backend as well, zero or more additional backends and an optional + * {@linkplain GraphCache graph cache}. + */ +public interface RuntimeProvider { + + /** + * Gets the host backend. + */ + Backend getHostBackend(); + + /** + * Gets the backend for a given architecture. + * + * @param arch a specific architecture class + */ + Backend getBackend(Class arch); + + /** + * Gets the graph cache (if any) maintained by this runtime. + */ + GraphCache getGraphCache(); +} diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/ExactMathTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.substitutions.*; import com.oracle.truffle.api.*; @@ -36,7 +37,8 @@ public ExactMathTest() { if (!substitutionsInstalled) { - Graal.getRequiredCapability(Replacements.class).registerSubstitutions(ExactMathSubstitutions.class); + Replacements replacements = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getReplacements(); + replacements.registerSubstitutions(ExactMathSubstitutions.class); substitutionsInstalled = true; } } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -28,6 +28,7 @@ import org.junit.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.debug.*; import com.oracle.graal.java.*; @@ -41,6 +42,7 @@ import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.printer.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; import com.oracle.graal.virtual.phases.ea.*; import com.oracle.truffle.api.*; @@ -58,7 +60,7 @@ Replacements truffleReplacements = ((GraalTruffleRuntime) Truffle.getRuntime()).getReplacements(); Providers providers = getProviders().copyWith(truffleReplacements); TruffleCache truffleCache = new TruffleCache(providers, GraphBuilderConfiguration.getDefault(), TruffleCompilerImpl.Optimizations); - this.partialEvaluator = new PartialEvaluator(providers, truffleCache); + this.partialEvaluator = new PartialEvaluator(Graal.getRequiredCapability(RuntimeProvider.class), providers, truffleCache); DebugEnvironment.initialize(System.out); } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/TruffleRuntimeTest.java Mon Oct 21 11:07:47 2013 +0200 @@ -26,8 +26,8 @@ import org.junit.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; import com.oracle.truffle.api.*; @@ -35,7 +35,7 @@ @Test public void testGraalCapabilities() { - assertNotNull(Graal.getRuntime().getCapability(MetaAccessProvider.class)); + assertNotNull(Graal.getRuntime().getCapability(RuntimeProvider.class)); } @Test diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/CompilationPolicy.java Mon Oct 21 11:07:47 2013 +0200 @@ -31,17 +31,21 @@ private int loopAndInvokeCounter; private long prevTimestamp; - private final int initialInvokeCounter; private final int compilationThreshold; + private final String name; - public CompilationPolicy(final int compilationThreshold, final int initialInvokeCounter) { + public CompilationPolicy(final int compilationThreshold, final int initialInvokeCounter, final String name) { this.invokeCounter = initialInvokeCounter; this.loopAndInvokeCounter = compilationThreshold; this.originalInvokeCounter = compilationThreshold; - this.prevTimestamp = System.currentTimeMillis(); + this.prevTimestamp = System.nanoTime(); this.compilationThreshold = compilationThreshold; - this.initialInvokeCounter = initialInvokeCounter; + this.name = name; + } + + public String getName() { + return this.name; } public int getInvokeCounter() { @@ -91,19 +95,23 @@ public boolean compileOrInline() { if (invokeCounter <= 0 && loopAndInvokeCounter <= 0) { if (TruffleUseTimeForCompilationDecision.getValue()) { - long timestamp = System.currentTimeMillis(); - if ((timestamp - prevTimestamp) < TruffleCompilationDecisionTime.getValue()) { + long timestamp = System.nanoTime(); + long timespan = (timestamp - prevTimestamp); + if (timespan < (TruffleCompilationDecisionTime.getValue())) { return true; } - this.invokeCounter = initialInvokeCounter; this.loopAndInvokeCounter = compilationThreshold; this.originalInvokeCounter = compilationThreshold; this.prevTimestamp = timestamp; + if (TruffleCompilationDecisionTimePrintFail.getValue()) { + // Checkstyle: stop + System.out.println(name + ": timespan " + (timespan / 1000000) + " ms larger than threshold"); + // Checkstyle: resume + } } else { return true; } } return false; } - } diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/OptimizedCallTarget.java Mon Oct 21 11:07:47 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.debug.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.impl.*; @@ -46,7 +45,7 @@ protected OptimizedCallTarget(RootNode rootNode, FrameDescriptor descriptor, TruffleCompiler compiler, int invokeCounter, int compilationThreshold) { super(rootNode, descriptor); this.compiler = compiler; - this.compilationPolicy = new CompilationPolicy(compilationThreshold, invokeCounter); + this.compilationPolicy = new CompilationPolicy(compilationThreshold, invokeCounter, rootNode.toString()); this.rootNode.setCallTarget(this); if (TruffleCallTargetProfiling.getValue()) { @@ -54,7 +53,7 @@ } } - private HotSpotNmethod compiledMethod; + private InstalledCode compiledMethod; private final TruffleCompiler compiler; private final CompilationPolicy compilationPolicy; @@ -129,7 +128,7 @@ public void compile() { CompilerAsserts.neverPartOfCompilation(); try { - compiledMethod = (HotSpotNmethod) compiler.compile(this); + compiledMethod = compiler.compile(this); if (compiledMethod == null) { throw new BailoutException(String.format("code installation failed (codeSize=%s)", codeSize)); } else { diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/PartialEvaluator.java Mon Oct 21 11:07:47 2013 +0200 @@ -36,8 +36,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node; import com.oracle.graal.graph.spi.*; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; import com.oracle.graal.loop.*; import com.oracle.graal.nodes.*; @@ -51,6 +49,7 @@ import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.nodes.asserts.*; import com.oracle.graal.truffle.nodes.frame.*; import com.oracle.graal.truffle.nodes.frame.NewFrameNode.VirtualOnlyInstanceNode; @@ -70,15 +69,15 @@ private final CanonicalizerPhase canonicalizer; private final ResolvedJavaType[] skippedExceptionTypes; private Set constantReceivers; - private final HotSpotGraphCache cache; + private final GraphCache cache; private final TruffleCache truffleCache; - public PartialEvaluator(Providers providers, TruffleCache truffleCache) { + public PartialEvaluator(RuntimeProvider runtime, Providers providers, TruffleCache truffleCache) { this.providers = providers; CustomCanonicalizer customCanonicalizer = new PartialEvaluatorCanonicalizer(providers.getMetaAccess(), providers.getConstantReflection()); this.canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue(), customCanonicalizer); this.skippedExceptionTypes = TruffleCompilerImpl.getSkippedExceptionTypes(providers.getMetaAccess()); - this.cache = HotSpotGraalRuntime.runtime().getCache(); + this.cache = runtime.getGraphCache(); this.truffleCache = truffleCache; try { diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerImpl.java Mon Oct 21 11:07:47 2013 +0200 @@ -36,7 +36,6 @@ import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; -import com.oracle.graal.hotspot.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -45,6 +44,7 @@ import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.printer.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.truffle.api.*; import com.oracle.truffle.api.nodes.*; @@ -59,7 +59,7 @@ private final PartialEvaluator partialEvaluator; private final Backend backend; private final ResolvedJavaType[] skippedExceptionTypes; - private final HotSpotGraalRuntime runtime; + private final RuntimeProvider runtime; private final TruffleCache truffleCache; private static final Class[] SKIPPED_EXCEPTION_CLASSES = new Class[]{SlowPathException.class, UnexpectedResultException.class, ArithmeticException.class}; @@ -68,18 +68,18 @@ OptimisticOptimizations.Optimization.RemoveNeverExecutedCode, OptimisticOptimizations.Optimization.UseTypeCheckedInlining, OptimisticOptimizations.Optimization.UseTypeCheckHints); public TruffleCompilerImpl() { + this.runtime = Graal.getRequiredCapability(RuntimeProvider.class); + this.backend = runtime.getHostBackend(); Replacements truffleReplacements = ((GraalTruffleRuntime) Truffle.getRuntime()).getReplacements(); - this.providers = GraalCompiler.getGraalProviders().copyWith(truffleReplacements); - this.suites = Graal.getRequiredCapability(SuitesProvider.class).createSuites(); - this.backend = Graal.getRequiredCapability(Backend.class); - this.runtime = HotSpotGraalRuntime.runtime(); + this.providers = backend.getProviders().copyWith(truffleReplacements); + this.suites = backend.getSuites().createSuites(); this.skippedExceptionTypes = getSkippedExceptionTypes(providers.getMetaAccess()); final GraphBuilderConfiguration config = GraphBuilderConfiguration.getEagerDefault(); config.setSkippedExceptionTypes(skippedExceptionTypes); this.truffleCache = new TruffleCache(providers, config, TruffleCompilerImpl.Optimizations); - this.partialEvaluator = new PartialEvaluator(providers, truffleCache); + this.partialEvaluator = new PartialEvaluator(runtime, providers, truffleCache); if (Debug.isEnabled()) { DebugEnvironment.initialize(System.out); @@ -113,7 +113,10 @@ final StructuredGraph graph; final GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(); config.setSkippedExceptionTypes(skippedExceptionTypes); - runtime.evictDeoptedGraphs(); + GraphCache graphCache = runtime.getGraphCache(); + if (graphCache != null) { + graphCache.removeStaleGraphs(); + } compilable.timeCompilationStarted = System.nanoTime(); Assumptions assumptions = new Assumptions(true); diff -r 935dcd8ad8eb -r e47f373499ec 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 Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompilerOptions.java Mon Oct 21 11:07:47 2013 +0200 @@ -70,7 +70,12 @@ @Option(help = "") public static final OptionValue TruffleUseTimeForCompilationDecision = new OptionValue<>(false); @Option(help = "") - public static final OptionValue TruffleCompilationDecisionTime = new OptionValue<>(100); + public static final OptionValue TruffleCompilationDecisionTime = new OptionValue<>(100 * 1000000L); + @Option(help = "") + public static final OptionValue TruffleCompilationDecisionTimePrintFail = new OptionValue<>(false); + @Option(help = "") + public static final OptionValue TruffleBackgroundCompilation = new OptionValue<>(true); + // tracing @Option(help = "") public static final OptionValue TraceTruffleCompilation = new OptionValue<>(true); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleReplacements.java Mon Oct 21 11:07:47 2013 +0200 @@ -26,12 +26,13 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; -import com.oracle.graal.compiler.*; +import com.oracle.graal.api.runtime.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.substitutions.*; /** @@ -47,7 +48,7 @@ } static Replacements makeInstance() { - Providers graalProviders = GraalCompiler.getGraalProviders(); + Providers graalProviders = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); Replacements truffleReplacements = new TruffleReplacements(graalProviders); truffleReplacements.registerSubstitutions(CompilerAssertsSubstitutions.class); diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/frame/NewFrameNode.java Mon Oct 21 11:07:47 2013 +0200 @@ -34,6 +34,7 @@ import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.nodes.virtual.*; +import com.oracle.graal.runtime.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.nodes.*; import com.oracle.truffle.api.*; @@ -45,7 +46,7 @@ */ public class NewFrameNode extends FixedWithNextNode implements IterableNodeType, VirtualizableAllocation, Canonicalizable { - static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(MetaAccessProvider.class).lookupJavaType(FrameWithoutBoxing.class); + static final ResolvedJavaType FRAME_TYPE = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders().getMetaAccess().lookupJavaType(FrameWithoutBoxing.class); @Input private ValueNode descriptor; @Input private ValueNode caller; diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Mon Oct 21 11:07:47 2013 +0200 @@ -178,7 +178,7 @@ stateAfter.virtualObjectMappings().remove(i); } } - stateAfter.addVirtualObjectMapping(graph.addWithoutUnique(state)); + stateAfter.addVirtualObjectMapping(graph.unique(state)); } @Override diff -r 935dcd8ad8eb -r e47f373499ec graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Oct 21 11:07:32 2013 +0200 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/Node.java Mon Oct 21 11:07:47 2013 +0200 @@ -170,8 +170,8 @@ * @param reason a description of the reason for the replacement * @return the new node */ - @SuppressWarnings({"unchecked"}) public final T replace(T newNode, String reason) { + CompilerDirectives.transferToInterpreter(); if (this.getParent() == null) { throw new IllegalStateException("This node cannot be replaced, because it does not yet have a parent."); } @@ -180,13 +180,40 @@ newNode.assignSourceSection(sourceSection); } onReplace(newNode, reason); - return (T) this.getParent().replaceChild(this, newNode); + ((Node) newNode).parent = this.parent; + if (!NodeUtil.replaceChild(this.parent, this, newNode)) { + fixupTree(); + } + return newNode; } - private T replaceChild(T oldChild, T newChild) { - NodeUtil.replaceChild(this, oldChild, newChild); - adoptChild(newChild); - return newChild; + /** + * Rewrite has failed; the tree is likely inconsistent, so fix any stale parent references. + * + * This is a rather expensive operation but rare to occur. + */ + private void fixupTree() { + Node rootNode = NodeUtil.findParent(this, RootNode.class); + if (rootNode == null) { + throw new UnsupportedOperationException("Tree does not have a root node."); + } + int fixCount = rootNode.fixupChildren(); + assert fixCount != 0 : "sanity check failed: missing @Child[ren] or adoptChild?"; + // if nothing had to be fixed, rewrite failed due to node not being a proper child. + } + + private int fixupChildren() { + int fixCount = 0; + for (Node child : getChildren()) { + if (child != null) { + if (child.parent != this) { + child.parent = this; + fixCount++; + } + fixCount += child.fixupChildren(); + } + } + return fixCount; } /** diff -r 935dcd8ad8eb -r e47f373499ec hotspot/.project --- a/hotspot/.project Mon Oct 21 11:07:32 2013 +0200 +++ b/hotspot/.project Mon Oct 21 11:07:47 2013 +0200 @@ -96,6 +96,11 @@ PARENT-1-PROJECT_LOC/src/cpu/x86/vm + ptx + 2 + PARENT-1-PROJECT_LOC/src/gpu/ptx/vm + + sparc 2 PARENT-1-PROJECT_LOC/src/cpu/sparc/vm @@ -121,6 +126,11 @@ PARENT-1-PROJECT_LOC/src/os_cpu/bsd_x86/vm + bsd_ptx + 2 + PARENT-1-PROJECT_LOC/src/os_gpu/bsd_ptx/vm + + windows 2 PARENT-1-PROJECT_LOC/src/os/windows/vm @@ -141,6 +151,11 @@ PARENT-1-PROJECT_LOC/src/os_cpu/linux_x86/vm + linux_ptx + 2 + PARENT-1-PROJECT_LOC/src/os_gpu/linux_ptx/vm + + linux_sparc 2 PARENT-1-PROJECT_LOC/src/os_cpu/linux_sparc/vm diff -r 935dcd8ad8eb -r e47f373499ec make/windows/makefiles/projectcreator.make --- a/make/windows/makefiles/projectcreator.make Mon Oct 21 11:07:32 2013 +0200 +++ b/make/windows/makefiles/projectcreator.make Mon Oct 21 11:07:47 2013 +0200 @@ -193,7 +193,6 @@ ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ -define_compiler2 COMPILER2 \ -define_compiler2 GRAAL \ - -define_compiler2 TIERED \ -ignorePath_compiler2 graal/generated \ -additionalFile_compiler2 $(Platform_arch_model).ad \ -additionalFile_compiler2 ad_$(Platform_arch_model).cpp \ diff -r 935dcd8ad8eb -r e47f373499ec mx/projects --- a/mx/projects Mon Oct 21 11:07:32 2013 +0200 +++ b/mx/projects Mon Oct 21 11:07:47 2013 +0200 @@ -28,7 +28,13 @@ library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.2.jar distribution@GRAAL@path=graal.jar -distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.ptx,com.oracle.graal.truffle,com.oracle.graal.hotspot.sparc,com.oracle.graal.hotspot,com.oracle.graal.compiler.hsail +distribution@GRAAL@dependencies=\ +com.oracle.graal.hotspot.amd64,\ +com.oracle.graal.hotspot.ptx,\ +com.oracle.graal.truffle,\ +com.oracle.graal.hotspot.sparc,\ +com.oracle.graal.hotspot,\ +com.oracle.graal.hotspot.hsail # graal.api.runtime project@com.oracle.graal.api.runtime@subDir=graal @@ -55,7 +61,7 @@ # graal.api.meta.test project@com.oracle.graal.api.meta.test@subDir=graal project@com.oracle.graal.api.meta.test@sourceDirs=src -project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.api.meta,com.oracle.graal.api.runtime +project@com.oracle.graal.api.meta.test@dependencies=JUNIT,com.oracle.graal.runtime,com.oracle.graal.java project@com.oracle.graal.api.meta.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.api.meta.test@javaCompliance=1.7 project@com.oracle.graal.api.meta.test@workingSets=API,Graal,Test @@ -111,7 +117,7 @@ # graal.hotspot project@com.oracle.graal.hotspot@subDir=graal project@com.oracle.graal.hotspot@sourceDirs=src -project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.printer +project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot@annotationProcessors=com.oracle.graal.replacements.verifier,com.oracle.graal.service.processor project@com.oracle.graal.hotspot@javaCompliance=1.7 @@ -137,7 +143,7 @@ # graal.hotspot.ptx project@com.oracle.graal.hotspot.ptx@subDir=graal project@com.oracle.graal.hotspot.ptx@sourceDirs=src -project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.hotspot,com.oracle.graal.ptx +project@com.oracle.graal.hotspot.ptx@dependencies=com.oracle.graal.ptx,com.oracle.graal.compiler.ptx project@com.oracle.graal.hotspot.ptx@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.ptx@annotationProcessors=com.oracle.graal.service.processor project@com.oracle.graal.hotspot.ptx@javaCompliance=1.7 @@ -387,7 +393,7 @@ # graal.compiler.ptx.test project@com.oracle.graal.compiler.ptx.test@subDir=graal project@com.oracle.graal.compiler.ptx.test@sourceDirs=src -project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.hotspot.ptx,com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.hotspot.ptx,com.oracle.graal.compiler.test project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7 project@com.oracle.graal.compiler.ptx.test@workingSets=Graal,PTX,Test @@ -408,6 +414,14 @@ project@com.oracle.graal.compiler.sparc.test@javaCompliance=1.7 project@com.oracle.graal.compiler.sparc.test@workingSets=Graal,SPARC,Test +# graal.runtime +project@com.oracle.graal.runtime@subDir=graal +project@com.oracle.graal.runtime@sourceDirs=src +project@com.oracle.graal.runtime@dependencies=com.oracle.graal.compiler +project@com.oracle.graal.runtime@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.runtime@javaCompliance=1.7 +project@com.oracle.graal.runtime@workingSets=Graal + # graal.bytecode project@com.oracle.graal.bytecode@subDir=graal project@com.oracle.graal.bytecode@sourceDirs=src @@ -434,7 +448,7 @@ # graal.java.decompiler.test project@com.oracle.graal.java.decompiler.test@subDir=graal project@com.oracle.graal.java.decompiler.test@sourceDirs=src -project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer +project@com.oracle.graal.java.decompiler.test@dependencies=com.oracle.graal.printer,com.oracle.graal.runtime project@com.oracle.graal.java.decompiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.java.decompiler.test@javaCompliance=1.7 project@com.oracle.graal.java.decompiler.test@workingSets=Graal,Test @@ -458,7 +472,7 @@ # graal.compiler.test project@com.oracle.graal.compiler.test@subDir=graal project@com.oracle.graal.compiler.test@sourceDirs=src -project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer +project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.test,com.oracle.graal.printer,com.oracle.graal.runtime project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.test@javaCompliance=1.7 project@com.oracle.graal.compiler.test@workingSets=Graal,Test @@ -482,7 +496,7 @@ # graal.asm.test project@com.oracle.graal.asm.test@subDir=graal project@com.oracle.graal.asm.test@sourceDirs=src -project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.test,com.oracle.graal.asm +project@com.oracle.graal.asm.test@dependencies=com.oracle.graal.test,com.oracle.graal.runtime project@com.oracle.graal.asm.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.test@javaCompliance=1.7 project@com.oracle.graal.asm.test@workingSets=Graal,Assembler,Test @@ -622,7 +636,7 @@ # graal.truffle project@com.oracle.graal.truffle@subDir=graal project@com.oracle.graal.truffle@sourceDirs=src -project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.hotspot +project@com.oracle.graal.truffle@dependencies=com.oracle.truffle.api,com.oracle.graal.replacements,com.oracle.graal.runtime,com.oracle.graal.printer project@com.oracle.graal.truffle@checkstyle=com.oracle.graal.graph project@com.oracle.graal.truffle@javaCompliance=1.7 project@com.oracle.graal.truffle@workingSets=Graal,Truffle diff -r 935dcd8ad8eb -r e47f373499ec mxtool/mx.py --- a/mxtool/mx.py Mon Oct 21 11:07:32 2013 +0200 +++ b/mxtool/mx.py Mon Oct 21 11:07:47 2013 +0200 @@ -55,17 +55,18 @@ commands.py Suite specific extensions to the commands available to mx. - includes + imports Other suites to be loaded. This is recursive. Each - line in an includes file is a path to a suite directory. + line in an imports file is the name of an imported suite. + The suite is located using a SuiteModel (cf searchpath) env A set of environment variable definitions. These override any existing environment variables. Common properties set here include JAVA_HOME and IGNORED_PROJECTS. -The includes and env files are typically not put under version control -as they usually contain local file-system paths. +The env file is typically not put under version control +as it usually contain local file-system paths. The projects file is like the pom.xml file from Maven except that it is a properties file (not XML). Each non-comment line @@ -156,9 +157,12 @@ _suites = dict() _annotationProcessors = None _mainSuite = None +_src_suitemodel = None +_dst_suitemodel = None _opts = None _java = None _check_global_structures = True # can be set False to allow suites with duplicate definitions to load without aborting +_warn = False """ @@ -493,41 +497,245 @@ deps.append(self) return deps +class SuiteModel: + """ + Defines how to locate a URL/path for a suite, including imported suites. + Conceptually a SuiteModel is defined by a primary suite URL/path and a + map from suite name to URL/path for imported suites. + Subclasses define a specfic implementation. + """ + def __init__(self): + self.primaryDir = None + self.suitenamemap = {} + + def _find_suite_dir(self, suitename): + """locates the URL/path for suitename or None if not found""" + abort('_find_suite_dir not implemented') + + def _set_primary_dir(self, d): + """informs that d is the primary suite directory""" + self._primaryDir = d + + def _importee_dir(self, importer_dir, suitename): + """returns the directory path for an import of suitename, given importer_dir""" + abort('_importee_dir not implemented') + + def _nestedsuites_dirname(self): + """Returns the dirname that contains any nested suites if the model supports that""" + return None + + def _mxDirName(self, name): + # temporary workaround until mx.graal exists + if name == 'graal': + return 'mx' + else: + return 'mx.' + name + + def _search_dir(self, searchDir, mxDirName): + for dd in os.listdir(searchDir): + sd = _is_suite_dir(join(searchDir, dd), mxDirName) + if sd is not None: + return sd + + def _create_suitenamemap(self, optionspec, suitemap): + """Three ways to specify a suite name mapping, in order of precedence: + 1. Explicitly in optionspec. + 2. In suitemap. + 3. in MXSUITEMAP environment variable. + """ + if optionspec != '': + spec = optionspec + elif suitemap is not None: + spec = suitemap + elif get_env('MXSUITEMAP') is not None: + spec = get_env('MXSUITEMAP') + else: + return + pairs = spec.split(',') + for pair in pairs: + mappair = pair.split('=') + self.suitenamemap[mappair[0]] = mappair[1] + + @staticmethod + def _set_suitemodel(option, suitemap): + if option.startswith('sibling'): + return SiblingSuiteModel(os.getcwd(), option, suitemap) + elif option.startswith('nested'): + return NestedImportsSuiteModel(os.getcwd(), option, suitemap) + elif option.startswith('path'): + return PathSuiteModel(option[len('path:'):]) + else: + abort('unknown suitemodel type: ' + option) + + @staticmethod + def _parse_options(): + # suite-specific args may match the known args so there is no way at this early stage + # to use ArgParser to handle the suite model global arguments, so we just do it manually. + def _get_argvalue(arg, args, i): + if i < len(args): + return args[i] + else: + abort('value expected with ' + arg) + + args = sys.argv[1:] + src_suitemodel_arg = dst_suitemodel_arg = 'sibling' + suitemap_arg = None + + i = 0 + while i < len(args): + arg = args[i] + if arg == '--src-suitemodel': + src_suitemodel_arg = _get_argvalue(arg, args, i + 1) + elif arg == '--dst-suitemodel': + dst_suitemodel_arg = _get_argvalue(arg, args, i + 1) + elif arg == '--suitemap': + suitemap_arg = _get_argvalue(arg, args, i + 1) + i = i + 1 + + global _src_suitemodel + _src_suitemodel = SuiteModel._set_suitemodel(src_suitemodel_arg, suitemap_arg) + global _dst_suitemodel + _dst_suitemodel = SuiteModel._set_suitemodel(dst_suitemodel_arg, suitemap_arg) + + +class SiblingSuiteModel(SuiteModel): + """All suites are siblings in the same parent directory, recorded as _suiteRootDir""" + def __init__(self, suiteRootDir, option, suitemap): + SuiteModel.__init__(self) + self._suiteRootDir = suiteRootDir + self._create_suitenamemap(option[len('sibling:'):], suitemap) + + def _find_suite_dir(self, name): + return self._search_dir(self._suiteRootDir, self._mxDirName(name)) + + def _set_primary_dir(self, d): + SuiteModel._set_primary_dir(self, d) + self._suiteRootDir = dirname(d) + + def _importee_dir(self, importer_dir, suitename): + if self.suitenamemap.has_key(suitename): + suitename = self.suitenamemap[suitename] + return join(dirname(importer_dir), suitename) + +class NestedImportsSuiteModel(SuiteModel): + """Imported suites are all siblings in an 'imported_suites' directory of the primary suite""" + def _imported_suites_dirname(self): + return "imported_suites" + + def __init__(self, primaryDir, option, suitemap): + SuiteModel.__init__(self) + self._primaryDir = primaryDir + self._create_suitenamemap(option[len('nested:'):], suitemap) + + def _find_suite_dir(self, name): + return self._search_dir(join(self._primaryDir, self._imported_suites_dirname()), self._mxDirName(name)) + + def _importee_dir(self, importer_dir, suitename): + if self.suitenamemap.has_key(suitename): + suitename = self.suitenamemap[suitename] + if basename(importer_dir) == basename(self._primaryDir): + # primary is importer + this_imported_suites_dirname = join(importer_dir, self._imported_suites_dirname()) + if not exists(this_imported_suites_dirname): + os.mkdir(this_imported_suites_dirname) + return join(this_imported_suites_dirname, suitename) + else: + return join(dirname(importer_dir), suitename) + + def _nestedsuites_dirname(self): + return self._imported_suites_dirname() + +class PathSuiteModel(SuiteModel): + """The most general model. Uses a map from suitename to URL/path provided by the user""" + def __init__(self, path): + SuiteModel.__init__(self) + paths = path.split(',') + self.suit_to_url = {} + for path in paths: + pair = path.split('=') + if len(pair) > 1: + suitename = pair[0] + suiteurl = pair[1] + else: + suitename = basename(pair[0]) + suiteurl = pair[0] + self.suit_to_url[suitename] = suiteurl + + def _find_suite_dir(self, suitename): + if self.suit_to_url.has_key(suitename): + return self.suit_to_url[suitename] + else: + return None + + def _importee_dir(self, importer_dir, suitename): + if suitename in self.suit_to_url: + return self.suit_to_url[suitename] + else: + abort('suite ' + suitename + ' not found') + +class SuiteImport: + def __init__(self, name, version): + self.name = name + self.version = version + + @staticmethod + def _parse_specification(specification): + pair = specification.split(',') + name = pair[0] + if len(pair) > 1: + version = pair[1] + else: + version = None + return SuiteImport(name, version) + + @staticmethod + def _tostring(name, version): + return name + ',' + version + + def _self_tostring(self): + return self.name + ',' + self.version + class Suite: - def __init__(self, d, mxDir, primary): - self.dir = d + def __init__(self, mxDir, primary, load=True): + self.dir = dirname(mxDir) self.mxDir = mxDir self.projects = [] self.libs = [] self.dists = [] - self.includes = [] + self.imports = [] self.commands = None self.primary = primary - self._load_env(mxDir) - self._load_commands(mxDir) - self._load_includes(mxDir) - self.name = d # re-initialized in _load_projects + self.name = _suitename(mxDir) # validated in _load_projects + self.version = None # _hgtip checks current version if not None + self.version = _hgtip(self, False) + if load: + # load suites bottom up to make sure command overriding works properly + self._load_imports() + self._load_env() + self._load_commands() + _suites[self.name] = self def __str__(self): return self.name - def _load_projects(self, mxDir): + def _load_projects(self): libsMap = dict() projsMap = dict() distsMap = dict() - projectsFile = join(mxDir, 'projects') + projectsFile = join(self.mxDir, 'projects') if not exists(projectsFile): return - def _find_suite_key(): - for items in _suites.items(): - if items[1].dir == self.dir: - return items[0] - raise KeyError - with open(projectsFile) as f: + prefix = '' for line in f: line = line.strip() + if line.endswith('\\'): + prefix = prefix + line[:-1] + continue + if len(prefix) != 0: + line = prefix + line + prefix = '' if len(line) != 0 and line[0] != '#': key, value = line.split('=', 1) @@ -537,10 +745,7 @@ if parts[0] != 'suite': abort('Single part property must be "suite": ' + key) if self.name != value: - currentKey = _find_suite_key() - _suites.pop(currentKey) - self.name = value - _suites[value] = self + abort('suite name in project file does not match ' + _suitename(self.mxDir)) continue if len(parts) != 3: abort('Property name does not have 3 parts separated by "@": ' + key) @@ -609,38 +814,89 @@ if self.name is None: abort('Missing "suite=" in ' + projectsFile) - def _load_commands(self, mxDir): - commandsPath = join(mxDir, 'commands.py') + def _commands_name(self): + return 'mx_' + self.name + + def _find_commands(self, name): + commandsPath = join(self.mxDir, name + '.py') if exists(commandsPath): + return name + else: + return None + + def _load_commands(self): + commandsName = self._find_commands(self._commands_name()) + if commandsName is None: + # backwards compatibility + commandsName = self._find_commands('commands') + if commandsName is not None: + if commandsName in sys.modules: + abort(commandsName + '.py in suite ' + self.name + ' duplicates ' + sys.modules[commandsName].__file__) # temporarily extend the Python path - sys.path.insert(0, mxDir) - mod = __import__('commands') - - self.commands = sys.modules.pop('commands') - sys.modules[join(mxDir, 'commands')] = self.commands + sys.path.insert(0, self.mxDir) + mod = __import__(commandsName) + + self.commands = sys.modules.pop(commandsName) + sys.modules[commandsName] = self.commands # revert the Python path del sys.path[0] if not hasattr(mod, 'mx_init'): - abort(commandsPath + ' must define an mx_init(env) function') + abort(commandsName + '.py in suite ' + self.name + ' must define an mx_init(suite) function') if hasattr(mod, 'mx_post_parse_cmd_line'): self.mx_post_parse_cmd_line = mod.mx_post_parse_cmd_line mod.mx_init(self) self.commands = mod - def _load_includes(self, mxDir): - includes = join(mxDir, 'includes') - if exists(includes): - with open(includes) as f: + def _visit_imports(self, visitor, **extra_args): + """ + Visitor support for the imports file. + For each line of the imports file that specifies an import, the visitor function is + called with this suite, a SuiteImport instance created from the line and any extra args + passed to this call. In addition, if extra_args contains a key 'update_versions' that is True, + a StringIO value is added to extra_args with key 'updated_imports', and the visitor is responsible + for writing a (possibly) updated import line to the file, and the file is (possibly) updated after + all imports are processed. + N.B. There is no built-in support for avoiding visiting the same suite multiple times, + as this function only visits the imports of a singkle suite. If a (recursive) visitor function + wishes to visit a suite exactly once, it must manage that through extra_args. + """ + importsFile = join(self.mxDir, 'imports') + if exists(importsFile): + update_versions = extra_args.has_key('update_versions') and extra_args['update_versions'] + out = StringIO.StringIO() if update_versions else None + extra_args['updated_imports'] = out + with open(importsFile) as f: for line in f: - include = expandvars_in_property(line.strip()) - self.includes.append(include) - _loadSuite(os.path.abspath(include), False) - - def _load_env(self, mxDir): - e = join(mxDir, 'env') + sline = line.strip() + if len(sline) == 0 or sline.startswith('#'): + if out is not None: + out.write(sline + '\n') + continue + suite_import = SuiteImport._parse_specification(line.strip()) + visitor(self, suite_import, **extra_args) + + if out is not None: + update_file(importsFile, out.getvalue()) + + @staticmethod + def _find_and_loadsuite(suite, suite_import, **extra_args): + """visitor for the initial suite load""" + importMxDir = _src_suitemodel._find_suite_dir(suite_import.name) + if importMxDir is None: + abort('import ' + suite_import.name + ' not found') + suite.imports.append(suite_import) + imported_suite = _loadSuite(importMxDir, False) + if imported_suite.version != suite.version: + warn('import version of ' + imported_suite.name +' does not match tip of ' + suite.version) + + def _load_imports(self): + self._visit_imports(self._find_and_loadsuite) + + def _load_env(self): + e = join(self.mxDir, 'env') if exists(e): with open(e) as f: lineNum = 0 @@ -654,8 +910,8 @@ os.environ[key.strip()] = expandvars_in_property(value.strip()) def _post_init(self, opts): - self._load_projects(self.mxDir) - # set the global data structures, checking for conflicts unless _global_structures is False + self._load_projects() + # set the global data structures, checking for conflicts unless _check_global_structures is False for p in self.projects: existing = _projects.get(p.name) if existing is not None and _check_global_structures: @@ -673,7 +929,7 @@ if existing is not None and _check_global_structures: # allow redefinition, so use path from existing # abort('cannot redefine distribution ' + d.name) - print('WARNING: distribution ' + d.name + ' redefined') + warn('distribution ' + d.name + ' redefined') d.path = existing.path _dists[d.name] = d if hasattr(self, 'mx_post_parse_cmd_line'): @@ -770,28 +1026,16 @@ else: abort('Unknown operating system ' + sys.platform) -def _loadSuite(d, primary=False): +def _loadSuite(mxDir, primary=False): """ - Load a suite from the 'mx' or 'mx.bbb' subdirectory of d, where 'bbb' is basename of d + Load a suite from 'mxDir'. """ - mxDefaultDir = join(d, 'mx') - name = os.path.basename(d) - mxTaggedDir = mxDefaultDir + '.' + name - mxDir = None - if exists(mxTaggedDir) and isdir(mxTaggedDir): - mxDir = mxTaggedDir - else: - if exists(mxDefaultDir) and isdir(mxDefaultDir): - mxDir = mxDefaultDir - - - if mxDir is None: - return None - if len([s for s in _suites.itervalues() if s.dir == d]) == 0: - s = Suite(d, mxDir, primary) - # N.B. this will be updated once the projects file has been read - _suites[name] = s - return s + for s in _suites.itervalues(): + if s.mxDir == mxDir: + return s + # create the new suite + s = Suite(mxDir, primary) + return s def suites(opt_limit_to_suite=False): """ @@ -815,6 +1059,7 @@ abort('suite named ' + name + ' not found') return s + def projects_from_names(projectNames): """ Get the list of projects corresponding to projectNames; all projects if None @@ -1013,7 +1258,7 @@ else: break - envPath = join(_mainSuite.dir, 'mx', 'env') + envPath = join(_mainSuite.mxDir, 'env') if ask_yes_no('Persist this setting by adding "JAVA_HOME=' + javaHome + '" to ' + envPath, 'y'): with open(envPath, 'a') as fp: print >> fp, 'JAVA_HOME=' + javaHome @@ -1021,7 +1266,6 @@ return javaHome class ArgParser(ArgumentParser): - # Override parent to append the list of available commands def format_help(self): return ArgumentParser.format_help(self) + _format_commands() @@ -1034,6 +1278,7 @@ self.add_argument('-v', action='store_true', dest='verbose', help='enable verbose output') self.add_argument('-V', action='store_true', dest='very_verbose', help='enable very verbose output') + self.add_argument('-w', action='store_true', dest='warn', help='enable warning messages') self.add_argument('--dbg', type=int, dest='java_dbg_port', help='make Java processes wait on for a debugger', metavar='') self.add_argument('-d', action='store_const', const=8000, dest='java_dbg_port', help='alias for "-dbg 8000"') self.add_argument('--cp-pfx', dest='cp_prefix', help='class path prefix', metavar='') @@ -1045,6 +1290,9 @@ self.add_argument('--java-home', help='bootstrap JDK installation directory (must be JDK 6 or later)', metavar='') self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='', default=[]) self.add_argument('--suite', action='append', dest='specific_suites', help='limit command to given suite', default=[]) + self.add_argument('--src-suitemodel', help='mechanism for locating imported suites', metavar='', default='sibling') + self.add_argument('--dst-suitemodel', help='mechanism for placing cloned/pushed suites', metavar='', default='sibling') + self.add_argument('--suitemap', help='explicit remapping of suite names', metavar='') if get_os() != 'windows': # Time outs are (currently) implemented with Unix specific functionality self.add_argument('--timeout', help='timeout (in seconds) for command', type=int, default=0, metavar='') @@ -1599,7 +1847,7 @@ javaCompliance = java().javaCompliance - defaultEcjPath = join(_mainSuite.dir, 'mx', 'ecj.jar') + defaultEcjPath = join(_mainSuite.mxDir, 'ecj.jar') parser = parser if parser is not None else ArgumentParser(prog='mx build') parser.add_argument('-f', action='store_true', dest='force', help='force build (disables timestamp checking)') @@ -1796,7 +2044,7 @@ jdtProperties = join(p.dir, '.settings', 'org.eclipse.jdt.core.prefs') - rootJdtProperties = join(p.suite.dir, 'mx', 'eclipse-settings', 'org.eclipse.jdt.core.prefs') + rootJdtProperties = join(p.suite.mxDir, 'eclipse-settings', 'org.eclipse.jdt.core.prefs') if not exists(jdtProperties) or os.path.getmtime(jdtProperties) < os.path.getmtime(rootJdtProperties): # Try to fix a missing properties file by running eclipseinit eclipseinit([], buildProcessorJars=False) @@ -2115,7 +2363,7 @@ The exit code of this command reflects how many files were updated.""" changedFiles = 0 - for s in suites(): + for s in suites(True): projectsFile = join(s.mxDir, 'projects') if not exists(projectsFile): continue @@ -2675,8 +2923,7 @@ if _isAnnotationProcessorDependency(p): _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh=False, async=False, xmlIndent='', xmlStandalone='no') - # Refresh.launch seems to cause occasional build looping in Eclipse - # _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True) + _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh=True, async=True) if projToDist.has_key(p.name): dist, distDeps = projToDist[p.name] @@ -2756,12 +3003,20 @@ launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn}) launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true' if async else 'false'}) - baseDir = dirname(dirname(os.path.abspath(__file__))) + # expect to find the OS command to invoke mx in the same directory + baseDir = dirname(os.path.abspath(__file__)) cmd = 'mx.sh' if get_os() == 'windows': cmd = 'mx.cmd' - launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': join(baseDir, cmd) }) + cmdPath = join(baseDir, cmd) + if not os.path.exists(cmdPath): + # backwards compatibility for when the commands lived in parent of mxtool + cmdPath = join(dirname(baseDir), cmd) + if not os.path.exists(cmdPath): + abort('cannot locate ' + cmd) + + launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': cmdPath}) launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'auto,full,incremental'}) launchOut.element('stringAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': mxCommand}) launchOut.element('booleanAttribute', {'key' : 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'}) @@ -3203,18 +3458,24 @@ """find directories corresponding to deleted Java projects and delete them""" for suite in suites(True): projectDirs = [p.dir for p in suite.projects] - for root, dirnames, files in os.walk(suite.dir): - currentDir = join(suite.dir, root) - if currentDir in projectDirs: - # don't traverse subdirs of an existing project + for dirpath, dirnames, files in os.walk(suite.dir): + if dirpath == suite.dir: + # no point in traversing .hg + if '.hg' in dirnames: + dirnames.remove('.hg') + # if there are nested suites must not scan those now, as they are not in projectDirs + if _src_suitemodel._nestedsuites_dirname() in dirnames: + dirnames.remove(_src_suitemodel._nestedsuites_dirname()) + elif dirpath in projectDirs: + # don't traverse subdirs of an existing project in this suite dirnames[:] = [] else: projectConfigFiles = frozenset(['.classpath', 'nbproject']) indicators = projectConfigFiles.intersection(files) if len(indicators) != 0: - if not sys.stdout.isatty() or ask_yes_no(currentDir + ' looks like a removed project -- delete it', 'n'): - shutil.rmtree(currentDir) - log('Deleted ' + currentDir) + if not sys.stdout.isatty() or ask_yes_no(dirpath + ' looks like a removed project -- delete it', 'n'): + shutil.rmtree(dirpath) + log('Deleted ' + dirpath) def javadoc(args, parser=None, docDir='javadoc', includeDeps=True, stdDoclet=True): """generate javadoc for some/all Java projects""" @@ -3618,9 +3879,292 @@ if exists(tmpbase): shutil.rmtree(tmpbase) +def _kwArg(kwargs): + if len(kwargs) > 0: + return kwargs.pop(0) + return None + +def sclone(args): + """clone a suite repository, and its imported suites""" + parser = ArgumentParser(prog='mx sclone') + parser.add_argument('--source', help='url/path of repo containing suite', metavar='') + parser.add_argument('--dest', help='destination directory (default basename of source)', metavar='') + parser.add_argument("--no-imports", action='store_true', help='do not clone imported suites') + parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') + args = parser.parse_args(args) + # check for non keyword args + if args.source is None: + args.source = _kwArg(args.nonKWArgs) + if args.dest is None: + args.dest = _kwArg(args.nonKWArgs) + if len(args.nonKWArgs) > 0: + abort('unrecognized args: ' + ' '.join(args.nonKWArgs)) + + if args.source is None: + # must be primary suite and dest is required + if _mainSuite is None: + abort('--source missing and no primary suite found') + if args.dest is None: + abort('--dest required when --source is not given') + source = _mainSuite.dir + else: + source = args.source + + if args.dest is not None: + dest = args.dest + else: + dest = basename(source) + + dest = os.path.abspath(dest) + # We can now set the primary dir for the src/dst suitemodel + _dst_suitemodel._set_primary_dir(dest) + _src_suitemodel._set_primary_dir(source) + + _sclone(source, dest, None, args.no_imports) + +def _sclone(source, dest, version, no_imports): + cmd = ['hg', 'clone'] + if version is not None: + cmd.append('-r') + cmd.append(version) + cmd.append(source) + cmd.append(dest) + + run(cmd) + + mxDir = _is_suite_dir(dest) + if mxDir is None: + warn(source + ' is not an mx suite') + return None + + # create a Suite (without loading) to enable imports visitor + s = Suite(mxDir, False, load=False) + if not no_imports: + s._visit_imports(_scloneimports_visitor, source=source) + return s + +def _scloneimports_visitor(s, suite_import, source, **extra_args): + """ + cloneimports visitor for Suite._visit_imports. + The destination information is encapsulated by 's' + """ + _scloneimports(s, suite_import, source) + +def _scloneimports_suitehelper(sdir): + mxDir = _is_suite_dir(sdir) + if mxDir is None: + abort(sdir + ' is not an mx suite') + else: + # create a Suite (without loading) to enable imports visitor + return Suite(mxDir, False, load=False) + +def _scloneimports(s, suite_import, source): + # clone first, then visit imports once we can locate them + importee_source = _src_suitemodel._importee_dir(source, suite_import.name) + importee_dest = _dst_suitemodel._importee_dir(s.dir, suite_import.name) + if exists(importee_dest): + importee_suite = _scloneimports_suitehelper(importee_dest) + importee_suite._visit_imports(_scloneimports_visitor, source=importee_source) + else: + _sclone(importee_source, importee_dest, suite_import.version, False) + # _clone handles the recursive visit of the new imports + +def scloneimports(args): + """clone the imports of an existing suite""" + parser = ArgumentParser(prog='mx scloneimports') + parser.add_argument('--source', help='url/path of repo containing suite', metavar='') + parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') + args = parser.parse_args(args) + # check for non keyword args + if args.source is None: + args.source = _kwArg(args.nonKWArgs) + + if not os.path.isdir(args.source): + abort(args.source + ' is not a directory') + + s = _scloneimports_suitehelper(args.source) + + default_path = _hgdefault_push(args.source) + + if default_path is None: + abort('no default path in ' + join(args.source, '.hg', 'hgrc')) + + # We can now set the primary dir for the dst suitemodel + # N.B. source is effectively the destination and the default_path is the (original) source + _dst_suitemodel._set_primary_dir(args.source) + + s._visit_imports(_scloneimports_visitor, source=default_path) + +def _spush_import_visitor(s, suite_import, dest, checks, clonemissing, **extra_args): + """push visitor for Suite._visit_imports""" + if dest is not None: + dest = _dst_suitemodel._importee_dir(dest, suite_import.name) + _spush(suite(suite_import.name), suite_import, dest, checks, clonemissing) + +def _spush_check_import_visitor(s, suite_import, **extra_args): + """push check visitor for Suite._visit_imports""" + currentTip = _hgtip(suite(suite_import.name)) + if currentTip != suite_import.version: + abort('import version of ' + suite_import.name + ' in suite ' + s.name + ' does not match tip') + +def _spush(s, suite_import, dest, checks, clonemissing): + if checks: + if not _hgcanpush(s): + abort('working directory ' + s.dir + ' contains uncommitted changes, push aborted') + + # check imports first + if checks: + s._visit_imports(_spush_check_import_visitor) + + # ok, push imports + s._visit_imports(_spush_import_visitor, dest=dest, checks=checks, clonemissing=clonemissing) + + dest_exists = True + + if clonemissing: + if not os.path.exists(dest): + dest_exists = False + + def add_version(cmd, suite_import): + if suite_import is not None and suite_import.version is not None: + cmd.append('-r') + cmd.append(suite_import.version) + + if dest_exists: + cmd = ['hg', '-R', s.dir, 'push'] + add_version(cmd, suite_import) + if dest is not None: + cmd.append(dest) + rc = run(cmd, nonZeroIsFatal=False) + if rc != 0: + # rc of 1 not an error, means no changes + if rc != 1: + abort("push failed, exit code " + str(rc)) + else: + cmd = ['hg', 'clone'] + add_version(cmd, suite_import) + cmd.append(s.dir) + cmd.append(dest) + run(cmd) + +def spush(args): + """push primary suite and all its imports""" + parser = ArgumentParser(prog='mx spush') + parser.add_argument('--dest', help='url/path of repo to push to (default as per hg push)', metavar='') + parser.add_argument('--no-checks', action='store_true', help='checks on status, versions are disabled') + parser.add_argument('--clonemissing', action='store_true', help='clone missing imported repos at destination (forces --no-checks)') + parser.add_argument('nonKWArgs', nargs=REMAINDER, metavar='source [dest]...') + args = parser.parse_args(args) + if args.dest is None: + args.dest = _kwArg(args.nonKWArgs) + if len(args.nonKWArgs) > 0: + abort('unrecognized args: ' + ' '.join(args.nonKWArgs)) + + if args.dest is not None and not os.path.isdir(args.dest): + abort('destination must be a directory') + + s = _check_primary_suite() + + if args.clonemissing: + if args.dest is None: + abort('--dest required with --clonemissing') + args.nochecks = True + + if args.dest is not None: + _dst_suitemodel._set_primary_dir(args.dest) + + _spush(s, None, args.dest, not args.nochecks, args.clonemissing) + +def _supdate_import_visitor(s, suite_import, **extra_args): + _supdate(suite(suite_import.name), suite_import) + +def _supdate(s, suite_import): + s._visit_imports(_supdate_import_visitor) + + run(['hg', '-R', s.dir, 'update']) + +def supdate(args): + """update primary suite and all its imports""" + + s = _check_primary_suite() + + _supdate(s, None) + +def _scheck_imports_visitor(s, suite_import, update_versions, updated_imports): + """checkimportversions visitor for Suite._visit_imports""" + _scheck_imports(suite(suite_import.name), suite_import, update_versions, updated_imports) + +def _scheck_imports(s, suite_import, update_versions, updated_imports): + # check imports recursively + s._visit_imports(_scheck_imports_visitor, update_versions=update_versions) + + currentTip = _hgtip(s) + if currentTip != suite_import.version: + print('import version of ' + s.name + ' does not match tip' + (': updating' if update_versions else '')) + + if update_versions: + suite_import.version = currentTip + line = suite_import._self_tostring() + updated_imports.write(line + '\n') + +def scheckimports(args): + """check that suite import versions are up to date""" + parser = ArgumentParser(prog='mx scheckimports') + parser.add_argument('--update-versions', help='update imported version ids', action='store_true') + args = parser.parse_args(args) + _check_primary_suite()._visit_imports(_scheck_imports_visitor, update_versions=args.update_versions) + +def _hgtip(s, abortOnError=True): + try: + version = subprocess.check_output(['hg', 'tip', '-R', s.dir, '--template', '{node}']) + if s.version is not None and s.version != version: + abort('version of suite ' + s.name +' has changed during run') + return version + except subprocess.CalledProcessError: + if abortOnError: + abort('failed to get tip revision id') + else: + return None + +def _hgcanpush(s): + try: + output = subprocess.check_output(['hg', '-R', s.dir, 'status']) + # super strict + return output == '' + except subprocess.CalledProcessError: + return False + +def _hgdefault_push(sdir): + with open(join(sdir, '.hg', 'hgrc')) as f: + for line in f: + line = line.rstrip() + if line.startswith('default = '): + return line[len('default = '):] + return None + +def _spull_import_visitor(s, suite_import, update_versions, updated_imports): + """pull visitor for Suite._visit_imports""" + _spull(suite(suite_import.name), update_versions, updated_imports) + +def _spull(s, update_versions, updated_imports): + # pull imports first + s._visit_imports(_spull_import_visitor, update_versions=update_versions) + + run(['hg', '-R', s.dir, 'pull', '-u']) + if update_versions and updated_imports is not None: + tip = _hgtip(s) + updated_imports.write(SuiteImport._tostring(s.name, tip) + '\n') + +def spull(args): + """pull primary suite and all its imports""" + parser = ArgumentParser(prog='mx spull') + parser.add_argument('--update-versions', action='store_true', help='update version ids of imported suites') + args = parser.parse_args(args) + + _spull(_check_primary_suite(), args.update_versions, None) + def findclass(args, logToConsole=True): """find all classes matching a given substring""" - matches = [] for entry, filename in classpath_walk(includeBootClasspath=True): if filename.endswith('.class'): @@ -3727,17 +4271,19 @@ def update_commands(suite, new_commands): for key, value in new_commands.iteritems(): - if _commands.has_key(key) and not suite.primary: - pass - # print("WARNING: attempt to redefine command '" + key + "' in suite " + suite.dir) - else: - _commands[key] = value + if _commands.has_key(key): + warn("redefining command '" + key + "' in suite " + suite.name) + _commands[key] = value + +def warn(msg): + if _warn: + print('WARNING: ' + msg) # Table of commands in alphabetical order. # Keys are command names, value are lists: [, , ...] # If any of the format args are instances of Callable, then they are called with an 'env' are before being # used in the call to str.format(). -# Extensions should update this table directly +# Suite extensions should not update this table directly, but use update_commands _commands = { 'about': [about, ''], 'build': [build, '[options]'], @@ -3753,6 +4299,12 @@ 'ideinit': [ideinit, ''], 'archive': [archive, '[options]'], 'projectgraph': [projectgraph, ''], + 'sclone': [sclone, '[options]'], + 'scheckimports': [scheckimports, ''], + 'scloneimports': [scloneimports, '[options]'], + 'spull': [spull, '[options'], + 'spush': [spush, '[options'], + 'supdate': [supdate, ''], 'pylint': [pylint, ''], 'javap': [javap, ''], 'javadoc': [javadoc, '[options]'], @@ -3763,36 +4315,68 @@ _argParser = ArgParser() -def _findPrimarySuite(): - def is_suite_dir(d): +def _suitename(mxDir): + base = os.path.basename(mxDir) + parts = base.split('.') + # temporary workaround until mx.graal exists + if len(parts) == 1: + return 'graal' + else: + return parts[1] + +def _is_suite_dir(d, mxDirName=None): + """ + Checks if d contains a suite. + If mxDirName is None, matches any suite name, otherwise checks for exactly that suite. + """ + if os.path.isdir(d): for f in os.listdir(d): - if f == 'mx' or fnmatch.fnmatch(f, 'mx.*'): + if (mxDirName == None and (f == 'mx' or fnmatch.fnmatch(f, 'mx.*'))) or f == mxDirName: mxDir = join(d, f) if exists(mxDir) and isdir(mxDir) and exists(join(mxDir, 'projects')): - return dirname(mxDir) - - - # try current working directory first - if is_suite_dir(os.getcwd()): - return os.getcwd() - - # now search path of my executable - me = sys.argv[0] - parent = dirname(me) - while parent: - if is_suite_dir(parent): - return parent - parent = dirname(parent) + return mxDir + +def _check_primary_suite(): + if _mainSuite is None: + abort('no primary suite found') + else: + return _mainSuite + +def _needs_primary_suite(command): + return not command.startswith("sclone") + +def _findPrimarySuiteMxDir(): + # try current working directory first, the look up the tree + curdir = os.getcwd() + while curdir: + mxDir = _is_suite_dir(curdir) + if mxDir is not None: + return mxDir + parent = dirname(curdir) + if curdir == parent: + return None + curdir = parent + return None def main(): - primarySuiteDir = _findPrimarySuite() - if primarySuiteDir: + SuiteModel._parse_options() + + primarySuiteMxDir = _findPrimarySuiteMxDir() + if primarySuiteMxDir: + _src_suitemodel._set_primary_dir(dirname(primarySuiteMxDir)) global _mainSuite - _mainSuite = _loadSuite(primarySuiteDir, True) + _mainSuite = _loadSuite(primarySuiteMxDir, True) opts, commandAndArgs = _argParser._parse_cmd_line() + if primarySuiteMxDir is None: + msg = 'no primary suite found' + if len(commandAndArgs) > 0 and _needs_primary_suite(commandAndArgs[0]): + abort(msg) + else: + warn(msg) + global _opts, _java _opts = opts _java = JavaConfig(opts) diff -r 935dcd8ad8eb -r e47f373499ec src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java --- a/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java Mon Oct 21 11:07:47 2013 +0200 @@ -201,12 +201,21 @@ } } + private static class Port { + public final boolean isList; + public final String name; + private Port(boolean isList, String name) { + this.isList = isList; + this.name = name; + } + } + private static class NodeClass { public final String className; public final String nameTemplate; - public final List inputs; - public final List sux; - private NodeClass(String className, String nameTemplate, List inputs, List sux) { + public final List inputs; + public final List sux; + private NodeClass(String className, String nameTemplate, List inputs, List sux) { this.className = className; this.nameTemplate = nameTemplate; this.inputs = inputs; @@ -301,9 +310,8 @@ int len = readInt(); ensureAvailable(len * 2); char[] chars = new char[len]; - for (int i = 0; i < len; i++) { - chars[i] = buffer.getChar(); - } + buffer.asCharBuffer().get(chars); + buffer.position(buffer.position() + len * 2); return new String(chars); } @@ -377,7 +385,7 @@ return (T) addPoolEntry(klass); } assert assertObjectType(klass, type); - int index = readInt(); + char index = readShort(); if (index < 0 || index >= constantPool.size()) { throw new IOException("Invalid constant pool index : " + index); } @@ -409,7 +417,7 @@ } private Object addPoolEntry(Class klass) throws IOException { - int index = readInt(); + char index = readShort(); int type = readByte(); assert assertObjectType(klass, type) : "Wrong object type : " + klass + " != " + type; Object obj; @@ -441,14 +449,18 @@ String className = readString(); String nameTemplate = readString(); int inputCount = readShort(); - List inputs = new ArrayList<>(inputCount); + List inputs = new ArrayList<>(inputCount); for (int i = 0; i < inputCount; i++) { - inputs.add(readPoolObject(String.class)); + boolean isList = readByte() != 0; + String name = readPoolObject(String.class); + inputs.add(new Port(isList, name)); } int suxCount = readShort(); - List sux = new ArrayList<>(suxCount); + List sux = new ArrayList<>(suxCount); for (int i = 0; i < suxCount; i++) { - sux.add(readPoolObject(String.class)); + boolean isList = readByte() != 0; + String name = readPoolObject(String.class); + sux.add(new Port(isList, name)); } obj = new NodeClass(className, nameTemplate, inputs, sux); break; @@ -685,17 +697,44 @@ } } int edgesStart = edges.size(); - int suxCount = readShort(); - for (int j = 0; j < suxCount; j++) { - int sux = readInt(); - int index = readShort(); - edges.add(new Edge(id, sux, (char) j, nodeClass.sux.get(index), false)); + int portNum = 0; + for (Port p : nodeClass.inputs) { + if (p.isList) { + int size = readShort(); + for (int j = 0; j < size; j++) { + int in = readInt(); + if (in >= 0) { + edges.add(new Edge(in, id, (char) (preds + portNum), p.name + "[" + j + "]", true)); + portNum++; + } + } + } else { + int in = readInt(); + if (in >= 0) { + edges.add(new Edge(in, id, (char) (preds + portNum), p.name, true)); + portNum++; + } + } + } - int inputCount = readShort(); - for (int j = 0; j < inputCount; j++) { - int in = readInt(); - int index = readShort(); - edges.add(new Edge(in, id, (char) (preds + j), nodeClass.inputs.get(index), true)); + portNum = 0; + for (Port p : nodeClass.sux) { + if (p.isList) { + int size = readShort(); + for (int j = 0; j < size; j++) { + int sux = readInt(); + if (sux >= 0) { + edges.add(new Edge(id, sux, (char) portNum, p.name + "[" + j + "]", false)); + portNum++; + } + } + } else { + int sux = readInt(); + if (sux >= 0) { + edges.add(new Edge(id, sux, (char) portNum, p.name, false)); + portNum++; + } + } } properties.setProperty("name", createName(edges.subList(edgesStart, edges.size()), props, nodeClass.nameTemplate)); properties.setProperty("class", nodeClass.className); diff -r 935dcd8ad8eb -r e47f373499ec src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Oct 21 11:07:47 2013 +0200 @@ -314,9 +314,6 @@ template(com_oracle_graal_hotspot_meta_HotSpotMonitorValue, "com/oracle/graal/hotspot/meta/HotSpotMonitorValue") \ template(com_oracle_graal_hotspot_debug_LocalImpl, "com/oracle/graal/hotspot/debug/LocalImpl") \ template(com_oracle_graal_hotspot_CompilerThread, "com/oracle/graal/hotspot/CompilerThread") \ - template(com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime, "com/oracle/graal/hotspot/ptx/PTXHotSpotGraalRuntime")\ - AMD64_ONLY(template(com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime,"com/oracle/graal/hotspot/amd64/AMD64HotSpotGraalRuntime"))\ - SPARC_ONLY(template(com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime,"com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime"))\ /* graal.api.meta */ \ template(com_oracle_graal_api_meta_Constant, "com/oracle/graal/api/meta/Constant") \ template(com_oracle_graal_api_meta_ConstantPool, "com/oracle/graal/api/meta/ConstantPool") \ @@ -387,11 +384,11 @@ template(createConstantObject_signature, "(Ljava/lang/Object;)Lcom/oracle/graal/api/meta/Constant;") \ template(getVMToCompiler_name, "getVMToCompiler") \ template(getVMToCompiler_signature, "()Lcom/oracle/graal/hotspot/bridge/VMToCompiler;") \ - template(getInstance_name, "getInstance") \ - template(getTruffleRuntimeInstance_signature, "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;") \ + template(runtime_name, "runtime") \ + template(runtime_signature, "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;") \ template(makeInstance_name, "makeInstance") \ + template(makeInstance_signature, "()Lcom/oracle/graal/truffle/GraalTruffleRuntime;") \ template(initialize_name, "initialize") \ - template(getInstance_signature, "()Lcom/oracle/graal/hotspot/HotSpotGraalRuntime;") \ template(forObject_name, "forObject") \ template(callbackInternal_name, "callbackInternal") \ template(callback_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \ diff -r 935dcd8ad8eb -r e47f373499ec src/share/vm/graal/graalCompilerToGPU.cpp --- a/src/share/vm/graal/graalCompilerToGPU.cpp Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToGPU.cpp Mon Oct 21 11:07:47 2013 +0200 @@ -23,6 +23,7 @@ #include "precompiled.hpp" +#include "memory/oopFactory.hpp" #include "graal/graalCompiler.hpp" #include "graal/graalEnv.hpp" #include "graal/graalJavaAccess.hpp" @@ -205,7 +206,7 @@ #define CONSTANT_POOL "Lcom/oracle/graal/api/meta/ConstantPool;" #define CONSTANT "Lcom/oracle/graal/api/meta/Constant;" #define KIND "Lcom/oracle/graal/api/meta/Kind;" -#define LOCAL "Lcom/oracle/graal/api/meta/Local;" +#define LOCAL "Lcom/oracle/graal/api/meta/Local;" #define RUNTIME_CALL "Lcom/oracle/graal/api/code/RuntimeCall;" #define EXCEPTION_HANDLERS "[Lcom/oracle/graal/api/meta/ExceptionHandler;" #define REFLECT_METHOD "Ljava/lang/reflect/Method;" diff -r 935dcd8ad8eb -r e47f373499ec src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Mon Oct 21 11:07:47 2013 +0200 @@ -53,32 +53,16 @@ KlassHandle klass = loadClass(name); JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::getTruffleRuntimeInstance_signature(), Thread::current()); + JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::makeInstance_signature(), Thread::current()); check_pending_exception("Couldn't initialize GraalTruffleRuntime"); return Handle((oop) result.get_jobject()); } Handle VMToCompiler::graalRuntime() { if (JNIHandles::resolve(_graalRuntimePermObject) == NULL) { -#ifdef AMD64 - Symbol* name = NULL; - // Set name to PTXHotSpotRuntime if nVidia GPU was detected. - if (UseGPU && (gpu::get_target_il_type() == gpu::PTX) && - gpu::is_available() && gpu::has_gpu_linkage()) { - name = vmSymbols::com_oracle_graal_hotspot_ptx_PTXHotSpotGraalRuntime(); - } - - if (name == NULL) { - name = vmSymbols::com_oracle_graal_hotspot_amd64_AMD64HotSpotGraalRuntime(); - } -#endif -#ifdef SPARC - Symbol* name = vmSymbols::com_oracle_graal_hotspot_sparc_SPARCHotSpotGraalRuntime(); -#endif - KlassHandle klass = loadClass(name); - + KlassHandle klass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotGraalRuntime()); JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, klass, vmSymbols::makeInstance_name(), vmSymbols::getInstance_signature(), Thread::current()); + JavaCalls::call_static(&result, klass, vmSymbols::runtime_name(), vmSymbols::runtime_signature(), Thread::current()); check_pending_exception("Couldn't initialize HotSpotGraalRuntime"); _graalRuntimePermObject = JNIHandles::make_global((oop) result.get_jobject()); } diff -r 935dcd8ad8eb -r e47f373499ec src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/vm/runtime/arguments.cpp Mon Oct 21 11:07:47 2013 +0200 @@ -35,6 +35,7 @@ #include "prims/jvmtiExport.hpp" #include "runtime/arguments.hpp" #include "runtime/globals_extension.hpp" +#include "runtime/gpu.hpp" #include "runtime/java.hpp" #include "services/management.hpp" #include "services/memTracker.hpp" @@ -130,6 +131,9 @@ SystemProperty *Arguments::_java_home = NULL; SystemProperty *Arguments::_java_class_path = NULL; SystemProperty *Arguments::_sun_boot_class_path = NULL; +#ifdef GRAAL +SystemProperty *Arguments::_graal_gpu_isalist = NULL; +#endif char* Arguments::_meta_index_path = NULL; char* Arguments::_meta_index_dir = NULL; @@ -193,6 +197,9 @@ _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL, true); _java_class_path = new SystemProperty("java.class.path", "", true); +#ifdef GRAAL + _graal_gpu_isalist = new SystemProperty("graal.gpu.isalist", NULL, true); +#endif // Add to System Property list. PropertyList_add(&_system_properties, _java_ext_dirs); @@ -202,6 +209,9 @@ PropertyList_add(&_system_properties, _java_home); PropertyList_add(&_system_properties, _java_class_path); PropertyList_add(&_system_properties, _sun_boot_class_path); +#ifdef GRAAL + PropertyList_add(&_system_properties, _graal_gpu_isalist); +#endif // Set OS specific system properties values os::init_system_properties_values(); @@ -3801,6 +3811,24 @@ } } +#ifdef GRAAL + if (_graal_gpu_isalist->value() == NULL) { + // Initialize the graal.gpu.isalist system property if + // a) it was not explicitly defined by the user and + // b) at least one GPU is available. + // GPU offload can be disabled by setting the property + // to the empty string on the command line + if (gpu::is_available() && gpu::has_gpu_linkage()) { + if (gpu::get_target_il_type() == gpu::PTX) { + _graal_gpu_isalist->append_value("PTX"); + } + if (gpu::get_target_il_type() == gpu::HSAIL) { + _graal_gpu_isalist->append_value("HSAIL"); + } + } + } +#endif + return JNI_OK; } diff -r 935dcd8ad8eb -r e47f373499ec src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/vm/runtime/arguments.hpp Mon Oct 21 11:07:47 2013 +0200 @@ -264,6 +264,9 @@ static SystemProperty *_java_home; static SystemProperty *_java_class_path; static SystemProperty *_sun_boot_class_path; +#ifdef GRAAL + static SystemProperty *_graal_gpu_isalist; +#endif // Meta-index for knowing what packages are in the boot class path static char* _meta_index_path; diff -r 935dcd8ad8eb -r e47f373499ec src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Mon Oct 21 11:07:32 2013 +0200 +++ b/src/share/vm/runtime/globals.hpp Mon Oct 21 11:07:47 2013 +0200 @@ -3774,9 +3774,6 @@ product(bool, TraceGPUInteraction, false, \ "Trace external GPU Interaction") \ \ - product(bool, UseGPU, false, \ - "Run code on GPU") \ - \ diagnostic(ccstr, SharedArchiveFile, NULL, \ "Override the default location of the CDS archive file") \ \