# HG changeset patch # User Christian Humer # Date 1360575689 -3600 # Node ID e8c71b8562e3bdc6b4935df928532bab685fab3b # Parent 3cec97eb3b5f6b8e20c2e2afe226ff339786ccfc# Parent 52fd6491fca8ae7c987825adaca9269c7d7b844e Merge diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java --- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Mon Feb 11 10:41:29 2013 +0100 @@ -26,6 +26,8 @@ import static com.oracle.graal.api.code.Register.RegisterFlag.*; import static com.oracle.graal.api.meta.Kind.*; +import java.nio.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.Register.*; @@ -109,7 +111,7 @@ public AMD64() { super("AMD64", 8, - ByteOrder.LittleEndian, + ByteOrder.LITTLE_ENDIAN, allRegisters, LOAD_STORE | STORE_STORE, 1, diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Architecture.java Mon Feb 11 10:41:29 2013 +0100 @@ -22,9 +22,10 @@ */ package com.oracle.graal.api.code; +import java.nio.*; import java.util.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.Register.RegisterFlag; /** * Represents a CPU architecture, including information such as its endianness, CPU registers, word @@ -33,13 +34,6 @@ public abstract class Architecture { /** - * The endianness of the architecture. - */ - public static enum ByteOrder { - LittleEndian, BigEndian - } - - /** * The number of bits required in a bit map covering all the registers that may store * references. The bit position of a register in the map is the register's * {@linkplain Register#number number}. diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Mon Feb 11 10:41:29 2013 +0100 @@ -103,4 +103,9 @@ * {@link CompilationResult}. A data patch is always created for an object constant. */ boolean needsDataPatch(Constant constant); + + /** + * Gets a description of the target architecture. + */ + TargetDescription getTarget(); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.interpreter/overview.html --- a/graal/com.oracle.graal.api.interpreter/overview.html Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ - - - - - - - - -Documentation for the com.oracle.graal.api.interpreter project. - - - diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java --- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/Interpreter.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +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.api.interpreter; - -import com.oracle.graal.api.meta.*; - -public interface Interpreter extends VirtualMachineComponent { - - boolean initialize(String args); - - Object execute(ResolvedJavaMethod method, Object... arguments) throws Throwable; -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/RuntimeInterpreterInterface.java --- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/RuntimeInterpreterInterface.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +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.api.interpreter; - -import com.oracle.graal.api.meta.*; - -/** - * Please note: The parameters of the interface are currently in reversed order since it was derived - * from the java ByteCodeInterpreter implementation. There it was simpler to use the parameters in - * reversed order since they are popped from the stack in reversed order. - */ -public interface RuntimeInterpreterInterface { - - Object invoke(ResolvedJavaMethod method, Object... args); - - void monitorEnter(Object value); - - void monitorExit(Object value); - - Object newObject(ResolvedJavaType type) throws InstantiationException; - - Object getFieldObject(Object base, ResolvedJavaField field); - - boolean getFieldBoolean(Object base, ResolvedJavaField field); - - byte getFieldByte(Object base, ResolvedJavaField field); - - char getFieldChar(Object base, ResolvedJavaField field); - - short getFieldShort(Object base, ResolvedJavaField field); - - int getFieldInt(Object base, ResolvedJavaField field); - - long getFieldLong(Object base, ResolvedJavaField field); - - double getFieldDouble(Object base, ResolvedJavaField field); - - float getFieldFloat(Object base, ResolvedJavaField field); - - void setFieldObject(Object value, Object base, ResolvedJavaField field); - - void setFieldInt(int value, Object base, ResolvedJavaField field); - - void setFieldFloat(float value, Object base, ResolvedJavaField field); - - void setFieldDouble(double value, Object base, ResolvedJavaField field); - - void setFieldLong(long value, Object base, ResolvedJavaField field); - - byte getArrayByte(long index, Object array); - - char getArrayChar(long index, Object array); - - short getArrayShort(long index, Object array); - - int getArrayInt(long index, Object array); - - long getArrayLong(long index, Object array); - - double getArrayDouble(long index, Object array); - - float getArrayFloat(long index, Object array); - - Object getArrayObject(long index, Object array); - - void setArrayByte(byte value, long index, Object array); - - void setArrayChar(char value, long index, Object array); - - void setArrayShort(short value, long index, Object array); - - void setArrayInt(int value, long index, Object array); - - void setArrayLong(long value, long index, Object array); - - void setArrayFloat(float value, long index, Object array); - - void setArrayDouble(double value, long index, Object array); - - void setArrayObject(Object value, long index, Object array); - - Class getMirror(ResolvedJavaType type); -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/VirtualMachineComponent.java --- a/graal/com.oracle.graal.api.interpreter/src/com/oracle/graal/api/interpreter/VirtualMachineComponent.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.api.interpreter; - -public interface VirtualMachineComponent { - - void setOption(String name, String value); -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Mon Feb 11 10:41:29 2013 +0100 @@ -39,5 +39,5 @@ Unresolved, JavaSubroutineMismatch, ArithmeticException, - RuntimeConstraint, + RuntimeConstraint } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Mon Feb 11 10:41:29 2013 +0100 @@ -410,9 +410,9 @@ * @return the annotation of type {@code annotationClass} (if any) for each formal parameter * present */ + @SuppressWarnings("unchecked") public static T[] getParameterAnnotations(Class annotationClass, ResolvedJavaMethod method) { Annotation[][] parameterAnnotations = method.getParameterAnnotations(); - @SuppressWarnings("unchecked") T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length); for (int i = 0; i < parameterAnnotations.length; i++) { for (Annotation a : parameterAnnotations[i]) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalAPITest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalAPITest.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.api.test; + +import static org.junit.Assert.*; + +import org.junit.*; + +import com.oracle.graal.api.runtime.*; + +public class GraalAPITest { + + @Test + public void testRuntimeAvailable() { + assertNotNull(Graal.getRuntime()); + System.out.println(Graal.getRuntime().getClass()); + } + + @Test + public void testRuntimeNamed() { + assertNotNull(Graal.getRuntime().getName()); + System.out.println(Graal.getRuntime().getName()); + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalTest.java --- a/graal/com.oracle.graal.api.test/src/com/oracle/graal/api/test/GraalTest.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.api.test; - -import static org.junit.Assert.*; - -import org.junit.*; - -import com.oracle.graal.api.runtime.*; - -public class GraalTest { - - @Test - public void testRuntimeAvailable() { - assertNotNull(Graal.getRuntime()); - System.out.println(Graal.getRuntime().getClass()); - } - - @Test - public void testRuntimeNamed() { - assertNotNull(Graal.getRuntime().getName()); - System.out.println(Graal.getRuntime().getName()); - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/SimpleAssemblerTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,75 @@ +/* + * 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.asm.amd64.test; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.test.*; + +public class SimpleAssemblerTest extends AssemblerTest { + + @Test + public void intTest() { + CodeGenTest test = new CodeGenTest() { + + @Override + public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + asm.movl(ret, 8472); + asm.ret(0); + return asm.codeBuffer; + } + }; + assertReturn("intStub", test, 8472); + } + + @Test + public void doubleTest() { + CodeGenTest test = new CodeGenTest() { + + @Override + public Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig) { + AMD64MacroAssembler asm = new AMD64MacroAssembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Double); + compResult.recordDataReference(asm.codeBuffer.position(), Constant.forDouble(84.72), 8, false); + asm.movdbl(ret, Address.Placeholder); + asm.ret(0); + return asm.codeBuffer; + } + }; + assertReturn("doubleStub", test, 84.72); + } + + public static int intStub() { + return 0; + } + + public static double doubleStub() { + return 0.0; + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64AsmOptions.java Mon Feb 11 10:41:29 2013 +0100 @@ -27,7 +27,7 @@ public static int Atomics = 0; public static boolean UseNormalNop = false; public static boolean UseAddressNop = true; - public static boolean UseIncDec = false; + public static boolean UseIncDec = true; public static boolean UseXmmLoadAndClearUpper = true; - public static boolean UseXmmRegToRegMoveAll = false; + public static boolean UseXmmRegToRegMoveAll = true; } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Mon Feb 11 10:41:29 2013 +0100 @@ -2863,6 +2863,12 @@ emitArith(0x85, 0xC0, dst, src); } + public final void testq(Register dst, Address src) { + prefixq(src, dst); + emitByte(0x85); + emitOperandHelper(dst, src); + } + public final void xaddq(Address dst, Register src) { prefixq(dst, src); emitByte(0x0F); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/X86InstructionDecoder.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/X86InstructionDecoder.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,506 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.asm.amd64; - -public final class X86InstructionDecoder { - - private boolean targetIs64Bit; - private byte[] code; - private int currentEndOfInstruction; - private int currentDisplacementPosition; - - private static class Prefix { - - // segment overrides - public static final int CSSegment = 0x2e; - public static final int SSSegment = 0x36; - public static final int DSSegment = 0x3e; - public static final int ESSegment = 0x26; - public static final int FSSegment = 0x64; - public static final int GSSegment = 0x65; - public static final int REX = 0x40; - public static final int REXB = 0x41; - public static final int REXX = 0x42; - public static final int REXXB = 0x43; - public static final int REXR = 0x44; - public static final int REXRB = 0x45; - public static final int REXRX = 0x46; - public static final int REXRXB = 0x47; - public static final int REXW = 0x48; - public static final int REXWB = 0x49; - public static final int REXWX = 0x4A; - public static final int REXWXB = 0x4B; - public static final int REXWR = 0x4C; - public static final int REXWRB = 0x4D; - public static final int REXWRX = 0x4E; - public static final int REXWRXB = 0x4F; - } - - private X86InstructionDecoder(byte[] code, boolean targetIs64Bit) { - this.code = code; - this.targetIs64Bit = targetIs64Bit; - } - - public int currentEndOfInstruction() { - return currentEndOfInstruction; - } - - public int currentDisplacementPosition() { - return currentDisplacementPosition; - } - - public void decodePosition(int inst) { - - assert inst >= 0 && inst < code.length; - - // Decode the given instruction, and return the Pointer of - // an embedded 32-bit operand word. - - // If "which" is WhichOperand.disp32operand, selects the displacement portion - // of an effective Pointer specifier. - // If "which" is imm64Operand, selects the trailing immediate constant. - // If "which" is WhichOperand.call32operand, selects the displacement of a call or jump. - // Caller is responsible for ensuring that there is such an operand, - // and that it is 32/64 bits wide. - - // If "which" is endPcOperand, find the end of the instruction. - - int ip = inst; - boolean is64bit = false; - - boolean hasDisp32 = false; - int tailSize = 0; // other random bytes (#32, #16, etc.) at end of insn - - boolean againAfterPrefix = true; - - while (againAfterPrefix) { - againAfterPrefix = false; - switch (0xFF & code[ip++]) { - - // These convenience macros generate groups of "case" labels for the switch. - - case Prefix.CSSegment: - case Prefix.SSSegment: - case Prefix.DSSegment: - case Prefix.ESSegment: - case Prefix.FSSegment: - case Prefix.GSSegment: - // Seems dubious - assert !targetIs64Bit : "shouldn't have that prefix"; - assert ip == inst + 1 : "only one prefix allowed"; - againAfterPrefix = true; - break; - - case 0x67: - case Prefix.REX: - case Prefix.REXB: - case Prefix.REXX: - case Prefix.REXXB: - case Prefix.REXR: - case Prefix.REXRB: - case Prefix.REXRX: - case Prefix.REXRXB: - assert targetIs64Bit : "64bit prefixes"; - againAfterPrefix = true; - break; - - case Prefix.REXW: - case Prefix.REXWB: - case Prefix.REXWX: - case Prefix.REXWXB: - case Prefix.REXWR: - case Prefix.REXWRB: - case Prefix.REXWRX: - case Prefix.REXWRXB: - assert targetIs64Bit : "64bit prefixes"; - is64bit = true; - againAfterPrefix = true; - break; - - case 0xFF: // pushq a; decl a; incl a; call a; jmp a - case 0x88: // movb a, r - case 0x89: // movl a, r - case 0x8A: // movb r, a - case 0x8B: // movl r, a - case 0x8F: // popl a - hasDisp32 = true; - break; - - case 0x68: // pushq #32 - currentEndOfInstruction = ip + 4; - currentDisplacementPosition = ip; - return; // not produced by emitOperand - - case 0x66: // movw ... (size prefix) - boolean againAfterSizePrefix2 = true; - while (againAfterSizePrefix2) { - againAfterSizePrefix2 = false; - switch (0xFF & code[ip++]) { - case Prefix.REX: - case Prefix.REXB: - case Prefix.REXX: - case Prefix.REXXB: - case Prefix.REXR: - case Prefix.REXRB: - case Prefix.REXRX: - case Prefix.REXRXB: - case Prefix.REXW: - case Prefix.REXWB: - case Prefix.REXWX: - case Prefix.REXWXB: - case Prefix.REXWR: - case Prefix.REXWRB: - case Prefix.REXWRX: - case Prefix.REXWRXB: - assert targetIs64Bit : "64bit prefix found"; - againAfterSizePrefix2 = true; - break; - case 0x8B: // movw r, a - case 0x89: // movw a, r - hasDisp32 = true; - break; - case 0xC7: // movw a, #16 - hasDisp32 = true; - tailSize = 2; // the imm16 - break; - case 0x0F: // several SSE/SSE2 variants - ip--; // reparse the 0x0F - againAfterPrefix = true; - break; - default: - throw new InternalError("should not reach here"); - } - } - break; - - case 0xB8: // movl/q r, #32/#64(oop?) - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - currentEndOfInstruction = ip + (is64bit ? 8 : 4); - currentDisplacementPosition = ip; - return; - - case 0x69: // imul r, a, #32 - case 0xC7: // movl a, #32(oop?) - tailSize = 4; - hasDisp32 = true; // has both kinds of operands! - break; - - case 0x0F: // movx..., etc. - switch (0xFF & code[ip++]) { - case 0x12: // movlps - case 0x28: // movaps - case 0x2E: // ucomiss - case 0x2F: // comiss - case 0x54: // andps - case 0x55: // andnps - case 0x56: // orps - case 0x57: // xorps - case 0x6E: // movd - case 0x7E: // movd - case 0xAE: // ldmxcsr a - // 64bit side says it these have both operands but that doesn't - // appear to be true - hasDisp32 = true; - break; - - case 0xAD: // shrd r, a, %cl - case 0xAF: // imul r, a - case 0xBE: // movsbl r, a (movsxb) - case 0xBF: // movswl r, a (movsxw) - case 0xB6: // movzbl r, a (movzxb) - case 0xB7: // movzwl r, a (movzxw) - case 0x40: // cmovl cc, r, a - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0xB0: // cmpxchgb - case 0xB1: // cmpxchg - case 0xC1: // xaddl - case 0xC7: // cmpxchg8 - case 0x90: // setcc a - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - hasDisp32 = true; - // fall out of the switch to decode the Pointer - break; - - case 0xAC: // shrd r, a, #8 - hasDisp32 = true; - tailSize = 1; // the imm8 - break; - - case 0x80: // jcc rdisp32 - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - currentEndOfInstruction = ip + 4; - currentDisplacementPosition = ip; - return; - default: - throw new InternalError("should not reach here"); - } - break; - - case 0x81: // addl a, #32; addl r, #32 - // also: orl, adcl, sbbl, andl, subl, xorl, cmpl - // on 32bit in the case of cmpl, the imm might be an oop - tailSize = 4; - hasDisp32 = true; // has both kinds of operands! - break; - - case 0x83: // addl a, #8; addl r, #8 - // also: orl, adcl, sbbl, andl, subl, xorl, cmpl - hasDisp32 = true; // has both kinds of operands! - tailSize = 1; - break; - - case 0x9B: - switch (0xFF & code[ip++]) { - case 0xD9: // fnstcw a - hasDisp32 = true; - break; - default: - throw new InternalError("should not reach here"); - } - break; - - case 0x00: // addb a, r; addl a, r; addb r, a; addl r, a - case 0x01: - case 0x02: - case 0x03: - case 0x10: // adc... - case 0x11: - case 0x12: - case 0x13: - case 0x20: // and... - case 0x21: - case 0x22: - case 0x23: - case 0x30: // xor... - case 0x31: - case 0x32: - case 0x33: - case 0x08: // or... - case 0x09: - case 0x0a: - case 0x0b: - case 0x18: // sbb... - case 0x19: - case 0x1a: - case 0x1b: - case 0x28: // sub... - case 0x29: - case 0x2a: - case 0x2b: - case 0xF7: // mull a - case 0x8D: // lea r, a - case 0x87: // xchg r, a - case 0x38: // cmp... - case 0x39: - case 0x3a: - case 0x3b: - case 0x85: // test r, a - hasDisp32 = true; // has both kinds of operands! - break; - - case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8 - case 0xC6: // movb a, #8 - case 0x80: // cmpb a, #8 - case 0x6B: // imul r, a, #8 - hasDisp32 = true; // has both kinds of operands! - tailSize = 1; // the imm8 - break; - - case 0xE8: // call rdisp32 - case 0xE9: // jmp rdisp32 - currentEndOfInstruction = ip + 4; - currentDisplacementPosition = ip; - return; - - case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1 - case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl - case 0xD9: // fldS a; fstS a; fstpS a; fldcw a - case 0xDD: // fldD a; fstD a; fstpD a - case 0xDB: // fildS a; fistpS a; fldX a; fstpX a - case 0xDF: // fildD a; fistpD a - case 0xD8: // faddS a; fsubrS a; fmulS a; fdivrS a; fcompS a - case 0xDC: // faddD a; fsubrD a; fmulD a; fdivrD a; fcompD a - case 0xDE: // faddpD a; fsubrpD a; fmulpD a; fdivrpD a; fcomppD a - hasDisp32 = true; - break; - - case 0xF0: // Lock - againAfterPrefix = true; - break; - - case 0xF3: // For SSE - case 0xF2: // For SSE2 - switch (0xFF & code[ip++]) { - case Prefix.REX: - case Prefix.REXB: - case Prefix.REXX: - case Prefix.REXXB: - case Prefix.REXR: - case Prefix.REXRB: - case Prefix.REXRX: - case Prefix.REXRXB: - case Prefix.REXW: - case Prefix.REXWB: - case Prefix.REXWX: - case Prefix.REXWXB: - case Prefix.REXWR: - case Prefix.REXWRB: - case Prefix.REXWRX: - case Prefix.REXWRXB: - assert targetIs64Bit : "found 64bit prefix"; - ip++; - // fall through - default: - ip++; - } - hasDisp32 = true; // has both kinds of operands! - break; - - default: - throw new InternalError("should not reach here"); - } - } - - assert hasDisp32 : "(thomaswue) not sure if this holds: instruction has no disp32 field"; - - // parse the output of emitOperand - int op2 = 0xFF & code[ip++]; - int base = op2 & 0x07; - int op3 = -1; - int b100 = 4; - int b101 = 5; - if (base == b100 && (op2 >> 6) != 3) { - op3 = 0xFF & code[ip++]; - base = op3 & 0x07; // refetch the base - } - // now ip points at the disp (if any) - - switch (op2 >> 6) { - case 0: - // [00 reg 100][ss index base] - // [00 reg 100][00 100 esp] - // [00 reg base] - // [00 reg 100][ss index 101][disp32] - // [00 reg 101] [disp32] - - if (base == b101) { - - currentDisplacementPosition = ip; - ip += 4; // skip the disp32 - } - break; - - case 1: - // [01 reg 100][ss index base][disp8] - // [01 reg 100][00 100 esp][disp8] - // [01 reg base] [disp8] - ip += 1; // skip the disp8 - break; - - case 2: - // [10 reg 100][ss index base][disp32] - // [10 reg 100][00 100 esp][disp32] - // [10 reg base] [disp32] - currentDisplacementPosition = ip; - ip += 4; // skip the disp32 - break; - - case 3: - // [11 reg base] (not a memory addressing mode) - break; - } - - currentEndOfInstruction = ip + tailSize; - } - - public static void patchRelativeInstruction(byte[] code, int codePos, int relative) { - X86InstructionDecoder decoder = new X86InstructionDecoder(code, true); - decoder.decodePosition(codePos); - int patchPos = decoder.currentDisplacementPosition(); - int endOfInstruction = decoder.currentEndOfInstruction(); - int offset = relative - endOfInstruction + codePos; - patchDisp32(code, patchPos, offset); - } - - private static void patchDisp32(byte[] code, int pos, int offset) { - assert pos + 4 <= code.length; - - assert code[pos] == 0; - assert code[pos + 1] == 0; - assert code[pos + 2] == 0; - assert code[pos + 3] == 0; - - code[pos] = (byte) (offset & 0xFF); - code[pos + 1] = (byte) ((offset >> 8) & 0xFF); - code[pos + 2] = (byte) ((offset >> 16) & 0xFF); - code[pos + 3] = (byte) ((offset >> 24) & 0xFF); - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,60 @@ +/* + * 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.asm.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.sparc.*; + +/** + * This class implements an assembler that can encode most SPARC instructions. + */ +public class SPARCAssembler extends AbstractAssembler { + + @SuppressWarnings("unused") + public SPARCAssembler(TargetDescription target) { + super(target); + // TODO Auto-generated constructor stub + SPARC sparc; + } + + @Override + public void align(int modulus) { + // SPARC: Implement alignment. + } + + @Override + public void jmp(Label l) { + // SPARC: Implement jump. + } + + @Override + protected void patchJumpTarget(int branch, int jumpTarget) { + // SPARC: Implement patching of jump target. + } + + @Override + public void bangStack(int disp) { + // SPARC: Implement stack banging. + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,67 @@ +/* + * 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.asm.test; + +import java.lang.reflect.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.test.*; + +public abstract class AssemblerTest extends GraalTest { + + protected final CodeCacheProvider codeCache; + + public interface CodeGenTest { + + Buffer generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig); + } + + public AssemblerTest() { + this.codeCache = Graal.getRequiredCapability(CodeCacheProvider.class); + } + + protected InstalledCode assembleMethod(Method m, CodeGenTest test) { + ResolvedJavaMethod method = codeCache.lookupJavaMethod(m); + RegisterConfig registerConfig = codeCache.lookupRegisterConfig(method); + + CompilationResult compResult = new CompilationResult(); + + Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig); + compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position()); + + return codeCache.addMethod(method, compResult, null); + } + + protected void assertReturn(String methodName, CodeGenTest test, Object expected, Object... args) { + Method method = getMethod(methodName); + InstalledCode code = assembleMethod(method, test); + + Object actual = code.executeVarargs(args); + Assert.assertEquals("unexpected return value: " + actual, actual, expected); + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java --- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Mon Feb 11 10:41:29 2013 +0100 @@ -22,8 +22,9 @@ */ package com.oracle.graal.asm; +import java.nio.*; + import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Architecture.*; /** * The platform-independent base class for the assembler. @@ -36,7 +37,7 @@ public AbstractAssembler(TargetDescription target) { this.target = target; - if (target.arch.getByteOrder() == ByteOrder.BigEndian) { + if (target.arch.getByteOrder() == ByteOrder.BIG_ENDIAN) { this.codeBuffer = new Buffer.BigEndian(); } else { this.codeBuffer = new Buffer.LittleEndian(); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Feb 11 10:41:29 2013 +0100 @@ -229,7 +229,7 @@ } @Override - public void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { + public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { boolean mirrored = emitCompare(left, right); Condition finalCondition = mirrored ? cond.mirror() : cond; switch (left.getKind().getStackKind()) { @@ -248,7 +248,13 @@ } @Override - public Variable emitCMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { + public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) { + emitIntegerTest(left, right); + append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, info)); + } + + @Override + public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { boolean mirrored = emitCompare(left, right); Condition finalCondition = mirrored ? cond.mirror() : cond; @@ -263,11 +269,29 @@ case Double: append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue))); break; - + default: + throw GraalInternalError.shouldNotReachHere("" + left.getKind()); } return result; } + @Override + public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { + emitIntegerTest(left, right); + Variable result = newVariable(trueValue.getKind()); + append(new CondMoveOp(result, Condition.EQ, load(trueValue), loadNonConst(falseValue))); + return result; + } + + private void emitIntegerTest(Value a, Value b) { + assert a.getKind().getStackKind() == Kind.Int || a.getKind() == Kind.Long; + if (LIRValueUtil.isVariable(b)) { + append(new AMD64TestOp(load(b), loadNonConst(a))); + } else { + append(new AMD64TestOp(load(a), loadNonConst(b))); + } + } + /** * This method emits the compare instruction, and may reorder the operands. It returns true if * it did so. diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.graal.compiler.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.sparc.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.ConvertNode.Op; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.java.*; + +/** + * This class implements the SPARC specific portion of the LIR generator. + */ +public class SPARCLIRGenerator extends LIRGenerator { + + public SPARCLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + super(graph, runtime, target, frameMap, method, lir); + // SPARC: Implement lir generator. + } + + @Override + public Variable emitMove(Value input) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + protected boolean peephole(ValueNode valueNode) { + // SPARC: Auto-generated method stub + return false; + } + + @Override + protected void emitReturn(Value input) { + // SPARC: Auto-generated method stub + + } + + @Override + protected void emitNullCheckGuard(ValueNode object) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitJump(LabelRef label, LIRFrameState info) { + @SuppressWarnings("unused") + SPARCLIRInstruction instruction = null; + // SPARC: Auto-generated method stub + + } + + @Override + public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) { + // SPARC: Auto-generated method stub + + } + + @Override + public Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + // SPARC: Auto-generated method stub + + } + + @Override + protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { + // SPARC: Auto-generated method stub + + } + + @Override + protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { + // SPARC: Auto-generated method stub + + } + + @Override + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + protected void emitSequentialSwitch(Constant[] keyConstants, LabelRef[] keyTargets, LabelRef defaultTarget, Value key) { + // SPARC: Auto-generated method stub + + } + + @Override + protected void emitSwitchRanges(int[] lowKeys, int[] highKeys, LabelRef[] targets, LabelRef defaultTarget, Value key) { + // SPARC: Auto-generated method stub + + } + + @Override + protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitBitCount(Variable result, Value operand) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitBitScanForward(Variable result, Value operand) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitBitScanReverse(Variable result, Value operand) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitMathAbs(Variable result, Variable input) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitMathSqrt(Variable result, Variable input) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitMathLog(Variable result, Variable input, boolean base10) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitMathCos(Variable result, Variable input) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitMathSin(Variable result, Variable input) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitMathTan(Variable result, Variable input) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitByteSwap(Variable result, Value operand) { + // SPARC: Auto-generated method stub + + } + + @Override + public boolean canInlineConstant(Constant c) { + // SPARC: Auto-generated method stub + return false; + } + + @Override + public boolean canStoreConstant(Constant c) { + // SPARC: Auto-generated method stub + return false; + } + + @Override + public Address makeAddress(LocationNode location, ValueNode object) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public void emitMove(Value src, Value dst) { + // SPARC: Auto-generated method stub + + } + + @Override + public Value emitLoad(Value loadAddress, boolean canTrap) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public void emitStore(Value storeAddress, Value input, boolean canTrap) { + // SPARC: Auto-generated method stub + + } + + @Override + public Value emitLea(Value address) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitNegate(Value input) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitAdd(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitSub(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitMul(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitDiv(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitRem(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitUDiv(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitURem(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitAnd(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitOr(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitXor(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitShl(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitShr(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitUShr(Value a, Value b) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public Value emitConvert(Op opcode, Value inputVal) { + // SPARC: Auto-generated method stub + return null; + } + + @Override + public void emitMembar(int barriers) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + // SPARC: Auto-generated method stub + + } + + @Override + public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + // SPARC: Auto-generated method stub + + } + + @Override + public void visitCompareAndSwap(CompareAndSwapNode i) { + // SPARC: Auto-generated method stub + + } + + @Override + public void visitExceptionObject(ExceptionObjectNode i) { + // SPARC: Auto-generated method stub + + } + + @Override + public void visitSafepointNode(SafepointNode i) { + // SPARC: Auto-generated method stub + + } + + @Override + public void visitBreakpointNode(BreakpointNode i) { + // SPARC: Auto-generated method stub + + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -22,14 +22,29 @@ */ package com.oracle.graal.compiler.test; +import static org.junit.Assert.*; + import org.junit.*; import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.phases.common.*; public class CompareCanonicalizerTest extends GraalCompilerTest { + private StructuredGraph getCanonicalizedGraph(String name) { + StructuredGraph graph = parse(name); + new CanonicalizerPhase(null, runtime(), null).apply(graph); + return graph; + } + + private static ValueNode getResult(StructuredGraph graph) { + assertTrue(graph.start().next() instanceof ReturnNode); + ReturnNode ret = (ReturnNode) graph.start().next(); + return ret.result(); + } + @Test public void testCanonicalComparison() { StructuredGraph referenceGraph = parse("referenceCanonicalComparison"); @@ -40,8 +55,7 @@ Assumptions assumptions = new Assumptions(false); new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); for (int i = 1; i < 4; i++) { - StructuredGraph graph = parse("canonicalCompare" + i); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i); assertEquals(referenceGraph, graph); } } @@ -77,4 +91,78 @@ return 1; } } + + @Test + public void testIntegerTest() { + for (int i = 1; i <= 4; i++) { + StructuredGraph graph = getCanonicalizedGraph("integerTest" + i); + + ValueNode result = getResult(graph); + assertTrue(result instanceof ConditionalNode); + ConditionalNode mat = (ConditionalNode) result; + assertTrue(mat.condition() instanceof IntegerTestNode); + IntegerTestNode test = (IntegerTestNode) mat.condition(); + LocalNode local0 = graph.getLocal(0); + LocalNode local1 = graph.getLocal(1); + assertTrue((test.x() == local0 && test.y() == local1) || (test.x() == local1 && test.y() == local0)); + } + } + + public static boolean integerTest1(int x, int y) { + return (x & y) == 0; + } + + public static boolean integerTest2(long x, long y) { + return 0 == (x & y); + } + + public static boolean integerTest3(long x, long y) { + int c = 5; + return (c - 5) == (x & y); + } + + public static boolean integerTest4(int x, int y) { + int c = 10; + return (x & y) == (10 - c); + } + + @Test + public void testIntegerTestCanonicalization() { + ValueNode result = getResult(getCanonicalizedGraph("integerTestCanonicalization1")); + assertTrue(result.isConstant() && result.asConstant().asLong() == 1); + result = getResult(getCanonicalizedGraph("integerTestCanonicalization2")); + assertTrue(result.isConstant() && result.asConstant().asLong() == 1); + result = getResult(getCanonicalizedGraph("integerTestCanonicalization3")); + assertTrue(result instanceof ConditionalNode); + } + + public static int integerTestCanonicalization1(boolean b) { + int x = b ? 128 : 256; + if ((x & 8) == 0) { + return 1; + } else { + return 2; + } + } + + public static int integerTestCanonicalization2(boolean b) { + int x = b ? 128 : 256; + int y = b ? 32 : 64; + if ((x & y) == 0) { + return 1; + } else { + return 2; + } + } + + public static int integerTestCanonicalization3(boolean b) { + int x = b ? 128 : 64; + int y = b ? 32 : 64; + if ((x & y) == 0) { + return 1; + } else { + return 2; + } + } + } diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -43,6 +43,7 @@ import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.schedule.*; import com.oracle.graal.printer.*; +import com.oracle.graal.test.*; /** * Base class for Graal compiler unit tests. @@ -63,7 +64,7 @@ *

* These tests will be run by the {@code mx unittest} command. */ -public abstract class GraalCompilerTest { +public abstract class GraalCompilerTest extends GraalTest { protected final GraalCodeCacheProvider runtime; protected final GraalCompiler graalCompiler; @@ -146,21 +147,6 @@ return parse(getMethod(methodName)); } - protected Method getMethod(String methodName) { - Method found = null; - for (Method m : this.getClass().getMethods()) { - if (m.getName().equals(methodName)) { - Assert.assertNull(found); - found = m; - } - } - if (found != null) { - return found; - } else { - throw new RuntimeException("method not found: " + methodName); - } - } - private static int compilationId = 0; /** diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -168,7 +168,7 @@ // TypeSystemTest.outputGraph(graph); Assumptions assumptions = new Assumptions(false); new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new ConditionalEliminationPhase().apply(graph); + new ConditionalEliminationPhase(runtime()).apply(graph); new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); StructuredGraph referenceGraph = parse(referenceSnippet); assertEquals(referenceGraph, graph); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -127,10 +127,7 @@ } } else { if (a == constantObject2 || a == constantObject3) { - if (a != null) { - return 11; - } - return 2; + return 11; } } if (a == constantObject1) { @@ -185,34 +182,25 @@ return ((InputStream) o).available(); } - @SuppressWarnings("unused") private void test(String snippet, String referenceSnippet) { - // TODO(ls) temporarily disabled, reintroduce when a proper type system is available - if (false) { - StructuredGraph graph = parse(snippet); - Debug.dump(graph, "Graph"); - Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new ConditionalEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new GlobalValueNumberingPhase().apply(graph); - StructuredGraph referenceGraph = parse(referenceSnippet); - new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); - new GlobalValueNumberingPhase().apply(referenceGraph); - assertEquals(referenceGraph, graph); - } + StructuredGraph graph = parse(snippet); + Debug.dump(graph, "Graph"); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new ConditionalEliminationPhase(runtime()).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + // a second canonicalizer is needed to process nested MaterializeNodes + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + StructuredGraph referenceGraph = parse(referenceSnippet); + new CanonicalizerPhase(null, runtime(), assumptions).apply(referenceGraph); + assertEquals(referenceGraph, graph); } @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { if (expected.getNodeCount() != graph.getNodeCount()) { - // Debug.dump(expected, "Node count not matching - expected"); - // Debug.dump(graph, "Node count not matching - actual"); - // System.out.println("================ expected"); - // outputGraph(expected); - // System.out.println("================ actual"); - // outputGraph(graph); - // new IdealGraphPrinterDumpHandler().dump(graph, "asdf"); + outputGraph(expected, "expected"); + outputGraph(graph, "actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); } } @@ -250,18 +238,14 @@ } } - @SuppressWarnings("unused") private void test(String snippet, Class clazz) { - // TODO(ls) temporarily disabled, reintroduce when a proper type system is available - if (false) { - StructuredGraph graph = parse(snippet); - Debug.dump(graph, "Graph"); - Assumptions assumptions = new Assumptions(false); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - new ConditionalEliminationPhase().apply(graph); - new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); - Debug.dump(graph, "Graph"); - Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); - } + StructuredGraph graph = parse(snippet); + Debug.dump(graph, "Graph"); + Assumptions assumptions = new Assumptions(false); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + new ConditionalEliminationPhase(runtime()).apply(graph); + new CanonicalizerPhase(null, runtime(), assumptions).apply(graph); + Debug.dump(graph, "Graph"); + Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext()); } } diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.test.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -184,8 +185,8 @@ public void testInstanceOf() { ReturnNode returnNode = testEscapeAnalysis("testInstanceOfSnippet", null, false); ValueNode result = returnNode.result(); - Assert.assertTrue(result instanceof MaterializeNode); - Assert.assertEquals(Constant.TRUE, ((MaterializeNode) result).condition().asConstant()); + Assert.assertTrue(result instanceof ConditionalNode); + Assert.assertEquals(Constant.TRUE, ((ConditionalNode) result).condition().asConstant()); } public boolean testInstanceOfSnippet() { @@ -198,7 +199,7 @@ StructuredGraph graph = parse(snippet); try { for (Invoke n : graph.getInvokes()) { - n.node().setProbability(100000); + n.setInliningRelevance(1); } Assumptions assumptions = new Assumptions(false); @@ -211,7 +212,7 @@ Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant()); Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant()); } - int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewObjectArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count(); + int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(MaterializeObjectNode.class).count(); Assert.assertEquals(0, newInstanceCount); return returnNode; } catch (AssertionFailedError t) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -126,8 +126,7 @@ final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class... invalidNodeClasses) { StructuredGraph result = processMethod(snippet); Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty()); - Assert.assertTrue("partial escape analysis should have removed all NewObjectArrayNode allocations", result.getNodes(NewObjectArrayNode.class).isEmpty()); - Assert.assertTrue("partial escape analysis should have removed all NewPrimitiveArrayNode allocations", result.getNodes(NewPrimitiveArrayNode.class).isEmpty()); + Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty()); double probabilitySum = 0; int materializeCount = 0; for (MaterializeObjectNode materialize : result.getNodes(MaterializeObjectNode.class)) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Feb 11 10:41:29 2013 +0100 @@ -612,6 +612,8 @@ emitCompareBranch((CompareNode) node, trueSuccessor, falseSuccessor, info); } else if (node instanceof ConstantNode) { emitConstantBranch(((ConstantNode) node).asConstant().asBoolean(), trueSuccessor, falseSuccessor, info); + } else if (node instanceof IntegerTestNode) { + emitIntegerTestBranch((IntegerTestNode) node, trueSuccessor, falseSuccessor, info); } else { throw GraalInternalError.unimplemented(node.toString()); } @@ -619,23 +621,34 @@ private void emitNullCheckBranch(IsNullNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) { if (falseSuccessor != null) { - emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info); + emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.NE, false, falseSuccessor, info); if (trueSuccessor != null) { emitJump(trueSuccessor, null); } } else { - emitBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info); + emitCompareBranch(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueSuccessor, info); } } public void emitCompareBranch(CompareNode compare, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) { if (falseSuccessorBlock != null) { - emitBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info); + emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition().negate(), !compare.unorderedIsTrue(), falseSuccessorBlock, info); if (trueSuccessorBlock != null) { emitJump(trueSuccessorBlock, null); } } else { - emitBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info); + emitCompareBranch(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueSuccessorBlock, info); + } + } + + public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) { + if (falseSuccessorBlock != null) { + emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock, info); + if (trueSuccessorBlock != null) { + emitJump(trueSuccessorBlock, null); + } + } else { + emitIntegerTestBranch(operand(test.x()), operand(test.y()), false, trueSuccessorBlock, info); } } @@ -655,33 +668,31 @@ public Variable emitConditional(BooleanNode node, Value trueValue, Value falseValue) { if (node instanceof IsNullNode) { - return emitNullCheckConditional((IsNullNode) node, trueValue, falseValue); + IsNullNode isNullNode = (IsNullNode) node; + return emitConditionalMove(operand(isNullNode.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue); } else if (node instanceof CompareNode) { - return emitCompareConditional((CompareNode) node, trueValue, falseValue); + CompareNode compare = (CompareNode) node; + return emitConditionalMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); } else if (node instanceof ConstantNode) { - return emitConstantConditional(((ConstantNode) node).asConstant().asBoolean(), trueValue, falseValue); + ConstantNode constantNode = (ConstantNode) node; + return emitMove(constantNode.asConstant().asBoolean() ? trueValue : falseValue); + } else if (node instanceof IntegerTestNode) { + IntegerTestNode test = (IntegerTestNode) node; + return emitIntegerTestMove(operand(test.x()), operand(test.y()), trueValue, falseValue); } else { throw GraalInternalError.unimplemented(node.toString()); } } - private Variable emitNullCheckConditional(IsNullNode node, Value trueValue, Value falseValue) { - return emitCMove(operand(node.object()), Constant.NULL_OBJECT, Condition.EQ, false, trueValue, falseValue); - } - - private Variable emitConstantConditional(boolean value, Value trueValue, Value falseValue) { - return emitMove(value ? trueValue : falseValue); - } - - private Variable emitCompareConditional(CompareNode compare, Value trueValue, Value falseValue) { - return emitCMove(operand(compare.x()), operand(compare.y()), compare.condition(), compare.unorderedIsTrue(), trueValue, falseValue); - } - public abstract void emitJump(LabelRef label, LIRFrameState info); - public abstract void emitBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info); + public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info); + + public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info); - public abstract Variable emitCMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); + public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); + + public abstract Variable emitIntegerTestMove(Value leftVal, Value right, Value trueValue, Value falseValue); @Override public void emitInvoke(Invoke x) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -195,5 +195,4 @@ protected RegisterConfig createRegisterConfig(boolean globalStubConfig) { return new AMD64HotSpotRegisterConfig(config, globalStubConfig); } - } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java --- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java Mon Feb 11 10:41:29 2013 +0100 @@ -62,7 +62,6 @@ */ public CompilationServer(boolean multiple) { this.multiple = multiple; - HotSpotOptions.setDefaultOptions(); } public void addConnectionObserver(ConnectionObserver observer) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.sparc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.sparc.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; + +/** + * HotSpot SPARC specific backend. + */ +public class SPARCHotSpotBackend extends HotSpotBackend { + + public SPARCHotSpotBackend(HotSpotRuntime runtime, TargetDescription target) { + super(runtime, target); + } + + @Override + public LIRGenerator newLIRGenerator(StructuredGraph graph, FrameMap frameMap, ResolvedJavaMethod method, LIR lir) { + return new SPARCLIRGenerator(graph, this.runtime(), this.target, frameMap, method, lir); + } + + @Override + public TargetMethodAssembler newAssembler(FrameMap frameMap, LIR lir) { + // SPARC: Create assembler. + return null; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, ResolvedJavaMethod method, LIR lir) { + // SPARC: Emit code + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotGraalRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,62 @@ +/* + * 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.hotspot.*; +import com.oracle.graal.hotspot.meta.*; + +/** + * 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() { + if (getInstance() == null) { + setInstance(new SPARCHotSpotGraalRuntime()); + } + return getInstance(); + } + + @Override + protected TargetDescription createTarget() { + // SPARC: Create target description. + return null; + } + + @Override + protected HotSpotBackend createBackend() { + return new SPARCHotSpotBackend(getRuntime(), getTarget()); + } + + @Override + protected HotSpotRuntime createRuntime() { + return new SPARCHotSpotRuntime(config, this); + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,53 @@ +/* + * 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.hotspot.*; +import com.oracle.graal.hotspot.meta.*; + +public class SPARCHotSpotRuntime extends HotSpotRuntime { + + public SPARCHotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) { + super(config, graalRuntime); + // SPARC: Register stubs. + } + + @Override + public Register threadRegister() { + // SPARC: Define thread register. + return null; + } + + @Override + public Register stackPointerRegister() { + // SPARC: Define stack pointer register. + return null; + } + + @Override + protected RegisterConfig createRegisterConfig(boolean globalStubConfig) { + // SPARC: Create register configuration. + return null; + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -28,7 +28,6 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.interpreter.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.*; @@ -259,15 +258,12 @@ @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { - if (clazz == GraalCodeCacheProvider.class || clazz == MetaAccessProvider.class || clazz == SnippetProvider.class) { + if (clazz == GraalCodeCacheProvider.class || clazz == CodeCacheProvider.class || clazz == MetaAccessProvider.class || clazz == SnippetProvider.class) { return (T) getRuntime(); } if (clazz == GraalCompiler.class) { return (T) getCompiler(); } - if (clazz == RuntimeInterpreterInterface.class) { - return (T) getRuntimeInterpreterInterface(); - } return null; } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Mon Feb 11 10:41:29 2013 +0100 @@ -31,11 +31,6 @@ public class HotSpotOptions { - public static void setDefaultOptions() { - GraalOptions.MethodEndBreakpointGuards = 2; - GraalOptions.ResolveClassBeforeStaticInvoke = false; - } - // Called from VM code public static boolean setOption(String option) { if (option.length() == 0) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeInterpreterInterface.java Mon Feb 11 10:41:29 2013 +0100 @@ -28,11 +28,10 @@ import sun.misc.*; -import com.oracle.graal.api.interpreter.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.meta.*; -public class HotSpotRuntimeInterpreterInterface implements RuntimeInterpreterInterface { +public class HotSpotRuntimeInterpreterInterface { private final MetaAccessProvider metaProvider; diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaField.java Mon Feb 11 10:41:29 2013 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.phases.*; +import com.oracle.graal.snippets.*; /** * Represents a field in a HotSpot type. @@ -86,10 +87,16 @@ } return constant; } else { + /* + * for non-static final fields, we must assume that they are only initialized if they + * have a non-default value. + */ assert !Modifier.isStatic(flags); - // TODO (chaeubl) HotSpot does not trust final non-static fields (see ciField.cpp) if (Modifier.isFinal(getModifiers())) { - return readValue(receiver); + Constant value = readValue(receiver); + if (assumeNonStaticFinalFieldsAsFinal(receiver.asObject().getClass()) || !value.isDefaultForKind()) { + return value; + } } } return null; @@ -113,6 +120,10 @@ return clazz == GraalOptions.class; } + private static boolean assumeNonStaticFinalFieldsAsFinal(Class clazz) { + return clazz == SnippetCounter.class; + } + @Override public HotSpotResolvedObjectType getDeclaringClass() { return holder; diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -943,4 +943,9 @@ throw GraalInternalError.shouldNotReachHere(); } } + + @Override + public TargetDescription getTarget() { + return graalRuntime.getTarget(); + } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CheckCastSnippets.java Mon Feb 11 10:41:29 2013 +0100 @@ -79,7 +79,7 @@ isNull.inc(); } else { Word objectHub = loadHub(object); - if (objectHub != exactHub) { + if (objectHub.notEqual(exactHub)) { probability(DEOPT_PATH_PROBABILITY); exactMiss.inc(); //bkpt(object, exactHub, objectHub); @@ -108,7 +108,7 @@ isNull.inc(); } else { Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset) != hub) { + if (objectHub.readWord(superCheckOffset).notEqual(hub)) { probability(DEOPT_PATH_PROBABILITY); displayMiss.inc(); DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); @@ -136,7 +136,7 @@ ExplodeLoopNode.explodeLoop(); for (int i = 0; i < hints.length; i++) { Word hintHub = hints[i]; - if (hintHub == objectHub) { + if (hintHub.equal(objectHub)) { hintsHit.inc(); return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic()); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/ClassSubstitutions.java Mon Feb 11 10:41:29 2013 +0100 @@ -27,7 +27,7 @@ import java.lang.reflect.*; -import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.snippets.*; import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; import com.oracle.graal.word.*; @@ -41,7 +41,7 @@ @MethodSubstitution(isStatic = false) public static int getModifiers(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass == Word.zero()) { + if (klass.equal(0)) { // Class for primitive type return Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC; } else { @@ -52,7 +52,7 @@ @MethodSubstitution(isStatic = false) public static boolean isInterface(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass == Word.zero()) { + if (klass.equal(0)) { return false; } else { int accessFlags = klass.readInt(klassAccessFlagsOffset()); @@ -63,7 +63,7 @@ @MethodSubstitution(isStatic = false) public static boolean isArray(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass == Word.zero()) { + if (klass.equal(0)) { return false; } else { int layoutHelper = klass.readInt(klassLayoutHelperOffset()); @@ -74,13 +74,13 @@ @MethodSubstitution(isStatic = false) public static boolean isPrimitive(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); - return klass == Word.zero(); + return klass.equal(0); } @MethodSubstitution(isStatic = false) public static Class getSuperclass(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass != Word.zero()) { + if (klass.notEqual(0)) { int accessFlags = klass.readInt(klassAccessFlagsOffset()); if ((accessFlags & Modifier.INTERFACE) == 0) { int layoutHelper = klass.readInt(klassLayoutHelperOffset()); @@ -88,7 +88,7 @@ return Object.class; } else { Word superKlass = klass.readWord(klassSuperKlassOffset()); - if (superKlass == Word.zero()) { + if (superKlass.equal(0)) { return null; } else { return unsafeCast(superKlass.readObject(classMirrorOffset()), Class.class, true, true); @@ -102,7 +102,7 @@ @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { Word klass = loadWordFromObject(thisObj, klassOffset()); - if (klass != Word.zero()) { + if (klass.notEqual(0)) { int layoutHelper = klass.readInt(klassLayoutHelperOffset()); if ((layoutHelper & arrayKlassLayoutHelperIdentifier()) != 0) { return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset()), Class.class, true, true); @@ -113,6 +113,6 @@ @MethodSubstitution(isStatic = false) public static boolean isInstance(final Class thisObj, Object obj) { - return !thisObj.isPrimitive() && MaterializeNode.isInstance(thisObj, obj); + return !thisObj.isPrimitive() && ConditionalNode.materializeIsInstance(thisObj, obj); } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Mon Feb 11 10:41:29 2013 +0100 @@ -458,7 +458,7 @@ // this code is independent from biased locking (although it does not look that way) final Word biasedLock = mark.and(biasedLockMaskInPlace()); - if (biasedLock == Word.unsigned(unlockedMask())) { + if (biasedLock.equal(Word.unsigned(unlockedMask()))) { probability(FAST_PATH_PROBABILITY); int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); if (hash != uninitializedIdentityHashCodeValue()) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/InstanceOfSnippets.java Mon Feb 11 10:41:29 2013 +0100 @@ -73,7 +73,7 @@ return falseValue; } Word objectHub = loadHub(object); - if (objectHub != exactHub) { + if (objectHub.notEqual(exactHub)) { probability(LIKELY_PROBABILITY); exactMiss.inc(); return falseValue; @@ -99,7 +99,7 @@ return falseValue; } Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset) != hub) { + if (objectHub.readWord(superCheckOffset).notEqual(hub)) { probability(NOT_LIKELY_PROBABILITY); displayMiss.inc(); return falseValue; @@ -129,7 +129,7 @@ ExplodeLoopNode.explodeLoop(); for (int i = 0; i < hints.length; i++) { Word hintHub = hints[i]; - if (hintHub == objectHub) { + if (hintHub.equal(objectHub)) { probability(NOT_FREQUENT_PROBABILITY); hintsHit.inc(); return trueValue; diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Mon Feb 11 10:41:29 2013 +0100 @@ -76,10 +76,7 @@ public static final boolean CHECK_BALANCED_MONITORS = Boolean.getBoolean("graal.monitors.checkBalanced"); @Snippet - public static void monitorenter(@Parameter("object") - Object object, @ConstantParameter("checkNull") - boolean checkNull, @ConstantParameter("trace") - boolean trace) { + public static void monitorenter(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { verifyOop(object); if (checkNull && object == null) { @@ -105,7 +102,7 @@ final Word biasableLockBits = mark.and(biasedLockMaskInPlace()); // First check to see whether biasing is enabled for this object - if (biasableLockBits != Word.unsigned(biasedLockPattern())) { + if (biasableLockBits.notEqual(Word.unsigned(biasedLockPattern()))) { // Biasing not enabled -> fall through to lightweight locking } else { probability(FREQUENT_PROBABILITY); @@ -118,7 +115,7 @@ trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); trace(trace, " thread: 0x%016lx\n", thread); trace(trace, " tmp: 0x%016lx\n", tmp); - if (tmp == Word.zero()) { + if (tmp.equal(0)) { // Object is already biased to current thread -> done probability(FREQUENT_PROBABILITY); traceObject(trace, "+lock{bias:existing}", object); @@ -134,7 +131,7 @@ // If the low three bits in the xor result aren't clear, that means // the prototype header is no longer biasable and we have to revoke // the bias on this object. - if (tmp.and(biasedLockMaskInPlace()) == Word.zero()) { + if (tmp.and(biasedLockMaskInPlace()).equal(0)) { probability(FREQUENT_PROBABILITY); // Biasing is still enabled for object's type. See whether the // epoch of the current bias is still valid, meaning that the epoch @@ -145,7 +142,7 @@ // that the current epoch is invalid in order to do this because // otherwise the manipulations it performs on the mark word are // illegal. - if (tmp.and(epochMaskInPlace()) == Word.zero()) { + if (tmp.and(epochMaskInPlace()).equal(0)) { probability(FREQUENT_PROBABILITY); // The epoch of the current bias is still valid but we know nothing // about the owner; it might be set or it might be clear. Try to @@ -157,7 +154,7 @@ Word biasedMark = unbiasedMark.or(thread); trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark) == unbiasedMark) { + if (compareAndSwap(object, markOffset(), unbiasedMark, biasedMark).equal(unbiasedMark)) { // Object is now biased to current thread -> done traceObject(trace, "+lock{bias:acquired}", object); return; @@ -178,7 +175,7 @@ // the bias from one thread to another directly in this situation. Word biasedMark = prototypeMarkWord.or(thread); trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (compareAndSwap(object, markOffset(), mark, biasedMark) == mark) { + if (compareAndSwap(object, markOffset(), mark, biasedMark).equal(mark)) { // Object is now biased to current thread -> done traceObject(trace, "+lock{bias:transfer}", object); return; @@ -223,7 +220,7 @@ // Test if the object's mark word is unlocked, and if so, store the // (address of) the lock slot into the object's mark word. Word currentMark = compareAndSwap(object, markOffset(), unlockedMark, lock); - if (currentMark != unlockedMark) { + if (currentMark.notEqual(unlockedMark)) { trace(trace, " currentMark: 0x%016lx\n", currentMark); // The mark word in the object header was not the same. // Either the object is locked by another thread or is already locked @@ -242,7 +239,7 @@ // significant 2 bits cleared and page_size is a power of 2 final Word alignedMask = Word.unsigned(wordSize() - 1); final Word stackPointer = stackPointer(); - if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())) != Word.zero()) { + if (currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0)) { // Most likely not a recursive lock, go into a slow runtime call probability(DEOPT_PATH_PROBABILITY); traceObject(trace, "+lock{stub:failed-cas}", object); @@ -268,10 +265,7 @@ * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(@Parameter("object") - Object object, @ConstantParameter("checkNull") - boolean checkNull, @ConstantParameter("trace") - boolean trace) { + public static void monitorenterStub(@Parameter("object") Object object, @ConstantParameter("checkNull") boolean checkNull, @ConstantParameter("trace") boolean trace) { verifyOop(object); incCounter(); if (checkNull && object == null) { @@ -285,9 +279,7 @@ } @Snippet - public static void monitorexit(@Parameter("object") - Object object, @ConstantParameter("trace") - boolean trace) { + public static void monitorexit(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { trace(trace, " object: 0x%016lx\n", Word.fromObject(object)); if (useBiasedLocking()) { // Check for biased locking unlock case, which is a no-op @@ -298,7 +290,7 @@ // the bias bit would be clear. final Word mark = loadWordFromObject(object, markOffset()); trace(trace, " mark: 0x%016lx\n", mark); - if (mark.and(biasedLockMaskInPlace()) == Word.unsigned(biasedLockPattern())) { + if (mark.and(biasedLockMaskInPlace()).equal(Word.unsigned(biasedLockPattern()))) { probability(FREQUENT_PROBABILITY); endLockScope(); decCounter(); @@ -313,7 +305,7 @@ final Word displacedMark = lock.readWord(lockDisplacedMarkOffset()); trace(trace, " displacedMark: 0x%016lx\n", displacedMark); - if (displacedMark == Word.zero()) { + if (displacedMark.equal(0)) { // Recursive locking => done traceObject(trace, "-lock{recursive}", object); } else { @@ -321,7 +313,7 @@ // Test if object's mark word is pointing to the displaced mark word, and if so, restore // the displaced mark in the object - if the object's mark word is not pointing to // the displaced mark word, do unlocking via runtime call. - if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark) != lock) { + if (DirectCompareAndSwapNode.compareAndSwap(object, markOffset(), lock, displacedMark).notEqual(lock)) { // The object's mark word was not pointing to the displaced header, // we do unlocking via runtime call. probability(DEOPT_PATH_PROBABILITY); @@ -339,9 +331,7 @@ * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(@Parameter("object") - Object object, @ConstantParameter("trace") - boolean trace) { + public static void monitorexitStub(@Parameter("object") Object object, @ConstantParameter("trace") boolean trace) { verifyOop(object); traceObject(trace, "-lock{stub}", object); MonitorExitStubCall.call(object); @@ -434,8 +424,7 @@ this.useFastLocking = useFastLocking; } - public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") - LoweringTool tool) { + public void lower(MonitorEnterNode monitorenterNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorenterNode.graph(); checkBalancedMonitors(graph); @@ -466,8 +455,7 @@ } } - public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") - LoweringTool tool) { + public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) { StructuredGraph graph = (StructuredGraph) monitorexitNode.graph(); FrameState stateAfter = monitorexitNode.stateAfter(); boolean eliminated = monitorexitNode.eliminated(); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Mon Feb 11 10:41:29 2013 +0100 @@ -84,7 +84,7 @@ @ConstantParameter("locked") boolean locked) { Object result; - if (memory == Word.zero()) { + if (memory.equal(0)) { new_stub.inc(); result = NewInstanceStubCall.call(hub); } else { @@ -118,7 +118,7 @@ private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) { Object result; - if (memory == Word.zero()) { + if (memory.equal(0)) { newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); } else { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/TypeCheckSnippetUtils.java Mon Feb 11 10:41:29 2013 +0100 @@ -41,7 +41,7 @@ static boolean checkSecondarySubType(Word t, Word s) { // if (S.cache == T) return true - if (s.readWord(secondarySuperCacheOffset()) == t) { + if (s.readWord(secondarySuperCacheOffset()).equal(t)) { cacheHit.inc(); return true; } @@ -55,7 +55,7 @@ boolean primary = superCheckOffset != secondarySuperCacheOffset(); // if (T = S[off]) return true - if (s.readWord(superCheckOffset) == t) { + if (s.readWord(superCheckOffset).equal(t)) { if (primary) { cacheHit.inc(); } else { @@ -75,7 +75,7 @@ private static boolean checkSelfAndSupers(Word t, Word s) { // if (T == S) return true - if (s == t) { + if (s.equal(t)) { T_equals_S.inc(); return true; } @@ -84,7 +84,7 @@ Word secondarySupers = s.readWord(secondarySupersOffset()); int length = secondarySupers.readInt(metaspaceArrayLengthOffset()); for (int i = 0; i < length; i++) { - if (t == loadWordElement(secondarySupers, i)) { + if (t.equal(loadWordElement(secondarySupers, i))) { probability(NOT_LIKELY_PROBABILITY); s.writeWord(secondarySuperCacheOffset(), t); secondariesHit.inc(); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Feb 11 10:41:29 2013 +0100 @@ -80,7 +80,7 @@ // check that array length is small enough for fast path. if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { Word memory = refillAllocate(intArrayHub, sizeInBytes, log); - if (memory != Word.zero()) { + if (memory.notEqual(0)) { log(log, "newArray: allocated new array at %p\n", memory); formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord()), true); return verifyOop(memory.toObject()); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Feb 11 10:41:29 2013 +0100 @@ -71,7 +71,7 @@ if (!forceSlowPath() && inlineContiguousAllocationSupported()) { if (hub.readInt(klassStateOffset()) == klassStateFullyInitialized()) { Word memory = refillAllocate(intArrayHub, sizeInBytes, log); - if (memory != Word.zero()) { + if (memory.notEqual(0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset()); memory.writeWord(markOffset(), prototypeMarkWord); memory.writeWord(hubOffset(), hub); @@ -129,7 +129,7 @@ // if TLAB is currently allocated (top or end != null) then // fill [top, end + alignment_reserve) with array object - if (top != Word.zero()) { + if (top.notEqual(0)) { int headerSize = arrayBaseOffset(Kind.Int); // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in // an int @@ -147,7 +147,7 @@ Word tlabRefillSizeInBytes = tlabRefillSizeInWords.multiply(wordSize()); // allocate new TLAB, address returned in top top = edenAllocate(tlabRefillSizeInBytes, log); - if (top != Word.zero()) { + if (top.notEqual(0)) { thread.writeWord(threadTlabStartOffset(), top); thread.writeWord(threadTlabTopOffset(), top); @@ -195,7 +195,7 @@ return Word.zero(); } - if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop) == heapTop) { + if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop).equal(heapTop)) { return heapTop; } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.interpreter/overview.html --- a/graal/com.oracle.graal.interpreter/overview.html Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ - - - - - - - - -Documentation for the com.oracle.graal.interpreter project. - - - diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java --- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/BytecodeInterpreter.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1679 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.interpreter; - -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.graal.api.interpreter.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.bytecode.*; - -/** - * High-level bytecode interpreter that executes on top of Java. Java native methods are executed - * using the {@link com.oracle.graal.api.interpreter.RuntimeInterpreterInterface}. - */ -@SuppressWarnings("static-method") -public final class BytecodeInterpreter implements Interpreter { - - private static final String OPTION_MAX_STACK_SIZE = "maxStackSize"; - private static final boolean TRACE = false; - private static final boolean TRACE_BYTE_CODE = false; - - private static final int DEFAULT_MAX_STACK_SIZE = 1500; - - private static final int NEXT = -1; - private static final int BRANCH = -2; - private static final int RETURN = -3; - private static final int CALL = -4; - - private InterpreterFrame callFrame; - - private Map methodDelegates; - - private int maxStackFrames; - - private ResolvedJavaMethod rootMethod; - private RuntimeInterpreterInterface runtimeInterface; - private MetaAccessProvider metaAccessProvider; - - public boolean initialize(String args) { - methodDelegates = new HashMap<>(); - maxStackFrames = DEFAULT_MAX_STACK_SIZE; - - GraalRuntime runtime = Graal.getRuntime(); - this.runtimeInterface = runtime.getCapability(RuntimeInterpreterInterface.class); - if (this.runtimeInterface == null) { - throw new UnsupportedOperationException("The provided Graal runtime does not support the required capability " + RuntimeInterpreterInterface.class.getName() + "."); - } - this.metaAccessProvider = runtime.getCapability(MetaAccessProvider.class); - if (this.metaAccessProvider == null) { - throw new UnsupportedOperationException("The provided Graal runtime does not support the required capability " + MetaAccessProvider.class.getName() + "."); - } - - this.rootMethod = resolveRootMethod(); - registerDelegates(); - return parseArguments(args); - } - - @Override - public void setOption(String name, String value) { - if (name != null && name.equals(OPTION_MAX_STACK_SIZE)) { - this.maxStackFrames = Integer.parseInt(value); - } - } - - private void registerDelegates() { - addDelegate(findMethod(Throwable.class, "fillInStackTrace"), new InterpreterCallable() { - - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { - setBackTrace(caller, (Throwable) arguments[0], createStackTraceElements(caller, runtimeInterface)); - return null; - } - }); - addDelegate(findMethod(Throwable.class, "getStackTraceDepth"), new InterpreterCallable() { - - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { - StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); - if (elements != null) { - return elements.length; - } - return 0; - } - }); - addDelegate(findMethod(Throwable.class, "getStackTraceElement", int.class), new InterpreterCallable() { - - @Override - public Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable { - StackTraceElement[] elements = getBackTrace(caller, (Throwable) arguments[0]); - if (elements != null) { - Integer index = (Integer) arguments[0]; - if (index != null) { - return elements[index]; - } - } - return null; - } - }); - } - - @SuppressWarnings("unused") - private boolean parseArguments(String stringArgs) { - // TODO: parse the arguments - return true; - } - - public void setMaxStackFrames(int maxStackSize) { - this.maxStackFrames = maxStackSize; - } - - public int getMaxStackFrames() { - return maxStackFrames; - } - - public void addDelegate(Method method, InterpreterCallable callable) { - ResolvedJavaMethod resolvedMethod = metaAccessProvider.lookupJavaMethod(method); - if (methodDelegates.containsKey(resolvedMethod)) { - throw new IllegalArgumentException("Delegate for method " + method + " already added."); - } - - methodDelegates.put(resolvedMethod, new MethodRedirectionInfo(callable)); - } - - public void removeDelegate(Method method) { - methodDelegates.remove(metaAccessProvider.lookupJavaMethod(method)); - } - - @Override - public Object execute(ResolvedJavaMethod method, Object... boxedArguments) throws Throwable { - try { - boolean receiver = hasReceiver(method); - Signature signature = method.getSignature(); - assert boxedArguments != null; - assert signature.getParameterCount(receiver) == boxedArguments.length; - - if (TRACE) { - trace(0, "Executing root method " + method); - } - - InterpreterFrame rootFrame = new InterpreterFrame(rootMethod, signature.getParameterSlots(true)); - rootFrame.pushObject(this); - rootFrame.pushObject(method); - rootFrame.pushObject(boxedArguments); - - int index = 0; - if (receiver) { - pushAsObject(rootFrame, Kind.Object, boxedArguments[index]); - index++; - } - - for (int i = 0; index < boxedArguments.length; i++, index++) { - pushAsObject(rootFrame, signature.getParameterKind(i), boxedArguments[index]); - } - - InterpreterFrame frame = rootFrame.create(method, receiver); - executeRoot(rootFrame, frame); - return popAsObject(rootFrame, signature.getReturnKind()); - } catch (Exception e) { - // TODO (chaeubl): remove this exception handler (only used for debugging) - throw e; - } - } - - public Object execute(Method javaMethod, Object... boxedArguments) throws Throwable { - return execute(metaAccessProvider.lookupJavaMethod(javaMethod), boxedArguments); - } - - private boolean hasReceiver(ResolvedJavaMethod method) { - return !Modifier.isStatic(method.getModifiers()); - } - - private void executeRoot(InterpreterFrame root, InterpreterFrame frame) throws Throwable { - // TODO reflection redirection - InterpreterFrame prevFrame = frame; - InterpreterFrame currentFrame = frame; - BytecodeStream bs = new BytecodeStream(currentFrame.getMethod().getCode()); - if (TRACE) { - traceCall(frame, "Call"); - } - while (currentFrame != root) { - if (prevFrame != currentFrame) { - bs = new BytecodeStream(currentFrame.getMethod().getCode()); - } - bs.setBCI(currentFrame.getBCI()); - - prevFrame = currentFrame; - currentFrame = loop(root, prevFrame, bs); - } - assert callFrame == null; - } - - private InterpreterFrame loop(InterpreterFrame root, final InterpreterFrame frame, final BytecodeStream bs) throws Throwable { - try { - while (true) { - int result = executeInstruction(frame, bs); - switch (result) { - case NEXT: - bs.next(); - break; - case RETURN: - return popFrame(frame); - case CALL: - return allocateFrame(frame, bs); - case BRANCH: - bs.setBCI(bs.readBranchDest()); - break; - default: - // the outcome depends on stack values - assert result >= 0 : "negative branch target"; - bs.setBCI(result); - break; - } - } - } catch (Throwable t) { - if (TRACE) { - traceOp(frame, "Exception " + t.toString()); - } - updateStackTrace(frame, t); - - // frame bci needs to be in sync when handling exceptions - frame.setBCI(bs.currentBCI()); - - InterpreterFrame handlerFrame = handleThrowable(root, frame, t); - if (handlerFrame == null) { - // matched root we just throw it again. - throw t; - } else { - if (TRACE) { - traceOp(frame, "Handler found " + handlerFrame.getMethod() + ":" + handlerFrame.getBCI()); - } - // update bci from frame - bs.setBCI(handlerFrame.getBCI()); - - // continue execution on the found frame - return handlerFrame; - } - } finally { - // TODO may be not necessary. - frame.setBCI(bs.currentBCI()); - } - } - - private int executeInstruction(InterpreterFrame frame, BytecodeStream bs) throws Throwable { - if (TRACE_BYTE_CODE) { - traceOp(frame, bs.currentBCI() + ": " + Bytecodes.baseNameOf(bs.currentBC())); - } - switch (bs.currentBC()) { - case Bytecodes.NOP: - break; - case Bytecodes.ACONST_NULL: - frame.pushObject(null); - break; - case Bytecodes.ICONST_M1: - frame.pushInt(-1); - break; - case Bytecodes.ICONST_0: - frame.pushInt(0); - break; - case Bytecodes.ICONST_1: - frame.pushInt(1); - break; - case Bytecodes.ICONST_2: - frame.pushInt(2); - break; - case Bytecodes.ICONST_3: - frame.pushInt(3); - break; - case Bytecodes.ICONST_4: - frame.pushInt(4); - break; - case Bytecodes.ICONST_5: - frame.pushInt(5); - break; - case Bytecodes.LCONST_0: - frame.pushLong(0L); - break; - case Bytecodes.LCONST_1: - frame.pushLong(1L); - break; - case Bytecodes.FCONST_0: - frame.pushFloat(0.0F); - break; - case Bytecodes.FCONST_1: - frame.pushFloat(1.0F); - break; - case Bytecodes.FCONST_2: - frame.pushFloat(2.0F); - break; - case Bytecodes.DCONST_0: - frame.pushDouble(0.0D); - break; - case Bytecodes.DCONST_1: - frame.pushDouble(1.0D); - break; - case Bytecodes.BIPUSH: - frame.pushInt(bs.readByte()); - break; - case Bytecodes.SIPUSH: - frame.pushInt(bs.readShort()); - break; - case Bytecodes.LDC: - case Bytecodes.LDC_W: - case Bytecodes.LDC2_W: - pushCPConstant(frame, bs.readCPI()); - break; - case Bytecodes.ILOAD: - frame.pushInt(frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex()))); - break; - case Bytecodes.LLOAD: - frame.pushLong(frame.getLong(frame.resolveLocalIndex(bs.readLocalIndex()))); - break; - case Bytecodes.FLOAD: - frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(bs.readLocalIndex()))); - break; - case Bytecodes.DLOAD: - frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(bs.readLocalIndex()))); - break; - case Bytecodes.ALOAD: - frame.pushObject(frame.getObject(frame.resolveLocalIndex(bs.readLocalIndex()))); - break; - case Bytecodes.ILOAD_0: - frame.pushInt(frame.getInt(frame.resolveLocalIndex(0))); - break; - case Bytecodes.ILOAD_1: - frame.pushInt(frame.getInt(frame.resolveLocalIndex(1))); - break; - case Bytecodes.ILOAD_2: - frame.pushInt(frame.getInt(frame.resolveLocalIndex(2))); - break; - case Bytecodes.ILOAD_3: - frame.pushInt(frame.getInt(frame.resolveLocalIndex(3))); - break; - case Bytecodes.LLOAD_0: - frame.pushLong(frame.getLong(frame.resolveLocalIndex(0))); - break; - case Bytecodes.LLOAD_1: - frame.pushLong(frame.getLong(frame.resolveLocalIndex(1))); - break; - case Bytecodes.LLOAD_2: - frame.pushLong(frame.getLong(frame.resolveLocalIndex(2))); - break; - case Bytecodes.LLOAD_3: - frame.pushLong(frame.getLong(frame.resolveLocalIndex(3))); - break; - case Bytecodes.FLOAD_0: - frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(0))); - break; - case Bytecodes.FLOAD_1: - frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(1))); - break; - case Bytecodes.FLOAD_2: - frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(2))); - break; - case Bytecodes.FLOAD_3: - frame.pushFloat(frame.getFloat(frame.resolveLocalIndex(3))); - break; - case Bytecodes.DLOAD_0: - frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(0))); - break; - case Bytecodes.DLOAD_1: - frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(1))); - break; - case Bytecodes.DLOAD_2: - frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(2))); - break; - case Bytecodes.DLOAD_3: - frame.pushDouble(frame.getDouble(frame.resolveLocalIndex(3))); - break; - case Bytecodes.ALOAD_0: - frame.pushObject(frame.getObject(frame.resolveLocalIndex(0))); - break; - case Bytecodes.ALOAD_1: - frame.pushObject(frame.getObject(frame.resolveLocalIndex(1))); - break; - case Bytecodes.ALOAD_2: - frame.pushObject(frame.getObject(frame.resolveLocalIndex(2))); - break; - case Bytecodes.ALOAD_3: - frame.pushObject(frame.getObject(frame.resolveLocalIndex(3))); - break; - case Bytecodes.IALOAD: - frame.pushInt(runtimeInterface.getArrayInt(frame.popInt(), frame.popObject())); - break; - case Bytecodes.LALOAD: - frame.pushLong(runtimeInterface.getArrayLong(frame.popInt(), frame.popObject())); - break; - case Bytecodes.FALOAD: - frame.pushFloat(runtimeInterface.getArrayFloat(frame.popInt(), frame.popObject())); - break; - case Bytecodes.DALOAD: - frame.pushDouble(runtimeInterface.getArrayDouble(frame.popInt(), frame.popObject())); - break; - case Bytecodes.AALOAD: - frame.pushObject(runtimeInterface.getArrayObject(frame.popInt(), frame.popObject())); - break; - case Bytecodes.BALOAD: - frame.pushInt(runtimeInterface.getArrayByte(frame.popInt(), frame.popObject())); - break; - case Bytecodes.CALOAD: - frame.pushInt(runtimeInterface.getArrayChar(frame.popInt(), frame.popObject())); - break; - case Bytecodes.SALOAD: - frame.pushInt(runtimeInterface.getArrayShort(frame.popInt(), frame.popObject())); - break; - case Bytecodes.ISTORE: - frame.setInt(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popInt()); - break; - case Bytecodes.LSTORE: - frame.setLong(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popLong()); - break; - case Bytecodes.FSTORE: - frame.setFloat(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popFloat()); - break; - case Bytecodes.DSTORE: - frame.setDouble(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popDouble()); - break; - case Bytecodes.ASTORE: - frame.setObject(frame.resolveLocalIndex(bs.readLocalIndex()), frame.popObject()); - break; - case Bytecodes.ISTORE_0: - frame.setInt(frame.resolveLocalIndex(0), frame.popInt()); - break; - case Bytecodes.ISTORE_1: - frame.setInt(frame.resolveLocalIndex(1), frame.popInt()); - break; - case Bytecodes.ISTORE_2: - frame.setInt(frame.resolveLocalIndex(2), frame.popInt()); - break; - case Bytecodes.ISTORE_3: - frame.setInt(frame.resolveLocalIndex(3), frame.popInt()); - break; - case Bytecodes.LSTORE_0: - frame.setLong(frame.resolveLocalIndex(0), frame.popLong()); - break; - case Bytecodes.LSTORE_1: - frame.setLong(frame.resolveLocalIndex(1), frame.popLong()); - break; - case Bytecodes.LSTORE_2: - frame.setLong(frame.resolveLocalIndex(2), frame.popLong()); - break; - case Bytecodes.LSTORE_3: - frame.setLong(frame.resolveLocalIndex(3), frame.popLong()); - break; - case Bytecodes.FSTORE_0: - frame.setFloat(frame.resolveLocalIndex(0), frame.popFloat()); - break; - case Bytecodes.FSTORE_1: - frame.setFloat(frame.resolveLocalIndex(1), frame.popFloat()); - break; - case Bytecodes.FSTORE_2: - frame.setFloat(frame.resolveLocalIndex(2), frame.popFloat()); - break; - case Bytecodes.FSTORE_3: - frame.setFloat(frame.resolveLocalIndex(3), frame.popFloat()); - break; - case Bytecodes.DSTORE_0: - frame.setDouble(frame.resolveLocalIndex(0), frame.popDouble()); - break; - case Bytecodes.DSTORE_1: - frame.setDouble(frame.resolveLocalIndex(1), frame.popDouble()); - break; - case Bytecodes.DSTORE_2: - frame.setDouble(frame.resolveLocalIndex(2), frame.popDouble()); - break; - case Bytecodes.DSTORE_3: - frame.setDouble(frame.resolveLocalIndex(3), frame.popDouble()); - break; - case Bytecodes.ASTORE_0: - frame.setObject(frame.resolveLocalIndex(0), frame.popObject()); - break; - case Bytecodes.ASTORE_1: - frame.setObject(frame.resolveLocalIndex(1), frame.popObject()); - break; - case Bytecodes.ASTORE_2: - frame.setObject(frame.resolveLocalIndex(2), frame.popObject()); - break; - case Bytecodes.ASTORE_3: - frame.setObject(frame.resolveLocalIndex(3), frame.popObject()); - break; - case Bytecodes.IASTORE: - runtimeInterface.setArrayInt(frame.popInt(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.LASTORE: - runtimeInterface.setArrayLong(frame.popLong(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.FASTORE: - runtimeInterface.setArrayFloat(frame.popFloat(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.DASTORE: - runtimeInterface.setArrayDouble(frame.popDouble(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.AASTORE: - runtimeInterface.setArrayObject(frame.popObject(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.BASTORE: - runtimeInterface.setArrayByte((byte) frame.popInt(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.CASTORE: - runtimeInterface.setArrayChar((char) frame.popInt(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.SASTORE: - runtimeInterface.setArrayShort((short) frame.popInt(), frame.popInt(), frame.popObject()); - break; - case Bytecodes.POP: - frame.popVoid(1); - break; - case Bytecodes.POP2: - frame.popVoid(2); - break; - case Bytecodes.DUP: - frame.dup(1); - break; - case Bytecodes.DUP_X1: - frame.dupx1(); - break; - case Bytecodes.DUP_X2: - frame.dupx2(); - break; - case Bytecodes.DUP2: - frame.dup(2); - break; - case Bytecodes.DUP2_X1: - frame.dup2x1(); - break; - case Bytecodes.DUP2_X2: - frame.dup2x2(); - break; - case Bytecodes.SWAP: - frame.swapSingle(); - break; - case Bytecodes.IADD: - frame.pushInt(frame.popInt() + frame.popInt()); - break; - case Bytecodes.LADD: - frame.pushLong(frame.popLong() + frame.popLong()); - break; - case Bytecodes.FADD: - frame.pushFloat(frame.popFloat() + frame.popFloat()); - break; - case Bytecodes.DADD: - frame.pushDouble(frame.popDouble() + frame.popDouble()); - break; - case Bytecodes.ISUB: - frame.pushInt(-frame.popInt() + frame.popInt()); - break; - case Bytecodes.LSUB: - frame.pushLong(-frame.popLong() + frame.popLong()); - break; - case Bytecodes.FSUB: - frame.pushFloat(-frame.popFloat() + frame.popFloat()); - break; - case Bytecodes.DSUB: - frame.pushDouble(-frame.popDouble() + frame.popDouble()); - break; - case Bytecodes.IMUL: - frame.pushInt(frame.popInt() * frame.popInt()); - break; - case Bytecodes.LMUL: - frame.pushLong(frame.popLong() * frame.popLong()); - break; - case Bytecodes.FMUL: - frame.pushFloat(frame.popFloat() * frame.popFloat()); - break; - case Bytecodes.DMUL: - frame.pushDouble(frame.popDouble() * frame.popDouble()); - break; - case Bytecodes.IDIV: - divInt(frame); - break; - case Bytecodes.LDIV: - divLong(frame); - break; - case Bytecodes.FDIV: - divFloat(frame); - break; - case Bytecodes.DDIV: - divDouble(frame); - break; - case Bytecodes.IREM: - remInt(frame); - break; - case Bytecodes.LREM: - remLong(frame); - break; - case Bytecodes.FREM: - remFloat(frame); - break; - case Bytecodes.DREM: - remDouble(frame); - break; - case Bytecodes.INEG: - frame.pushInt(-frame.popInt()); - break; - case Bytecodes.LNEG: - frame.pushLong(-frame.popLong()); - break; - case Bytecodes.FNEG: - frame.pushFloat(-frame.popFloat()); - break; - case Bytecodes.DNEG: - frame.pushDouble(-frame.popDouble()); - break; - case Bytecodes.ISHL: - shiftLeftInt(frame); - break; - case Bytecodes.LSHL: - shiftLeftLong(frame); - break; - case Bytecodes.ISHR: - shiftRightSignedInt(frame); - break; - case Bytecodes.LSHR: - shiftRightSignedLong(frame); - break; - case Bytecodes.IUSHR: - shiftRightUnsignedInt(frame); - break; - case Bytecodes.LUSHR: - shiftRightUnsignedLong(frame); - break; - case Bytecodes.IAND: - frame.pushInt(frame.popInt() & frame.popInt()); - break; - case Bytecodes.LAND: - frame.pushLong(frame.popLong() & frame.popLong()); - break; - case Bytecodes.IOR: - frame.pushInt(frame.popInt() | frame.popInt()); - break; - case Bytecodes.LOR: - frame.pushLong(frame.popLong() | frame.popLong()); - break; - case Bytecodes.IXOR: - frame.pushInt(frame.popInt() ^ frame.popInt()); - break; - case Bytecodes.LXOR: - frame.pushLong(frame.popLong() ^ frame.popLong()); - break; - case Bytecodes.IINC: - iinc(frame, bs); - break; - case Bytecodes.I2L: - frame.pushLong(frame.popInt()); - break; - case Bytecodes.I2F: - frame.pushFloat(frame.popInt()); - break; - case Bytecodes.I2D: - frame.pushDouble(frame.popInt()); - break; - case Bytecodes.L2I: - frame.pushInt((int) frame.popLong()); - break; - case Bytecodes.L2F: - frame.pushFloat(frame.popLong()); - break; - case Bytecodes.L2D: - frame.pushDouble(frame.popLong()); - break; - case Bytecodes.F2I: - frame.pushInt((int) frame.popFloat()); - break; - case Bytecodes.F2L: - frame.pushLong((long) frame.popFloat()); - break; - case Bytecodes.F2D: - frame.pushDouble(frame.popFloat()); - break; - case Bytecodes.D2I: - frame.pushInt((int) frame.popDouble()); - break; - case Bytecodes.D2L: - frame.pushLong((long) frame.popDouble()); - break; - case Bytecodes.D2F: - frame.pushFloat((float) frame.popDouble()); - break; - case Bytecodes.I2B: - frame.pushInt((byte) frame.popInt()); - break; - case Bytecodes.I2C: - frame.pushInt((char) frame.popInt()); - break; - case Bytecodes.I2S: - frame.pushInt((short) frame.popInt()); - break; - case Bytecodes.LCMP: - compareLong(frame); - break; - case Bytecodes.FCMPL: - compareFloatLess(frame); - break; - case Bytecodes.FCMPG: - compareFloatGreater(frame); - break; - case Bytecodes.DCMPL: - compareDoubleLess(frame); - break; - case Bytecodes.DCMPG: - compareDoubleGreater(frame); - break; - case Bytecodes.IFEQ: - if (frame.popInt() == 0) { - return BRANCH; - } - break; - case Bytecodes.IFNE: - if (frame.popInt() != 0) { - return BRANCH; - } - break; - case Bytecodes.IFLT: - if (frame.popInt() < 0) { - return BRANCH; - } - break; - case Bytecodes.IFGE: - if (frame.popInt() >= 0) { - return BRANCH; - } - break; - case Bytecodes.IFGT: - if (frame.popInt() > 0) { - return BRANCH; - } - break; - case Bytecodes.IFLE: - if (frame.popInt() <= 0) { - return BRANCH; - } - break; - case Bytecodes.IF_ICMPEQ: - if (frame.popInt() == frame.popInt()) { - return BRANCH; - } - break; - case Bytecodes.IF_ICMPNE: - if (frame.popInt() != frame.popInt()) { - return BRANCH; - } - break; - case Bytecodes.IF_ICMPLT: - if (frame.popInt() > frame.popInt()) { - return BRANCH; - } - break; - case Bytecodes.IF_ICMPGE: - if (frame.popInt() <= frame.popInt()) { - return BRANCH; - } - break; - case Bytecodes.IF_ICMPGT: - if (frame.popInt() < frame.popInt()) { - return BRANCH; - } - break; - case Bytecodes.IF_ICMPLE: - if (frame.popInt() >= frame.popInt()) { - return BRANCH; - } - break; - case Bytecodes.IF_ACMPEQ: - if (frame.popObject() == frame.popObject()) { - return BRANCH; - } - break; - case Bytecodes.IF_ACMPNE: - if (frame.popObject() != frame.popObject()) { - return BRANCH; - } - break; - case Bytecodes.GOTO: - case Bytecodes.GOTO_W: - return BRANCH; - case Bytecodes.JSR: - case Bytecodes.JSR_W: - frame.pushInt(bs.currentBCI()); - return BRANCH; - case Bytecodes.RET: - return frame.getInt(frame.resolveLocalIndex(bs.readLocalIndex())); - case Bytecodes.TABLESWITCH: - return tableSwitch(frame, bs); - case Bytecodes.LOOKUPSWITCH: - return lookupSwitch(frame, bs); - case Bytecodes.IRETURN: - frame.getParentFrame().pushInt(frame.popInt()); - return RETURN; - case Bytecodes.LRETURN: - frame.getParentFrame().pushLong(frame.popLong()); - return RETURN; - case Bytecodes.FRETURN: - frame.getParentFrame().pushFloat(frame.popFloat()); - return RETURN; - case Bytecodes.DRETURN: - frame.getParentFrame().pushDouble(frame.popDouble()); - return RETURN; - case Bytecodes.ARETURN: - frame.getParentFrame().pushObject(frame.popObject()); - return RETURN; - case Bytecodes.RETURN: - return RETURN; - case Bytecodes.GETSTATIC: - getField(frame, null, bs.currentBC(), bs.readCPI()); - break; - case Bytecodes.PUTSTATIC: - putStatic(frame, bs.readCPI()); - break; - case Bytecodes.GETFIELD: - getField(frame, nullCheck(frame.popObject()), bs.currentBC(), bs.readCPI()); - break; - case Bytecodes.PUTFIELD: - putField(frame, bs.readCPI()); - break; - case Bytecodes.INVOKEVIRTUAL: - callFrame = invokeVirtual(frame, bs.readCPI()); - if (callFrame == null) { - break; - } - return CALL; - case Bytecodes.INVOKESPECIAL: - callFrame = invokeSpecial(frame, bs.readCPI()); - if (callFrame == null) { - break; - } - return CALL; - case Bytecodes.INVOKESTATIC: - callFrame = invokeStatic(frame, bs.readCPI()); - if (callFrame == null) { - break; - } - return CALL; - case Bytecodes.INVOKEINTERFACE: - callFrame = invokeInterface(frame, bs.readCPI()); - if (callFrame == null) { - break; - } - return CALL; - case Bytecodes.XXXUNUSEDXXX: - assert false : "unused bytecode used. behaviour unspecified."; - // nop - break; - case Bytecodes.NEW: - frame.pushObject(allocateInstance(frame, bs.readCPI())); - break; - case Bytecodes.NEWARRAY: - frame.pushObject(allocateNativeArray(frame, bs.readByte())); - break; - case Bytecodes.ANEWARRAY: - frame.pushObject(allocateArray(frame, bs.readCPI())); - break; - case Bytecodes.ARRAYLENGTH: - frame.pushInt(Array.getLength(nullCheck(frame.popObject()))); - break; - case Bytecodes.ATHROW: - Throwable t = (Throwable) frame.popObject(); - if ("break".equals(t.getMessage())) { - t.printStackTrace(); - } - throw t; - case Bytecodes.CHECKCAST: - checkCast(frame, bs.readCPI()); - break; - case Bytecodes.INSTANCEOF: - instanceOf(frame, bs.readCPI()); - break; - case Bytecodes.MONITORENTER: - runtimeInterface.monitorEnter(frame.popObject()); - break; - case Bytecodes.MONITOREXIT: - runtimeInterface.monitorExit(frame.popObject()); - break; - case Bytecodes.WIDE: - assert false; - break; - case Bytecodes.MULTIANEWARRAY: - frame.pushObject(allocateMultiArray(frame, bs.readCPI(), bs.readUByte(bs.currentBCI() + 3))); - break; - case Bytecodes.IFNULL: - if (frame.popObject() == null) { - return BRANCH; - } - break; - case Bytecodes.IFNONNULL: - if (frame.popObject() != null) { - return BRANCH; - } - break; - case Bytecodes.BREAKPOINT: - assert false : "no breakpoints supported at this time."; - break; // nop - } - return NEXT; - } - - private InterpreterFrame handleThrowable(InterpreterFrame root, InterpreterFrame frame, Throwable t) { - ExceptionHandler handler; - InterpreterFrame currentFrame = frame; - do { - handler = resolveExceptionHandlers(currentFrame, currentFrame.getBCI(), t); - if (handler == null) { - // no handler found pop frame - // and continue searching - currentFrame = popFrame(currentFrame); - } else { - // found a handler -> execute it - currentFrame.setBCI(handler.getHandlerBCI()); - currentFrame.popStack(); - currentFrame.pushObject(t); - return currentFrame; - } - } while (handler == null && currentFrame != root); - - // will throw exception up the interpreter - return null; - } - - private void updateStackTrace(InterpreterFrame frame, Throwable t) { - StackTraceElement[] elements = getBackTrace(frame, t); - if (elements != null) { - setStackTrace(frame, t, elements); - setBackTrace(frame, t, null); - } else { - setBackTrace(frame, t, createStackTraceElements(frame, runtimeInterface)); - } - } - - private void setStackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] stackTrace) { - runtimeInterface.setFieldObject(stackTrace, t, findThrowableField(frame, "stackTrace")); - } - - private StackTraceElement[] getBackTrace(InterpreterFrame frame, Throwable t) { - Object value = runtimeInterface.getFieldObject(t, findThrowableField(frame, "backtrace")); - if (value instanceof StackTraceElement[]) { - return (StackTraceElement[]) value; - } - return null; - } - - private void setBackTrace(InterpreterFrame frame, Throwable t, StackTraceElement[] backtrace) { - runtimeInterface.setFieldObject(backtrace, t, findThrowableField(frame, "backtrace")); - } - - private ExceptionHandler resolveExceptionHandlers(InterpreterFrame frame, int bci, Throwable t) { - ExceptionHandler[] handlers = frame.getMethod().getExceptionHandlers(); - for (int i = 0; i < handlers.length; i++) { - ExceptionHandler handler = handlers[i]; - if (bci >= handler.getStartBCI() && bci <= handler.getEndBCI()) { - ResolvedJavaType catchType = null; - if (!handler.isCatchAll()) { - // exception handlers are similar to instanceof bytecodes, so we pass instanceof - catchType = resolveType(frame, Bytecodes.INSTANCEOF, (char) handler.catchTypeCPI()); - } - - if (catchType == null || catchType.isInstance(Constant.forObject(t))) { - // the first found exception handler is our exception handler - return handler; - } - } - } - return null; - } - - private Class mirror(ResolvedJavaType type) { - return runtimeInterface.getMirror(type); - } - - private InterpreterFrame allocateFrame(InterpreterFrame frame, BytecodeStream bs) { - try { - InterpreterFrame nextFrame = this.callFrame; - - assert nextFrame != null; - assert nextFrame.getParentFrame() == frame; - - // store bci when leaving method - frame.setBCI(bs.currentBCI()); - - if (TRACE) { - traceCall(nextFrame, "Call"); - } - if (Modifier.isSynchronized(nextFrame.getMethod().getModifiers())) { - if (TRACE) { - traceOp(frame, "Method monitor enter"); - } - if (Modifier.isStatic(nextFrame.getMethod().getModifiers())) { - runtimeInterface.monitorEnter(mirror(nextFrame.getMethod().getDeclaringClass())); - } else { - Object enterObject = nextFrame.getObject(frame.resolveLocalIndex(0)); - assert enterObject != null; - runtimeInterface.monitorEnter(enterObject); - } - } - - return nextFrame; - } finally { - callFrame = null; - bs.next(); - } - } - - private InterpreterFrame popFrame(InterpreterFrame frame) { - InterpreterFrame parent = frame.getParentFrame(); - if (Modifier.isSynchronized(frame.getMethod().getModifiers())) { - if (TRACE) { - traceOp(frame, "Method monitor exit"); - } - if (Modifier.isStatic(frame.getMethod().getModifiers())) { - runtimeInterface.monitorExit(mirror(frame.getMethod().getDeclaringClass())); - } else { - Object exitObject = frame.getObject(frame.resolveLocalIndex(0)); - if (exitObject != null) { - runtimeInterface.monitorExit(exitObject); - } - } - } - if (TRACE) { - traceCall(frame, "Ret"); - } - - frame.dispose(); - return parent; - } - - private void traceOp(InterpreterFrame frame, String opName) { - trace(frame.depth(), opName); - } - - private void traceCall(InterpreterFrame frame, String type) { - trace(frame.depth(), type + " " + frame.getMethod() + " - " + frame.getMethod().getSignature()); - } - - private void trace(int level, String message) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < level; i++) { - builder.append(" "); - } - builder.append(message); - System.out.println(builder); - } - - private void divInt(InterpreterFrame frame) { - int dividend = frame.popInt(); - int divisor = frame.popInt(); - frame.pushInt(divisor / dividend); - } - - private void divLong(InterpreterFrame frame) { - long dividend = frame.popLong(); - long divisor = frame.popLong(); - frame.pushLong(divisor / dividend); - } - - private void divFloat(InterpreterFrame frame) { - float dividend = frame.popFloat(); - float divisor = frame.popFloat(); - frame.pushFloat(divisor / dividend); - } - - private void divDouble(InterpreterFrame frame) { - double dividend = frame.popDouble(); - double divisor = frame.popDouble(); - frame.pushDouble(divisor / dividend); - } - - private void remInt(InterpreterFrame frame) { - int dividend = frame.popInt(); - int divisor = frame.popInt(); - frame.pushInt(divisor % dividend); - } - - private void remLong(InterpreterFrame frame) { - long dividend = frame.popLong(); - long divisor = frame.popLong(); - frame.pushLong(divisor % dividend); - } - - private void remFloat(InterpreterFrame frame) { - float dividend = frame.popFloat(); - float divisor = frame.popFloat(); - frame.pushFloat(divisor % dividend); - } - - private void remDouble(InterpreterFrame frame) { - double dividend = frame.popDouble(); - double divisor = frame.popDouble(); - frame.pushDouble(divisor % dividend); - } - - private void shiftLeftInt(InterpreterFrame frame) { - int bits = frame.popInt(); - int value = frame.popInt(); - frame.pushInt(value << bits); - } - - private void shiftLeftLong(InterpreterFrame frame) { - int bits = frame.popInt(); - long value = frame.popLong(); - frame.pushLong(value << bits); - } - - private void shiftRightSignedInt(InterpreterFrame frame) { - int bits = frame.popInt(); - int value = frame.popInt(); - frame.pushInt(value >> bits); - } - - private void shiftRightSignedLong(InterpreterFrame frame) { - int bits = frame.popInt(); - long value = frame.popLong(); - frame.pushLong(value >> bits); - } - - private void shiftRightUnsignedInt(InterpreterFrame frame) { - int bits = frame.popInt(); - int value = frame.popInt(); - frame.pushInt(value >>> bits); - } - - private void shiftRightUnsignedLong(InterpreterFrame frame) { - int bits = frame.popInt(); - long value = frame.popLong(); - frame.pushLong(value >>> bits); - } - - private int lookupSwitch(InterpreterFrame frame, BytecodeStream bs) { - return lookupSearch(new BytecodeLookupSwitch(bs, bs.currentBCI()), frame.popInt()); - } - - /** - * Binary search implementation for the lookup switch. - */ - private int lookupSearch(BytecodeLookupSwitch switchHelper, int key) { - int low = 0; - int high = switchHelper.numberOfCases() - 1; - while (low <= high) { - int mid = (low + high) >>> 1; - int midVal = switchHelper.keyAt(mid); - - if (midVal < key) { - low = mid + 1; - } else if (midVal > key) { - high = mid - 1; - } else { - return switchHelper.bci() + switchHelper.offsetAt(mid); // key found - } - } - return switchHelper.defaultTarget(); // key not found. - } - - private int tableSwitch(InterpreterFrame frame, BytecodeStream bs) { - BytecodeTableSwitch switchHelper = new BytecodeTableSwitch(bs, bs.currentBCI()); - - int low = switchHelper.lowKey(); - int high = switchHelper.highKey(); - - assert low <= high; - - int index = frame.popInt(); - if (index < low || index > high) { - return switchHelper.defaultTarget(); - } else { - return switchHelper.targetAt(index - low); - } - } - - private void checkCast(InterpreterFrame frame, char cpi) { - frame.pushObject(mirror(resolveType(frame, Bytecodes.CHECKCAST, cpi)).cast(frame.popObject())); - } - - private ResolvedJavaType resolveType(InterpreterFrame frame, int opcode, char cpi) { - ConstantPool constantPool = frame.getConstantPool(); - constantPool.loadReferencedType(cpi, opcode); - return constantPool.lookupType(cpi, opcode).resolve(frame.getMethod().getDeclaringClass()); - } - - private ResolvedJavaType resolveType(InterpreterFrame frame, Class javaClass) { - return metaAccessProvider.lookupJavaType(javaClass).resolve(frame.getMethod().getDeclaringClass()); - } - - private ResolvedJavaMethod resolveMethod(InterpreterFrame frame, int opcode, char cpi) { - ConstantPool constantPool = frame.getConstantPool(); - constantPool.loadReferencedType(cpi, opcode); - return (ResolvedJavaMethod) constantPool.lookupMethod(cpi, opcode); - } - - private ResolvedJavaField resolveField(InterpreterFrame frame, int opcode, char cpi) { - ConstantPool constantPool = frame.getConstantPool(); - constantPool.loadReferencedType(cpi, opcode); - return (ResolvedJavaField) constantPool.lookupField(cpi, opcode); - } - - private void instanceOf(InterpreterFrame frame, char cpi) { - frame.pushInt(resolveType(frame, Bytecodes.INSTANCEOF, cpi).isInstance(Constant.forObject(frame.popObject())) ? 1 : 0); - } - - private void pushCPConstant(InterpreterFrame frame, char cpi) { - ResolvedJavaMethod method = frame.getMethod(); - Object constant = method.getConstantPool().lookupConstant(cpi); - - if (constant instanceof Constant) { - Constant c = ((Constant) constant); - switch (c.getKind()) { - case Int: - frame.pushInt(c.asInt()); - break; - case Float: - frame.pushFloat(c.asFloat()); - break; - case Object: - frame.pushObject(c.asObject()); - break; - case Double: - frame.pushDouble(c.asDouble()); - break; - case Long: - frame.pushLong(c.asLong()); - break; - default: - assert false : "unspecified case"; - } - } else if (constant instanceof JavaType) { - frame.pushObject(mirror(((JavaType) constant).resolve(method.getDeclaringClass()))); - } else { - assert false : "unexpected case"; - } - } - - private void compareLong(InterpreterFrame frame) { - long y = frame.popLong(); - long x = frame.popLong(); - frame.pushInt((x < y) ? -1 : ((x == y) ? 0 : 1)); - } - - private void compareDoubleGreater(InterpreterFrame frame) { - double y = frame.popDouble(); - double x = frame.popDouble(); - frame.pushInt(x < y ? -1 : ((x == y) ? 0 : 1)); - } - - private void compareDoubleLess(InterpreterFrame frame) { - double y = frame.popDouble(); - double x = frame.popDouble(); - frame.pushInt(x > y ? 1 : ((x == y) ? 0 : -1)); - } - - private void compareFloatGreater(InterpreterFrame frame) { - float y = frame.popFloat(); - float x = frame.popFloat(); - frame.pushInt(x < y ? -1 : ((x == y) ? 0 : 1)); - } - - private void compareFloatLess(InterpreterFrame frame) { - float y = frame.popFloat(); - float x = frame.popFloat(); - frame.pushInt(x > y ? 1 : ((x == y) ? 0 : -1)); - } - - private Object nullCheck(Object value) { - if (value == null) { - throw new NullPointerException(); - } - return value; - } - - private InterpreterFrame invokeStatic(InterpreterFrame frame, char cpi) throws Throwable { - return invoke(frame, resolveMethod(frame, Bytecodes.INVOKESTATIC, cpi), null); - } - - private InterpreterFrame invokeInterface(InterpreterFrame frame, char cpi) throws Throwable { - return resolveAndInvoke(frame, resolveMethod(frame, Bytecodes.INVOKEINTERFACE, cpi)); - } - - private InterpreterFrame resolveAndInvoke(InterpreterFrame parent, ResolvedJavaMethod m) throws Throwable { - Object receiver = nullCheck(parent.peekReceiver(m)); - - ResolvedJavaMethod method = resolveType(parent, receiver.getClass()).resolveMethod(m); - - if (method == null) { - throw new AbstractMethodError(); - } - - return invoke(parent, method, receiver); - } - - private InterpreterFrame invokeVirtual(InterpreterFrame frame, char cpi) throws Throwable { - ResolvedJavaMethod m = resolveMethod(frame, Bytecodes.INVOKEVIRTUAL, cpi); - if (Modifier.isFinal(m.getModifiers())) { - return invoke(frame, m, nullCheck(frame.peekReceiver(m))); - } else { - return resolveAndInvoke(frame, m); - } - } - - private InterpreterFrame invokeSpecial(InterpreterFrame frame, char cpi) throws Throwable { - ResolvedJavaMethod m = resolveMethod(frame, Bytecodes.INVOKESPECIAL, cpi); - return invoke(frame, m, nullCheck(frame.peekReceiver(m))); - } - - private Object[] popArgumentsAsObject(InterpreterFrame frame, ResolvedJavaMethod method, boolean hasReceiver) { - Signature signature = method.getSignature(); - int argumentCount = method.getSignature().getParameterCount(hasReceiver); - Object[] parameters = new Object[argumentCount]; - - int lastSignatureIndex = hasReceiver ? 1 : 0; - for (int i = argumentCount - 1; i >= lastSignatureIndex; i--) { - ResolvedJavaType type = signature.getParameterType(i - lastSignatureIndex, method.getDeclaringClass()).resolve(method.getDeclaringClass()); - parameters[i] = popAsObject(frame, type.getKind()); - } - - if (hasReceiver) { - parameters[0] = frame.popObject(); - } - return parameters; - } - - private InterpreterFrame invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object receiver) throws Throwable { - if (caller.depth() >= maxStackFrames) { - throw new StackOverflowError("Maximum callstack of " + maxStackFrames + " exceeded."); - } - - if (Modifier.isNative(method.getModifiers())) { - return invokeNativeMethodViaVM(caller, method, receiver != null); - } else { - MethodRedirectionInfo redirectedMethod = methodDelegates.get(method); - if (redirectedMethod != null) { - return invokeRedirectedMethodViaVM(caller, method, redirectedMethod, receiver != null); - } else { - return invokeOptimized(caller, method, receiver != null); - } - } - } - - private InterpreterFrame invokeNativeMethodViaVM(InterpreterFrame caller, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable { - assert !methodDelegates.containsKey(method) : "must not be redirected"; - if (TRACE) { - traceCall(caller, "Native " + method); - } - - // mark the current thread as high level and execute the native method - Object[] parameters = popArgumentsAsObject(caller, method, hasReceiver); - Object returnValue = runtimeInterface.invoke(method, parameters); - pushAsObject(caller, method.getSignature().getReturnKind(), returnValue); - - return null; - } - - private InterpreterFrame invokeRedirectedMethodViaVM(InterpreterFrame caller, ResolvedJavaMethod originalMethod, MethodRedirectionInfo redirectionInfo, boolean hasReceiver) throws Throwable { - assert methodDelegates.containsKey(originalMethod) : "must be redirected"; - if (TRACE) { - traceCall(caller, "Delegate " + originalMethod); - } - - // current thread is low level and we also execute the target method in the low-level - // interpreter - Object[] originalCalleeParameters = popArgumentsAsObject(caller, originalMethod, hasReceiver); - Object[] parameters = new Object[]{caller, originalMethod, originalCalleeParameters}; - Object returnValue = redirectionInfo.getTargetMethod().invoke(redirectionInfo.getReceiver(), parameters); - pushAsObject(caller, originalMethod.getSignature().getReturnKind(), returnValue); - - return null; - } - - private InterpreterFrame invokeOptimized(InterpreterFrame parent, ResolvedJavaMethod method, boolean hasReceiver) throws Throwable { - return parent.create(method, hasReceiver); - } - - private Object allocateMultiArray(InterpreterFrame frame, char cpi, int dimension) { - ResolvedJavaType type = getLastDimensionType(resolveType(frame, Bytecodes.MULTIANEWARRAY, cpi)); - - int[] dimensions = new int[dimension]; - for (int i = dimension - 1; i >= 0; i--) { - dimensions[i] = frame.popInt(); - } - return Array.newInstance(mirror(type), dimensions); - } - - private ResolvedJavaType getLastDimensionType(ResolvedJavaType type) { - ResolvedJavaType result = type; - while (result.isArray()) { - result = result.getComponentType(); - } - return result; - } - - private Object allocateArray(InterpreterFrame frame, char cpi) { - ResolvedJavaType type = resolveType(frame, Bytecodes.ANEWARRAY, cpi); - return Array.newInstance(runtimeInterface.getMirror(type), frame.popInt()); - } - - private Object allocateNativeArray(InterpreterFrame frame, byte cpi) { - // the constants for the cpi are loosely defined and no real cpi indices. - switch (cpi) { - case 4: - return new byte[frame.popInt()]; - case 8: - return new byte[frame.popInt()]; - case 5: - return new char[frame.popInt()]; - case 7: - return new double[frame.popInt()]; - case 6: - return new float[frame.popInt()]; - case 10: - return new int[frame.popInt()]; - case 11: - return new long[frame.popInt()]; - case 9: - return new short[frame.popInt()]; - default: - assert false : "unexpected case"; - return null; - } - } - - private Object allocateInstance(InterpreterFrame frame, char cpi) throws InstantiationException { - return runtimeInterface.newObject(resolveType(frame, Bytecodes.NEW, cpi)); - } - - private void iinc(InterpreterFrame frame, BytecodeStream bs) { - int index = frame.resolveLocalIndex(bs.readLocalIndex()); - frame.setInt(index, frame.getInt(index) + bs.readIncrement()); - } - - private void putStatic(InterpreterFrame frame, char cpi) { - putFieldStatic(frame, resolveField(frame, Bytecodes.PUTSTATIC, cpi)); - } - - private void putField(InterpreterFrame frame, char cpi) { - putFieldVirtual(frame, resolveField(frame, Bytecodes.PUTFIELD, cpi)); - } - - private void putFieldStatic(InterpreterFrame frame, ResolvedJavaField field) { - switch (field.getKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - runtimeInterface.setFieldInt(frame.popInt(), null, field); - break; - case Double: - runtimeInterface.setFieldDouble(frame.popDouble(), null, field); - break; - case Float: - runtimeInterface.setFieldFloat(frame.popFloat(), null, field); - break; - case Long: - runtimeInterface.setFieldLong(frame.popLong(), null, field); - break; - case Object: - runtimeInterface.setFieldObject(frame.popObject(), null, field); - break; - default: - assert false : "unexpected case"; - } - } - - private void putFieldVirtual(InterpreterFrame frame, ResolvedJavaField field) { - switch (field.getKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - runtimeInterface.setFieldInt(frame.popInt(), nullCheck(frame.popObject()), field); - break; - case Double: - runtimeInterface.setFieldDouble(frame.popDouble(), nullCheck(frame.popObject()), field); - break; - case Float: - runtimeInterface.setFieldFloat(frame.popFloat(), nullCheck(frame.popObject()), field); - break; - case Long: - runtimeInterface.setFieldLong(frame.popLong(), nullCheck(frame.popObject()), field); - break; - case Object: - runtimeInterface.setFieldObject(frame.popObject(), nullCheck(frame.popObject()), field); - break; - default: - assert false : "unexpected case"; - } - } - - private void getField(InterpreterFrame frame, Object base, int opcode, char cpi) { - ResolvedJavaField field = resolveField(frame, opcode, cpi); - switch (field.getKind()) { - case Boolean: - frame.pushInt(runtimeInterface.getFieldBoolean(base, field) ? 1 : 0); - break; - case Byte: - frame.pushInt(runtimeInterface.getFieldByte(base, field)); - break; - case Char: - frame.pushInt(runtimeInterface.getFieldChar(base, field)); - break; - case Short: - frame.pushInt(runtimeInterface.getFieldShort(base, field)); - break; - case Int: - frame.pushInt(runtimeInterface.getFieldInt(base, field)); - break; - case Double: - frame.pushDouble(runtimeInterface.getFieldDouble(base, field)); - break; - case Float: - frame.pushFloat(runtimeInterface.getFieldFloat(base, field)); - break; - case Long: - frame.pushLong(runtimeInterface.getFieldLong(base, field)); - break; - case Object: - frame.pushObject(runtimeInterface.getFieldObject(base, field)); - break; - default: - assert false : "unexpected case"; - } - } - - private int pushAsObject(InterpreterFrame frame, Kind typeKind, Object value) { - switch (typeKind) { - case Int: - frame.pushInt((int) value); - break; - case Long: - frame.pushLong((long) value); - return 2; - case Boolean: - frame.pushInt(((boolean) value) ? 1 : 0); - break; - case Byte: - frame.pushInt((byte) value); - break; - case Char: - frame.pushInt((char) value); - break; - case Double: - frame.pushDouble((double) value); - return 2; - case Float: - frame.pushFloat((float) value); - break; - case Short: - frame.pushInt((short) value); - break; - case Object: - frame.pushObject(value); - break; - case Void: - return 0; - default: - assert false : "case not specified"; - } - return 1; - } - - private Object popAsObject(InterpreterFrame frame, Kind typeKind) { - switch (typeKind) { - case Boolean: - return frame.popInt() == 1 ? true : false; - case Byte: - return (byte) frame.popInt(); - case Char: - return (char) frame.popInt(); - case Double: - return frame.popDouble(); - case Int: - return frame.popInt(); - case Float: - return frame.popFloat(); - case Long: - return frame.popLong(); - case Short: - return (short) frame.popInt(); - case Object: - return frame.popObject(); - case Void: - return null; - default: - assert false : "unexpected case"; - } - return null; - } - - private ResolvedJavaMethod resolveRootMethod() { - try { - return metaAccessProvider.lookupJavaMethod(BytecodeInterpreter.class.getDeclaredMethod("execute", Method.class, Object[].class)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static Method findMethod(Class clazz, String name, Class... parameters) { - try { - return clazz.getDeclaredMethod(name, parameters); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - private static StackTraceElement[] createStackTraceElements(InterpreterFrame frame, RuntimeInterpreterInterface runtimeInterface) { - InterpreterFrame tmp = frame; - List elements = new ArrayList<>(); - boolean first = false; // filter only first stack elements - while (tmp != null) { - if (first || !filterStackElement(tmp, runtimeInterface)) { - first = true; - elements.add(tmp.getMethod().asStackTraceElement(tmp.getBCI())); - } - tmp = tmp.getParentFrame(); - } - return elements.toArray(new StackTraceElement[elements.size()]); - } - - private static boolean filterStackElement(InterpreterFrame frame, RuntimeInterpreterInterface runtimeInterface) { - return Throwable.class.isAssignableFrom(runtimeInterface.getMirror(frame.getMethod().getDeclaringClass())); - } - - private ResolvedJavaField findThrowableField(InterpreterFrame frame, String name) { - ResolvedJavaType throwableType = resolveType(frame, Throwable.class); - ResolvedJavaField[] fields = throwableType.getInstanceFields(false); - for (int i = 0; i < fields.length; i++) { - if (fields[i].getName().equals(name)) { - return fields[i]; - } - } - assert false; - return null; - } - - private class MethodRedirectionInfo { - - private InterpreterCallable receiver; - private Method method; - - public MethodRedirectionInfo(InterpreterCallable instance) { - this.receiver = instance; - this.method = resolveMethod(instance); - } - - public InterpreterCallable getReceiver() { - return receiver; - } - - public Method getTargetMethod() { - return method; - } - - private Method resolveMethod(InterpreterCallable instance) { - try { - return instance.getClass().getMethod(InterpreterCallable.INTERPRETER_CALLABLE_INVOKE_NAME, InterpreterCallable.INTERPRETER_CALLABLE_INVOKE_SIGNATURE); - } catch (NoSuchMethodException e) { - throw new InterpreterException(e); - } catch (SecurityException e) { - throw new InterpreterException(e); - } - } - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/Frame.java --- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/Frame.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.interpreter; - -import java.lang.reflect.*; - -import sun.misc.*; - -public class Frame { - - public static final Object[] EMPTY_ARRAY = new Object[0]; - public static final int PARENT_FRAME_SLOT = 0; - public static final int MIN_FRAME_SIZE = 1; - private static final Unsafe unsafe = getUnsafe(); - - protected final Object[] locals; - protected final long[] primitiveLocals; - - public Frame(int numLocals, Frame parent) { - assert numLocals >= MIN_FRAME_SIZE; - this.locals = new Object[numLocals]; - this.locals[PARENT_FRAME_SLOT] = parent; - this.primitiveLocals = new long[numLocals]; - } - - public Frame(int numLocals) { - this(numLocals, null); - } - - public Object getObject(int index) { - return locals[index]; - } - - public void setObject(int index, Object value) { - locals[index] = value; - } - - public float getFloat(int index) { - return unsafe.getFloat(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); - } - - public void setFloat(int index, float value) { - unsafe.putFloat(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); - } - - public long getLong(int index) { - return unsafe.getLong(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); - } - - public void setLong(int index, long value) { - unsafe.putLong(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); - } - - public int getInt(int index) { - return unsafe.getInt(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); - } - - public void setInt(int index, int value) { - unsafe.putInt(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); - } - - public double getDouble(int index) { - return unsafe.getDouble(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET); - } - - public void setDouble(int index, double value) { - unsafe.putDouble(primitiveLocals, (long) index * Unsafe.ARRAY_LONG_INDEX_SCALE + Unsafe.ARRAY_LONG_BASE_OFFSET, value); - } - - public static Frame getParentFrame(Frame frame, int level) { - assert level >= 0; - if (level == 0) { - return frame; - } else { - return getParentFrame((Frame) frame.getObject(PARENT_FRAME_SLOT), level - 1); - } - } - - public static Frame getTopFrame(Frame frame) { - Frame parentFrame = (Frame) frame.getObject(PARENT_FRAME_SLOT); - if (parentFrame == null) { - return frame; - } else { - return getTopFrame(parentFrame); - } - } - - public static Object[] getArguments(Frame frame, int argOffset) { - return (Object[]) frame.getObject(argOffset); - } - - public int size() { - return locals.length; - } - - @SuppressWarnings("unused") - private boolean indexExists(int index) { - return index >= 0 && index < locals.length; - } - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java --- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterCallable.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.interpreter; - -import com.oracle.graal.api.meta.*; - -public interface InterpreterCallable { - - // static final fields - String INTERPRETER_CALLABLE_INVOKE_NAME = "invoke"; - Class[] INTERPRETER_CALLABLE_INVOKE_SIGNATURE = {InterpreterFrame.class, ResolvedJavaMethod.class, Object[].class}; - - // methods - Object invoke(InterpreterFrame caller, ResolvedJavaMethod method, Object[] arguments) throws Throwable; -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterException.java --- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterException.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.interpreter; - -/** - * Thrown if executed byte code caused an error in {@link BytecodeInterpreter}. The actual execution - * exception is accessible using {@link #getCause()} or {@link #getExecutionThrowable()}. - */ -public class InterpreterException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - public InterpreterException(Throwable cause) { - super(cause); - } - - public Throwable getExecutionThrowable() { - return getCause(); - } - -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java --- a/graal/com.oracle.graal.interpreter/src/com/oracle/graal/interpreter/InterpreterFrame.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.interpreter; - -import java.util.*; - -import com.oracle.graal.api.meta.*; - -public class InterpreterFrame extends Frame { - - public static final int BASE_LENGTH = 3; - - private static final int METHOD_FRAME_SLOT = 1; - private static final int BCI_FRAME_SLOT = 2; - - private static final int DOUBLE = 2; - private static final int SINGLE = 1; - - /** Pointer to the top-most stack frame element. */ - private int depth; - private int tos; - - public InterpreterFrame(ResolvedJavaMethod method, int additionalStackSpace) { - this(method, null, additionalStackSpace, 0); - } - - private InterpreterFrame(ResolvedJavaMethod method, InterpreterFrame parent, int additionalStackSpace, int depth) { - super(method.getMaxLocals() + method.getMaxStackSize() + BASE_LENGTH + additionalStackSpace, parent); - setMethod(method); - setBCI(0); - this.depth = depth; - this.tos = BASE_LENGTH; - } - - public InterpreterFrame create(ResolvedJavaMethod method, boolean hasReceiver) { - InterpreterFrame frame = new InterpreterFrame(method, this, 0, this.depth + 1); - int length = method.getSignature().getParameterSlots(hasReceiver); - - frame.pushVoid(method.getMaxLocals()); - if (length > 0) { - copyArguments(frame, length); - popVoid(length); - } - - return frame; - } - - public int resolveLocalIndex(int index) { - return BASE_LENGTH + index; - } - - public int depth() { - return depth; - } - - private int stackTos() { - return BASE_LENGTH + getMethod().getMaxLocals(); - } - - private void copyArguments(InterpreterFrame dest, int length) { - System.arraycopy(locals, tosSingle(length - 1), dest.locals, BASE_LENGTH, length); - System.arraycopy(primitiveLocals, tosSingle(length - 1), dest.primitiveLocals, BASE_LENGTH, length); - } - - public Object peekReceiver(ResolvedJavaMethod method) { - return getObject(tosSingle(method.getSignature().getParameterSlots(false))); - } - - public void pushBoth(Object oValue, int intValue) { - incrementTos(SINGLE); - setObject(tosSingle(0), oValue); - setInt(tosSingle(0), intValue); - } - - public void pushBoth(Object oValue, long longValue) { - incrementTos(SINGLE); - setObject(tosSingle(0), oValue); - setLong(tosSingle(0), longValue); - } - - public void pushObject(Object value) { - incrementTos(SINGLE); - setObject(tosSingle(0), value); - } - - public void pushInt(int value) { - incrementTos(SINGLE); - setInt(tosSingle(0), value); - } - - public void pushDouble(double value) { - incrementTos(DOUBLE); - setDouble(tosDouble(0), value); - } - - public void pushFloat(float value) { - incrementTos(SINGLE); - setFloat(tosSingle(0), value); - } - - public void pushLong(long value) { - incrementTos(DOUBLE); - setLong(tosDouble(0), value); - } - - public int popInt() { - int value = getInt(tosSingle(0)); - decrementTos(SINGLE); - return value; - } - - public double popDouble() { - double value = getDouble(tosDouble(0)); - decrementTos(DOUBLE); - return value; - } - - public float popFloat() { - float value = getFloat(tosSingle(0)); - decrementTos(SINGLE); - return value; - } - - public long popLong() { - long value = getLong(tosDouble(0)); - decrementTos(DOUBLE); - return value; - } - - public Object popObject() { - Object value = getObject(tosSingle(0)); - decrementTos(SINGLE); - return value; - } - - public void swapSingle() { - int tmpInt = getInt(tosSingle(1)); - Object tmpObject = getObject(tosSingle(1)); - - setInt(tosSingle(1), getInt(tosSingle(0))); - setObject(tosSingle(1), getObject(tosSingle(0))); - - setInt(tosSingle(0), tmpInt); - setObject(tosSingle(0), tmpObject); - } - - public void dupx1() { - long tosLong = getLong(tosSingle(0)); - Object tosObject = getObject(tosSingle(0)); - - swapSingle(); - - pushBoth(tosObject, tosLong); - } - - public void dup2x1() { - long tosLong2 = getLong(tosSingle(2)); - Object tosObject2 = getObject(tosSingle(2)); - long tosLong1 = getLong(tosSingle(1)); - Object tosObject1 = getObject(tosSingle(1)); - long tosLong0 = getLong(tosSingle(0)); - Object tosObject0 = getObject(tosSingle(0)); - - popVoid(3); - - pushBoth(tosObject1, tosLong1); - pushBoth(tosObject0, tosLong0); - - pushBoth(tosObject2, tosLong2); - - pushBoth(tosObject1, tosLong1); - pushBoth(tosObject0, tosLong0); - } - - public void dup2x2() { - long tosLong3 = getLong(tosSingle(3)); - Object tosObject3 = getObject(tosSingle(3)); - long tosLong2 = getLong(tosSingle(2)); - Object tosObject2 = getObject(tosSingle(2)); - long tosLong1 = getLong(tosSingle(1)); - Object tosObject1 = getObject(tosSingle(1)); - long tosLong0 = getLong(tosSingle(0)); - Object tosObject0 = getObject(tosSingle(0)); - - popVoid(4); - - pushBoth(tosObject1, tosLong1); - pushBoth(tosObject0, tosLong0); - - pushBoth(tosObject3, tosLong3); - pushBoth(tosObject2, tosLong2); - - pushBoth(tosObject1, tosLong1); - pushBoth(tosObject0, tosLong0); - } - - public void dupx2() { - long tosLong2 = getLong(tosSingle(2)); - Object tosObject2 = getObject(tosSingle(2)); - long tosLong1 = getLong(tosSingle(1)); - Object tosObject1 = getObject(tosSingle(1)); - long tosLong0 = getLong(tosSingle(0)); - Object tosObject0 = getObject(tosSingle(0)); - - popVoid(3); - - pushBoth(tosObject0, tosLong0); - pushBoth(tosObject2, tosLong2); - pushBoth(tosObject1, tosLong1); - pushBoth(tosObject0, tosLong0); - } - - public void dup(int length) { - assert length > 0; - for (int i = 0; i < length; i++) { - long valueN1 = getLong(tosSingle(length - i - 1)); - Object valueO1 = getObject(tosSingle(length - i - 1)); - - pushVoid(1); - - setLong(tosSingle(0), valueN1); - setObject(tosSingle(0), valueO1); - } - } - - private void incrementTos(int size) { - tos += size; - } - - private void decrementTos(int size) { - assert tos - size >= stackTos(); - tos -= size; - } - - private int tosDouble(int offset) { - assert offset >= 0; - return tos - DOUBLE - (offset * DOUBLE); - } - - private int tosSingle(int offset) { - assert offset >= 0; - return tos - SINGLE - offset; - } - - public int getStackTop() { - return tos; - } - - public void pushVoid(int count) { - incrementTos(count * SINGLE); - } - - public void popVoid(int count) { - decrementTos(count * SINGLE); - } - - public ConstantPool getConstantPool() { - return getMethod().getConstantPool(); - } - - private void setMethod(ResolvedJavaMethod method) { - setObject(METHOD_FRAME_SLOT, method); - } - - public ResolvedJavaMethod getMethod() { - return (ResolvedJavaMethod) getObject(METHOD_FRAME_SLOT); - } - - public void setBCI(int bci) { - setInt(BCI_FRAME_SLOT, bci); - } - - public int getBCI() { - return getInt(BCI_FRAME_SLOT); - } - - public void pushTo(InterpreterFrame childFrame, int argumentSlots) { - System.arraycopy(locals, tos - argumentSlots, childFrame.locals, InterpreterFrame.MIN_FRAME_SIZE, argumentSlots); - - System.arraycopy(primitiveLocals, tos - argumentSlots, childFrame.primitiveLocals, InterpreterFrame.MIN_FRAME_SIZE, argumentSlots); - popVoid(argumentSlots); - } - - public InterpreterFrame getParentFrame() { - return (InterpreterFrame) getObject(PARENT_FRAME_SLOT); - } - - public void dispose() { - // Clear out references in locals array. - Arrays.fill(locals, null); - } - - @Override - public String toString() { - ResolvedJavaMethod method = getMethod(); - StringBuilder b = new StringBuilder(getMethod().asStackTraceElement(getBCI()).toString()); - for (int i = 0; i < tos; i++) { - Object object = getObject(tosSingle(i)); - long primitive = getLong(tosSingle(i)); - - String objectString = null; - if (object != null) { - objectString = object.getClass().getSimpleName() + "@" + Integer.toHexString(object.hashCode()); - } - String primitiveString = "0x" + Long.toHexString(primitive).toUpperCase(); - String typeString; - - int index = tosSingle(i); - if (index == METHOD_FRAME_SLOT) { - typeString = "method"; - } else if (index == BCI_FRAME_SLOT) { - typeString = "bci"; - } else if (index == PARENT_FRAME_SLOT) { - typeString = "parent"; - } else if (index < BASE_LENGTH + method.getMaxLocals()) { - typeString = "var " + (index - BASE_LENGTH); - } else { - typeString = "local"; - } - b.append(String.format("%n [%d] %7s Primitive: %10s Object: %s", index, typeString, primitiveString, objectString)); - } - if (getParentFrame() != null) { - b.append("\n").append(getParentFrame().toString()); - } - return b.toString(); - } - - public void popStack() { - // TODO(chumer): prevent popping local variables. - popVoid(tos - stackTos()); - } - -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -708,7 +708,8 @@ if (type instanceof ResolvedJavaType) { ResolvedJavaType resolvedType = (ResolvedJavaType) type; InstanceOfNode instanceOfNode = new InstanceOfNode((ResolvedJavaType) type, object, getProfileForTypeCheck(resolvedType)); - frameState.ipush(append(MaterializeNode.create(currentGraph.unique(instanceOfNode)))); + ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph))); + frameState.ipush(append(conditional)); } else { BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); @@ -765,7 +766,7 @@ private void genNewPrimitiveArray(int typeCode) { Class clazz = arrayTypeCodeToClass(typeCode); ResolvedJavaType elementType = runtime.lookupJavaType(clazz); - NewPrimitiveArrayNode nta = currentGraph.add(new NewPrimitiveArrayNode(elementType, frameState.ipop(), true, false)); + NewArrayNode nta = currentGraph.add(new NewArrayNode(elementType, frameState.ipop(), true, false)); frameState.apush(append(nta)); } @@ -773,7 +774,7 @@ JavaType type = lookupType(cpi, ANEWARRAY); ValueNode length = frameState.ipop(); if (type instanceof ResolvedJavaType) { - NewArrayNode n = currentGraph.add(new NewObjectArrayNode((ResolvedJavaType) type, length, true, false)); + NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false)); frameState.apush(append(n)); } else { append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); @@ -1143,6 +1144,19 @@ return true; } + /** + * Helper function that sums up the probabilities of all keys that lead to a specific successor. + * + * @return an array of size successorCount with the accumulated probability for each successor. + */ + private static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { + double[] probability = new double[successorCount]; + for (int i = 0; i < keySuccessors.length; i++) { + probability[keySuccessors[i]] += keyProbabilities[i]; + } + return probability; + } + private void genSwitch(BytecodeSwitch bs) { int bci = bci(); ValueNode value = frameState.ipop(); @@ -1185,7 +1199,7 @@ } } - double[] successorProbabilities = IntegerSwitchNode.successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); + double[] successorProbabilities = successorProbabilites(actualSuccessors.size(), keySuccessors, keyProbabilities); IntegerSwitchNode switchNode = currentGraph.add(new IntegerSwitchNode(value, actualSuccessors.size(), keys, keyProbabilities, keySuccessors)); for (int i = 0; i < actualSuccessors.size(); i++) { switchNode.setBlockSuccessor(i, createBlockTarget(successorProbabilities[i], actualSuccessors.get(i), frameState)); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,76 @@ +/* + * 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.lir.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.asm.*; + +//@formatter:off +public class AMD64TestOp extends AMD64LIRInstruction { + + @Use({REG}) protected Value x; + @Use({REG, STACK, CONST}) protected Value y; + + public AMD64TestOp(Value x, Value y) { + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + emit(tasm, masm, x, y); + } + + @Override + protected void verify() { + super.verify(); + assert (x.getKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (x.getKind() == Kind.Long && y.getKind() == Kind.Long) : x + " " + y; + } + + public static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value x, Value y) { + if (isRegister(y)) { + switch (x.getKind()) { + case Int: masm.testl(asIntReg(x), asIntReg(y)); break; + case Long: masm.testq(asLongReg(x), asLongReg(y)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else if (isConstant(y)) { + switch (x.getKind()) { + case Int: masm.testl(asIntReg(x), tasm.asIntConst(y)); break; + case Long: masm.testq(asLongReg(x), tasm.asIntConst(y)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } else { + switch (x.getKind()) { + case Int: masm.testl(asIntReg(x), tasm.asIntAddr(y)); break; + case Long: masm.testq(asLongReg(x), tasm.asLongAddr(y)); break; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCLIRInstruction.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,40 @@ +/* + * 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.lir.sparc; + +import com.oracle.graal.asm.sparc.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.asm.*; + +/** + * Convenience class to provide AMD64MacroAssembler for the {@link #emitCode} method. + */ +public abstract class SPARCLIRInstruction extends LIRInstruction { + + @Override + public final void emitCode(TargetMethodAssembler tasm) { + emitCode(tasm, (SPARCAssembler) tasm.asm); + } + + public abstract void emitCode(TargetMethodAssembler tasm, SPARCAssembler masm); +} diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -191,7 +191,7 @@ return false; } if (trueValue.isConstant() && falseValue.isConstant()) { - MaterializeNode materialize = MaterializeNode.create(condition(), trueValue, falseValue); + ConditionalNode materialize = graph().unique(new ConditionalNode(condition(), trueValue, falseValue)); ((StructuredGraph) graph()).replaceFloating(singlePhi, materialize); removeEmptyIf(tool); return true; @@ -323,6 +323,7 @@ } } assert !ends.hasNext(); + assert falseEnds.size() + trueEnds.size() == xs.length; connectEnds(falseEnds, phiValues, oldFalseSuccessor, merge, tool); connectEnds(trueEnds, phiValues, oldTrueSuccessor, merge, tool); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MaterializeNode.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes; - -import static com.oracle.graal.nodes.calc.CompareNode.*; - -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.java.*; - -public final class MaterializeNode extends ConditionalNode { - - private MaterializeNode(Condition condition, ValueNode x, ValueNode y) { - this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph())); - } - - private MaterializeNode(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) { - super(condition, trueValue, falseValue); - } - - private MaterializeNode(ValueNode type, ValueNode object) { - super(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph())); - } - - public static MaterializeNode create(BooleanNode condition, ValueNode trueValue, ValueNode falseValue) { - Graph graph = condition.graph(); - MaterializeNode result = new MaterializeNode(condition, trueValue, falseValue); - return graph.unique(result); - - } - - public static MaterializeNode create(BooleanNode condition) { - return create(condition, ConstantNode.forInt(1, condition.graph()), ConstantNode.forInt(0, condition.graph())); - } - - @NodeIntrinsic - public static native boolean materialize(@ConstantNodeParameter Condition condition, int x, int y); - - @NodeIntrinsic - public static native boolean materialize(@ConstantNodeParameter Condition condition, long x, long y); - - @NodeIntrinsic - public static native boolean isInstance(Class mirror, Object object); -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -22,15 +22,18 @@ */ package com.oracle.graal.nodes.calc; +import static com.oracle.graal.nodes.calc.CompareNode.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.spi.*; /** * The {@code ConditionalNode} class represents a comparison that yields one of two values. Note * that these nodes are not built directly from the bytecode but are introduced by canonicalization. */ -public class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable { +public final class ConditionalNode extends BinaryNode implements Canonicalizable, LIRLowerable, Negatable { @Input private BooleanNode condition; @@ -44,6 +47,11 @@ this.condition = condition; } + @Override + public boolean inferStamp() { + return updateStamp(x().stamp().meet(y().stamp())); + } + public ValueNode trueValue() { return x(); } @@ -91,4 +99,21 @@ ((StructuredGraph) graph()).replaceFloating(this, replacement); return replacement; } + + private ConditionalNode(Condition condition, ValueNode x, ValueNode y) { + this(createCompareNode(condition, x, y), ConstantNode.forInt(1, x.graph()), ConstantNode.forInt(0, x.graph())); + } + + private ConditionalNode(ValueNode type, ValueNode object) { + this(type.graph().add(new InstanceOfDynamicNode(type, object)), ConstantNode.forInt(1, type.graph()), ConstantNode.forInt(0, type.graph())); + } + + @NodeIntrinsic + public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, int x, int y); + + @NodeIntrinsic + public static native boolean materializeCondition(@ConstantNodeParameter Condition condition, long x, long y); + + @NodeIntrinsic + public static native boolean materializeIsInstance(Class mirror, Object object); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -74,6 +74,12 @@ } else if (x().integerStamp().alwaysDistinct(y().integerStamp())) { return ConstantNode.forBoolean(false, graph()); } + + if (x() instanceof AndNode && y().isConstant() && y().asConstant().asLong() == 0) { + return graph().unique(new IntegerTestNode(((AndNode) x()).x(), ((AndNode) x()).y())); + } else if (y() instanceof AndNode && x().isConstant() && x().asConstant().asLong() == 0) { + return graph().unique(new IntegerTestNode(((AndNode) y()).x(), ((AndNode) y()).y())); + } return super.canonical(tool); } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.calc; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +public class IntegerTestNode extends BooleanNode implements Canonicalizable, LIRLowerable { + + @Input private ValueNode x; + @Input private ValueNode y; + + public ValueNode x() { + return x; + } + + public ValueNode y() { + return y; + } + + /** + * Constructs a new Test instruction. + * + * @param x the instruction producing the first input to the instruction + * @param y the instruction that produces the second input to this instruction + */ + public IntegerTestNode(ValueNode x, ValueNode y) { + super(StampFactory.condition()); + assert (x == null && y == null) || x.kind() == y.kind(); + this.x = x; + this.y = y; + } + + @Override + public void generate(LIRGeneratorTool gen) { + } + + public ValueNode canonical(CanonicalizerTool tool) { + if (x().isConstant() && y().isConstant()) { + return ConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph()); + } + if ((x().integerStamp().mask() & y().integerStamp().mask()) == 0) { + return ConstantNode.forBoolean(true, graph()); + } + return this; + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NormalizeCompareNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -61,8 +61,8 @@ lessComp = graph.unique(new IntegerLessThanNode(x(), y())); } - MaterializeNode equalValue = MaterializeNode.create(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph)); - MaterializeNode value = MaterializeNode.create(lessComp, ConstantNode.forInt(-1, graph), equalValue); + ConditionalNode equalValue = graph.unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph), ConstantNode.forInt(1, graph))); + ConditionalNode value = graph.unique(new ConditionalNode(lessComp, ConstantNode.forInt(-1, graph), equalValue)); graph.replaceFloating(this, value); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IntegerSwitchNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -49,7 +49,7 @@ * @param keySuccessors the successor index for each key */ public IntegerSwitchNode(ValueNode value, BeginNode[] successors, int[] keys, double[] keyProbabilities, int[] keySuccessors) { - super(value, successors, successorProbabilites(successors.length, keySuccessors, keyProbabilities), keySuccessors, keyProbabilities); + super(value, successors, keySuccessors, keyProbabilities); assert keySuccessors.length == keys.length + 1; assert keySuccessors.length == keyProbabilities.length; this.keys = keys; diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SwitchNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -35,7 +35,6 @@ public abstract class SwitchNode extends ControlSplitNode { @Successor protected final NodeSuccessorList successors; - protected double[] successorProbabilities; @Input private ValueNode value; private double[] keyProbabilities; private int[] keySuccessors; @@ -46,9 +45,8 @@ * @param value the instruction that provides the value to be switched over * @param successors the list of successors of this switch */ - public SwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, int[] keySuccessors, double[] keyProbabilities) { + public SwitchNode(ValueNode value, BeginNode[] successors, int[] keySuccessors, double[] keyProbabilities) { super(StampFactory.forVoid()); - this.successorProbabilities = successorProbabilities; assert keySuccessors.length == keyProbabilities.length; this.successors = new NodeSuccessorList<>(this, successors); this.value = value; @@ -59,9 +57,9 @@ @Override public double probability(BeginNode successor) { double sum = 0; - for (int i = 0; i < successors.size(); i++) { - if (successors.get(i) == successor) { - sum += successorProbabilities[i]; + for (int i = 0; i < keySuccessors.length; i++) { + if (successors.get(keySuccessors[i]) == successor) { + sum += keyProbabilities[i]; } } return sum; @@ -133,23 +131,9 @@ return defaultSuccessorIndex() == -1 ? null : successors.get(defaultSuccessorIndex()); } - /** - * Helper function that sums up the probabilities of all keys that lead to a specific successor. - * - * @return an array of size successorCount with the accumulated probability for each successor. - */ - public static double[] successorProbabilites(int successorCount, int[] keySuccessors, double[] keyProbabilities) { - double[] probability = new double[successorCount]; - for (int i = 0; i < keySuccessors.length; i++) { - probability[keySuccessors[i]] += keyProbabilities[i]; - } - return probability; - } - @Override public SwitchNode clone(Graph into) { SwitchNode newSwitch = (SwitchNode) super.clone(into); - newSwitch.successorProbabilities = Arrays.copyOf(successorProbabilities, successorProbabilities.length); newSwitch.keyProbabilities = Arrays.copyOf(keyProbabilities, keyProbabilities.length); newSwitch.keySuccessors = Arrays.copyOf(keySuccessors, keySuccessors.length); return newSwitch; diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/MethodCallTargetNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -131,10 +131,6 @@ return this; } - public JavaType returnType() { - return returnType; - } - @Override public Stamp returnStamp() { Kind returnKind = targetMethod.getSignature().getReturnKind(); @@ -145,6 +141,10 @@ } } + public JavaType returnType() { + return returnType; + } + @Override public String targetName() { if (targetMethod() == null) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewArrayNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -23,15 +23,16 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.virtual.*; /** - * The {@code NewArrayNode} class is the base of all instructions that allocate arrays. + * The {@code NewArrayNode} is used for all 1-dimensional array allocations. */ -public abstract class NewArrayNode extends FixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation, ArrayLengthProvider { +public class NewArrayNode extends FixedWithNextNode implements Canonicalizable, Lowerable, VirtualizableAllocation, ArrayLengthProvider, Node.IterableNodeType { @Input private ValueNode length; private final ResolvedJavaType elementType; @@ -53,7 +54,7 @@ * @param fillContents determines whether the array elements should be initialized to zero/null. * @param locked determines whether the array should be locked immediately. */ - protected NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) { + public NewArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) { super(StampFactory.exactNonNull(elementType.getArrayClass())); this.length = length; this.elementType = elementType; @@ -123,7 +124,7 @@ for (int i = 0; i < constantLength; i++) { state[i] = defaultForKind; } - VirtualObjectNode virtualObject = new VirtualArrayNode(tool.getNextVirtualId(), elementType, constantLength); + VirtualObjectNode virtualObject = new VirtualArrayNode(elementType, constantLength); tool.createVirtualObject(virtualObject, state, 0); tool.replaceWithVirtual(virtualObject); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewInstanceNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -100,7 +100,7 @@ for (int i = 0; i < state.length; i++) { state[i] = ConstantNode.defaultForKind(fields[i].getType().getKind(), graph()); } - VirtualObjectNode virtualObject = new VirtualInstanceNode(tool.getNextVirtualId(), instanceClass(), fields); + VirtualObjectNode virtualObject = new VirtualInstanceNode(instanceClass(), fields); tool.createVirtualObject(virtualObject, state, 0); tool.replaceWithVirtual(virtualObject); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewObjectArrayNode.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; - -/** - * The {@code NewObjectArrayNode} represents an allocation of an object array. - */ -@NodeInfo(nameTemplate = "NewArray {p#elementType}") -public final class NewObjectArrayNode extends NewArrayNode implements Node.IterableNodeType { - - /** - * Constructs a new NewObjectArrayNode. - * - * @param elementClass the class of elements in this array - * @param length the node producing the length of the array - * @param fillContents determines whether the array elements should be initialized to null. - * @param locked determines whether the array should be locked immediately. - */ - public NewObjectArrayNode(ResolvedJavaType elementClass, ValueNode length, boolean fillContents, boolean locked) { - super(elementClass, length, fillContents, locked); - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewPrimitiveArrayNode.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.java; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; - -/** - * The {@code NewPrimitiveArrayNode} class definition. - */ -@NodeInfo(nameTemplate = "NewArray {p#elementType}") -public final class NewPrimitiveArrayNode extends NewArrayNode implements Node.IterableNodeType { - - /** - * Constructs a new NewPrimitiveArrayNode. - * - * @param elementType the type of elements in this array - * @param length the node producing the length of the array - * @param fillContents determines whether the array elements should be initialized to zero. - * @param locked determines whether the array should be locked immediately. - */ - public NewPrimitiveArrayNode(ResolvedJavaType elementType, ValueNode length, boolean fillContents, boolean locked) { - super(elementType, length, fillContents, locked); - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeSwitchNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -44,14 +44,14 @@ * Constructs a type switch instruction. The keyProbabilities array contain key.length + 1 * entries. The last entry in every array describes the default case. * - * @param value the instruction producing the value being switched on + * @param value the instruction producing the value being switched on, the object hub * @param successors the list of successors * @param keys the list of types * @param keyProbabilities the probabilities of the keys * @param keySuccessors the successor index for each key */ - public TypeSwitchNode(ValueNode value, BeginNode[] successors, double[] successorProbabilities, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { - super(value, successors, successorProbabilities, keySuccessors, keyProbabilities); + public TypeSwitchNode(ValueNode value, BeginNode[] successors, ResolvedJavaType[] keys, double[] keyProbabilities, int[] keySuccessors) { + super(value, successors, keySuccessors, keyProbabilities); assert successors.length <= keys.length + 1; assert keySuccessors.length == keyProbabilities.length; this.keys = keys; @@ -63,8 +63,12 @@ } @Override - public Constant keyAt(int i) { - return keys[i].getEncoding(Representation.ObjectHub); + public Constant keyAt(int index) { + return keys[index].getEncoding(Representation.ObjectHub); + } + + public ResolvedJavaType typeAt(int index) { + return keys[index]; } @Override @@ -134,8 +138,6 @@ } } - double[] newSuccessorProbabilities = successorProbabilites(newSuccessors.size(), newKeySuccessors, newKeyProbabilities); - for (int i = 0; i < blockSuccessorCount(); i++) { BeginNode successor = blockSuccessor(i); if (!newSuccessors.contains(successor)) { @@ -145,7 +147,7 @@ } BeginNode[] successorsArray = newSuccessors.toArray(new BeginNode[newSuccessors.size()]); - TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newSuccessorProbabilities, newKeys, newKeyProbabilities, newKeySuccessors)); + TypeSwitchNode newSwitch = graph().add(new TypeSwitchNode(value(), successorsArray, newKeys, newKeyProbabilities, newKeySuccessors)); ((FixedWithNextNode) predecessor()).setNext(newSwitch); GraphUtil.killWithUnusedFloatingInputs(this); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/VirtualizerTool.java Mon Feb 11 10:41:29 2013 +0100 @@ -50,11 +50,6 @@ */ int getMaximumEntryCount(); - /** - * @return the next id for virtual objects (can be used for the VirtualObject constructor). - */ - int getNextVirtualId(); - // methods working on virtualized/materialized objects /** diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/util/GraphUtil.java Mon Feb 11 10:41:29 2013 +0100 @@ -232,7 +232,7 @@ RuntimeException exception = new RuntimeException(cause.getMessage(), cause) { @Override - public synchronized Throwable fillInStackTrace() { + public final synchronized Throwable fillInStackTrace() { setStackTrace(elements); return this; } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/BoxedVirtualObjectNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -33,8 +33,7 @@ private final ResolvedJavaType type; private final Kind kind; - public BoxedVirtualObjectNode(int virtualId, ResolvedJavaType type, Kind kind, ValueNode unboxedValue) { - super(virtualId); + public BoxedVirtualObjectNode(ResolvedJavaType type, Kind kind, ValueNode unboxedValue) { this.type = type; this.kind = kind; this.unboxedValue = unboxedValue; diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualArrayNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -34,8 +34,7 @@ private final ResolvedJavaType componentType; private final int length; - public VirtualArrayNode(long virtualId, ResolvedJavaType componentType, int length) { - super(virtualId); + public VirtualArrayNode(ResolvedJavaType componentType, int length) { this.componentType = componentType; this.length = length; } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualInstanceNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -34,8 +34,7 @@ private final ResolvedJavaField[] fields; private final HashMap fieldMap = new HashMap<>(); - public VirtualInstanceNode(long virtualId, ResolvedJavaType type, ResolvedJavaField[] fields) { - super(virtualId); + public VirtualInstanceNode(ResolvedJavaType type, ResolvedJavaField[] fields) { this.type = type; this.fields = fields; for (int i = 0; i < fields.length; i++) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/virtual/VirtualObjectNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -25,28 +25,20 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @NodeInfo(nameTemplate = "VirtualObject {p#type}") -public abstract class VirtualObjectNode extends FloatingNode implements LIRLowerable { - - private final long virtualId; +public abstract class VirtualObjectNode extends ValueNode implements LIRLowerable { - public VirtualObjectNode(long virtualId) { + public VirtualObjectNode() { super(StampFactory.virtual()); - this.virtualId = virtualId; } public abstract ResolvedJavaType type(); public abstract int entryCount(); - public long virtualId() { - return virtualId; - } - @Override public void generate(LIRGeneratorTool gen) { // nothing to do... diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/BoxingEliminationPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -38,7 +38,6 @@ public class BoxingEliminationPhase extends Phase { private final MetaAccessProvider metaAccess; - private int virtualIds = Integer.MIN_VALUE; public BoxingEliminationPhase(MetaAccessProvider metaAccess) { this.metaAccess = metaAccess; @@ -113,7 +112,7 @@ } } - private void tryEliminate(BoxNode boxNode) { + private static void tryEliminate(BoxNode boxNode) { assert boxNode.objectStamp().isExactType(); virtualizeUsages(boxNode, boxNode.source(), boxNode.objectStamp().type(), boxNode.getSourceKind()); @@ -130,12 +129,12 @@ ((StructuredGraph) boxNode.graph()).removeFixed(boxNode); } - private void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) { + private static void virtualizeUsages(ValueNode boxNode, ValueNode replacement, ResolvedJavaType exactType, Kind sourceKind) { ValueNode virtualValueNode = null; VirtualObjectNode virtualObjectNode = null; for (Node n : boxNode.usages().filter(NodePredicates.isA(VirtualState.class)).snapshot()) { if (virtualValueNode == null) { - virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(virtualIds++, exactType, sourceKind, replacement)); + virtualObjectNode = n.graph().unique(new BoxedVirtualObjectNode(exactType, sourceKind, replacement)); } n.replaceFirstInput(boxNode, virtualObjectNode); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/CanonicalizerPhase.java diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ComputeProbabilityPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -60,63 +60,9 @@ computeLoopFactors(); Debug.dump(graph, "After computeLoopFactors"); new PropagateLoopFrequency(graph.start()).apply(); - - if (GraalOptions.LoopFrequencyPropagationPolicy < 0) { - ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false); - BitSet visitedBlocks = new BitSet(cfg.getBlocks().length); - for (Loop loop : cfg.getLoops()) { - if (loop.parent == null) { - correctLoopFrequencies(loop, 1, visitedBlocks); - } - } - } - new ComputeInliningRelevanceIterator(graph).apply(); } - private void correctLoopFrequencies(Loop loop, double parentFrequency, BitSet visitedBlocks) { - LoopBeginNode loopBegin = ((LoopBeginNode) loop.header.getBeginNode()); - double frequency = parentFrequency * loopBegin.loopFrequency(); - if (frequency < 1) { - frequency = 1; - } - for (Loop child : loop.children) { - correctLoopFrequencies(child, frequency, visitedBlocks); - } - - double factor = getCorrectionFactor(loopBegin.probability(), frequency); - for (Block block : loop.blocks) { - int blockId = block.getId(); - if (!visitedBlocks.get(blockId)) { - visitedBlocks.set(blockId); - - FixedNode node = block.getBeginNode(); - while (node != block.getEndNode()) { - node.setProbability(node.probability() * factor); - node = ((FixedWithNextNode) node).next(); - } - node.setProbability(node.probability() * factor); - } - } - } - - private static double getCorrectionFactor(double probability, double frequency) { - switch (GraalOptions.LoopFrequencyPropagationPolicy) { - case -1: - return 1 / frequency; - case -2: - return (1 / frequency) * (Math.log(Math.E + frequency) - 1); - case -3: - double originalProbability = probability / frequency; - assert isRelativeProbability(originalProbability); - return (1 / frequency) * Math.max(1, Math.pow(originalProbability, 1.5) * Math.log10(frequency)); - case -4: - return 1 / probability; - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - private void computeLoopFactors() { for (LoopInfo info : loopInfos) { double frequency = info.loopFrequency(); @@ -330,124 +276,184 @@ private class PropagateLoopFrequency extends PostOrderNodeIterator { - private final FrequencyPropagationPolicy policy; - public PropagateLoopFrequency(FixedNode start) { super(start, new LoopCount(1d)); - this.policy = createFrequencyPropagationPolicy(); } @Override protected void node(FixedNode node) { - node.setProbability(policy.compute(node.probability(), state.count)); + node.setProbability(node.probability() * state.count); } } - private static FrequencyPropagationPolicy createFrequencyPropagationPolicy() { - switch (GraalOptions.LoopFrequencyPropagationPolicy) { - case -4: - case -3: - case -2: - case -1: - case 0: - return new FullFrequencyPropagation(); - case 1: - return new NoFrequencyPropagation(); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - private interface FrequencyPropagationPolicy { - - double compute(double probability, double frequency); - } - - private static class FullFrequencyPropagation implements FrequencyPropagationPolicy { - - @Override - public double compute(double probability, double frequency) { - return probability * frequency; - } - } - - private static class NoFrequencyPropagation implements FrequencyPropagationPolicy { - - @Override - public double compute(double probability, double frequency) { - return probability; - } - } - private static class ComputeInliningRelevanceIterator extends ScopedPostOrderNodeIterator { - private final HashMap lowestPathProbabilities; + private final HashMap scopes; private double currentProbability; + private double parentRelevance; public ComputeInliningRelevanceIterator(StructuredGraph graph) { super(graph); - this.lowestPathProbabilities = computeLowestPathProbabilities(graph); + this.scopes = computeLowestPathProbabilities(computeScopeInformation(graph)); } @Override protected void initializeScope() { - currentProbability = lowestPathProbabilities.get(currentScope); + Scope scope = scopes.get(currentScopeStart); + parentRelevance = getParentScopeRelevance(scope); + currentProbability = scope.minPathProbability; + } + + private static double getParentScopeRelevance(Scope scope) { + if (scope.start instanceof LoopBeginNode) { + assert scope.parent != null; + double parentProbability = 0; + for (EndNode end : ((LoopBeginNode) scope.start).forwardEnds()) { + parentProbability += end.probability(); + } + return parentProbability / scope.parent.minPathProbability; + } else { + assert scope.parent == null; + return 1.0; + } } @Override protected void invoke(Invoke invoke) { assert !Double.isNaN(invoke.probability()); - invoke.setInliningRelevance(invoke.probability() / currentProbability); + invoke.setInliningRelevance((invoke.probability() / currentProbability) * Math.min(1.0, parentRelevance)); + assert !Double.isNaN(invoke.inliningRelevance()); } - private HashMap computeLowestPathProbabilities(StructuredGraph graph) { - HashMap result = new HashMap<>(); - Deque scopes = getScopes(graph); + private static Scope[] computeScopeInformation(StructuredGraph graph) { + ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, false, false); + + Loop[] loops = cfg.getLoops(); + HashMap processedScopes = new HashMap<>(); + Scope[] scopes = new Scope[loops.length + 1]; + Scope methodScope = new Scope(graph.start(), null); + processedScopes.put(null, methodScope); + + scopes[0] = methodScope; + for (int i = 0; i < loops.length; i++) { + scopes[i + 1] = createScope(loops[i], processedScopes); + } + + return scopes; + } - while (!scopes.isEmpty()) { - FixedNode scopeBegin = scopes.pop(); - double probability = computeLowestPathProbability(scopeBegin); - result.put(scopeBegin, probability); + private static Scope createScope(Loop loop, HashMap processedLoops) { + Scope parent = processedLoops.get(loop.parent); + if (parent == null) { + parent = createScope(loop, processedLoops); + } + Scope result = new Scope(loop.loopBegin(), parent); + processedLoops.put(loop, result); + return result; + } + + private static HashMap computeLowestPathProbabilities(Scope[] scopes) { + HashMap result = new HashMap<>(); + + for (Scope scope : scopes) { + double lowestPathProbability = computeLowestPathProbability(scope); + scope.minPathProbability = Math.max(EPSILON, lowestPathProbability); + result.put(scope.start, scope); } return result; } - private static double computeLowestPathProbability(FixedNode scopeStart) { + private static double computeLowestPathProbability(Scope scope) { + FixedNode scopeStart = scope.start; + ArrayList pathBeginNodes = new ArrayList<>(); + pathBeginNodes.add(scopeStart); double minPathProbability = scopeStart.probability(); - Node current = scopeStart; + boolean isLoopScope = scopeStart instanceof LoopBeginNode; - while (current != null) { - if (current.successors().count() > 1) { - assert current instanceof ControlSplitNode; - ControlSplitNode controlSplit = (ControlSplitNode) current; - current = getMaxProbabilitySux(controlSplit); - if (((FixedNode) current).probability() < minPathProbability) { - minPathProbability = ((FixedNode) current).probability(); + do { + Node current = pathBeginNodes.remove(pathBeginNodes.size() - 1); + do { + if (isLoopScope && current instanceof LoopExitNode && ((LoopBeginNode) scopeStart).loopExits().contains((LoopExitNode) current)) { + return minPathProbability; + } else if (current instanceof LoopBeginNode && current != scopeStart) { + current = getMaxProbabilityLoopExit((LoopBeginNode) current, pathBeginNodes); + minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability); + } else if (current instanceof ControlSplitNode) { + current = getMaxProbabilitySux((ControlSplitNode) current, pathBeginNodes); + minPathProbability = getMinPathProbability((FixedNode) current, minPathProbability); + } else { + assert current.successors().count() <= 1; + current = current.successors().first(); } - } else { - current = current.successors().first(); - } - } + } while (current != null); + } while (!pathBeginNodes.isEmpty()); return minPathProbability; } - private static Node getMaxProbabilitySux(ControlSplitNode controlSplit) { + private static double getMinPathProbability(FixedNode current, double minPathProbability) { + if (current != null && current.probability() < minPathProbability) { + return current.probability(); + } + return minPathProbability; + } + + private static Node getMaxProbabilitySux(ControlSplitNode controlSplit, ArrayList pathBeginNodes) { Node maxSux = null; double maxProbability = 0.0; + int pathBeginCount = pathBeginNodes.size(); - // TODO: process recursively if we have multiple successors with same probability for (Node sux : controlSplit.successors()) { double probability = controlSplit.probability((BeginNode) sux); if (probability > maxProbability) { maxProbability = probability; maxSux = sux; + truncate(pathBeginNodes, pathBeginCount); + } else if (probability == maxProbability) { + pathBeginNodes.add((FixedNode) sux); } } return maxSux; } + + private static Node getMaxProbabilityLoopExit(LoopBeginNode loopBegin, ArrayList pathBeginNodes) { + Node maxSux = null; + double maxProbability = 0.0; + int pathBeginCount = pathBeginNodes.size(); + + for (LoopExitNode sux : loopBegin.loopExits()) { + double probability = sux.probability(); + if (probability > maxProbability) { + maxProbability = probability; + maxSux = sux; + truncate(pathBeginNodes, pathBeginCount); + } else if (probability == maxProbability) { + pathBeginNodes.add(sux); + } + } + + return maxSux; + } + + public static void truncate(ArrayList pathBeginNodes, int pathBeginCount) { + for (int i = pathBeginNodes.size() - pathBeginCount; i > 0; i--) { + pathBeginNodes.remove(pathBeginNodes.size() - 1); + } + } + } + + private static class Scope { + + public final FixedNode start; + public final Scope parent; + public double minPathProbability; + + public Scope(FixedNode start, Scope parent) { + this.start = start; + this.parent = parent; + } } } diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -38,16 +39,24 @@ public class ConditionalEliminationPhase extends Phase { - private static final DebugMetric metricInstanceOfRegistered = Debug.metric("InstanceOfRegistered"); - private static final DebugMetric metricNullCheckRegistered = Debug.metric("NullCheckRegistered"); + private static final DebugMetric metricConditionRegistered = Debug.metric("ConditionRegistered"); + private static final DebugMetric metricTypeRegistered = Debug.metric("TypeRegistered"); + private static final DebugMetric metricNullnessRegistered = Debug.metric("NullnessRegistered"); + private static final DebugMetric metricObjectEqualsRegistered = Debug.metric("ObjectEqualsRegistered"); private static final DebugMetric metricCheckCastRemoved = Debug.metric("CheckCastRemoved"); private static final DebugMetric metricInstanceOfRemoved = Debug.metric("InstanceOfRemoved"); private static final DebugMetric metricNullCheckRemoved = Debug.metric("NullCheckRemoved"); - private static final DebugMetric metricNullCheckGuardRemoved = Debug.metric("NullCheckGuardRemoved"); - private static final DebugMetric metricGuardsReplaced = Debug.metric("GuardsReplaced"); + private static final DebugMetric metricObjectEqualsRemoved = Debug.metric("ObjectEqualsRemoved"); + private static final DebugMetric metricGuardsRemoved = Debug.metric("GuardsRemoved"); + + private final MetaAccessProvider metaAccessProvider; private StructuredGraph graph; + public ConditionalEliminationPhase(MetaAccessProvider metaAccessProvider) { + this.metaAccessProvider = metaAccessProvider; + } + @Override protected void run(StructuredGraph inputGraph) { graph = inputGraph; @@ -57,14 +66,14 @@ public static class State implements MergeableState { private IdentityHashMap knownTypes; - private HashSet knownNotNull; + private HashSet knownNonNull; private HashSet knownNull; private IdentityHashMap trueConditions; private IdentityHashMap falseConditions; public State() { this.knownTypes = new IdentityHashMap<>(); - this.knownNotNull = new HashSet<>(); + this.knownNonNull = new HashSet<>(); this.knownNull = new HashSet<>(); this.trueConditions = new IdentityHashMap<>(); this.falseConditions = new IdentityHashMap<>(); @@ -72,7 +81,7 @@ public State(State other) { this.knownTypes = new IdentityHashMap<>(other.knownTypes); - this.knownNotNull = new HashSet<>(other.knownNotNull); + this.knownNonNull = new HashSet<>(other.knownNonNull); this.knownNull = new HashSet<>(other.knownNull); this.trueConditions = new IdentityHashMap<>(other.trueConditions); this.falseConditions = new IdentityHashMap<>(other.falseConditions); @@ -81,11 +90,16 @@ @Override public boolean merge(MergeNode merge, List withStates) { IdentityHashMap newKnownTypes = new IdentityHashMap<>(); - HashSet newKnownNotNull = new HashSet<>(); - HashSet newKnownNull = new HashSet<>(); IdentityHashMap newTrueConditions = new IdentityHashMap<>(); IdentityHashMap newFalseConditions = new IdentityHashMap<>(); + HashSet newKnownNull = new HashSet<>(knownNull); + HashSet newKnownNonNull = new HashSet<>(knownNonNull); + for (State state : withStates) { + newKnownNull.retainAll(state.knownNull); + newKnownNonNull.retainAll(state.knownNonNull); + } + for (Map.Entry entry : knownTypes.entrySet()) { ValueNode node = entry.getKey(); ResolvedJavaType type = entry.getValue(); @@ -101,30 +115,7 @@ newKnownTypes.put(node, type); } } - for (ValueNode node : knownNotNull) { - boolean notNull = true; - for (State other : withStates) { - if (!other.knownNotNull.contains(node)) { - notNull = false; - break; - } - } - if (notNull) { - newKnownNotNull.add(node); - } - } - for (ValueNode node : knownNull) { - boolean isNull = true; - for (State other : withStates) { - if (!other.knownNull.contains(node)) { - isNull = false; - break; - } - } - if (isNull) { - newKnownNull.add(node); - } - } + for (Map.Entry entry : trueConditions.entrySet()) { BooleanNode check = entry.getKey(); ValueNode guard = entry.getValue(); @@ -162,14 +153,13 @@ } } - // this piece of code handles phis (merges the types and knownNull/knownNotNull of the - // values) + // this piece of code handles phis if (!(merge instanceof LoopBeginNode)) { for (PhiNode phi : merge.phis()) { if (phi.type() == PhiType.Value && phi.kind() == Kind.Object) { ValueNode firstValue = phi.valueAt(0); ResolvedJavaType type = getNodeType(firstValue); - boolean notNull = knownNotNull.contains(firstValue); + boolean nonNull = knownNonNull.contains(firstValue); boolean isNull = knownNull.contains(firstValue); for (int i = 0; i < withStates.size(); i++) { @@ -177,14 +167,14 @@ ValueNode value = phi.valueAt(i + 1); ResolvedJavaType otherType = otherState.getNodeType(value); type = widen(type, otherType); - notNull &= otherState.knownNotNull.contains(value); + nonNull &= otherState.knownNonNull.contains(value); isNull &= otherState.knownNull.contains(value); } if (type != null) { newKnownTypes.put(phi, type); } - if (notNull) { - newKnownNotNull.add(phi); + if (nonNull) { + newKnownNonNull.add(phi); } if (isNull) { newKnownNull.add(phi); @@ -194,7 +184,7 @@ } this.knownTypes = newKnownTypes; - this.knownNotNull = newKnownNotNull; + this.knownNonNull = newKnownNonNull; this.knownNull = newKnownNull; this.trueConditions = newTrueConditions; this.falseConditions = newFalseConditions; @@ -206,6 +196,14 @@ return result == null ? node.objectStamp().type() : result; } + public boolean isNull(ValueNode value) { + return value.objectStamp().alwaysNull() || knownNull.contains(value); + } + + public boolean isNonNull(ValueNode value) { + return value.objectStamp().nonNull() || knownNonNull.contains(value); + } + @Override public void loopBegin(LoopBeginNode loopBegin) { } @@ -222,6 +220,52 @@ public State clone() { return new State(this); } + + /** + * Adds information about a condition. If isTrue is true then the condition is known to + * hold, otherwise the condition is known not to hold. + */ + public void addCondition(boolean isTrue, BooleanNode condition, ValueNode anchor) { + if (isTrue) { + if (!trueConditions.containsKey(condition)) { + trueConditions.put(condition, anchor); + metricConditionRegistered.increment(); + } + } else { + if (!falseConditions.containsKey(condition)) { + falseConditions.put(condition, anchor); + metricConditionRegistered.increment(); + } + } + } + + /** + * Adds information about the nullness of a value. If isNull is true then the value is known + * to be null, otherwise the value is known to be non-null. + */ + public void addNullness(boolean isNull, ValueNode value) { + if (isNull) { + if (!isNull(value)) { + metricNullnessRegistered.increment(); + knownNull.add(value); + } + } else { + if (!isNonNull(value)) { + metricNullnessRegistered.increment(); + knownNonNull.add(value); + } + } + } + + public void addType(ResolvedJavaType type, ValueNode value) { + ResolvedJavaType knownType = getNodeType(value); + ResolvedJavaType newType = tighten(type, knownType); + + if (newType != knownType) { + knownTypes.put(value, newType); + metricTypeRegistered.increment(); + } + } } public static ResolvedJavaType widen(ResolvedJavaType a, ResolvedJavaType b) { @@ -241,8 +285,6 @@ return a; } else if (a == b) { return a; - } else if (b.isAssignableFrom(a)) { - return a; } else if (a.isAssignableFrom(b)) { return b; } else { @@ -252,131 +294,219 @@ public class ConditionalElimination extends PostOrderNodeIterator { - private BeginNode lastBegin = null; + private final BooleanNode trueConstant; + private final BooleanNode falseConstant; public ConditionalElimination(FixedNode start, State initialState) { super(start, initialState); + this.trueConstant = ConstantNode.forBoolean(true, graph); + this.falseConstant = ConstantNode.forBoolean(false, graph); + } + + private void registerCondition(boolean isTrue, BooleanNode condition, ValueNode 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(true, y); + } else if (!state.isNonNull(x) && state.isNull(y)) { + metricObjectEqualsRegistered.increment(); + state.addNullness(true, x); + } + } + } + } + + private void registerControlSplitInfo(Node pred, BeginNode begin) { + assert pred != null && begin != null; + + if (pred instanceof IfNode) { + IfNode ifNode = (IfNode) pred; + + if (!(ifNode.condition() instanceof ConstantNode)) { + registerCondition(begin == ifNode.trueSuccessor(), ifNode.condition(), begin); + } + } else if (pred instanceof TypeSwitchNode) { + TypeSwitchNode typeSwitch = (TypeSwitchNode) pred; + + if (typeSwitch.value() instanceof LoadHubNode) { + LoadHubNode loadHub = (LoadHubNode) typeSwitch.value(); + ResolvedJavaType type = null; + for (int i = 0; i < typeSwitch.keyCount(); i++) { + if (typeSwitch.keySuccessor(i) == begin) { + if (type == null) { + type = typeSwitch.typeAt(i); + } else { + type = widen(type, typeSwitch.typeAt(i)); + } + } + } + if (type != null) { + state.addNullness(false, loadHub.object()); + state.addType(type, loadHub.object()); + } + } + } + } + + private void registerGuard(GuardNode guard) { + BooleanNode condition = guard.condition(); + + ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition); + if (existingGuards != null) { + guard.replaceAtUsages(existingGuards); + GraphUtil.killWithUnusedFloatingInputs(guard); + metricGuardsRemoved.increment(); + } else { + BooleanNode replacement = evaluateCondition(condition, trueConstant, falseConstant); + if (replacement != null) { + guard.setCondition(replacement); + if (condition.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(condition); + } + metricGuardsRemoved.increment(); + } else { + registerCondition(!guard.negated(), condition, guard); + } + } + } + + /** + * Determines if, at the current point in the control flow, the condition is known to be + * true, false or unknown. In case of true or false the corresponding value is returned, + * otherwise null. + */ + private T evaluateCondition(BooleanNode condition, T trueValue, T falseValue) { + if (state.trueConditions.containsKey(condition)) { + return trueValue; + } else if (state.falseConditions.containsKey(condition)) { + return falseValue; + } else { + if (condition instanceof InstanceOfNode) { + InstanceOfNode instanceOf = (InstanceOfNode) condition; + ValueNode object = instanceOf.object(); + if (state.isNull(object)) { + metricInstanceOfRemoved.increment(); + return falseValue; + } else if (state.isNonNull(object)) { + ResolvedJavaType type = state.getNodeType(object); + if (type != null && instanceOf.type().isAssignableFrom(type)) { + metricInstanceOfRemoved.increment(); + return trueValue; + } + } + } else if (condition instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) condition; + ValueNode object = isNull.object(); + if (state.isNull(object)) { + metricNullCheckRemoved.increment(); + return trueValue; + } else if (state.isNonNull(object)) { + metricNullCheckRemoved.increment(); + return falseValue; + } + } else if (condition instanceof ObjectEqualsNode) { + ObjectEqualsNode equals = (ObjectEqualsNode) condition; + ValueNode x = equals.x(); + ValueNode y = equals.y(); + if (state.isNull(x) && state.isNonNull(y) || state.isNonNull(x) && state.isNull(y)) { + metricObjectEqualsRemoved.increment(); + return falseValue; + } else if (state.isNull(x) && state.isNull(y)) { + metricObjectEqualsRemoved.increment(); + return trueValue; + } + } + } + return null; } @Override protected void node(FixedNode node) { if (node instanceof BeginNode) { BeginNode begin = (BeginNode) node; - lastBegin = begin; Node pred = node.predecessor(); - if (pred != null && pred instanceof IfNode) { - IfNode ifNode = (IfNode) pred; - if (!(ifNode.condition() instanceof ConstantNode)) { - boolean isTrue = (node == ifNode.trueSuccessor()); - if (isTrue) { - state.trueConditions.put(ifNode.condition(), begin); - } else { - state.falseConditions.put(ifNode.condition(), begin); - } - } - if (ifNode.condition() instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition(); - if ((node == ifNode.trueSuccessor())) { - ValueNode object = instanceOf.object(); - state.knownNotNull.add(object); - state.knownTypes.put(object, tighten(instanceOf.type(), state.getNodeType(object))); - metricInstanceOfRegistered.increment(); - } - } else if (ifNode.condition() instanceof IsNullNode) { - IsNullNode nullCheck = (IsNullNode) ifNode.condition(); - boolean isNull = (node == ifNode.trueSuccessor()); - if (isNull) { - state.knownNull.add(nullCheck.object()); - } else { - state.knownNotNull.add(nullCheck.object()); - } - metricNullCheckRegistered.increment(); - } + + if (pred != null) { + registerControlSplitInfo(pred, begin); } for (GuardNode guard : begin.guards().snapshot()) { - BooleanNode condition = guard.condition(); - ValueNode existingGuards = guard.negated() ? state.falseConditions.get(condition) : state.trueConditions.get(condition); - if (existingGuards != null) { - guard.replaceAtUsages(existingGuards); - GraphUtil.killWithUnusedFloatingInputs(guard); - metricGuardsReplaced.increment(); - } else { - boolean removeCheck = false; - if (condition instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) condition; - if (guard.negated() && state.knownNotNull.contains(isNull.object())) { - removeCheck = true; - } else if (!guard.negated() && state.knownNull.contains(isNull.object())) { - removeCheck = true; - } - if (removeCheck) { - metricNullCheckGuardRemoved.increment(); - } - } - if (removeCheck) { - guard.replaceAtUsages(begin); - GraphUtil.killWithUnusedFloatingInputs(guard); - } else { - if (guard.negated()) { - state.falseConditions.put(condition, guard); - } else { - state.trueConditions.put(condition, guard); - } - } - } + registerGuard(guard); } } else if (node instanceof CheckCastNode) { CheckCastNode checkCast = (CheckCastNode) node; - ResolvedJavaType type = state.getNodeType(checkCast.object()); - if (type != null && checkCast.type().isAssignableFrom(type)) { + ValueNode object = checkCast.object(); + boolean isNull = state.isNull(object); + ResolvedJavaType type = state.getNodeType(object); + if (isNull || (type != null && checkCast.type().isAssignableFrom(type))) { + boolean nonNull = state.isNonNull(object); + ValueAnchorNode anchor = graph.add(new ValueAnchorNode()); PiNode piNode; - boolean nonNull = state.knownNotNull.contains(checkCast.object()); - piNode = graph.unique(new PiNode(checkCast.object(), lastBegin, nonNull ? StampFactory.declaredNonNull(type) : StampFactory.declared(type))); + if (isNull) { + ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph); + piNode = graph.unique(new PiNode(nullObject, anchor, StampFactory.forConstant(nullObject.value, metaAccessProvider))); + } else { + piNode = graph.unique(new PiNode(object, anchor, StampFactory.declared(type, nonNull))); + } checkCast.replaceAtUsages(piNode); - graph.removeFixed(checkCast); + graph.replaceFixedWithFixed(checkCast, anchor); metricCheckCastRemoved.increment(); } } else if (node instanceof IfNode) { IfNode ifNode = (IfNode) node; - BooleanNode replaceWith = null; BooleanNode compare = ifNode.condition(); + BooleanNode replacement = evaluateCondition(compare, trueConstant, falseConstant); - if (state.trueConditions.containsKey(compare)) { - replaceWith = ConstantNode.forBoolean(true, graph); - } else if (state.falseConditions.containsKey(compare)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } else { - if (compare instanceof InstanceOfNode) { - InstanceOfNode instanceOf = (InstanceOfNode) compare; - ValueNode object = instanceOf.object(); - if (state.knownNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } else if (state.knownNotNull.contains(object)) { - ResolvedJavaType type = state.getNodeType(object); - if (type != null && instanceOf.type().isAssignableFrom(type)) { - replaceWith = ConstantNode.forBoolean(true, graph); + if (replacement != null) { + ifNode.setCondition(replacement); + if (compare.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(compare); + } + } + } else if (node instanceof EndNode) { + EndNode endNode = (EndNode) node; + for (PhiNode phi : endNode.merge().phis()) { + int index = endNode.merge().phiPredecessorIndex(endNode); + ValueNode value = phi.valueAt(index); + if (value instanceof ConditionalNode) { + ConditionalNode materialize = (ConditionalNode) value; + BooleanNode compare = materialize.condition(); + ValueNode replacement = evaluateCondition(compare, materialize.trueValue(), materialize.falseValue()); + + if (replacement != null) { + phi.setValueAt(index, replacement); + if (materialize.usages().isEmpty()) { + GraphUtil.killWithUnusedFloatingInputs(materialize); } } - if (replaceWith != null) { - metricInstanceOfRemoved.increment(); - } - } else if (compare instanceof IsNullNode) { - IsNullNode isNull = (IsNullNode) compare; - ValueNode object = isNull.object(); - if (state.knownNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(true, graph); - } else if (state.knownNotNull.contains(object)) { - replaceWith = ConstantNode.forBoolean(false, graph); - } - if (replaceWith != null) { - metricNullCheckRemoved.increment(); - } - } - } - if (replaceWith != null) { - ifNode.setCondition(replaceWith); - if (compare.usages().isEmpty()) { - GraphUtil.killWithUnusedFloatingInputs(compare); } } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -73,6 +73,7 @@ return "Map=" + lastMemorySnapshot.toString() + " Loops=" + loops.toString(); } + @SuppressWarnings("unchecked") @Override public boolean merge(MergeNode merge, List withStates) { if (withStates.size() == 0) { @@ -106,7 +107,6 @@ keys.add(key); } } - @SuppressWarnings("unchecked") IdentityHashMap newMemorySnapshot = (IdentityHashMap) lastMemorySnapshot.clone(); for (Object key : keys) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GlobalValueNumberingPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GlobalValueNumberingPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.phases.common; - -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; - -public class GlobalValueNumberingPhase extends Phase { - - public static final DebugMetric metricGlobalValueNumberingHits = Debug.metric("GlobalValueNumberingHits"); - - @Override - protected void run(StructuredGraph graph) { - NodeBitMap visited = graph.createNodeBitMap(); - for (Node n : graph.getNodes()) { - apply(n, visited, graph); - } - } - - private void apply(Node n, NodeBitMap visited, StructuredGraph compilerGraph) { - if (!visited.isMarked(n)) { - visited.mark(n); - for (Node input : n.inputs()) { - apply(input, visited, compilerGraph); - } - if (n.getNodeClass().valueNumberable()) { - Node newNode = compilerGraph.findDuplicate(n); - if (newNode != null) { - assert !(n instanceof FixedNode || newNode instanceof FixedNode); - n.replaceAtUsages(newNode); - n.safeDelete(); - metricGlobalValueNumberingHits.increment(); - Debug.log("GVN applied and new node is %1s", newNode); - } - } - } - } -} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -32,9 +32,11 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; -import com.oracle.graal.phases.PhasePlan.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; import com.oracle.graal.phases.common.CanonicalizerPhase.CustomCanonicalizer; -import com.oracle.graal.phases.common.InliningUtil.*; +import com.oracle.graal.phases.common.InliningUtil.InlineInfo; +import com.oracle.graal.phases.common.InliningUtil.InliningCallback; +import com.oracle.graal.phases.common.InliningUtil.InliningPolicy; public class InliningPhase extends Phase implements InliningCallback { @@ -52,6 +54,7 @@ private final Assumptions assumptions; private final GraphCache cache; private final InliningPolicy inliningPolicy; + private final OptimisticOptimizations optimisticOpts; private CustomCanonicalizer customCanonicalizer; // Metrics @@ -62,20 +65,22 @@ public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Collection hints, Assumptions assumptions, GraphCache cache, PhasePlan plan, OptimisticOptimizations optimisticOpts) { - this(target, runtime, assumptions, cache, plan, createInliningPolicy(assumptions, optimisticOpts, hints)); + this(target, runtime, assumptions, cache, plan, createInliningPolicy(runtime, assumptions, optimisticOpts, hints), optimisticOpts); } public void setCustomCanonicalizer(CustomCanonicalizer customCanonicalizer) { this.customCanonicalizer = customCanonicalizer; } - public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy) { + public InliningPhase(TargetDescription target, GraalCodeCacheProvider runtime, Assumptions assumptions, GraphCache cache, PhasePlan plan, InliningPolicy inliningPolicy, + OptimisticOptimizations optimisticOpts) { this.target = target; this.runtime = runtime; this.assumptions = assumptions; this.cache = cache; this.plan = plan; this.inliningPolicy = inliningPolicy; + this.optimisticOpts = optimisticOpts; } @Override @@ -96,14 +101,12 @@ candidate.inline(graph, runtime, this, assumptions); Debug.dump(graph, "after %s", candidate); Iterable newNodes = graph.getNewNodes(mark); + inliningPolicy.scanInvokes(newNodes); if (GraalOptions.OptCanonicalizer) { new CanonicalizerPhase(target, runtime, assumptions, invokeUsages, mark, customCanonicalizer).apply(graph); } metricInliningPerformed.increment(); - - inliningPolicy.scanInvokes(newNodes); } catch (BailoutException bailout) { - // TODO determine if we should really bail out of the whole compilation. throw bailout; } catch (AssertionError e) { throw new GraalInternalError(e).addContext(candidate.toString()); @@ -112,6 +115,8 @@ } catch (GraalInternalError e) { throw e.addContext(candidate.toString()); } + } else if (optimisticOpts.devirtualizeInvokes()) { + candidate.tryToDevirtualizeInvoke(graph, runtime, assumptions); } } } @@ -153,171 +158,174 @@ boolean isWorthInlining(InlineInfo info); } - private abstract static class AbstractInliningDecision implements InliningDecision { - - protected static boolean decideSizeBasedInlining(InlineInfo info, double maxSize) { - assert !Double.isNaN(info.weight()) && !Double.isNaN(maxSize); - boolean success = info.weight() <= maxSize; - if (GraalOptions.Debug) { - String formatterString = success ? "(size %f <= %f)" : "(too large %f > %f)"; - InliningUtil.logInliningDecision(info, success, formatterString, info.weight(), maxSize); - } - return success; - } + private static class GreedySizeBasedInliningDecision implements InliningDecision { - protected static boolean checkCompiledCodeSize(InlineInfo info) { - if (GraalOptions.SmallCompiledCodeSize >= 0 && info.compiledCodeSize() > GraalOptions.SmallCompiledCodeSize) { - InliningUtil.logNotInlinedMethod(info, "(CompiledCodeSize %d > %d)", info.compiledCodeSize(), GraalOptions.SmallCompiledCodeSize); - return false; - } - return true; - } - - protected static double getRelevance(Invoke invoke) { - if (GraalOptions.UseRelevanceBasedInlining) { - return invoke.inliningRelevance(); - } else { - return invoke.probability(); - } - } - } - - private static class C1StaticSizeBasedInliningDecision extends AbstractInliningDecision { - - @Override - public boolean isWorthInlining(InlineInfo info) { - double maxSize = Math.max(GraalOptions.MaximumTrivialSize, Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize); - return decideSizeBasedInlining(info, maxSize); - } - } + private final GraalCodeCacheProvider runtime; + private final Collection hints; - private static class MinimumCodeSizeBasedInliningDecision extends AbstractInliningDecision { - - @Override - public boolean isWorthInlining(InlineInfo info) { - assert GraalOptions.ProbabilityAnalysis; - if (!checkCompiledCodeSize(info)) { - return false; - } - - double inlineWeight = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke())); - double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize * inlineWeight; - maxSize = Math.max(GraalOptions.MaximumTrivialSize, maxSize); - - return decideSizeBasedInlining(info, maxSize); + public GreedySizeBasedInliningDecision(GraalCodeCacheProvider runtime, Collection hints) { + this.runtime = runtime; + this.hints = hints; } - } - - private static class DynamicSizeBasedInliningDecision extends AbstractInliningDecision { - - @Override - public boolean isWorthInlining(InlineInfo info) { - assert GraalOptions.ProbabilityAnalysis; - if (!checkCompiledCodeSize(info)) { - return false; - } - - double relevance = getRelevance(info.invoke()); - double inlineBoost = Math.min(GraalOptions.RatioCapForInlining, relevance) + Math.log10(Math.max(1, relevance - GraalOptions.RatioCapForInlining + 1)); - double maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * GraalOptions.MaximumInlineSize; - maxSize = maxSize + maxSize * inlineBoost; - maxSize = Math.min(GraalOptions.MaximumGreedyInlineSize, Math.max(GraalOptions.MaximumTrivialSize, maxSize)); - - return decideSizeBasedInlining(info, maxSize); - } - } - - private static class GreedySizeBasedInliningDecision extends AbstractInliningDecision { @Override public boolean isWorthInlining(InlineInfo info) { assert GraalOptions.ProbabilityAnalysis; - if (!checkCompiledCodeSize(info)) { - return false; + /* + * TODO (chaeubl): invoked methods that are on important paths but not yet compiled -> + * will be compiled anyways and it is likely that we are the only caller... might be + * useful to inline those methods but increases bootstrap time (maybe those methods are + * also getting queued in the compilation queue concurrently) + */ + + if (GraalOptions.AlwaysInlineIntrinsics && onlyIntrinsics(info)) { + return InliningUtil.logInlinedMethod(info, "intrinsic"); } - double maxSize = GraalOptions.MaximumGreedyInlineSize; - if (GraalOptions.InliningBonusPerTransferredValue != 0) { - Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature(); - int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers())); - if (signature.getReturnKind() != Kind.Void) { - transferredValues++; + int bytecodeSize = bytecodeCodeSize(info); + int complexity = compilationComplexity(info); + int compiledCodeSize = compiledCodeSize(info); + double relevance = info.invoke().inliningRelevance(); + + /* + * as long as the compiled code size is small enough (or the method was not yet + * compiled), we can do a pretty general inlining that suits most situations + */ + if (compiledCodeSize < GraalOptions.SmallCompiledCodeSize) { + if (isTrivialInlining(bytecodeSize, complexity, compiledCodeSize)) { + return InliningUtil.logInlinedMethod(info, "trivial (bytecodes=%d, complexity=%d, codeSize=%d)", bytecodeSize, complexity, compiledCodeSize); } - maxSize += transferredValues * GraalOptions.InliningBonusPerTransferredValue; + + if (canInlineRelevanceBased(relevance, bytecodeSize, complexity, compiledCodeSize)) { + return InliningUtil.logInlinedMethod(info, "relevance-based (relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d)", relevance, bytecodeSize, complexity, compiledCodeSize); + } } - double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke())); - maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio; - maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize); + /* + * the normal inlining did not fit this invoke, so check if we have any reason why we + * should still do the inlining + */ + double probability = info.invoke().probability(); + int transferredValues = numberOfTransferredValues(info); + int invokeUsages = countInvokeUsages(info); + int moreSpecificArguments = countMoreSpecificArgumentInfo(info); + int level = info.level(); + boolean preferredInvoke = hints != null && hints.contains(info.invoke()); - return decideSizeBasedInlining(info, maxSize); + // TODO (chaeubl): compute metric that is used to check if this method should be inlined + + return InliningUtil.logNotInlinedMethod(info, + "(relevance=%f, bytecodes=%d, complexity=%d, codeSize=%d, probability=%f, transferredValues=%d, invokeUsages=%d, moreSpecificArguments=%d, level=%d, preferred=%b)", + relevance, bytecodeSize, complexity, compiledCodeSize, probability, transferredValues, invokeUsages, moreSpecificArguments, level, preferredInvoke); } - } + + private static boolean isTrivialInlining(int bytecodeSize, int complexity, int compiledCodeSize) { + return bytecodeSize < GraalOptions.TrivialBytecodeSize || complexity < GraalOptions.TrivialComplexity || compiledCodeSize > 0 && compiledCodeSize < GraalOptions.TrivialCompiledCodeSize; + } - private static class GreedyMachineCodeInliningDecision extends AbstractInliningDecision { + private static boolean canInlineRelevanceBased(double relevance, int bytecodeSize, int complexity, int compiledCodeSize) { + return bytecodeSize < computeMaximumSize(relevance, GraalOptions.NormalBytecodeSize) || complexity < computeMaximumSize(relevance, GraalOptions.NormalComplexity) || compiledCodeSize > 0 && + compiledCodeSize < computeMaximumSize(relevance, GraalOptions.NormalCompiledCodeSize); + } - @Override - public boolean isWorthInlining(InlineInfo info) { - assert GraalOptions.ProbabilityAnalysis; + private static double computeMaximumSize(double relevance, int configuredMaximum) { + double inlineRatio = Math.min(GraalOptions.RelevanceCapForInlining, relevance); + return configuredMaximum * inlineRatio; + } + + private static int numberOfTransferredValues(InlineInfo info) { + Signature signature = info.invoke().methodCallTarget().targetMethod().getSignature(); + int transferredValues = signature.getParameterCount(!Modifier.isStatic(info.invoke().methodCallTarget().targetMethod().getModifiers())); + if (signature.getReturnKind() != Kind.Void) { + transferredValues++; + } + return transferredValues; + } - double maxSize = GraalOptions.MaximumGreedyInlineSize; - double inlineRatio = Math.min(GraalOptions.RatioCapForInlining, getRelevance(info.invoke())); - maxSize = Math.pow(GraalOptions.NestedInliningSizeRatio, info.level()) * maxSize * inlineRatio; - maxSize = Math.max(maxSize, GraalOptions.MaximumTrivialSize); - - return decideSizeBasedInlining(info, maxSize); + private static int countInvokeUsages(InlineInfo info) { + // inlining calls with lots of usages simplifies the caller + int usages = 0; + for (Node n : info.invoke().node().usages()) { + if (!(n instanceof FrameState)) { + usages++; + } + } + return usages; } - } - private static class BytecodeSizeBasedWeightComputationPolicy implements WeightComputationPolicy { + private int countMoreSpecificArgumentInfo(InlineInfo info) { + /* + * inlining invokes where the caller has very specific information about the passed + * argument simplifies the callee + */ + int moreSpecificArgumentInfo = 0; + boolean isStatic = info.invoke().methodCallTarget().isStatic(); + int signatureOffset = isStatic ? 0 : 1; + NodeInputList arguments = info.invoke().methodCallTarget().arguments(); + ResolvedJavaMethod targetMethod = info.invoke().methodCallTarget().targetMethod(); + ResolvedJavaType methodHolderClass = targetMethod.getDeclaringClass(); + Signature signature = targetMethod.getSignature(); - @Override - public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { - if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) { - return 0; + for (int i = 0; i < arguments.size(); i++) { + Node n = arguments.get(i); + if (n instanceof ConstantNode) { + moreSpecificArgumentInfo++; + } else if (n instanceof ValueNode && !((ValueNode) n).kind().isPrimitive()) { + ResolvedJavaType actualType = ((ValueNode) n).stamp().javaType(runtime); + JavaType declaredType; + if (i == 0 && !isStatic) { + declaredType = methodHolderClass; + } else { + declaredType = signature.getParameterType(i - signatureOffset, methodHolderClass); + } + + if (declaredType instanceof ResolvedJavaType && !actualType.equals(declaredType) && ((ResolvedJavaType) declaredType).isAssignableFrom(actualType)) { + moreSpecificArgumentInfo++; + } + } + } - double codeSize = method.getCodeSize(); - if (preferredInvoke) { - codeSize = codeSize / GraalOptions.BoostInliningForEscapeAnalysis; - } - return codeSize; + return moreSpecificArgumentInfo; } - } - private static class ComplexityBasedWeightComputationPolicy implements WeightComputationPolicy { - - @Override - public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { - if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) { - return 0; + private static int bytecodeCodeSize(InlineInfo info) { + int result = 0; + for (int i = 0; i < info.numberOfMethods(); i++) { + result += info.methodAt(i).getCodeSize(); } + return result; + } - double complexity = method.getCompilationComplexity(); - if (preferredInvoke) { - complexity = complexity / GraalOptions.BoostInliningForEscapeAnalysis; + private static int compilationComplexity(InlineInfo info) { + int result = 0; + for (int i = 0; i < info.numberOfMethods(); i++) { + result += info.methodAt(i).getCompilationComplexity(); } - return complexity; + return result; } - } - private static class CompiledCodeSizeWeightComputationPolicy implements WeightComputationPolicy { + private static int compiledCodeSize(InlineInfo info) { + int result = 0; + for (int i = 0; i < info.numberOfMethods(); i++) { + result += info.methodAt(i).getCompiledCodeSize(); + } + return result; + } - @Override - public double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke) { - if (GraalOptions.AlwaysInlineIntrinsics && InliningUtil.canIntrinsify(method)) { - return 0; + private static boolean onlyIntrinsics(InlineInfo info) { + for (int i = 0; i < info.numberOfMethods(); i++) { + if (!InliningUtil.canIntrinsify(info.methodAt(i))) { + return false; + } } - - int compiledCodeSize = method.getCompiledCodeSize(); - return compiledCodeSize > 0 ? compiledCodeSize : method.getCodeSize() * 10; + return true; } } private static class CFInliningPolicy implements InliningPolicy { private final InliningDecision inliningDecision; - private final WeightComputationPolicy weightComputationPolicy; private final Collection hints; private final Assumptions assumptions; private final OptimisticOptimizations optimisticOpts; @@ -325,10 +333,8 @@ private NodeBitMap visitedFixedNodes; private FixedNode invokePredecessor; - public CFInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection hints, Assumptions assumptions, - OptimisticOptimizations optimisticOpts) { + public CFInliningPolicy(InliningDecision inliningPolicy, Collection hints, Assumptions assumptions, OptimisticOptimizations optimisticOpts) { this.inliningDecision = inliningPolicy; - this.weightComputationPolicy = weightComputationPolicy; this.hints = hints; this.assumptions = assumptions; this.optimisticOpts = optimisticOpts; @@ -347,7 +353,7 @@ public InlineInfo next() { Invoke invoke = sortedInvokes.pop(); - InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, this, optimisticOpts); + InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, optimisticOpts); if (info != null) { invokePredecessor = (FixedNode) info.invoke().predecessor(); assert invokePredecessor.isAlive(); @@ -368,171 +374,105 @@ } public void scanInvokes(Iterable newNodes) { - scanGraphForInvokes(invokePredecessor); + assert invokePredecessor.isAlive(); + int invokes = scanGraphForInvokes(invokePredecessor); + assert invokes == countInvokes(newNodes); } - private void scanGraphForInvokes(FixedNode start) { + private int scanGraphForInvokes(FixedNode start) { ArrayList invokes = new InliningIterator(start, visitedFixedNodes).apply(); // insert the newly found invokes in their correct control-flow order for (int i = invokes.size() - 1; i >= 0; i--) { - sortedInvokes.addFirst(invokes.get(i)); - } - } - - public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) { - boolean preferredInvoke = hints != null && hints.contains(invoke); - return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke); - } - } - - private static class PriorityInliningPolicy implements InliningPolicy { + Invoke invoke = invokes.get(i); + assert !sortedInvokes.contains(invoke); + sortedInvokes.addFirst(invoke); - private final InliningDecision inliningDecision; - private final WeightComputationPolicy weightComputationPolicy; - private final Collection hints; - private final Assumptions assumptions; - private final OptimisticOptimizations optimisticOpts; - private final PriorityQueue sortedCandidates; - - public PriorityInliningPolicy(InliningDecision inliningPolicy, WeightComputationPolicy weightComputationPolicy, Collection hints, Assumptions assumptions, - OptimisticOptimizations optimisticOpts) { - this.inliningDecision = inliningPolicy; - this.weightComputationPolicy = weightComputationPolicy; - this.hints = hints; - this.assumptions = assumptions; - this.optimisticOpts = optimisticOpts; - sortedCandidates = new PriorityQueue<>(); - } - - public boolean continueInlining(StructuredGraph graph) { - if (graph.getNodeCount() >= GraalOptions.MaximumDesiredSize) { - InliningUtil.logInliningDecision("inlining is cut off by MaximumDesiredSize"); - metricInliningStoppedByMaxDesiredSize.increment(); - return false; } - return !sortedCandidates.isEmpty(); + return invokes.size(); } - public InlineInfo next() { - // refresh cached info before using it (it might have been in the queue for a long time) - InlineInfo info = sortedCandidates.remove(); - return InliningUtil.getInlineInfo(info.invoke(), assumptions, this, optimisticOpts); - } - - @Override - public boolean isWorthInlining(InlineInfo info) { - return inliningDecision.isWorthInlining(info); - } - - @SuppressWarnings("unchecked") - public void initialize(StructuredGraph graph) { - if (hints == null) { - scanInvokes(graph.getNodes(InvokeNode.class)); - scanInvokes(graph.getNodes(InvokeWithExceptionNode.class)); - } else { - scanInvokes((Iterable) (Iterable) hints); - } - } - - public void scanInvokes(Iterable nodes) { - for (Node node : nodes) { - if (node != null) { - if (node instanceof Invoke) { - Invoke invoke = (Invoke) node; - scanInvoke(invoke); - } - for (Node usage : node.usages().filterInterface(Invoke.class).snapshot()) { - scanInvoke((Invoke) usage); - } + private static int countInvokes(Iterable nodes) { + int count = 0; + for (Node n : nodes) { + if (n instanceof Invoke) { + count++; } } - } - - private void scanInvoke(Invoke invoke) { - InlineInfo info = InliningUtil.getInlineInfo(invoke, assumptions, this, optimisticOpts); - if (info != null) { - sortedCandidates.add(info); - } - } - - @Override - public double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke) { - boolean preferredInvoke = hints != null && hints.contains(invoke); - return weightComputationPolicy.computeWeight(caller, method, invoke, preferredInvoke); + return count; } } private static class InliningIterator { private final FixedNode start; - private final NodeBitMap processedNodes; - private final Deque nodeQueue; private final NodeBitMap queuedNodes; public InliningIterator(FixedNode start, NodeBitMap visitedFixedNodes) { this.start = start; - this.processedNodes = visitedFixedNodes; - this.nodeQueue = new ArrayDeque<>(); - this.queuedNodes = visitedFixedNodes.copy(); - + this.queuedNodes = visitedFixedNodes; assert start.isAlive(); } public ArrayList apply() { ArrayList invokes = new ArrayList<>(); - FixedNode current = start; - do { + FixedNode current; + forcedQueue(start); + + while ((current = nextQueuedNode()) != null) { assert current.isAlive(); - processedNodes.mark(current); - if (current instanceof InvokeWithExceptionNode || current instanceof InvokeNode) { - invokes.add((Invoke) current); + if (current instanceof Invoke) { + if (current != start) { + invokes.add((Invoke) current); + } queueSuccessors(current); - current = nextQueuedNode(); } else if (current instanceof LoopBeginNode) { - current = ((LoopBeginNode) current).next(); - assert current != null; + queueSuccessors(current); } else if (current instanceof LoopEndNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof MergeNode) { - current = ((MergeNode) current).next(); - assert current != null; + queueSuccessors(current); } else if (current instanceof FixedWithNextNode) { queueSuccessors(current); - current = nextQueuedNode(); } else if (current instanceof EndNode) { queueMerge((EndNode) current); - current = nextQueuedNode(); } else if (current instanceof DeoptimizeNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof ReturnNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof UnwindNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof ControlSplitNode) { queueSuccessors(current); - current = nextQueuedNode(); } else { assert false : current; } - } while (current != null); + } return invokes; } private void queueSuccessors(FixedNode x) { for (Node node : x.successors()) { - if (node != null && !queuedNodes.isMarked(node)) { - queuedNodes.mark(node); - nodeQueue.addFirst((FixedNode) node); - } + queue(node); } } + private void queue(Node node) { + if (node != null && !queuedNodes.isMarked(node)) { + forcedQueue(node); + } + } + + private void forcedQueue(Node node) { + queuedNodes.mark(node); + nodeQueue.addFirst((FixedNode) node); + } + private FixedNode nextQueuedNode() { if (nodeQueue.isEmpty()) { return null; @@ -553,7 +493,7 @@ private boolean visitedAllEnds(MergeNode merge) { for (int i = 0; i < merge.forwardEndCount(); i++) { - if (!processedNodes.isMarked(merge.forwardEndAt(i))) { + if (!queuedNodes.isMarked(merge.forwardEndAt(i))) { return false; } } @@ -561,49 +501,8 @@ } } - private static InliningPolicy createInliningPolicy(Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection hints) { - switch (GraalOptions.InliningPolicy) { - case 0: - return new CFInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, assumptions, optimisticOpts); - case 1: - return new PriorityInliningPolicy(createInliningDecision(), createWeightComputationPolicy(), hints, assumptions, optimisticOpts); - default: - GraalInternalError.shouldNotReachHere(); - return null; - } - } - - private static InliningDecision createInliningDecision() { - switch (GraalOptions.InliningDecision) { - case 1: - return new C1StaticSizeBasedInliningDecision(); - case 2: - return new MinimumCodeSizeBasedInliningDecision(); - case 3: - return new DynamicSizeBasedInliningDecision(); - case 4: - return new GreedySizeBasedInliningDecision(); - case 5: - return new GreedyMachineCodeInliningDecision(); - default: - GraalInternalError.shouldNotReachHere(); - return null; - } - } - - private static WeightComputationPolicy createWeightComputationPolicy() { - switch (GraalOptions.WeightComputationPolicy) { - case 0: - throw new GraalInternalError("removed because of invokation counter changes"); - case 1: - return new BytecodeSizeBasedWeightComputationPolicy(); - case 2: - return new ComplexityBasedWeightComputationPolicy(); - case 3: - return new CompiledCodeSizeWeightComputationPolicy(); - default: - GraalInternalError.shouldNotReachHere(); - return null; - } + private static InliningPolicy createInliningPolicy(GraalCodeCacheProvider runtime, Assumptions assumptions, OptimisticOptimizations optimisticOpts, Collection hints) { + InliningDecision inliningDecision = new GreedySizeBasedInliningDecision(runtime, hints); + return new CFInliningPolicy(inliningDecision, hints, assumptions, optimisticOpts); } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Feb 11 10:41:29 2013 +0100 @@ -70,18 +70,13 @@ void scanInvokes(Iterable newNodes); - double inliningWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke); - boolean isWorthInlining(InlineInfo info); } - public interface WeightComputationPolicy { + public static boolean logNotInlinedMethod(InlineInfo info, String msg, Object... args) { - double computeWeight(ResolvedJavaMethod caller, ResolvedJavaMethod method, Invoke invoke, boolean preferredInvoke); - } - - public static void logNotInlinedMethod(InlineInfo info, String msg, Object... args) { logInliningDecision(info, false, msg, args); + return false; } public static void logInliningDecision(InlineInfo info, boolean success, String msg, final Object... args) { @@ -99,6 +94,11 @@ }); } + public static boolean logInlinedMethod(InlineInfo info, String string, Object... args) { + logInliningDecision(info, true, string, args); + return true; + } + private static boolean logNotInlinedMethodAndReturnFalse(Invoke invoke, String msg) { if (shouldLogInliningDecision()) { String methodString = invoke.toString() + (invoke.callTarget() == null ? " callTarget=null" : invoke.callTarget().targetName()); @@ -135,7 +135,7 @@ logInliningDecision(inliningMsg, args); } - private static boolean shouldLogInliningDecision() { + public static boolean shouldLogInliningDecision() { return Debug.scope(inliningDecisionsScopeString, new Callable() { public Boolean call() { @@ -178,49 +178,43 @@ * The weight is the amortized weight of the additional code - so smaller is better. The level * is the number of nested inlinings that lead to this invoke. */ - public interface InlineInfo extends Comparable { + public interface InlineInfo { Invoke invoke(); - double weight(); - int level(); - int compiledCodeSize(); + int numberOfMethods(); - int compareTo(InlineInfo o); + ResolvedJavaMethod methodAt(int index); /** * Performs the inlining described by this object and returns the node that represents the * return value of the inlined method (or null for void methods and methods that have no * non-exceptional exit). + **/ + void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions); + + /** + * Try to make the call static bindable to avoid interface and virtual method calls. */ - void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions); + void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions); } public abstract static class AbstractInlineInfo implements InlineInfo { protected final Invoke invoke; - protected final double weight; - public AbstractInlineInfo(Invoke invoke, double weight) { + public AbstractInlineInfo(Invoke invoke) { this.invoke = invoke; - this.weight = weight; } @Override - public int compareTo(InlineInfo o) { - return (weight < o.weight()) ? -1 : (weight > o.weight()) ? 1 : 0; - } - public Invoke invoke() { return invoke; } - public double weight() { - return weight; - } - + @Override public int level() { return computeInliningLevel(invoke); } @@ -260,7 +254,7 @@ } } - private static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) { + protected static StructuredGraph getGraph(final ResolvedJavaMethod concrete, final InliningCallback callback) { return Debug.scope("GetInliningGraph", concrete, new Callable() { @Override @@ -270,6 +264,12 @@ } }); } + + protected void replaceInvokeCallTarget(StructuredGraph graph, InvokeKind invokeKind, ResolvedJavaMethod targetMethod) { + MethodCallTargetNode oldCallTarget = invoke.methodCallTarget(); + MethodCallTargetNode newCallTarget = graph.add(new MethodCallTargetNode(invokeKind, targetMethod, oldCallTarget.arguments().toArray(new ValueNode[0]), oldCallTarget.returnType())); + invoke.node().replaceFirstInput(oldCallTarget, newCallTarget); + } } /** @@ -280,8 +280,8 @@ public final ResolvedJavaMethod concrete; - public ExactInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete) { - super(invoke, weight); + public ExactInlineInfo(Invoke invoke, ResolvedJavaMethod concrete) { + super(invoke); this.concrete = concrete; } @@ -291,8 +291,19 @@ } @Override - public int compiledCodeSize() { - return InliningUtil.compiledCodeSize(concrete); + public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) { + // nothing todo, can already be bound statically + } + + @Override + public int numberOfMethods() { + return 1; + } + + @Override + public ResolvedJavaMethod methodAt(int index) { + assert index == 0; + return concrete; } @Override @@ -311,20 +322,36 @@ public final ResolvedJavaMethod concrete; public final ResolvedJavaType type; - public TypeGuardInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete, ResolvedJavaType type) { - super(invoke, weight); + public TypeGuardInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, ResolvedJavaType type) { + super(invoke); this.concrete = concrete; this.type = type; } @Override - public int compiledCodeSize() { - return InliningUtil.compiledCodeSize(concrete); + public int numberOfMethods() { + return 1; + } + + @Override + public ResolvedJavaMethod methodAt(int index) { + assert index == 0; + return concrete; } @Override public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { - // receiver null check must be before the type check + createGuard(graph, runtime); + inline(invoke, concrete, callback, assumptions, false); + } + + @Override + public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) { + createGuard(graph, runtime); + replaceInvokeCallTarget(graph, InvokeKind.Special, concrete); + } + + private void createGuard(StructuredGraph graph, GraalCodeCacheProvider runtime) { InliningUtil.receiverNullCheck(invoke); ValueNode receiver = invoke.methodCallTarget().receiver(); ConstantNode typeHub = ConstantNode.forConstant(type.getEncoding(Representation.ObjectHub), runtime, graph); @@ -340,8 +367,6 @@ graph.addBeforeFixed(invoke.node(), receiverHub); graph.addBeforeFixed(invoke.node(), guard); graph.addBeforeFixed(invoke.node(), anchor); - - inline(invoke, concrete, callback, assumptions, false); } @Override @@ -362,8 +387,8 @@ public final int[] typesToConcretes; public final double notRecordedTypeProbability; - public MultiTypeGuardInlineInfo(Invoke invoke, double weight, ArrayList concretes, ArrayList ptypes, int[] typesToConcretes, double notRecordedTypeProbability) { - super(invoke, weight); + public MultiTypeGuardInlineInfo(Invoke invoke, ArrayList concretes, ArrayList ptypes, int[] typesToConcretes, double notRecordedTypeProbability) { + super(invoke); assert concretes.size() > 0 && concretes.size() <= ptypes.size() : "must have at least one method but no more than types methods"; assert ptypes.size() == typesToConcretes.length : "array lengths must match"; @@ -374,33 +399,37 @@ } @Override - public int compiledCodeSize() { - int result = 0; - for (ResolvedJavaMethod m : concretes) { - result += InliningUtil.compiledCodeSize(m); - } - return result; + public int numberOfMethods() { + return concretes.size(); + } + + @Override + public ResolvedJavaMethod methodAt(int index) { + assert index >= 0 && index < concretes.size(); + return concretes.get(index); } @Override public void inline(StructuredGraph graph, GraalCodeCacheProvider runtime, InliningCallback callback, Assumptions assumptions) { - int numberOfMethods = concretes.size(); - boolean hasReturnValue = invoke.node().kind() != Kind.Void; - // receiver null check must be the first node InliningUtil.receiverNullCheck(invoke); - if (numberOfMethods > 1 || shouldFallbackToInvoke()) { - inlineMultipleMethods(graph, callback, assumptions, numberOfMethods, hasReturnValue); + if (hasSingleMethod()) { + inlineSingleMethod(graph, callback, assumptions); } else { - inlineSingleMethod(graph, callback, assumptions); + inlineMultipleMethods(graph, callback, assumptions); } } + private boolean hasSingleMethod() { + return concretes.size() == 1 && !shouldFallbackToInvoke(); + } + private boolean shouldFallbackToInvoke() { return notRecordedTypeProbability > 0; } - private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Assumptions assumptions, int numberOfMethods, boolean hasReturnValue) { + private void inlineMultipleMethods(StructuredGraph graph, InliningCallback callback, Assumptions assumptions) { + int numberOfMethods = concretes.size(); FixedNode continuation = invoke.next(); ValueNode originalReceiver = invoke.methodCallTarget().receiver(); @@ -410,7 +439,7 @@ returnMerge.setStateAfter(invoke.stateAfter().duplicate(invoke.stateAfter().bci)); PhiNode returnValuePhi = null; - if (hasReturnValue) { + if (invoke.node().kind() != Kind.Void) { returnValuePhi = graph.unique(new PhiNode(invoke.node().kind(), returnMerge)); } @@ -465,16 +494,13 @@ assert invoke.node().isAlive(); // replace the invoke with a switch on the type of the actual receiver - Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); - LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind)); - graph.addBeforeFixed(invoke.node(), receiverHub); - FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, successors); + createDispatchOnTypeBeforeInvoke(graph, successors, false); assert invoke.next() == continuation; invoke.setNext(null); returnMerge.setNext(continuation); invoke.node().replaceAtUsages(returnValuePhi); - invoke.node().replaceAndDelete(dispatchOnType); + invoke.node().replaceAndDelete(null); ArrayList replacements = new ArrayList<>(); @@ -544,46 +570,52 @@ return commonType; } + private ResolvedJavaType getLeastCommonType() { + ResolvedJavaType result = getLeastCommonType(0); + for (int i = 1; i < concretes.size(); i++) { + result = result.findLeastCommonAncestor(getLeastCommonType(i)); + } + return result; + } + private void inlineSingleMethod(StructuredGraph graph, InliningCallback callback, Assumptions assumptions) { assert concretes.size() == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0; BeginNode calleeEntryNode = graph.add(new BeginNode()); calleeEntryNode.setProbability(invoke.probability()); - Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); - LoadHubNode receiverHub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind)); - graph.addBeforeFixed(invoke.node(), receiverHub); - BeginNode unknownTypeSux = BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); + BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); BeginNode[] successors = new BeginNode[]{calleeEntryNode, unknownTypeSux}; - FixedNode dispatchOnType = createDispatchOnType(graph, receiverHub, successors); + createDispatchOnTypeBeforeInvoke(graph, successors, false); - FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor(); - pred.setNext(dispatchOnType); calleeEntryNode.setNext(invoke.node()); ResolvedJavaMethod concrete = concretes.get(0); inline(invoke, concrete, callback, assumptions, false); } - private FixedNode createDispatchOnType(StructuredGraph graph, LoadHubNode hub, BeginNode[] successors) { + private void createDispatchOnTypeBeforeInvoke(StructuredGraph graph, BeginNode[] successors, boolean invokeIsOnlySuccessor) { assert ptypes.size() > 1; + Kind hubKind = invoke.methodCallTarget().targetMethod().getDeclaringClass().getEncoding(Representation.ObjectHub).getKind(); + LoadHubNode hub = graph.add(new LoadHubNode(invoke.methodCallTarget().receiver(), hubKind)); + graph.addBeforeFixed(invoke.node(), hub); + ResolvedJavaType[] keys = new ResolvedJavaType[ptypes.size()]; double[] keyProbabilities = new double[ptypes.size() + 1]; int[] keySuccessors = new int[ptypes.size() + 1]; for (int i = 0; i < ptypes.size(); i++) { keys[i] = ptypes.get(i).getType(); keyProbabilities[i] = ptypes.get(i).getProbability(); - keySuccessors[i] = typesToConcretes[i]; + keySuccessors[i] = invokeIsOnlySuccessor ? 0 : typesToConcretes[i]; assert keySuccessors[i] < successors.length - 1 : "last successor is the unknownTypeSux"; } keyProbabilities[keyProbabilities.length - 1] = notRecordedTypeProbability; keySuccessors[keySuccessors.length - 1] = successors.length - 1; - double[] successorProbabilities = SwitchNode.successorProbabilites(successors.length, keySuccessors, keyProbabilities); - TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, successorProbabilities, keys, keyProbabilities, keySuccessors)); - - return typeSwitch; + TypeSwitchNode typeSwitch = graph.add(new TypeSwitchNode(hub, successors, keys, keyProbabilities, keySuccessors)); + FixedWithNextNode pred = (FixedWithNextNode) invoke.node().predecessor(); + pred.setNext(typeSwitch); } private static BeginNode createInvocationBlock(StructuredGraph graph, Invoke invoke, MergeNode returnMerge, PhiNode returnValuePhi, MergeNode exceptionMerge, PhiNode exceptionObjectPhi, @@ -646,6 +678,56 @@ } @Override + public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) { + if (hasSingleMethod()) { + tryToDevirtualizeSingleMethod(graph); + } else { + tryToDevirtualizeMultipleMethods(graph); + } + } + + private void tryToDevirtualizeSingleMethod(StructuredGraph graph) { + devirtualizeWithTypeSwitch(graph, InvokeKind.Special, concretes.get(0)); + } + + private void tryToDevirtualizeMultipleMethods(StructuredGraph graph) { + MethodCallTargetNode methodCallTarget = invoke.methodCallTarget(); + if (methodCallTarget.invokeKind() == InvokeKind.Interface) { + ResolvedJavaMethod targetMethod = methodCallTarget.targetMethod(); + ResolvedJavaType leastCommonType = getLeastCommonType(); + // check if we have a common base type that implements the interface -> in that case +// we have a vtable entry for the interface method and can use a less expensive virtual call + if (!leastCommonType.isInterface() && targetMethod.getDeclaringClass().isAssignableFrom(leastCommonType)) { + ResolvedJavaMethod baseClassTargetMethod = leastCommonType.resolveMethod(targetMethod); + if (baseClassTargetMethod != null) { + devirtualizeWithTypeSwitch(graph, InvokeKind.Virtual, leastCommonType.resolveMethod(targetMethod)); + } + } + } + } + + private void devirtualizeWithTypeSwitch(StructuredGraph graph, InvokeKind kind, ResolvedJavaMethod target) { + InliningUtil.receiverNullCheck(invoke); + + BeginNode invocationEntry = graph.add(new BeginNode()); + invocationEntry.setProbability(invoke.probability()); + + BeginNode unknownTypeSux = createUnknownTypeSuccessor(graph); + BeginNode[] successors = new BeginNode[]{invocationEntry, unknownTypeSux}; + createDispatchOnTypeBeforeInvoke(graph, successors, true); + + invocationEntry.setNext(invoke.node()); + ValueNode receiver = invoke.methodCallTarget().receiver(); + PiNode anchoredReceiver = createAnchoredReceiver(graph, invocationEntry, target.getDeclaringClass(), receiver, false); + invoke.callTarget().replaceFirstInput(receiver, anchoredReceiver); + replaceInvokeCallTarget(graph, kind, target); + } + + private static BeginNode createUnknownTypeSuccessor(StructuredGraph graph) { + return BeginNode.begin(graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TypeCheckedInliningViolated))); + } + + @Override public String toString() { StringBuilder builder = new StringBuilder(shouldFallbackToInvoke() ? "megamorphic" : "polymorphic"); builder.append(", "); @@ -675,8 +757,8 @@ private final Assumption takenAssumption; - public AssumptionInlineInfo(Invoke invoke, double weight, ResolvedJavaMethod concrete, Assumption takenAssumption) { - super(invoke, weight, concrete); + public AssumptionInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, Assumption takenAssumption) { + super(invoke, concrete); this.takenAssumption = takenAssumption; } @@ -689,6 +771,12 @@ } @Override + public void tryToDevirtualizeInvoke(StructuredGraph graph, GraalCodeCacheProvider runtime, Assumptions assumptions) { + assumptions.record(takenAssumption); + replaceInvokeCallTarget(graph, InvokeKind.Special, concrete); + } + + @Override public String toString() { return "assumption " + MetaUtil.format("%H.%n(%p):%r", concrete); } @@ -698,10 +786,9 @@ * Determines if inlining is possible at the given invoke node. * * @param invoke the invoke that should be inlined - * @param inliningPolicy used to determine the weight of a specific inlining * @return an instance of InlineInfo, or null if no inlining is possible at the given invoke */ - public static InlineInfo getInlineInfo(Invoke invoke, Assumptions assumptions, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts) { + public static InlineInfo getInlineInfo(Invoke invoke, Assumptions assumptions, OptimisticOptimizations optimisticOpts) { if (!checkInvokeConditions(invoke)) { return null; } @@ -710,7 +797,7 @@ ResolvedJavaMethod targetMethod = callTarget.targetMethod(); if (callTarget.invokeKind() == InvokeKind.Special || targetMethod.canBeStaticallyBound()) { - return getExactInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, targetMethod); + return getExactInlineInfo(invoke, optimisticOpts, targetMethod); } assert callTarget.invokeKind() == InvokeKind.Virtual || callTarget.invokeKind() == InvokeKind.Interface; @@ -725,57 +812,49 @@ holder = receiverType; if (receiverStamp.isExactType()) { assert targetMethod.getDeclaringClass().isAssignableFrom(holder) : holder + " subtype of " + targetMethod.getDeclaringClass() + " for " + targetMethod; - return getExactInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, holder.resolveMethod(targetMethod)); + return getExactInlineInfo(invoke, optimisticOpts, holder.resolveMethod(targetMethod)); } } } if (holder.isArray()) { // arrays can be treated as Objects - return getExactInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, holder.resolveMethod(targetMethod)); + return getExactInlineInfo(invoke, optimisticOpts, holder.resolveMethod(targetMethod)); } - // TODO (chaeubl): we could also use the type determined after assumptions for the - // type-checked inlining case as it might have an effect on type filtering if (assumptions.useOptimisticAssumptions()) { ResolvedJavaType uniqueSubtype = holder.findUniqueConcreteSubtype(); if (uniqueSubtype != null) { - return getAssumptionInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype)); + return getAssumptionInlineInfo(invoke, optimisticOpts, uniqueSubtype.resolveMethod(targetMethod), new Assumptions.ConcreteSubtype(holder, uniqueSubtype)); } ResolvedJavaMethod concrete = holder.findUniqueConcreteMethod(targetMethod); if (concrete != null) { - return getAssumptionInlineInfo(invoke, inliningPolicy, optimisticOpts, caller, concrete, new Assumptions.ConcreteMethod(targetMethod, holder, concrete)); + return getAssumptionInlineInfo(invoke, optimisticOpts, concrete, new Assumptions.ConcreteMethod(targetMethod, holder, concrete)); } - - // TODO (chaeubl): C1 has one more assumption in the case of interfaces } // type check based inlining - return getTypeCheckedInlineInfo(invoke, inliningPolicy, caller, holder, targetMethod, optimisticOpts); + return getTypeCheckedInlineInfo(invoke, caller, holder, targetMethod, optimisticOpts); } - private static InlineInfo getAssumptionInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod caller, ResolvedJavaMethod concrete, - Assumption takenAssumption) { + private static InlineInfo getAssumptionInlineInfo(Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod concrete, Assumption takenAssumption) { assert !Modifier.isAbstract(concrete.getModifiers()); if (!checkTargetConditions(invoke, concrete, optimisticOpts)) { return null; } - double weight = inliningPolicy.inliningWeight(caller, concrete, invoke); - return new AssumptionInlineInfo(invoke, weight, concrete, takenAssumption); + return new AssumptionInlineInfo(invoke, concrete, takenAssumption); } - private static InlineInfo getExactInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod caller, ResolvedJavaMethod targetMethod) { + private static InlineInfo getExactInlineInfo(Invoke invoke, OptimisticOptimizations optimisticOpts, ResolvedJavaMethod targetMethod) { assert !Modifier.isAbstract(targetMethod.getModifiers()); if (!checkTargetConditions(invoke, targetMethod, optimisticOpts)) { return null; } - double weight = inliningPolicy.inliningWeight(caller, targetMethod, invoke); - return new ExactInlineInfo(invoke, weight, targetMethod); + return new ExactInlineInfo(invoke, targetMethod); } - private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, InliningPolicy inliningPolicy, ResolvedJavaMethod caller, ResolvedJavaType holder, ResolvedJavaMethod targetMethod, - OptimisticOptimizations optimisticOpts) { + private static InlineInfo getTypeCheckedInlineInfo(Invoke invoke, ResolvedJavaMethod caller, ResolvedJavaType holder, ResolvedJavaMethod targetMethod, OptimisticOptimizations optimisticOpts) { ProfilingInfo profilingInfo = caller.getProfilingInfo(); JavaTypeProfile typeProfile = profilingInfo.getTypeProfile(invoke.bci()); if (typeProfile == null) { @@ -799,8 +878,7 @@ if (!checkTargetConditions(invoke, concrete, optimisticOpts)) { return null; } - double weight = inliningPolicy.inliningWeight(caller, concrete, invoke); - return new TypeGuardInlineInfo(invoke, weight, concrete, type); + return new TypeGuardInlineInfo(invoke, concrete, type); } else { invoke.setPolymorphic(true); @@ -814,14 +892,6 @@ notRecordedTypeProbability * 100); } - // TODO (chaeubl) inlining of multiple methods should work differently - // 1. check which methods can be inlined - // 2. for those methods, use weight and probability to compute which of them should be - // inlined - // 3. do the inlining - // a) all seen methods can be inlined -> do so and guard with deopt - // b) some methods can be inlined -> inline them and fall back to invocation if violated - // determine concrete methods and map type to specific method ArrayList concreteMethods = new ArrayList<>(); int[] typesToConcretes = new int[ptypes.size()]; @@ -836,14 +906,12 @@ typesToConcretes[i] = index; } - double totalWeight = 0; for (ResolvedJavaMethod concrete : concreteMethods) { if (!checkTargetConditions(invoke, concrete, optimisticOpts)) { return logNotInlinedMethodAndReturnNull(invoke, targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined"); } - totalWeight += inliningPolicy.inliningWeight(caller, concrete, invoke); } - return new MultiTypeGuardInlineInfo(invoke, totalWeight, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability); + return new MultiTypeGuardInlineInfo(invoke, concreteMethods, ptypes, typesToConcretes, notRecordedTypeProbability); } } @@ -1034,7 +1102,7 @@ if (node instanceof Invoke) { Invoke newInvoke = (Invoke) node; double newRelevance = newInvoke.inliningRelevance() * invoke.inliningRelevance(); - if (GraalOptions.LimitInlinedProbability) { + if (GraalOptions.LimitInlinedRelevance) { newRelevance = Math.min(newRelevance, invoke.inliningRelevance()); } newInvoke.setInliningRelevance(newRelevance); @@ -1106,14 +1174,6 @@ return (StructuredGraph) target.getCompilerStorage().get(Graph.class); } - private static int compiledCodeSize(ResolvedJavaMethod target) { - if (GraalOptions.AlwaysInlineIntrinsics && canIntrinsify(target)) { - return 0; - } else { - return target.getCompiledCodeSize(); - } - } - public static Class getMacroNodeClass(ResolvedJavaMethod target) { Object result = target.getCompilerStorage().get(Node.class); return result == null ? null : ((Class) result).asSubclass(FixedWithNextNode.class); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/IterativeConditionalEliminationPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -46,7 +46,7 @@ @Override protected void run(StructuredGraph graph) { Set canonicalizationRoots = new HashSet<>(); - ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(); + ConditionalEliminationPhase eliminate = new ConditionalEliminationPhase(runtime); Listener listener = new Listener(canonicalizationRoots); while (true) { graph.trackInputChange(listener); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Mon Feb 11 10:41:29 2013 +0100 @@ -43,30 +43,24 @@ static boolean InlineMonomorphicCalls = true; static boolean InlinePolymorphicCalls = true; static boolean InlineMegamorphicCalls = ____; - public static int InliningPolicy = 1; - public static int InliningDecision = 4; - public static int WeightComputationPolicy = 2; - public static int MaximumTrivialSize = 10; public static int MaximumInlineLevel = 30; - public static int MaximumDesiredSize = 3000; + public static int MaximumDesiredSize = 5000; public static int MaximumRecursiveInlining = 1; - public static int SmallCompiledCodeSize = 2200; public static boolean LimitInlinedProbability = ____; - public static boolean UseRelevanceBasedInlining = ____; - // WeightBasedInliningPolicy (0) - public static float InliningSizePenaltyExp = 20; - public static float MaximumInlineWeight = 1.25f; - public static float InliningSizePenalty = 1; - // StaticSizeBasedInliningPolicy (1), MinimumCodeSizeBasedInlining (2), - // DynamicSizeBasedInliningPolicy (3) - public static int MaximumInlineSize = 35; - // GreedySizeBasedInlining (4) - public static int MaximumGreedyInlineSize = 100; - public static int InliningBonusPerTransferredValue = 10; - // Common options for inlining policies 1 to 4 - public static float NestedInliningSizeRatio = 1f; + public static boolean LimitInlinedRelevance = true; public static float BoostInliningForEscapeAnalysis = 2f; - public static float RatioCapForInlining = 1f; + public static float RelevanceCapForInlining = 1f; + + public static int TrivialBytecodeSize = 10; + public static int NormalBytecodeSize = 150; + public static int MaximumBytecodeSize = 500; + public static int TrivialComplexity = 10; + public static int NormalComplexity = 60; + public static int MaximumComplexity = 400; + public static int TrivialCompiledCodeSize = 150; + public static int NormalCompiledCodeSize = 750; + public static int MaximumCompiledCodeSize = 4000; + public static int SmallCompiledCodeSize = 1000; // escape analysis settings public static boolean PartialEscapeAnalysis = true; @@ -80,7 +74,6 @@ // absolute probability analysis public static boolean ProbabilityAnalysis = true; - public static int LoopFrequencyPropagationPolicy = -2; // profiling information public static int DeoptsToDisableOptimisticOptimization = 40; @@ -113,7 +106,7 @@ public static int LoopUnswitchUncertaintyBoost = 5; // debugging settings - public static int MethodEndBreakpointGuards = 0; + public static int MethodEndBreakpointGuards = 2; public static boolean ZapStackOnMethodEntry = ____; public static boolean DeoptALot = ____; public static boolean VerifyPhases = true; @@ -172,7 +165,7 @@ public static boolean AlwaysInlineVTableStubs = ____; public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true; - public static boolean ResolveClassBeforeStaticInvoke = true; + public static boolean ResolveClassBeforeStaticInvoke = ____; public static boolean CanOmitFrame = true; public static int SafepointPollOffset = 256; @@ -201,6 +194,7 @@ public static boolean OptTailDuplication = true; public static boolean OptEliminatePartiallyRedundantGuards = true; public static boolean OptFilterProfiledTypes = true; + public static boolean OptDevirtualizeInvokesOptimistically = true; // Intrinsification settings public static boolean IntrinsifyArrayCopy = true; diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/OptimisticOptimizations.java Mon Feb 11 10:41:29 2013 +0100 @@ -52,9 +52,10 @@ if (checkDeoptimizations(method.getProfilingInfo(), deoptReason)) { enabledOpts.add(optimization); } else { - // TODO (chaeubl): change to Debug.log when we are sure that optimistic optimizations - // are not disabled - // unnecessarily + /* + * TODO (chaeubl): see GRAAL-75 (remove when we are sure that optimistic optimizations + * are not disabled unnecessarily + */ TTY.println("WARN: deactivated optimistic optimization %s for %s", optimization.name(), MetaUtil.format("%H.%n(%p)", method)); disabledOptimisticOptsMetric.increment(); } @@ -84,6 +85,10 @@ return GraalOptions.InlineMegamorphicCalls && enabledOpts.contains(Optimization.UseTypeCheckedInlining); } + public boolean devirtualizeInvokes() { + return GraalOptions.OptDevirtualizeInvokesOptimistically && enabledOpts.contains(Optimization.UseTypeCheckedInlining); + } + public boolean useExceptionProbability() { return GraalOptions.UseExceptionProbability && enabledOpts.contains(Optimization.UseExceptionProbability); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScopedPostOrderNodeIterator.java Mon Feb 11 10:41:29 2013 +0100 @@ -30,15 +30,13 @@ public abstract class ScopedPostOrderNodeIterator { - private final NodeBitMap processedNodes; private final Deque nodeQueue; private final NodeBitMap queuedNodes; private final Deque scopes; - protected FixedNode currentScope; + protected FixedNode currentScopeStart; public ScopedPostOrderNodeIterator(StructuredGraph graph) { - this.processedNodes = graph.createNodeBitMap(); this.queuedNodes = graph.createNodeBitMap(); this.nodeQueue = new ArrayDeque<>(); this.scopes = getScopes(graph); @@ -46,64 +44,57 @@ public void apply() { while (!scopes.isEmpty()) { - processedNodes.clearAll(); queuedNodes.clearAll(); - this.currentScope = scopes.pop(); + this.currentScopeStart = scopes.pop(); initializeScope(); processScope(); } } public void processScope() { - FixedNode current = currentScope; - do { + FixedNode current; + queue(currentScopeStart); + + while ((current = nextQueuedNode()) != null) { assert current.isAlive(); - processedNodes.mark(current); if (current instanceof Invoke) { invoke((Invoke) current); queueSuccessors(current); - current = nextQueuedNode(); } else if (current instanceof LoopBeginNode) { queueLoopBeginSuccessors((LoopBeginNode) current); - current = nextQueuedNode(); } else if (current instanceof LoopExitNode) { queueLoopExitSuccessors((LoopExitNode) current); - current = nextQueuedNode(); } else if (current instanceof LoopEndNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof MergeNode) { - current = ((MergeNode) current).next(); - assert current != null; + queueSuccessors(current); } else if (current instanceof FixedWithNextNode) { queueSuccessors(current); - current = nextQueuedNode(); } else if (current instanceof EndNode) { queueMerge((EndNode) current); - current = nextQueuedNode(); } else if (current instanceof DeoptimizeNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof ReturnNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof UnwindNode) { - current = nextQueuedNode(); + // nothing todo } else if (current instanceof ControlSplitNode) { queueSuccessors(current); - current = nextQueuedNode(); } else { assert false : current; } - } while (current != null); + } } protected void queueLoopBeginSuccessors(LoopBeginNode node) { - if (currentScope == node) { + if (currentScopeStart == node) { queue(node.next()); - } else if (currentScope instanceof LoopBeginNode) { + } else if (currentScopeStart instanceof LoopBeginNode) { // so we are currently processing loop A and found another loop B // -> queue all loop exits of B except those that also exit loop A for (LoopExitNode loopExit : node.loopExits()) { - if (!((LoopBeginNode) currentScope).loopExits().contains(loopExit)) { + if (!((LoopBeginNode) currentScopeStart).loopExits().contains(loopExit)) { queue(loopExit); } } @@ -113,7 +104,7 @@ } protected void queueLoopExitSuccessors(LoopExitNode node) { - if (!(currentScope instanceof LoopBeginNode) || !((LoopBeginNode) currentScope).loopExits().contains(node)) { + if (!(currentScopeStart instanceof LoopBeginNode) || !((LoopBeginNode) currentScopeStart).loopExits().contains(node)) { queueSuccessors(node); } } @@ -157,14 +148,13 @@ private void queueMerge(EndNode end) { MergeNode merge = end.merge(); if (!queuedNodes.isMarked(merge) && visitedAllEnds(merge)) { - queuedNodes.mark(merge); - nodeQueue.add(merge); + queue(merge); } } private boolean visitedAllEnds(MergeNode merge) { for (int i = 0; i < merge.forwardEndCount(); i++) { - if (!processedNodes.isMarked(merge.forwardEndAt(i))) { + if (!queuedNodes.isMarked(merge.forwardEndAt(i))) { return false; } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Mon Feb 11 10:41:29 2013 +0100 @@ -172,7 +172,7 @@ // Can simply use the phi result if the same materialized values are expected. return result; } else { - return MaterializeNode.create(asCondition(trueValue), t, f); + return t.graph().unique(new ConditionalNode(asCondition(trueValue), t, f)); } } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/UnsignedMathSubstitutions.java Mon Feb 11 10:41:29 2013 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.snippets; -import static com.oracle.graal.nodes.MaterializeNode.*; +import static com.oracle.graal.nodes.calc.ConditionalNode.*; import static com.oracle.graal.nodes.calc.Condition.*; import com.oracle.graal.api.code.*; @@ -38,12 +38,12 @@ @MethodSubstitution public static boolean aboveThan(int a, int b) { - return materialize(BT, b, a); + return materializeCondition(BT, b, a); } @MethodSubstitution public static boolean aboveOrEqual(int a, int b) { - return !materialize(BT, a, b); + return !materializeCondition(BT, a, b); } /** @@ -51,7 +51,7 @@ */ @MethodSubstitution public static boolean belowThan(int a, int b) { - return materialize(BT, a, b); + return materializeCondition(BT, a, b); } /** @@ -59,7 +59,7 @@ */ @MethodSubstitution public static boolean belowOrEqual(int a, int b) { - return !materialize(BT, b, a); + return !materializeCondition(BT, b, a); } /** @@ -67,7 +67,7 @@ */ @MethodSubstitution public static boolean aboveThan(long a, long b) { - return materialize(BT, b, a); + return materializeCondition(BT, b, a); } /** @@ -75,7 +75,7 @@ */ @MethodSubstitution public static boolean aboveOrEqual(long a, long b) { - return !materialize(BT, a, b); + return !materializeCondition(BT, a, b); } /** @@ -83,7 +83,7 @@ */ @MethodSubstitution public static boolean belowThan(long a, long b) { - return materialize(BT, a, b); + return materializeCondition(BT, a, b); } /** @@ -91,7 +91,7 @@ */ @MethodSubstitution public static boolean belowOrEqual(long a, long b) { - return !materialize(BT, b, a); + return !materializeCondition(BT, b, a); } /** diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARC.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.sparc; + +import static com.oracle.graal.api.code.MemoryBarriers.*; + +import java.nio.*; + +import com.oracle.graal.api.code.*; + +/** + * Represents the SPARC architecture. + */ +public class SPARC extends Architecture { + + // SPARC: Define registers. + + public SPARC() { + super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, null, LOAD_STORE | STORE_STORE, 1, 0, 8); + // SPARC: Fix architecture parameters. + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.test/src/com/oracle/graal/test/GraalTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,50 @@ +/* + * 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.test; + +import java.lang.reflect.*; + +import org.junit.*; + +/** + * Base class for Graal tests. + *

+ * This contains common utility methods that are used in multiple test projects. + */ +public class GraalTest { + + protected Method getMethod(String methodName) { + Method found = null; + for (Method m : this.getClass().getMethods()) { + if (m.getName().equals(methodName)) { + Assert.assertNull(found); + found = m; + } + } + if (found != null) { + return found; + } else { + throw new RuntimeException("method not found: " + methodName); + } + } +} diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/nodes/MaterializeObjectNode.java Mon Feb 11 10:41:29 2013 +0100 @@ -94,12 +94,7 @@ VirtualArrayNode virtual = (VirtualArrayNode) virtualObject; ResolvedJavaType element = virtual.componentType(); - NewArrayNode newArray; - if (element.getKind() == Kind.Object) { - newArray = graph.add(new NewObjectArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0)); - } else { - newArray = graph.add(new NewPrimitiveArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0)); - } + NewArrayNode newArray = graph.add(new NewArrayNode(element, ConstantNode.forInt(virtual.entryCount(), graph), defaultValuesOnly, lockCount > 0)); this.replaceAtUsages(newArray); graph.addBeforeFixed(this, newArray); diff -r 3cec97eb3b5f -r e8c71b8562e3 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 Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/GraphEffectList.java Mon Feb 11 10:41:29 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.virtual.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.virtual.nodes.*; @@ -62,7 +61,7 @@ * * @param node The floating node to be added. */ - public void addFloatingNode(final FloatingNode node) { + public void addFloatingNode(final ValueNode node) { add(new Effect() { @Override diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeAnalysisPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -95,7 +95,7 @@ PartialEscapeClosure closure = new PartialEscapeClosure(graph.createNodeBitMap(), schedule, runtime); ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock(), new BlockState(), null); - if (closure.getVirtualIdCount() == 0) { + if (closure.getNewVirtualObjectCount() == 0) { return false; } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Mon Feb 11 10:41:29 2013 +0100 @@ -69,8 +69,8 @@ return effects; } - public int getVirtualIdCount() { - return tool.getNextVirtualId(); + public int getNewVirtualObjectCount() { + return tool.getNewVirtualObjectCount(); } @Override diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/VirtualizerToolImpl.java Mon Feb 11 10:41:29 2013 +0100 @@ -49,7 +49,7 @@ private boolean customAction; private BlockState state; private ValueNode current; - private int virtualIds = 0; + private int newVirtualObjectCount = 0; @Override public MetaAccessProvider getMetaAccessProvider() { @@ -71,9 +71,8 @@ return customAction; } - @Override - public int getNextVirtualId() { - return virtualIds; + public int getNewVirtualObjectCount() { + return newVirtualObjectCount; } @Override @@ -156,7 +155,7 @@ state.addObject(virtualObject, new ObjectState(virtualObject, entryState, EscapeState.Virtual, lockCount)); state.addAndMarkAlias(virtualObject, virtualObject, usages); PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment(); - virtualIds++; + newVirtualObjectCount++; } @Override diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Signed.java Mon Feb 11 10:41:29 2013 +0100 @@ -119,6 +119,22 @@ * Compares this Signed with the specified value. * * @param val value to which this Signed is to be compared. + * @return {@code this == val} + */ + boolean equal(Signed val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this != val} + */ + boolean notEqual(Signed val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. * @return {@code this < val} */ boolean lessThan(Signed val); @@ -234,6 +250,22 @@ * Compares this Signed with the specified value. * * @param val value to which this Signed is to be compared. + * @return {@code this == val} + */ + boolean equal(int val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. + * @return {@code this != val} + */ + boolean notEqual(int val); + + /** + * Compares this Signed with the specified value. + * + * @param val value to which this Signed is to be compared. * @return {@code this < val} */ boolean lessThan(int val); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Unsigned.java Mon Feb 11 10:41:29 2013 +0100 @@ -115,6 +115,22 @@ * Compares this Unsigned with the specified value. * * @param val value to which this Unsigned is to be compared. + * @return {@code this == val} + */ + boolean equal(Unsigned val); + + /** + * Compares this Unsigned with the specified value. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this != val} + */ + boolean notEqual(Unsigned val); + + /** + * Compares this Unsigned with the specified value. + * + * @param val value to which this Unsigned is to be compared. * @return {@code this < val} */ boolean belowThan(Unsigned val); @@ -260,6 +276,28 @@ * Therefore, the result is only well-defined for positive right operands. * * @param val value to which this Unsigned is to be compared. + * @return {@code this == val} + */ + boolean equal(int val); + + /** + * Compares this Unsigned with the specified value. + *

+ * Note that the right operand is a signed value, while the operation is performed unsigned. + * Therefore, the result is only well-defined for positive right operands. + * + * @param val value to which this Unsigned is to be compared. + * @return {@code this != val} + */ + boolean notEqual(int val); + + /** + * Compares this Unsigned with the specified value. + *

+ * Note that the right operand is a signed value, while the operation is performed unsigned. + * Therefore, the result is only well-defined for positive right operands. + * + * @param val value to which this Unsigned is to be compared. * @return {@code this < val} */ boolean belowThan(int val); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Feb 11 10:41:29 2013 +0100 @@ -25,9 +25,9 @@ import static com.oracle.graal.graph.UnsafeAccess.*; import java.lang.annotation.*; -import java.util.concurrent.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -415,6 +415,52 @@ } @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ) + public boolean equal(Signed val) { + return equal((Word) val); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ) + public boolean equal(Unsigned val) { + return equal((Word) val); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ) + public boolean equal(int val) { + return equal(intParam(val)); + } + + @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ) + public boolean equal(Word val) { + return unbox() == val.unbox(); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE) + public boolean notEqual(Signed val) { + return notEqual((Word) val); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE) + public boolean notEqual(Unsigned val) { + return notEqual((Word) val); + } + + @Override + @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE) + public boolean notEqual(int val) { + return notEqual(intParam(val)); + } + + @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE) + public boolean notEqual(Word val) { + return unbox() != val.unbox(); + } + + @Override @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT) public boolean lessThan(Signed val) { return lessThan((Word) val); @@ -815,6 +861,21 @@ public void writeObject(int offset, Object val) { writeObject(signed(offset), val); } + + @Override + public final boolean equals(Object obj) { + throw GraalInternalError.shouldNotReachHere("equals must not be called on words"); + } + + @Override + public final int hashCode() { + throw GraalInternalError.shouldNotReachHere("hashCode must not be called on words"); + } + + @Override + public String toString() { + throw GraalInternalError.shouldNotReachHere("toString must not be called on words"); + } } final class HostedWord extends Word { @@ -823,7 +884,6 @@ private static final int SMALL_TO = 100; private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1]; - private static final ConcurrentHashMap cache = new ConcurrentHashMap<>(); static { for (int i = SMALL_FROM; i <= SMALL_TO; i++) { @@ -841,18 +901,16 @@ if (val >= SMALL_FROM && val <= SMALL_TO) { return smallCache[(int) val - SMALL_FROM]; } - Long key = val; - HostedWord result = cache.get(key); - if (result != null) { - return result; - } - HostedWord newValue = new HostedWord(val); - HostedWord oldValue = cache.putIfAbsent(key, newValue); - return oldValue == null ? newValue : oldValue; + return new HostedWord(val); } @Override protected long unbox() { return rawValue; } + + @Override + public String toString() { + return "Word<" + rawValue + ">"; + } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -95,12 +95,13 @@ if (x.kind() == wordKind || y.kind() == wordKind) { assert x.kind() == wordKind; assert y.kind() == wordKind; - graph.replaceFloating(objectEqualsNode, graph.unique(new IntegerEqualsNode(x, y))); + + // TODO Remove the whole iteration of ObjectEqualsNodes when we are sure that there + // is no more code where this triggers. + throw GraalInternalError.shouldNotReachHere("Comparison of words with == and != is no longer supported"); } } - // Replace ObjectEqualsNodes with IntegerEqualsNodes where the values being compared are - // words for (LoadIndexedNode load : graph.getNodes().filter(LoadIndexedNode.class).snapshot()) { if (isWord(load)) { load.setStamp(StampFactory.forKind(wordKind)); @@ -247,7 +248,7 @@ } else { comparison = new IntegerLessThanNode(a, b); } - MaterializeNode materialize = MaterializeNode.create(graph.unique(comparison)); + ConditionalNode materialize = graph.unique(new ConditionalNode(graph.unique(comparison), ConstantNode.forInt(1, graph), ConstantNode.forInt(0, graph))); ValueNode op; if (condition.canonicalNegate()) { diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeVerificationPhase.java Mon Feb 11 10:41:29 2013 +0100 @@ -97,10 +97,8 @@ } } } else if (usage instanceof ObjectEqualsNode) { - ObjectEqualsNode compare = (ObjectEqualsNode) usage; - if (compare.x() == node || compare.y() == node) { - verify(isWord(compare.x()) == isWord(compare.y()), node, compare.usages().first(), "cannot mixed word and non-word type in use of '==' or '!='"); - } + verify(!isWord(node) || ((ObjectEqualsNode) usage).x() != node, node, usage, "cannot use word type in comparison"); + verify(!isWord(node) || ((ObjectEqualsNode) usage).y() != node, node, usage, "cannot use word type in comparison"); } else if (usage instanceof ArrayLengthNode) { verify(!isWord(node) || ((ArrayLengthNode) usage).array() != node, node, usage, "cannot get array length from word value"); } else if (usage instanceof PhiNode) { @@ -148,7 +146,7 @@ return buf.toString(); } else { String loc = GraphUtil.approxSourceLocation(n); - return loc == null ? "" : loc; + return loc == null ? MetaUtil.format("method %h.%n", ((StructuredGraph) n.graph()).method()) : loc; } } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java --- a/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/FrameTest.java Mon Feb 11 10:41:29 2013 +0100 @@ -35,7 +35,7 @@ * The frame is the preferred data structure for passing values between nodes. It can in particular * be used for storing the values of local variables of the guest language. The * {@link FrameDescriptor} represents the current structure of the frame. The method - * {@link FrameDescriptor#addFrameSlot(String, Class)} can be used to create predefined frame slots. + * {@link FrameDescriptor#addFrameSlot(Object, Class)} can be used to create predefined frame slots. * The setter and getter methods in the {@link Frame} class can be used to access the current value * of a particular frame slot. *

diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -58,4 +58,20 @@ * @return the new call target object */ CallTarget createCallTarget(RootNode rootNode, FrameDescriptor frameDescriptor); + + /** + * Creates a new materialized frame object that can be used to store values. + * + * @return the newly created materialized frame object + */ + MaterializedFrame createMaterializedFrame(Arguments arguments); + + /** + * Creates a new materialized frame object with the given frame descriptor that can be used to + * store values. + * + * @param frameDescriptor the frame descriptor describing this frame's values + * @return the newly created materialized frame object + */ + MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/Frame.java Mon Feb 11 10:41:29 2013 +0100 @@ -31,6 +31,11 @@ public interface Frame { /** + * @return the object describing the layout of this frame + */ + FrameDescriptor getFrameDescriptor(); + + /** * @return the arguments used when calling this method */ Arguments getArguments(); @@ -132,4 +137,23 @@ void setDouble(FrameSlot slot, double value); void updateToLatestVersion(); + + /** + * Converts this virtual frame into a packed frame that has no longer direct access to the local + * variables. This packing is an important hint to the Truffle optimizer and therefore passing + * around a {@link PackedFrame} should be preferred over passing around a {@link VirtualFrame} + * when the probability that an unpacking will occur is low. + * + * @return the packed frame + */ + PackedFrame pack(); + + /** + * Materializes this frame, which allows it to be stored in a field or cast to + * {@link java.lang.Object}. The frame however looses the ability to be packed or to access the + * caller frame. + * + * @return the new materialized frame + */ + MaterializedFrame materialize(); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameDescriptor.java Mon Feb 11 10:41:29 2013 +0100 @@ -33,7 +33,7 @@ protected final TypeConversion typeConversion; private final ArrayList slots; private FrameVersionImpl lastVersion; - private final HashMap nameToSlotMap; + private final HashMap identifierToSlotMap; public FrameDescriptor() { this(DefaultTypeConversion.getInstance()); @@ -42,32 +42,32 @@ public FrameDescriptor(TypeConversion typeConversion) { this.typeConversion = typeConversion; slots = new ArrayList<>(); - nameToSlotMap = new HashMap<>(); + identifierToSlotMap = new HashMap<>(); lastVersion = new FrameVersionImpl(); } - public FrameSlot addFrameSlot(String name) { - return addFrameSlot(name, typeConversion.getTopType()); + public FrameSlot addFrameSlot(Object identifier) { + return addFrameSlot(identifier, typeConversion.getTopType()); } - public FrameSlot addFrameSlot(String name, Class type) { - assert !nameToSlotMap.containsKey(name); - FrameSlotImpl slot = new FrameSlotImpl(this, name, slots.size(), type); + public FrameSlot addFrameSlot(Object identifier, Class type) { + assert !identifierToSlotMap.containsKey(identifier); + FrameSlotImpl slot = new FrameSlotImpl(this, identifier, slots.size(), type); slots.add(slot); - nameToSlotMap.put(name, slot); + identifierToSlotMap.put(identifier, slot); return slot; } - public FrameSlot findFrameSlot(String name) { - return nameToSlotMap.get(name); + public FrameSlot findFrameSlot(Object identifier) { + return identifierToSlotMap.get(identifier); } - public FrameSlot findOrAddFrameSlot(String name) { - FrameSlot result = findFrameSlot(name); + public FrameSlot findOrAddFrameSlot(Object identifier) { + FrameSlot result = findFrameSlot(identifier); if (result != null) { return result; } - return addFrameSlot(name); + return addFrameSlot(identifier); } public FrameVersion getCurrentVersion() { @@ -120,21 +120,21 @@ class FrameSlotImpl implements FrameSlot { private final FrameDescriptor descriptor; - private final String name; + private final Object identifier; private final int index; private Class type; private ArrayList listeners; - protected FrameSlotImpl(FrameDescriptor descriptor, String name, int index, Class type) { + protected FrameSlotImpl(FrameDescriptor descriptor, Object identifier, int index, Class type) { this.descriptor = descriptor; - this.name = name; + this.identifier = identifier; this.index = index; this.type = type; assert type != null; } - public String getName() { - return name; + public Object getIdentifier() { + return identifier; } public int getIndex() { @@ -189,7 +189,7 @@ @Override public String toString() { - return "[" + index + "," + name + "]"; + return "[" + index + "," + identifier + "]"; } @Override diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/FrameSlot.java Mon Feb 11 10:41:29 2013 +0100 @@ -27,7 +27,7 @@ */ public interface FrameSlot { - String getName(); + Object getIdentifier(); int getIndex(); diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/NativeFrame.java Mon Feb 11 10:41:29 2013 +0100 @@ -126,4 +126,9 @@ @Override public void updateToLatestVersion() { } + + @Override + public FrameDescriptor getFrameDescriptor() { + throw new UnsupportedOperationException("native frame"); + } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/PackedFrame.java Mon Feb 11 10:41:29 2013 +0100 @@ -35,5 +35,5 @@ * * @return the virtual frame that was the content of this packed frame */ - VirtualFrame unpack(); + Frame unpack(); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/frame/VirtualFrame.java Mon Feb 11 10:41:29 2013 +0100 @@ -35,29 +35,10 @@ public interface VirtualFrame extends Frame { /** - * Converts this virtual frame into a packed frame that has no longer direct access to the local - * variables. This packing is an important hint to the Truffle optimizer and therefore passing - * around a {@link PackedFrame} should be preferred over passing around a {@link VirtualFrame} - * when the probability that an unpacking will occur is low. - * - * @return the packed frame - */ - PackedFrame pack(); - - /** * Accesses the caller frame passed in via {@link CallTarget#call}. To get full access, it must * be first unpacked using {@link PackedFrame#unpack()}. * * @return the caller frame or null if this was a root method call */ PackedFrame getCaller(); - - /** - * Materializes this frame, which allows it to be stored in a field or cast to - * {@link java.lang.Object}. The frame however looses the ability to be packed or to access the - * caller frame. - * - * @return the new materialized frame - */ - MaterializedFrame materialize(); } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultMaterializedFrame.java Mon Feb 11 10:41:29 2013 +0100 @@ -25,7 +25,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; -final class DefaultMaterializedFrame implements MaterializedFrame { +final class DefaultMaterializedFrame implements MaterializedFrame, PackedFrame { private final DefaultVirtualFrame wrapped; @@ -102,4 +102,24 @@ public void updateToLatestVersion() { wrapped.updateToLatestVersion(); } + + @Override + public PackedFrame pack() { + return this; + } + + @Override + public MaterializedFrame materialize() { + return this; + } + + @Override + public Frame unpack() { + return this; + } + + @Override + public FrameDescriptor getFrameDescriptor() { + return wrapped.getFrameDescriptor(); + } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Mon Feb 11 10:41:29 2013 +0100 @@ -46,4 +46,14 @@ public CallTarget createCallTarget(RootNode rootNode) { return createCallTarget(rootNode, new FrameDescriptor()); } + + @Override + public MaterializedFrame createMaterializedFrame(Arguments arguments) { + return createMaterializedFrame(arguments, new FrameDescriptor()); + } + + @Override + public MaterializedFrame createMaterializedFrame(Arguments arguments, FrameDescriptor frameDescriptor) { + return new DefaultMaterializedFrame(new DefaultVirtualFrame(frameDescriptor, null, arguments)); + } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultVirtualFrame.java Mon Feb 11 10:41:29 2013 +0100 @@ -192,4 +192,9 @@ } currentVersion = version; } + + @Override + public FrameDescriptor getFrameDescriptor() { + return this.descriptor; + } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/ControlFlowException.java Mon Feb 11 10:41:29 2013 +0100 @@ -39,8 +39,9 @@ /** * For performance reasons, this exception does not record any stack trace information. */ + @SuppressWarnings("sync-override") @Override - public synchronized Throwable fillInStackTrace() { + public final Throwable fillInStackTrace() { return null; } } diff -r 3cec97eb3b5f -r e8c71b8562e3 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java --- a/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Mon Feb 11 10:41:02 2013 +0100 +++ b/graal/com.oracle.truffle.api/src/com/oracle/truffle/api/nodes/UnexpectedResultException.java Mon Feb 11 10:41:29 2013 +0100 @@ -54,8 +54,9 @@ /** * For performance reasons, this exception does not record any stack trace information. */ + @SuppressWarnings("sync-override") @Override - public synchronized Throwable fillInStackTrace() { + public Throwable fillInStackTrace() { return null; } } diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/compiler1.make --- a/make/solaris/makefiles/compiler1.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/compiler1.make Mon Feb 11 10:41:29 2013 +0100 @@ -29,3 +29,7 @@ VM_SUBDIR = client CFLAGS += -DCOMPILER1 + +ifndef OMIT_GRAAL + CFLAGS += -DGRAAL +endif diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/compiler2.make --- a/make/solaris/makefiles/compiler2.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/compiler2.make Mon Feb 11 10:41:29 2013 +0100 @@ -29,3 +29,7 @@ VM_SUBDIR = server CFLAGS += -DCOMPILER2 + +ifndef OMIT_GRAAL + CFLAGS += -DGRAAL +endif diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/debug.make --- a/make/solaris/makefiles/debug.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/debug.make Mon Feb 11 10:41:29 2013 +0100 @@ -43,7 +43,7 @@ MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug #ifdef GRAAL -MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal +MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL #endif # This mapfile is only needed when compiling with dtrace support, diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/fastdebug.make --- a/make/solaris/makefiles/fastdebug.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/fastdebug.make Mon Feb 11 10:41:29 2013 +0100 @@ -118,7 +118,7 @@ MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug #ifdef GRAAL -MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal +MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL #endif # This mapfile is only needed when compiling with dtrace support, diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/jvmg.make --- a/make/solaris/makefiles/jvmg.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/jvmg.make Mon Feb 11 10:41:29 2013 +0100 @@ -47,7 +47,7 @@ MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers \ $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-debug #ifdef GRAAL -MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal +MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL #endif # This mapfile is only needed when compiling with dtrace support, diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/optimized.make --- a/make/solaris/makefiles/optimized.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/optimized.make Mon Feb 11 10:41:29 2013 +0100 @@ -55,7 +55,7 @@ # Linker mapfiles MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers #ifdef GRAAL -MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal +MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL #endif # This mapfile is only needed when compiling with dtrace support, diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/product.make --- a/make/solaris/makefiles/product.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/product.make Mon Feb 11 10:41:29 2013 +0100 @@ -67,7 +67,7 @@ # Linker mapfiles MAPFILE = $(GAMMADIR)/make/solaris/makefiles/mapfile-vers ifdef GRAAL -MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-graal +MAPFILE += $(GAMMADIR)/make/solaris/makefiles/mapfile-vers-GRAAL endif ifndef USE_GCC diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/tiered.make --- a/make/solaris/makefiles/tiered.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/tiered.make Mon Feb 11 10:41:29 2013 +0100 @@ -29,3 +29,7 @@ VM_SUBDIR = server CFLAGS += -DCOMPILER2 -DCOMPILER1 + +ifndef OMIT_GRAAL + CFLAGS += -DGRAAL +endif diff -r 3cec97eb3b5f -r e8c71b8562e3 make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Mon Feb 11 10:41:02 2013 +0100 +++ b/make/solaris/makefiles/vm.make Mon Feb 11 10:41:29 2013 +0100 @@ -192,11 +192,11 @@ # Include dirs per type. Src_Dirs/CORE := $(CORE_PATHS) -Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) -Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) -Src_Dirs/TIERED := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) +Src_Dirs/COMPILER1 := $(CORE_PATHS) $(COMPILER1_PATHS) $(GRAAL_PATHS) +Src_Dirs/COMPILER2 := $(CORE_PATHS) $(COMPILER2_PATHS) $(GRAAL_PATHS) +Src_Dirs/TIERED := $(CORE_PATHS) $(COMPILER1_PATHS) $(COMPILER2_PATHS) $(GRAAL_PATHS) Src_Dirs/ZERO := $(CORE_PATHS) -Src_Dirs/SHARK := $(CORE_PATHS) +Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS) Src_Dirs/GRAAL := $(CORE_PATHS) $(GRAAL_PATHS) Src_Dirs := $(Src_Dirs/$(TYPE)) @@ -216,7 +216,7 @@ Src_Files_EXCLUDE/TIERED := $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) Src_Files_EXCLUDE/ZERO := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp Src_Files_EXCLUDE/SHARK := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) -Src_Files_EXCLUDE/GRAAL := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) $(GRAAL_SPECIFIC_FILES) ciTypeFlow.cpp +Src_Files_EXCLUDE/GRAAL := $(COMPILER1_SPECIFIC_FILES) $(COMPILER2_SPECIFIC_FILES) $(ZERO_SPECIFIC_FILES) $(SHARK_SPECIFIC_FILES) ciTypeFlow.cpp Src_Files_EXCLUDE += $(Src_Files_EXCLUDE/$(TYPE)) diff -r 3cec97eb3b5f -r e8c71b8562e3 mx/commands.py --- a/mx/commands.py Mon Feb 11 10:41:02 2013 +0100 +++ b/mx/commands.py Mon Feb 11 10:41:29 2013 +0100 @@ -786,7 +786,7 @@ tasks.append(t.stop()) t = Task('BuildJava') - build(['--no-native']) + build(['--no-native', '--jdt-warning-as-error']) tasks.append(t.stop()) if exists('jacoco.exec'): @@ -966,7 +966,7 @@ if ('specjbb2005' in args or 'all' in args): benchmarks += [sanitycheck.getSPECjbb2005()] - if ('specjbb2013' in args or 'all' in args): + if ('specjbb2013' in args): # or 'all' in args //currently not in default set benchmarks += [sanitycheck.getSPECjbb2013()] for test in benchmarks: diff -r 3cec97eb3b5f -r e8c71b8562e3 mx/eclipse-settings/org.eclipse.jdt.core.prefs diff -r 3cec97eb3b5f -r e8c71b8562e3 mx/projects --- a/mx/projects Mon Feb 11 10:41:02 2013 +0100 +++ b/mx/projects Mon Feb 11 10:41:29 2013 +0100 @@ -55,13 +55,6 @@ project@com.oracle.graal.api.code@checkstyle=com.oracle.graal.graph project@com.oracle.graal.api.code@javaCompliance=1.7 -# graal.api.interpreter -project@com.oracle.graal.api.interpreter@subDir=graal -project@com.oracle.graal.api.interpreter@sourceDirs=src -project@com.oracle.graal.api.interpreter@dependencies=com.oracle.graal.api.meta -project@com.oracle.graal.api.interpreter@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.api.interpreter@javaCompliance=1.7 - # graal.amd64 project@com.oracle.graal.amd64@subDir=graal project@com.oracle.graal.amd64@sourceDirs=src @@ -69,10 +62,17 @@ project@com.oracle.graal.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.amd64@javaCompliance=1.7 +# graal.sparc +project@com.oracle.graal.sparc@subDir=graal +project@com.oracle.graal.sparc@sourceDirs=src +project@com.oracle.graal.sparc@dependencies=com.oracle.graal.api.code +project@com.oracle.graal.sparc@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.sparc@javaCompliance=1.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.snippets,com.oracle.graal.api.interpreter,com.oracle.graal.api.runtime,com.oracle.graal.printer +project@com.oracle.graal.hotspot@dependencies=com.oracle.graal.snippets,com.oracle.graal.api.runtime,com.oracle.graal.printer project@com.oracle.graal.hotspot@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot@javaCompliance=1.7 @@ -83,6 +83,13 @@ project@com.oracle.graal.hotspot.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.hotspot.amd64@javaCompliance=1.7 +# graal.hotspot.sparc +project@com.oracle.graal.hotspot.sparc@subDir=graal +project@com.oracle.graal.hotspot.sparc@sourceDirs=src +project@com.oracle.graal.hotspot.sparc@dependencies=com.oracle.graal.hotspot,com.oracle.graal.compiler.sparc +project@com.oracle.graal.hotspot.sparc@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.hotspot.sparc@javaCompliance=1.7 + # graal.hotspot.server project@com.oracle.graal.hotspot.server@subDir=graal project@com.oracle.graal.hotspot.server@sourceDirs=src @@ -130,6 +137,13 @@ project@com.oracle.graal.lir.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.lir.amd64@javaCompliance=1.7 +# graal.lir.sparc +project@com.oracle.graal.lir.sparc@subDir=graal +project@com.oracle.graal.lir.sparc@sourceDirs=src +project@com.oracle.graal.lir.sparc@dependencies=com.oracle.graal.lir,com.oracle.graal.asm.sparc +project@com.oracle.graal.lir.sparc@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.lir.sparc@javaCompliance=1.7 + # graal.alloc project@com.oracle.graal.alloc@subDir=graal project@com.oracle.graal.alloc@sourceDirs=src @@ -165,13 +179,6 @@ project@com.oracle.graal.nodes@checkstyle=com.oracle.graal.graph project@com.oracle.graal.nodes@javaCompliance=1.7 -# graal.interpreter -project@com.oracle.graal.interpreter@subDir=graal -project@com.oracle.graal.interpreter@sourceDirs=src -project@com.oracle.graal.interpreter@dependencies=com.oracle.graal.api.interpreter,com.oracle.graal.bytecode,com.oracle.graal.api.runtime -project@com.oracle.graal.interpreter@checkstyle=com.oracle.graal.graph -project@com.oracle.graal.interpreter@javaCompliance=1.7 - # graal.phases project@com.oracle.graal.phases@subDir=graal project@com.oracle.graal.phases@sourceDirs=src @@ -214,6 +221,13 @@ project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.amd64@javaCompliance=1.7 +# graal.compiler.sparc +project@com.oracle.graal.compiler.sparc@subDir=graal +project@com.oracle.graal.compiler.sparc@sourceDirs=src +project@com.oracle.graal.compiler.sparc@dependencies=com.oracle.graal.compiler,com.oracle.graal.lir.sparc +project@com.oracle.graal.compiler.sparc@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.sparc@javaCompliance=1.7 + # graal.bytecode project@com.oracle.graal.bytecode@subDir=graal project@com.oracle.graal.bytecode@sourceDirs=src @@ -234,10 +248,17 @@ project@com.oracle.graal.printer@checkstyle=com.oracle.graal.graph project@com.oracle.graal.printer@javaCompliance=1.7 +# graal.test +project@com.oracle.graal.test@subDir=graal +project@com.oracle.graal.test@sourceDirs=src +project@com.oracle.graal.test@dependencies=JUNIT +project@com.oracle.graal.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.test@javaCompliance=1.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.api.runtime,com.oracle.graal.printer,JUNIT +project@com.oracle.graal.compiler.test@dependencies=com.oracle.graal.api.runtime,com.oracle.graal.printer,com.oracle.graal.test project@com.oracle.graal.compiler.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.test@javaCompliance=1.7 @@ -255,6 +276,13 @@ project@com.oracle.graal.asm@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm@javaCompliance=1.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@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.asm.test@javaCompliance=1.7 + # graal.asm.amd64 project@com.oracle.graal.asm.amd64@subDir=graal project@com.oracle.graal.asm.amd64@sourceDirs=src @@ -262,6 +290,20 @@ project@com.oracle.graal.asm.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.amd64@javaCompliance=1.7 +# graal.asm.amd64.test +project@com.oracle.graal.asm.amd64.test@subDir=graal +project@com.oracle.graal.asm.amd64.test@sourceDirs=src +project@com.oracle.graal.asm.amd64.test@dependencies=com.oracle.graal.asm.test,com.oracle.graal.asm.amd64 +project@com.oracle.graal.asm.amd64.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.asm.amd64.test@javaCompliance=1.7 + +# graal.asm.sparc +project@com.oracle.graal.asm.sparc@subDir=graal +project@com.oracle.graal.asm.sparc@sourceDirs=src +project@com.oracle.graal.asm.sparc@dependencies=com.oracle.graal.asm,com.oracle.graal.sparc +project@com.oracle.graal.asm.sparc@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.asm.sparc@javaCompliance=1.7 + # truffle.api project@com.oracle.truffle.api@subDir=graal project@com.oracle.truffle.api@sourceDirs=src diff -r 3cec97eb3b5f -r e8c71b8562e3 src/cpu/sparc/vm/c2_globals_sparc.hpp --- a/src/cpu/sparc/vm/c2_globals_sparc.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -37,6 +37,7 @@ define_pd_global(bool, PreferInterpreterNativeStubs, false); define_pd_global(bool, ProfileTraps, true); define_pd_global(bool, UseOnStackReplacement, true); +define_pd_global(intx, TypeProfileWidth, 2 ); #ifdef CC_INTERP define_pd_global(bool, ProfileInterpreter, false); #else diff -r 3cec97eb3b5f -r e8c71b8562e3 src/cpu/sparc/vm/frame_sparc.inline.hpp --- a/src/cpu/sparc/vm/frame_sparc.inline.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -74,7 +74,8 @@ // return address: -inline address frame::sender_pc() const { return *I7_addr() + pc_return_offset; } +inline address* frame::sender_pc_addr() const { return (address*) (I7_addr() + pc_return_offset); } +inline address frame::sender_pc() const { return *sender_pc_addr(); } inline address* frame::I7_addr() const { return (address*) &sp()[ I7->sp_offset_in_saved_window()]; } inline address* frame::I0_addr() const { return (address*) &sp()[ I0->sp_offset_in_saved_window()]; } diff -r 3cec97eb3b5f -r e8c71b8562e3 src/cpu/sparc/vm/graalGlobals_sparc.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cpu/sparc/vm/graalGlobals_sparc.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2000, 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. + * + */ + +#ifndef CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP +#define CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP + +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +// Sets the default values for platform dependent flags used by the Graal compiler. +// (see graalGlobals.hpp) + +define_pd_global(intx, GraalSafepointPollOffset, 0 ); + +#endif // CPU_SPARC_VM_GRAALGLOBALS_SPARC_HPP diff -r 3cec97eb3b5f -r e8c71b8562e3 src/cpu/sparc/vm/jniTypes_sparc.hpp --- a/src/cpu/sparc/vm/jniTypes_sparc.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/cpu/sparc/vm/jniTypes_sparc.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -112,6 +112,25 @@ return *(jdouble *)&jl; } #endif + static inline jint get_int (intptr_t *from, int& pos) { + return get_int(from + pos++); + } + static inline jlong get_long (intptr_t *from, int& pos) { + jlong result = get_long(from + pos); + pos += 2; + return result; + } + static inline oop get_obj (intptr_t *from, int& pos) { + return get_obj(from + pos++); + } + static inline jfloat get_float (intptr_t *from, int& pos) { + return get_float(from + pos++); + } + static inline jdouble get_double(intptr_t *from, int& pos) { + jdouble result = get_double(from + pos); + pos += 2; + return result; + } }; #endif // CPU_SPARC_VM_JNITYPES_SPARC_HPP diff -r 3cec97eb3b5f -r e8c71b8562e3 src/cpu/x86/vm/frame_x86.hpp --- a/src/cpu/x86/vm/frame_x86.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/cpu/x86/vm/frame_x86.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -191,8 +191,6 @@ // Note: not necessarily the real 'frame pointer' (see real_fp) intptr_t* fp() const { return _fp; } - inline address* sender_pc_addr() const; - // return address of param, zero origin index. inline address* native_param_addr(int idx) const; diff -r 3cec97eb3b5f -r e8c71b8562e3 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/os/windows/vm/os_windows.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -2103,18 +2103,32 @@ #ifdef _M_IA64 assert(0, "Fix Handle_IDiv_Exception"); #elif _M_AMD64 - PCONTEXT ctx = exceptionInfo->ContextRecord; - address pc = (address)ctx->Rip; -#ifndef GRAAL - assert(pc[0] == 0xF7, "not an idiv opcode"); - assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands"); - assert(ctx->Rax == min_jint, "unexpected idiv exception"); -#endif - // set correct result values and continue after idiv instruction - ctx->Rip = (DWORD)pc + 2; // idiv reg, reg is 2 bytes - ctx->Rax = (DWORD)min_jint; // result - ctx->Rdx = (DWORD)0; // remainder - // Continue the execution + #ifdef GRAAL + PCONTEXT ctx = exceptionInfo->ContextRecord; + address pc = (address)ctx->Rip; + assert(pc[0] == 0x48 && pc[1] == 0xF7 || pc[0] == 0xF7, "not an idiv opcode"); + if (pc[0] == 0x48) { + // set correct result values and continue after idiv instruction + ctx->Rip = (DWORD64)pc + 3; // REX idiv reg, reg is 3 bytes + ctx->Rax = (DWORD64)min_jlong; // result + } else { + ctx->Rip = (DWORD64)pc + 2; // idiv reg, reg is 2 bytes + ctx->Rax = (DWORD64)min_jint; // result + } + ctx->Rdx = (DWORD64)0; // remainder + // Continue the execution + #else + PCONTEXT ctx = exceptionInfo->ContextRecord; + address pc = (address)ctx->Rip; + assert(pc[0] == 0xF7, "not an idiv opcode"); + assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands"); + assert(ctx->Rax == min_jint, "unexpected idiv exception"); + // set correct result values and continue after idiv instruction + ctx->Rip = (DWORD)pc + 2; // idiv reg, reg is 2 bytes + ctx->Rax = (DWORD)min_jint; // result + ctx->Rdx = (DWORD)0; // remainder + // Continue the execution + #endif // GRAAL #else PCONTEXT ctx = exceptionInfo->ContextRecord; address pc = (address)ctx->Eip; diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -339,7 +339,6 @@ template(compileMethod_name, "compileMethod") \ template(compileMethod_signature, "(JLcom/oracle/graal/hotspot/meta/HotSpotResolvedObjectType;IZI)Z") \ template(setOption_name, "setOption") \ - template(setDefaultOptions_name, "setDefaultOptions") \ template(setOption_signature, "(Ljava/lang/String;)Z") \ template(createUnresolvedJavaMethod_name, "createUnresolvedJavaMethod") \ template(createUnresolvedJavaMethod_signature, "(Ljava/lang/String;Ljava/lang/String;Lcom/oracle/graal/api/meta/JavaType;)Lcom/oracle/graal/api/meta/JavaMethod;") \ diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/code/dependencies.cpp --- a/src/share/vm/code/dependencies.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/code/dependencies.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -30,6 +30,7 @@ #include "code/dependencies.hpp" #include "compiler/compileLog.hpp" #include "oops/oop.inline.hpp" +#include "oops/objArrayKlass.hpp" #include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" #include "utilities/copy.hpp" diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/code/nmethod.cpp --- a/src/share/vm/code/nmethod.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/code/nmethod.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -595,7 +595,7 @@ { assert(debug_info->oop_recorder() == code_buffer->oop_recorder(), "shared OR"); code_buffer->finalize_oop_references(method); - size_t leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize); + int leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize); // create nmethod nmethod* nm = NULL; { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); @@ -911,7 +911,7 @@ _unwind_handler_offset = -1; } - size_t leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize); + int leaf_graph_ids_size = leaf_graph_ids == NULL ? 0 : round_to(sizeof(jlong) * leaf_graph_ids->length(), oopSize); _oops_offset = data_offset(); _metadata_offset = _oops_offset + round_to(code_buffer->total_oop_size(), oopSize); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/code/stubs.cpp --- a/src/share/vm/code/stubs.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/code/stubs.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -254,7 +254,7 @@ guarantee(_queue_begin != _queue_end || n == 0, "buffer indices must be the same"); } -void StubQueue::print_on(outputStream* st) { +void StubQueue::print_on(outputStream* st) const { MutexLockerEx lock(_mutex); for (Stub* s = first(); s != NULL; s = next(s)) { stub_print(s, st); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/code/stubs.hpp --- a/src/share/vm/code/stubs.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/code/stubs.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -107,20 +107,21 @@ public: // Initialization/finalization virtual void initialize(Stub* self, int size, - CodeComments& comments) = 0; // called after creation (called twice if allocated via (request, commit)) - virtual void finalize(Stub* self) = 0; // called before deallocation + CodeComments& comments) = 0; // called after creation (called twice if allocated via (request, commit)) + virtual void finalize(Stub* self) = 0; // called before deallocation // General info/converters - virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment) - virtual int code_size_to_size(int code_size) const = 0; // computes the total stub size in bytes given the code size in bytes + virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment) + virtual int code_size_to_size(int code_size) const = 0; // computes the total stub size in bytes given the code size in bytes // Code info - virtual address code_begin(Stub* self) const = 0; // points to the first code byte - virtual address code_end(Stub* self) const = 0; // points to the first byte after the code + virtual address code_begin(Stub* self) const = 0; // points to the first code byte + virtual address code_end(Stub* self) const = 0; // points to the first byte after the code // Debugging - virtual void verify(Stub* self) = 0; // verifies the stub - virtual void print_on(Stub* self, outputStream* st) = 0; // prints information about the stub + virtual void verify(Stub* self) const = 0; // verifies the stub + NOT_PRODUCT(using AllocatedObj::print_on;) + virtual void print_on(Stub* self, outputStream* st) const = 0; // prints information about the stub }; @@ -128,28 +129,29 @@ // class, forwarding stub interface calls to the corresponding // stub calls. -#define DEF_STUB_INTERFACE(stub) \ - class stub##Interface: public StubInterface { \ - private: \ - static stub* cast(Stub* self) { return (stub*)self; } \ - \ - public: \ - /* Initialization/finalization */ \ - virtual void initialize(Stub* self, int size, \ - CodeComments& comments) { cast(self)->initialize(size, comments); } \ - virtual void finalize(Stub* self) { cast(self)->finalize(); } \ - \ - /* General info */ \ - virtual int size(Stub* self) const { return cast(self)->size(); } \ - virtual int code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \ - \ - /* Code info */ \ - virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \ - virtual address code_end(Stub* self) const { return cast(self)->code_end(); } \ - \ - /* Debugging */ \ - virtual void verify(Stub* self) { cast(self)->verify(); } \ - virtual void print_on(Stub* self, outputStream* st) { cast(self)->print_on(st); } \ +#define DEF_STUB_INTERFACE(stub) \ + class stub##Interface: public StubInterface { \ + private: \ + static stub* cast(Stub* self) { return (stub*)self; } \ + \ + public: \ + /* Initialization/finalization */ \ + virtual void initialize(Stub* self, int size, \ + CodeComments& comments) { cast(self)->initialize(size, comments); } \ + virtual void finalize(Stub* self) { cast(self)->finalize(); } \ + \ + /* General info */ \ + virtual int size(Stub* self) const { return cast(self)->size(); } \ + virtual int code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \ + \ + /* Code info */ \ + virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \ + virtual address code_end(Stub* self) const { return cast(self)->code_end(); } \ + \ + /* Debugging */ \ + virtual void verify(Stub* self) const { cast(self)->verify(); } \ + NOT_PRODUCT(using AllocatedObj::print_on;) \ + virtual void print_on(Stub* self, outputStream* st) const { cast(self)->print_on(st); } \ }; @@ -182,7 +184,7 @@ bool stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); } int stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); } void stub_verify(Stub* s) { _stub_interface->verify(s); } - void stub_print(Stub* s, outputStream* st) { _stub_interface->print_on(s, st); } + void stub_print(Stub* s, outputStream* st) const { _stub_interface->print_on(s, st); } static void register_queue(StubQueue*); @@ -226,9 +228,9 @@ address stub_code_end(Stub* s) const { return _stub_interface->code_end(s); } // Debugging/printing - void verify(); // verifies the stub queue - void print() { print_on(tty); } - void print_on(outputStream* st); + void verify(); // verifies the stub queue + virtual void print() const { print_on(tty); } + virtual void print_on(outputStream* st) const; }; #endif // SHARE_VM_CODE_STUBS_HPP diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "compiler/disassembler.hpp" #include "runtime/javaCalls.hpp" #include "graal/graalEnv.hpp" #include "graal/graalCompiler.hpp" @@ -30,27 +31,38 @@ #include "graal/graalCompilerToVM.hpp" #include "graal/graalVmIds.hpp" #include "graal/graalRuntime.hpp" +#include "asm/register.hpp" #include "classfile/vmSymbols.hpp" -#include "vmreg_x86.inline.hpp" - +#include "code/vmreg.hpp" -// TODO this should be handled in a more robust way - not hard coded... -Register CPU_REGS[] = { rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 }; -bool OOP_ALLOWED[] = {true, true, true, true, false, false, true, true, true, true, false, true, true, true, true, true}; -const static int NUM_CPU_REGS = sizeof(CPU_REGS) / sizeof(Register); -XMMRegister XMM_REGS[] = { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; -const static int NUM_XMM_REGS = sizeof(XMM_REGS) / sizeof(XMMRegister); -const static int NUM_REGS = NUM_CPU_REGS + NUM_XMM_REGS; -const static jlong NO_REF_MAP = 0x8000000000000000L; +#ifdef TARGET_ARCH_x86 +# include "vmreg_x86.inline.hpp" +#endif +#ifdef TARGET_ARCH_sparc +# include "vmreg_sparc.inline.hpp" +#endif +#ifdef TARGET_ARCH_zero +# include "vmreg_zero.inline.hpp" +#endif +#ifdef TARGET_ARCH_arm +# include "vmreg_arm.inline.hpp" +#endif +#ifdef TARGET_ARCH_ppc +# include "vmreg_ppc.inline.hpp" +#endif // convert Graal register indices (as used in oop maps) to HotSpot registers VMReg get_hotspot_reg(jint graal_reg) { - - assert(graal_reg >= 0 && graal_reg < NUM_REGS, "invalid register number"); - if (graal_reg < NUM_CPU_REGS) { - return CPU_REGS[graal_reg]->as_VMReg(); + if (graal_reg < RegisterImpl::number_of_registers) { + return as_Register(graal_reg)->as_VMReg(); } else { - return XMM_REGS[graal_reg - NUM_CPU_REGS]->as_VMReg(); + int remainder = graal_reg - RegisterImpl::number_of_registers; +#ifdef TARGET_ARCH_x86 + if (remainder < XMMRegisterImpl::number_of_registers) { + return as_XMMRegister(remainder)->as_VMReg(); + } +#endif + ShouldNotReachHere(); } } @@ -76,11 +88,10 @@ oop frame_map = (oop) DebugInfo::frameRefMap(debug_info); if (register_map != NULL) { - for (jint i = 0; i < NUM_CPU_REGS; i++) { + for (jint i = 0; i < RegisterImpl::number_of_registers; i++) { bool is_oop = is_bit_set(register_map, i); VMReg reg = get_hotspot_reg(i); if (is_oop) { - assert(OOP_ALLOWED[i], "this register may never be an oop, register map misaligned?"); map->set_oop(reg); } else { map->set_value(reg); @@ -156,11 +167,15 @@ } else { locationType = Location::dbl; } +#ifdef TARGET_ARCH_x86 ScopeValue* value = new LocationValue(Location::new_reg_loc(locationType, as_XMMRegister(number - 16)->as_VMReg())); if (type == T_DOUBLE) { second = value; } return value; +#else + ShouldNotReachHere("Platform currently does not support floating point values."); +#endif } } else if (value->is_a(StackSlot::klass())) { if (type == T_DOUBLE) { @@ -291,8 +306,15 @@ GrowableArray* get_leaf_graph_ids(Handle& comp_result) { arrayOop leafGraphArray = (arrayOop) CompilationResult::leafGraphIds(HotSpotCompilationResult::comp(comp_result)); - GrowableArray* result = new GrowableArray(leafGraphArray->length()); - for (int i = 0; i < leafGraphArray->length(); i++) { + jint length; + if (leafGraphArray == NULL) { + length = 0; + } else { + length = leafGraphArray->length(); + } + + GrowableArray* result = new GrowableArray(length); + for (int i = 0; i < length; i++) { result->append(((jlong*) leafGraphArray->base(T_LONG))[i]); } diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -48,7 +48,7 @@ MARK_POLL_NEAR = 0x3001, MARK_POLL_RETURN_NEAR = 0x3002, MARK_POLL_FAR = 0x3003, - MARK_POLL_RETURN_FAR = 0x3004, + MARK_POLL_RETURN_FAR = 0x3004 }; Arena _arena; diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -79,7 +79,6 @@ { GRAAL_VM_ENTRY_MARK; HandleMark hm; - VMToCompiler::setDefaultOptions(); for (int i = 0; i < Arguments::num_graal_args(); ++i) { const char* arg = Arguments::graal_args_array()[i]; Handle option = java_lang_String::create_from_str(arg, THREAD); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -30,6 +30,7 @@ #include "graal/graalRuntime.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerOracle.hpp" +#include "compiler/disassembler.hpp" #include "graal/graalCompilerToVM.hpp" #include "graal/graalCompiler.hpp" #include "graal/graalEnv.hpp" diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -22,12 +22,13 @@ */ #include "precompiled.hpp" -#include "runtime/interfaceSupport.hpp" -#include "prims/jvm.h" +#include "asm/codeBuffer.hpp" #include "graal/graalRuntime.hpp" #include "graal/graalVMToCompiler.hpp" -#include "asm/codeBuffer.hpp" +#include "memory/oopFactory.hpp" +#include "prims/jvm.h" #include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.hpp" // Implementation of GraalStubAssembler @@ -128,7 +129,7 @@ // These stubs don't need to have an oopmap case graal_slow_subtype_check_id: #if defined(SPARC) || defined(PPC) - case handle_exception_nofpu_id: // Unused on sparc + case graal_handle_exception_nofpu_id: // Unused on sparc #endif case graal_verify_oop_id: case graal_unwind_exception_call_id: diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalVMToCompiler.cpp --- a/src/share/vm/graal/graalVMToCompiler.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -86,15 +86,6 @@ return result.get_jboolean(); } -void VMToCompiler::setDefaultOptions() { - KlassHandle compilerKlass = loadClass(vmSymbols::com_oracle_graal_hotspot_HotSpotOptions()); - - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD); - check_pending_exception("Error while calling setDefaultOptions"); -} - jboolean VMToCompiler::compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority) { assert(method != NULL, "just checking"); assert(!holder.is_null(), "just checking"); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/graal/graalVMToCompiler.hpp --- a/src/share/vm/graal/graalVMToCompiler.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/graal/graalVMToCompiler.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -53,9 +53,6 @@ // public static boolean HotSpotOptions.setOption(String option); static jboolean setOption(Handle option); - // public static void HotSpotOptions.setDefaultOptions(); - static void setDefaultOptions(); - // public abstract boolean compileMethod(long vmId, String name, int entry_bci, boolean blocking); static jboolean compileMethod(Method* method, Handle holder, int entry_bci, jboolean blocking, int priority); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/runtime/arguments.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -2270,7 +2270,6 @@ "com.oracle.graal.api.runtime", "com.oracle.graal.api.meta", "com.oracle.graal.api.code", - "com.oracle.graal.api.interpreter", "com.oracle.graal.hotspot", "com.oracle.graal.asm", "com.oracle.graal.alloc", diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/runtime/compilationPolicy.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -492,7 +492,7 @@ int hot_count = m->backedge_count(); const char* comment = "backedge_count"; - if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m)) { + if (is_compilation_enabled() && !m->is_not_osr_compilable() && can_be_compiled(m) && !m->queued_for_compilation() && m->code() == NULL) { if (TraceCompilationPolicy) { tty->print("backedge invocation trigger: "); m->print_short_name(tty); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/runtime/fieldDescriptor.hpp --- a/src/share/vm/runtime/fieldDescriptor.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/runtime/fieldDescriptor.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -25,7 +25,10 @@ #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP +#include "oops/annotations.hpp" #include "oops/constantPool.hpp" +#include "oops/fieldInfo.hpp" +#include "oops/instanceKlass.hpp" #include "oops/symbol.hpp" #include "runtime/fieldType.hpp" #include "utilities/accessFlags.hpp" diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/runtime/frame.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -637,8 +637,10 @@ st->print("; "); interpreter_frame_method()->print_name(st); st->cr(); +#ifdef AMD64 // last sp st->print_cr(" - last sp at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_last_sp_addr(), *interpreter_frame_last_sp_addr()); +#endif // sender sp st->print_cr(" - sender sp at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_sender_sp_addr(), *interpreter_frame_sender_sp_addr()); // old fp diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/runtime/frame.hpp --- a/src/share/vm/runtime/frame.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/runtime/frame.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -208,6 +208,7 @@ void set_link(intptr_t* addr); // Return address + address* sender_pc_addr() const; address sender_pc() const; // Support for deoptimization diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/runtime/java.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -375,6 +375,10 @@ CompileBroker::print_times(); } + if(PrintNMethodStatistics) { + nmethod::print_statistics(); + } + if (PrintCodeCache) { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); CodeCache::print(); diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/utilities/machineCodePrinter.cpp --- a/src/share/vm/utilities/machineCodePrinter.cpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/utilities/machineCodePrinter.cpp Mon Feb 11 10:41:29 2013 +0100 @@ -21,7 +21,10 @@ * questions. */ -#include "precompiled.hpp" +#include "precompiled.hpp" +#include "code/stubs.hpp" +#include "compiler/disassembler.hpp" +#include "runtime/thread.hpp" #include "utilities/machineCodePrinter.hpp" #include "utilities/ostream.hpp" diff -r 3cec97eb3b5f -r e8c71b8562e3 src/share/vm/utilities/machineCodePrinter.hpp --- a/src/share/vm/utilities/machineCodePrinter.hpp Mon Feb 11 10:41:02 2013 +0100 +++ b/src/share/vm/utilities/machineCodePrinter.hpp Mon Feb 11 10:41:29 2013 +0100 @@ -23,6 +23,9 @@ #ifndef SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP #define SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP + +#include "memory/allocation.hpp" +#include "utilities/ostream.hpp" class MachineCodePrinter : public AllStatic { private: